-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·159 lines (141 loc) · 5.74 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·159 lines (141 loc) · 5.74 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
#!/bin/sh
# construct installer.
#
# curl -fsSL https://raw.githubusercontent.com/construct-worlds/construct/main/install.sh | sh
#
# Downloads the prebuilt binaries for your platform from a GitHub Release,
# verifies their SHA-256 checksum, and drops them all into one directory on
# your PATH. The daemon finds its adapters as siblings of its own binary, so
# everything must live together — this script keeps them together.
#
# Environment overrides:
# CONSTRUCT_VERSION release tag to install (e.g. v0.2.0). Default: latest.
# CONSTRUCT_BIN_DIR install directory. Default: $HOME/.local/bin.
# CONSTRUCT_BASE_URL download base URL (mirror / testing). Default: the
# GitHub release for CONSTRUCT_VERSION. The script fetches
# <base>/construct-<target>.tar.gz and <base>/SHA256SUMS.
set -eu
REPO="construct-worlds/construct"
VERSION="${CONSTRUCT_VERSION:-latest}"
BIN_DIR="${CONSTRUCT_BIN_DIR:-$HOME/.local/bin}"
BINS="construct"
say() { printf '%s\n' "$*"; }
err() { printf 'error: %s\n' "$*" >&2; exit 1; }
abs_path() {
case "$1" in
/*) printf '%s\n' "$1" ;;
*) printf '%s/%s\n' "$(pwd -P)" "$1" ;;
esac
}
# --- detect platform ------------------------------------------------------
os="$(uname -s)"
arch="$(uname -m)"
case "$os" in
Darwin)
case "$arch" in
arm64 | aarch64) target="aarch64-apple-darwin" ;;
x86_64) target="x86_64-apple-darwin" ;;
*) err "unsupported macOS architecture: $arch" ;;
esac ;;
Linux)
case "$arch" in
x86_64 | amd64) target="x86_64-unknown-linux-musl" ;;
aarch64 | arm64) target="aarch64-unknown-linux-gnu" ;;
*) err "unsupported Linux architecture: $arch" ;;
esac ;;
*) err "unsupported OS: $os (only macOS and Linux have prebuilt binaries; build from source instead)" ;;
esac
# --- pick a downloader + sha tool ----------------------------------------
if command -v curl >/dev/null 2>&1; then
fetch() { curl -fsSL "$1" -o "$2"; }
elif command -v wget >/dev/null 2>&1; then
fetch() { wget -qO "$2" "$1"; }
else
err "need curl or wget to download"
fi
if command -v sha256sum >/dev/null 2>&1; then
sha256() { sha256sum "$1" | awk '{print $1}'; }
elif command -v shasum >/dev/null 2>&1; then
sha256() { shasum -a 256 "$1" | awk '{print $1}'; }
else
err "need sha256sum or shasum to verify the download"
fi
# --- resolve URLs ---------------------------------------------------------
asset="construct-${target}.tar.gz"
if [ -n "${CONSTRUCT_BASE_URL:-}" ]; then
base="${CONSTRUCT_BASE_URL%/}"
elif [ "$VERSION" = "latest" ]; then
base="https://github.com/${REPO}/releases/latest/download"
else
base="https://github.com/${REPO}/releases/download/${VERSION}"
fi
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
say "Installing construct ($VERSION) for $target"
if ! fetch "${base}/${asset}" "${tmp}/${asset}"; then
err "could not download ${base}/${asset}
The release may not exist yet, or the repository is still private
(no public download URL). Check https://github.com/${REPO}/releases"
fi
fetch "${base}/SHA256SUMS" "${tmp}/SHA256SUMS" || err "could not download SHA256SUMS"
# --- verify checksum ------------------------------------------------------
want="$(grep " ${asset}$" "${tmp}/SHA256SUMS" | awk '{print $1}')"
[ -n "$want" ] || err "no checksum for ${asset} in SHA256SUMS"
got="$(sha256 "${tmp}/${asset}")"
[ "$want" = "$got" ] || err "checksum mismatch for ${asset}
expected $want
got $got"
say "Checksum OK"
# --- install --------------------------------------------------------------
tar -xzf "${tmp}/${asset}" -C "$tmp"
src="${tmp}/construct-${target}"
[ -d "$src" ] || err "unexpected archive layout (no construct-${target}/ inside ${asset})"
mkdir -p "$BIN_DIR"
# Validate the whole set before touching anything (all-or-nothing-ish).
for b in $BINS; do
[ -f "${src}/${b}" ] || err "binary '$b' missing from archive"
done
for b in $BINS; do
# Atomic install: stage the binary as a temp file *in the destination
# dir* (so the rename stays on one filesystem), make it executable, then
# rename it over any existing copy. Replacing the directory entry rather
# than writing the busy inode avoids ETXTBSY when upgrading a running
# daemon/adapter on Linux, and matches the atomic-rename upgrade the
# daemon's restart path expects.
tmpbin="${BIN_DIR}/.${b}.tmp.$$"
cp "${src}/${b}" "$tmpbin"
chmod 0755 "$tmpbin"
mv -f "$tmpbin" "${BIN_DIR}/${b}"
done
say "Installed into ${BIN_DIR}:"
for b in $BINS; do say " ${b}"; done
# --- PATH guidance --------------------------------------------------------
case ":${PATH}:" in
*":${BIN_DIR}:"*) ;;
*)
say ""
say "⚠ ${BIN_DIR} is not on your PATH. Add it, e.g.:"
say " echo 'export PATH=\"${BIN_DIR}:\$PATH\"' >> ~/.profile # or ~/.zshrc, ~/.bashrc"
;;
esac
# --- config guidance ------------------------------------------------------
if [ -n "${CONSTRUCT_CONFIG_DIR:-}" ]; then
config_dir="${CONSTRUCT_CONFIG_DIR}"
elif [ -n "${XDG_CONFIG_HOME:-}" ]; then
config_dir="${XDG_CONFIG_HOME%/}/construct"
else
config_dir="${HOME}/.config/construct"
fi
config_dir="$(abs_path "$config_dir")"
say ""
say "Config directory: ${config_dir}"
say "Configure construct by copying the generated template to config.toml:"
say " cp \"${config_dir}/config.toml.template\" \"${config_dir}/config.toml\""
say " \${EDITOR:-vi} \"${config_dir}/config.toml\""
say "If config.toml.template is not there yet, run construct once to let the daemon create it."
say ""
say "Done. Try: construct"
# A fresh machine is the likeliest one to be missing a harness CLI, a login,
# or a writable directory. `doctor` reports all of it without starting a
# daemon, and exits 0 on a healthy install, so this is safe to suggest here.
say "If anything looks off: construct doctor"