Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·164 lines (136 loc) · 5.51 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·164 lines (136 loc) · 5.51 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
#!/bin/sh
# Downloads a Plum release and puts `plum` on your PATH.
#
# curl -fsSL https://raw.githubusercontent.com/bradcypert/plum/main/install.sh | sh
#
# Or, having cloned: ./install.sh
#
# Options, as environment variables:
# PLUM_VERSION a tag like `v0.0.4` (default: the latest release)
# PLUM_PREFIX where to install (default: $HOME/.local/bin)
#
# **It does not edit your shell configuration.** If the install
# directory is not on your PATH it prints the line to add and stops.
# Printing a line you can read is undoable; rewriting `.zshrc` is not,
# and a script piped from the internet is the worst possible place to
# do something you cannot see.
#
# POSIX sh on purpose: this runs before Plum exists on the machine, and
# possibly before bash does.
set -eu
REPO="bradcypert/plum"
PREFIX="${PLUM_PREFIX:-$HOME/.local/bin}"
die() { printf 'install: %s\n' "$1" >&2; exit 1; }
# --- which archive ---
os="$(uname -s)"
arch="$(uname -m)"
case "$os" in
Linux) os_slug="linux" ;;
Darwin) os_slug="macos" ;;
MINGW*|MSYS*|CYGWIN*) os_slug="windows" ;;
*) die "unsupported operating system: $os" ;;
esac
case "$arch" in
x86_64|amd64) arch_slug="x86_64" ;;
arm64|aarch64) arch_slug="arm64" ;;
*) die "unsupported architecture: $arch" ;;
esac
slug="${arch_slug}-${os_slug}"
# Only these four are built and tested. Anything else is refused with
# the honest reason rather than a 404 from the download.
case "$slug" in
x86_64-linux|arm64-linux|arm64-macos|x86_64-macos|x86_64-windows) ;;
*) die "no published binary for $slug.
Build one instead -- it needs only clang:
git clone https://github.com/$REPO && cd plum
./bootstrap/from-seed -o plum && ./plum build bootstrap/self_host -o plum" ;;
esac
# --- tools ---
if command -v curl > /dev/null 2>&1; then
fetch() { curl -fsSL "$1" -o "$2"; }
fetch_stdout() { curl -fsSL "$1"; }
elif command -v wget > /dev/null 2>&1; then
fetch() { wget -qO "$2" "$1"; }
fetch_stdout() { wget -qO - "$1"; }
else
die "needs curl or wget"
fi
# GNU coreutils and the BSD/macOS tools disagree on the name.
if command -v sha256sum > /dev/null 2>&1; then
sha256() { sha256sum "$1" | cut -d' ' -f1; }
elif command -v shasum > /dev/null 2>&1; then
sha256() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
sha256() { echo ""; }
fi
# --- which version ---
tag="${PLUM_VERSION:-}"
if [ -z "$tag" ]; then
# The releases API rather than the `latest/download` redirect: the
# file name contains the version, so the version has to be known
# before the URL can be built.
tag="$(fetch_stdout "https://api.github.com/repos/$REPO/releases/latest" \
| sed -n 's/.*"tag_name" *: *"\([^"]*\)".*/\1/p' | head -n 1)"
[ -n "$tag" ] || die "could not determine the latest release"
fi
version="${tag#v}"
name="plum-${version}-${slug}"
url="https://github.com/$REPO/releases/download/$tag/${name}.tar.gz"
printf 'installing plum %s (%s)\n' "$version" "$slug"
# --- download and verify ---
tmp="$(mktemp -d 2>/dev/null || mktemp -d -t pluminstall)"
trap 'rm -rf "$tmp"' EXIT INT TERM
# A 404 here almost always means the platform is supported NOW but was
# not when this release was cut -- the docs and the release move
# independently, and the docs move first. Say that, rather than leaving
# someone staring at a curl error code.
fetch "$url" "$tmp/archive.tar.gz" || die "no ${slug} archive in release ${tag}.
That platform may have been added after this release was cut. Try
the newest release explicitly, or build from source:
PLUM_VERSION=<newer tag> ...
git clone https://github.com/$REPO && cd plum
./bootstrap/from-seed -o plum && ./plum build bootstrap/self_host -o plum
(url was $url)"
# Verification is not optional when it is possible. A checksum is
# published beside every archive; skipping the check would make this
# script the weakest link in a chain that otherwise has one.
if fetch "${url}.sha256" "$tmp/archive.sha256" 2>/dev/null; then
want="$(cut -d' ' -f1 < "$tmp/archive.sha256")"
got="$(sha256 "$tmp/archive.tar.gz")"
if [ -z "$got" ]; then
printf 'warning: no sha256 tool found, checksum NOT verified\n' >&2
elif [ "$want" != "$got" ]; then
die "checksum mismatch
expected $want
got $got"
else
printf 'checksum ok\n'
fi
else
printf 'warning: no published checksum, integrity NOT verified\n' >&2
fi
tar -xzf "$tmp/archive.tar.gz" -C "$tmp"
exe="plum"
[ "$os_slug" = "windows" ] && exe="plum.exe"
[ -f "$tmp/$name/$exe" ] || die "the archive did not contain $exe"
# --- install ---
mkdir -p "$PREFIX" || die "could not create $PREFIX"
cp "$tmp/$name/$exe" "$PREFIX/$exe" || die "could not write to $PREFIX"
chmod +x "$PREFIX/$exe"
printf 'installed %s\n' "$PREFIX/$exe"
# Prove it runs before claiming success. A binary for the wrong
# architecture copies perfectly well and then fails on first use.
if ! "$PREFIX/$exe" version > /dev/null 2>&1; then
die "installed, but $PREFIX/$exe does not run -- wrong architecture?"
fi
printf '%s\n' "$("$PREFIX/$exe" version)"
# --- PATH ---
case ":${PATH}:" in
*":${PREFIX}:"*)
printf '\nready. try: plum new hello && plum run hello\n' ;;
*)
printf '\n%s is not on your PATH. Add it:\n\n' "$PREFIX"
printf ' export PATH="%s:$PATH"\n\n' "$PREFIX"
printf 'then: plum new hello && plum run hello\n' ;;
esac
printf '\nplum needs clang on your PATH to compile -- it shells out to it\nto assemble and link. Nothing else is required.\n'