-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·202 lines (177 loc) · 6.23 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·202 lines (177 loc) · 6.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/bin/env bash
# Downloads a precompiled Burrito release of `lc` for the current machine
# and installs it, plus the bin/ wrapper scripts (lcreate, lcls, lclose,
# lcomment, lproj) already bundled in the same release tarball, onto a
# directory already on $PATH. Fallback path for machines without
# Homebrew - see rubyists/homebrew-tap for that.
#
# LC_VERSION pins a specific release tag (e.g. "v1.0.0") instead of the
# latest one. LC_INSTALL_DIR pins a specific install directory instead of
# the first writable $PATH entry found.
#
# Records exactly what it installed and where in a manifest file, so
# uninstall.sh can remove precisely those files even if $PATH changes
# between install and uninstall.
repo=rubyists/linear-cli
version=${LC_VERSION:-latest}
state_dir="${XDG_STATE_HOME:-$HOME/.local/state}/linear-cli"
manifest="$state_dir/manifest"
detect_target() {
case "$(uname -s)" in
Darwin)
case "$(uname -m)" in
arm64) printf '%s\n' macos_aarch64 ;;
*)
printf 'error: unsupported macOS architecture: %s (only aarch64 is built)\n' "$(uname -m)" >&2
exit 1
;;
esac
;;
Linux)
case "$(uname -m)" in
x86_64) printf '%s\n' linux_x86_64 ;;
*)
printf 'error: unsupported Linux architecture: %s (only x86_64 is built)\n' "$(uname -m)" >&2
exit 1
;;
esac
;;
*)
printf 'error: unsupported OS: %s (use the container image on Windows)\n' "$(uname -s)" >&2
exit 1
;;
esac
}
# Prefer an install dir the user already has on $PATH (so no shell rc
# editing is required) over inventing a new one. $LC_INSTALL_DIR always
# wins if set, for anyone who wants a specific target.
pick_install_dir() {
if [ -n "${LC_INSTALL_DIR:-}" ]
then
printf '%s\n' "$LC_INSTALL_DIR"
return
fi
local dir
IFS=: read -ra path_dirs <<< "$PATH"
for dir in "${path_dirs[@]}"
do
if [ -n "$dir" ] && [ -d "$dir" ] && [ -w "$dir" ]
then
printf '%s\n' "$dir"
return
fi
done
printf '%s\n' "$HOME/.local/bin"
}
# GNU coreutils' sha256sum vs. macOS's shasum -a 256 - both read the same
# "<hash> <filename>" format via `-c -` on stdin.
checksum_cmd() {
if command -v sha256sum >/dev/null 2>&1
then
printf 'sha256sum\n'
elif command -v shasum >/dev/null 2>&1
then
printf 'shasum -a 256\n'
else
printf 'error: need sha256sum or shasum on $PATH to verify the download\n' >&2
exit 1
fi
}
release_url() {
local asset="$1"
if [ "$version" = "latest" ]
then
printf 'https://github.com/%s/releases/latest/download/%s\n' "$repo" "$asset"
else
printf 'https://github.com/%s/releases/download/%s/%s\n' "$repo" "$version" "$asset"
fi
}
# Downloads lc_<target>.tar.gz + SHA256SUMS, verifies the tarball's
# checksum against just its own line (SHA256SUMS covers every target,
# not only the one being installed here), and extracts it. Prints the
# directory it extracted into.
fetch_lc() {
local target="$1" tarball tmp_dir sum_tool
tarball="lc_${target}.tar.gz"
tmp_dir=$(mktemp -d) || {
printf 'error: could not create a temp directory\n' >&2
exit 1
}
trap 'rm -rf "$tmp_dir"' EXIT
printf 'Downloading %s (%s)...\n' "$tarball" "$version" >&2
# --retry-all-errors: GitHub's release-download redirect chain
# occasionally drops the connection outright mid-stream (curl: (56)
# Connection died) - verified directly, reproduced it repeatedly, and
# confirmed plain --retry alone does NOT cover this specific error
# (it's outside curl's default retriable set), only succeeding once
# --retry-all-errors was added too.
if ! curl -fsSL --retry 5 --retry-all-errors "$(release_url "$tarball")" -o "$tmp_dir/$tarball"
then
printf 'error: failed to download %s\n' "$tarball" >&2
exit 1
fi
if ! curl -fsSL --retry 5 --retry-all-errors "$(release_url "SHA256SUMS")" -o "$tmp_dir/SHA256SUMS"
then
printf 'error: failed to download SHA256SUMS\n' >&2
exit 1
fi
sum_tool=$(checksum_cmd)
if ! grep -- " $tarball\$" "$tmp_dir/SHA256SUMS" | (cd "$tmp_dir" && $sum_tool -c -) >/dev/null
then
printf 'error: checksum verification failed for %s\n' "$tarball" >&2
exit 1
fi
if ! tar -xzf "$tmp_dir/$tarball" -C "$tmp_dir"
then
printf 'error: failed to extract %s\n' "$tarball" >&2
exit 1
fi
printf '%s\n' "$tmp_dir"
}
if ! command -v curl >/dev/null 2>&1
then
printf 'error: curl is required\n' >&2
exit 1
fi
target=$(detect_target) || exit 1
install_dir=$(pick_install_dir)
extracted_dir=$(fetch_lc "$target") || exit 1
if ! mkdir -p "$install_dir"
then
printf 'error: could not create install dir %s\n' "$install_dir" >&2
exit 1
fi
if ! mkdir -p "$state_dir"
then
printf 'error: could not create state dir %s\n' "$state_dir" >&2
exit 1
fi
: > "$manifest"
for name in lc lcreate lcls lclose lcomment lproj
do
if ! install -m 755 "$extracted_dir/$name" "$install_dir/$name"
then
printf 'error: failed to install %s to %s\n' "$name" "$install_dir" >&2
exit 1
fi
printf '%s\n' "$install_dir/$name" >> "$manifest"
done
# Gatekeeper blocks lc itself (a real Mach-O binary) on macOS since it
# isn't signed/notarized - the wrapper scripts are plain shell, so they're
# unaffected. Best-effort: xattr not existing/failing shouldn't fail the
# install, since the user can still do this by hand (see the README).
if [ "$(uname -s)" = Darwin ]
then
xattr -d com.apple.quarantine "$install_dir/lc" 2>/dev/null || true
fi
printf 'Installed lc, lcreate, lcls, lclose, lcomment, lproj to %s\n' "$install_dir"
printf '(uninstall.sh will remove exactly these files - manifest at %s)\n' "$manifest"
case ":$PATH:" in
*":$install_dir:"*) ;;
*)
printf '\n'
printf 'warning: %s is not on your $PATH.\n' "$install_dir"
printf 'Add it to your shell profile, e.g.:\n'
printf ' export PATH="%s:$PATH"\n' "$install_dir"
;;
esac