-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
224 lines (200 loc) · 8.88 KB
/
Copy pathinstall.sh
File metadata and controls
224 lines (200 loc) · 8.88 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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#!/bin/sh
# QuantoScript installer for macOS and Linux.
#
# curl -fsSL https://raw.githubusercontent.com/PySudo/QuantoScript/main/install.sh | sh
#
# Environment variables:
# QUANTO_INSTALL install prefix (default: $HOME/.quanto)
# QS_VERSION version to install, e.g. 1.0.0 (default: latest release)
# QS_REPO owner/repo (default: PySudo/QuantoScript)
# QS_ARCHIVE install from a local .tar.gz instead of downloading
# NO_MODIFY_PATH set to 1 to skip editing your shell profile
#
# Flags:
# --uninstall remove a previous installation
# --help show this message
set -eu
# ── Configuration ──────────────────────────────────────────────────
REPO="${QS_REPO:-PySudo/QuantoScript}"
PREFIX="${QUANTO_INSTALL:-$HOME/.quanto}"
BIN_NAME="qs"
DATA_SUBDIR="share/quantoscript"
RED=''; GREEN=''; BLUE=''; BOLD=''; RESET=''
if [ -t 1 ]; then
RED=$(printf '\033[31m'); GREEN=$(printf '\033[32m')
BLUE=$(printf '\033[34m'); BOLD=$(printf '\033[1m'); RESET=$(printf '\033[0m')
fi
say() { printf '%s%s%s\n' "$BLUE" "$*" "$RESET"; }
ok() { printf '%s%s%s\n' "$GREEN" "$*" "$RESET"; }
warn() { printf '%s%s%s\n' "$RED" "$*" "$RESET" >&2; }
die() { printf '%serror:%s %s\n' "$RED" "$RESET" "$*" >&2; exit 1; }
need() { command -v "$1" >/dev/null 2>&1; }
# ── Uninstall ──────────────────────────────────────────────────────
uninstall() {
say "Removing QuantoScript from $PREFIX"
rm -f "$PREFIX/bin/$BIN_NAME"
rm -rf "$PREFIX/$DATA_SUBDIR"
rmdir "$PREFIX/bin" "$PREFIX/share" 2>/dev/null || true
rmdir "$PREFIX" 2>/dev/null || true
remove_profile_block
ok "Uninstalled. Open a new terminal for the PATH change to take effect."
exit 0
}
# ── Detect target triple ───────────────────────────────────────────
detect_target() {
os=$(uname -s)
arch=$(uname -m)
case "$os" in
Darwin) os_part="apple-darwin" ;;
Linux) os_part="unknown-linux-gnu" ;;
*) die "unsupported OS: $os (Windows users: use install.ps1)" ;;
esac
case "$arch" in
x86_64|amd64) arch_part="x86_64" ;;
arm64|aarch64) arch_part="aarch64" ;;
*) die "unsupported architecture: $arch" ;;
esac
printf '%s-%s' "$arch_part" "$os_part"
}
# ── HTTP helpers ───────────────────────────────────────────────────
fetch() { # fetch <url> <output-file>
if need curl; then
curl -fsSL "$1" -o "$2"
elif need wget; then
wget -qO "$2" "$1"
else
die "need curl or wget to download files"
fi
}
fetch_stdout() { # fetch <url> to stdout
if need curl; then
curl -fsSL "$1"
elif need wget; then
wget -qO- "$1"
else
die "need curl or wget to download files"
fi
}
latest_version() {
# Parse the tag_name from the GitHub "latest release" API without jq.
fetch_stdout "https://api.github.com/repos/$REPO/releases/latest" \
| grep -m1 '"tag_name"' \
| sed -E 's/.*"tag_name" *: *"v?([^"]+)".*/\1/'
}
verify_checksum() { # verify_checksum <file> <sha-file>
[ -f "$2" ] || { warn "no checksum file; skipping verification"; return 0; }
expected=$(awk '{print $1}' "$2")
if need sha256sum; then
actual=$(sha256sum "$1" | awk '{print $1}')
elif need shasum; then
actual=$(shasum -a 256 "$1" | awk '{print $1}')
else
warn "no sha256 tool; skipping checksum verification"; return 0
fi
[ "$expected" = "$actual" ] || die "checksum mismatch for $(basename "$1")"
ok " checksum verified"
}
# ── Profile / PATH management ──────────────────────────────────────
BEGIN_MARK="# >>> quantoscript >>>"
END_MARK="# <<< quantoscript <<<"
profile_files() {
# Emit the shell rc files we should update.
case "${SHELL:-}" in
*zsh) printf '%s\n' "${ZDOTDIR:-$HOME}/.zshrc" ;;
*bash) printf '%s\n' "$HOME/.bashrc" ;;
esac
printf '%s\n' "$HOME/.profile"
}
remove_profile_block() {
profile_files | sort -u | while IFS= read -r rc; do
[ -f "$rc" ] || continue
grep -qF "$BEGIN_MARK" "$rc" 2>/dev/null || continue
tmp="$rc.qs.tmp"
awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
$0==b {skip=1} skip==0 {print} $0==e {skip=0}
' "$rc" > "$tmp" && mv "$tmp" "$rc"
done
}
update_profile() {
[ "${NO_MODIFY_PATH:-0}" = "1" ] && return 0
remove_profile_block
profile_files | sort -u | while IFS= read -r rc; do
{
printf '\n%s\n' "$BEGIN_MARK"
printf 'export QUANTO_HOME="%s"\n' "$PREFIX/$DATA_SUBDIR"
printf 'case ":$PATH:" in *":%s/bin:"*) ;; *) export PATH="%s/bin:$PATH" ;; esac\n' "$PREFIX" "$PREFIX"
printf '%s\n' "$END_MARK"
} >> "$rc"
say " updated $rc"
done
}
# ── Main install ───────────────────────────────────────────────────
do_install() {
target=$(detect_target)
say "${BOLD}Installing QuantoScript${RESET}"
say " target: $target"
say " prefix: $PREFIX"
tmp=$(mktemp -d 2>/dev/null || mktemp -d -t quanto)
trap 'rm -rf "$tmp"' EXIT INT TERM
if [ -n "${QS_ARCHIVE:-}" ]; then
[ -f "$QS_ARCHIVE" ] || die "QS_ARCHIVE not found: $QS_ARCHIVE"
say " source: $QS_ARCHIVE (local)"
cp "$QS_ARCHIVE" "$tmp/pkg.tar.gz"
else
version="${QS_VERSION:-}"
if [ -z "$version" ]; then
say " resolving latest release..."
version=$(latest_version)
[ -n "$version" ] || die "could not determine the latest release. Set QS_VERSION or check that $REPO has published releases."
fi
say " version: $version"
asset="quantoscript-${version}-${target}.tar.gz"
base="https://github.com/$REPO/releases/download/v${version}"
say " downloading $asset ..."
if ! fetch "$base/$asset" "$tmp/pkg.tar.gz"; then
die "no prebuilt binary for $target (v$version). Build from source: https://github.com/$REPO#building-from-source"
fi
fetch "$base/$asset.sha256" "$tmp/pkg.sha256" 2>/dev/null || true
verify_checksum "$tmp/pkg.tar.gz" "$tmp/pkg.sha256"
fi
say " extracting..."
tar -xzf "$tmp/pkg.tar.gz" -C "$tmp"
pkgdir=$(find "$tmp" -maxdepth 1 -type d -name 'quantoscript-*' | head -n1)
[ -n "$pkgdir" ] || pkgdir=$(find "$tmp" -maxdepth 2 -name "$BIN_NAME" -type f -exec dirname {} \; | head -n1 | sed 's#/bin$##')
[ -d "$pkgdir" ] || die "unexpected archive layout"
[ -f "$pkgdir/bin/$BIN_NAME" ] || die "binary not found in archive"
# Install into: PREFIX/bin/qs and PREFIX/share/quantoscript/{stdlib,examples}
mkdir -p "$PREFIX/bin" "$PREFIX/$DATA_SUBDIR"
command install -m 0755 "$pkgdir/bin/$BIN_NAME" "$PREFIX/bin/$BIN_NAME" 2>/dev/null \
|| { cp "$pkgdir/bin/$BIN_NAME" "$PREFIX/bin/$BIN_NAME"; chmod 0755 "$PREFIX/bin/$BIN_NAME"; }
rm -rf "$PREFIX/$DATA_SUBDIR/stdlib" "$PREFIX/$DATA_SUBDIR/examples"
[ -d "$pkgdir/stdlib" ] && cp -R "$pkgdir/stdlib" "$PREFIX/$DATA_SUBDIR/stdlib"
[ -d "$pkgdir/examples" ] && cp -R "$pkgdir/examples" "$PREFIX/$DATA_SUBDIR/examples"
ok " installed $BIN_NAME to $PREFIX/bin/$BIN_NAME"
update_profile
# Verify
if QUANTO_HOME="$PREFIX/$DATA_SUBDIR" "$PREFIX/bin/$BIN_NAME" version >/dev/null 2>&1; then
installed_ver=$(QUANTO_HOME="$PREFIX/$DATA_SUBDIR" "$PREFIX/bin/$BIN_NAME" version)
printf '\n'
ok "${BOLD}$installed_ver installed successfully!${RESET}"
else
die "installation completed but '$BIN_NAME version' failed to run"
fi
printf '\n'
say "Next steps:"
printf ' Restart your terminal, or run: %sexport PATH="%s/bin:$PATH"%s\n' "$BOLD" "$PREFIX" "$RESET"
printf ' Then try: %sqs --help%s\n' "$BOLD" "$RESET"
printf ' %sqs %s/examples/full_tour.qs%s\n' "$BOLD" "$PREFIX/$DATA_SUBDIR" "$RESET"
}
# ── Entry point ────────────────────────────────────────────────────
case "${1:-}" in
--uninstall) uninstall ;;
--help|-h)
sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'
exit 0 ;;
--version)
[ -n "${2:-}" ] || die "--version requires an argument"
QS_VERSION="$2"; do_install ;;
"") do_install ;;
*) die "unknown option: $1 (try --help)" ;;
esac