-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathinstall.sh
268 lines (226 loc) · 6.69 KB
/
install.sh
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#!/usr/bin/env sh
set -eu
(set -o pipefail 2>/dev/null) && set -o pipefail
help() {
cat <<'EOF'
Install spaces binaries (spaced and space-cli) from GitHub releases.
USAGE:
install.sh [options]
FLAGS:
-h, --help Display this message
-f, --force Force overwriting existing binaries
-v, --verbose Show detailed output
OPTIONS:
--tag VERSION Specific version to install (e.g., 0.0.6a), defaults to latest release
--to LOCATION Where to install the binaries (default: auto-detected based on OS)
For macOS: ~/.local/bin if exists, else ~/bin
For Linux: ~/.local/bin
NOTES:
The script will automatically choose an appropriate user-writable location.
The chosen directory will be added to your PATH if needed.
EOF
}
say() {
echo "install: $*" >&2
}
err() {
if [ -n "${td-}" ]; then
rm -rf "$td"
fi
say "error: $*"
say "run './install.sh --help' to see available options"
exit 1
}
need() {
if ! command -v "$1" > /dev/null 2>&1; then
err "need $1 (command not found)"
fi
}
add_to_path() {
local install_dir="$1"
local shell_rc
local reload_needed=false
# Detect shell configuration file based on $SHELL environment variable
if [[ "$SHELL" == */zsh ]]; then
shell_rc="$HOME/.zshrc"
shell_type="zsh"
else
shell_type="bash"
shell_rc="$HOME/.bashrc"
[ "$(uname -s)" = "Darwin" ] && shell_rc="$HOME/.bash_profile"
fi
if ! echo "$PATH" | tr ':' '\n' | grep -Fq "$install_dir"; then
say "Adding $install_dir to PATH in $shell_rc"
echo "export PATH=\"$install_dir:\$PATH\"" >> "$shell_rc"
reload_needed=true
fi
# Return whether reload is needed
[ "$reload_needed" = true ] && echo "reload" || echo "noreload"
}
determine_install_dir() {
local os="$1"
local specified_dir="$2"
local install_dir
if [ -n "$specified_dir" ]; then
install_dir="$specified_dir"
else
case "$os" in
darwin)
if [ -d "$HOME/.local/bin" ]; then
install_dir="$HOME/.local/bin"
else
install_dir="$HOME/bin"
fi
;;
linux)
install_dir="$HOME/.local/bin"
;;
*)
err "unsupported operating system: $os"
;;
esac
fi
# Create directory if it doesn't exist
if [ ! -d "$install_dir" ]; then
mkdir -p "$install_dir" || err "failed to create $install_dir"
fi
echo "$install_dir"
}
download() {
url="$1"
output="$2"
if command -v curl > /dev/null; then
if [ "$output" = "-" ]; then
curl --proto =https --tlsv1.2 -sSfL "$url"
else
curl --proto =https --tlsv1.2 -sSfL "$url" -o "$output"
fi
else
wget --https-only --secure-protocol=TLSv1_2 --quiet "$url" -O "$output"
fi
}
# Initialize default values
force=true
verbose=false
dest=""
tag=""
td=""
# Process command line arguments
while test $# -gt 0; do
case $1 in
--force | -f)
force=true
;;
--help | -h)
help
exit 0
;;
--verbose | -v)
verbose=true
;;
--tag)
tag="$2"
shift
;;
--to)
dest="$2"
shift
;;
*)
say "error: unrecognized argument '$1'"
help
exit 1
;;
esac
shift
done
# Check for required commands
command -v curl > /dev/null 2>&1 || command -v wget > /dev/null 2>&1 || err "need wget or curl"
need mktemp
need tar
# Detect OS and architecture
os=$(uname -s | tr '[:upper:]' '[:lower:]')
arch=$(uname -m)
# Map architecture to match release files
case "$arch" in
x86_64) arch="x86_64" ;;
aarch64|arm64) arch="arm64" ;;
*) err "unsupported architecture: $arch" ;;
esac
# Determine installation directory
dest=$(determine_install_dir "$os" "$dest")
[ "$verbose" = true ] && say "installing to: $dest"
# Get latest version if not specified
if [ -z "$tag" ]; then
[ "$verbose" = true ] && say "fetching latest release version..."
api_response=$(download "https://api.github.com/repos/spacesprotocol/spaces/releases/latest" - || echo "failed")
if [ "$api_response" = "failed" ]; then
err "could not fetch release information from GitHub"
fi
tag=$(echo "$api_response" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [ -z "$tag" ]; then
err "no releases found in the repository"
fi
fi
# Standardize tag format
tag_without_v="${tag#v}" # Remove 'v' prefix if present
check_tag="v$tag_without_v" # Add 'v' prefix for consistency
# Verify the tag exists
[ "$verbose" = true ] && say "verifying tag $check_tag exists..."
api_response=$(download "https://api.github.com/repos/spacesprotocol/spaces/releases/tags/$check_tag" - || echo "failed")
if [ "$api_response" = "failed" ] || echo "$api_response" | grep -q "Not Found"; then
err "release tag '$check_tag' not found"
fi
[ -z "$tag_without_v" ] && err "could not determine version to install"
[ "$verbose" = true ] && say "installing spaces version $check_tag"
# Create temporary directory
td=$(mktemp -d || mktemp -d -t tmp)
trap 'rm -rf "$td"' EXIT
# Construct download URL
download_url="https://github.com/spacesprotocol/spaces/releases/download/$check_tag/spaces-$check_tag-${os}-${arch}.tar.gz"
[ "$verbose" = true ] && say "downloading from: $download_url"
# Download and extract
download "$download_url" "$td/spaces.tar.gz" || err "download failed"
tar xzf "$td/spaces.tar.gz" -C "$td" || err "failed to extract archive"
# Install binaries
for binary in spaced space-cli; do
if [ -f "$dest/$binary" ] && [ "$force" = false ]; then
err "Found existing spaces executables at $dest. Use --force flag to overwrite"
fi
binary_path="$dest/$binary"
if ! find "$td" -type f -name "$binary" -exec cp {} "$binary_path" \; ; then
err "failed to copy $binary to $dest (permission denied)"
fi
if ! chmod 755 "$binary_path"; then
err "failed to set permissions on $binary (permission denied)"
fi
[ "$verbose" = true ] && say "installed $binary to $binary_path"
done
# Verify installation
for binary in spaced space-cli; do
if ! [ -x "$dest/$binary" ]; then
err "installation verification failed for $binary"
fi
done
# Add to PATH if needed and get reload status
reload_status=$(add_to_path "$dest")
# Final instructions
say "Successfully installed spaces $check_tag to $dest"
# Reload shell if needed
if [ "$reload_status" = "reload" ]; then
if [[ "$SHELL" == */zsh ]]; then
say "Please run 'source $HOME/.zshrc' to update your PATH"
else
if [ "$(uname -s)" = "Darwin" ]; then
say "Please run 'source $HOME/.bash_profile' to update your PATH"
else
say "Please run 'source $HOME/.bashrc' to update your PATH"
fi
fi
say "Or start a new terminal session to apply changes"
fi
# Show versions if verbose
if [ "$verbose" = true ]; then
say "installed version:"
"$dest/spaced" --version
fi