Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·180 lines (146 loc) · 6.04 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·180 lines (146 loc) · 6.04 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
#!/usr/bin/env bash
#
# Puts `diffyard` on the PATH.
#
# By symlinking rather than copying or installing globally: the tool is
# developed in this checkout, so a link means `diffyard` is always what is in the
# working tree, and removing it is removing a link. Nothing is written outside
# the bin directory, and no shell file is edited — where something has to be
# added to one, this prints the line and leaves the choice.
set -euo pipefail
readonly PROJECT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly COMMANDS=(diffyard diffyard-mcp)
readonly NODE_MINIMUM=24
BIN_DIR="${DIFFYARD_BIN_DIR:-$HOME/.local/bin}"
ACTION=install
# ---------------------------------------------------------------- appearance
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
readonly BOLD=$'\033[1m' GREY=$'\033[90m' RED=$'\033[31m' GREEN=$'\033[32m' OFF=$'\033[0m'
else
readonly BOLD='' GREY='' RED='' GREEN='' OFF=''
fi
say() { printf ' %s\n' "$*"; }
note() { printf ' %s%s%s\n' "$GREY" "$*" "$OFF"; }
ok() { printf ' %s✓%s %s\n' "$GREEN" "$OFF" "$*"; }
die() { printf '\n %s✗%s %s\n\n' "$RED" "$OFF" "$*" >&2; exit 1; }
usage() {
cat <<USAGE
${BOLD}install.sh${OFF} — put diffyard on the PATH
./install.sh link into ~/.local/bin
./install.sh --prefix DIR link into DIR instead
./install.sh --uninstall remove the links again
The directory can also come from DIFFYARD_BIN_DIR.
USAGE
}
# ------------------------------------------------------------------ argument
while [ $# -gt 0 ]; do
case "$1" in
--prefix)
[ $# -ge 2 ] || die "--prefix needs a directory"
BIN_DIR="$2"
shift 2
;;
--prefix=*) BIN_DIR="${1#*=}"; shift ;;
--uninstall) ACTION=uninstall; shift ;;
-h|--help) usage; exit 0 ;;
*) usage; die "Unknown option: $1" ;;
esac
done
printf '\n %sdiffyard%s %s\n\n' "$BOLD" "$OFF" "${GREY}${PROJECT}${OFF}"
# ----------------------------------------------------------------- uninstall
if [ "$ACTION" = uninstall ]; then
removed=0
for command in "${COMMANDS[@]}"; do
link="$BIN_DIR/$command"
# Only ever remove a link that points into this checkout, so an install
# from somewhere else — or a real file of that name — is left alone.
if [ -L "$link" ] && [ "$(readlink "$link")" = "$PROJECT/bin/$command.mjs" ]; then
rm "$link"
ok "removed $link"
removed=$((removed + 1))
fi
done
[ "$removed" -gt 0 ] || note "nothing of this checkout was linked in $BIN_DIR"
printf '\n'
exit 0
fi
# ------------------------------------------------------------- what it needs
command -v node >/dev/null 2>&1 || die "Node is not on the PATH. diffyard needs Node ${NODE_MINIMUM} or newer."
node_version="$(node --version)"
node_major="${node_version#v}"
node_major="${node_major%%.*}"
if [ "$node_major" -lt "$NODE_MINIMUM" ]; then
die "Node ${node_version} is too old; diffyard needs ${NODE_MINIMUM} or newer."
fi
ok "node ${node_version}"
# The bundles are what get linked, so both have to exist and be no older than
# anything they were built from: every file under src/ at any depth — the
# report lives a folder down — the script that bundles them, and the manifest
# and lockfile that decide what was bundled in from node_modules. Files only:
# a directory is not something the bundle is built from, and its time moves
# whenever an editor drops a swap file into it.
needs_build=false
for command in "${COMMANDS[@]}"; do
bundle="$PROJECT/bin/$command.mjs"
if [ ! -f "$bundle" ] || [ -n "$(find "$PROJECT/src" "$PROJECT/build.mjs" \
"$PROJECT/package.json" "$PROJECT/package-lock.json" \
-type f -newer "$bundle" -print -quit 2>/dev/null)" ]; then
needs_build=true
break
fi
done
if [ "$needs_build" = true ]; then
# Fetching them is what the reader would do next anyway, and telling them to
# go and do it is a step that exists only because this script would not.
if [ ! -d "$PROJECT/node_modules" ]; then
say "installing dependencies…"
(cd "$PROJECT" && npm install --silent --ignore-scripts) \
|| die "npm install failed. Run it in $PROJECT to see why."
fi
say "building…"
(cd "$PROJECT" && npm run build --silent && npm run bundle --silent) >/dev/null \
|| die "The build failed. Run 'npm run build && npm run bundle' to see why."
fi
ok "bundle is current"
# --------------------------------------------------------------------- links
mkdir -p "$BIN_DIR" || die "Cannot create $BIN_DIR"
[ -w "$BIN_DIR" ] || die "$BIN_DIR is not writable. Choose another with --prefix."
for command in "${COMMANDS[@]}"; do
target="$PROJECT/bin/$command.mjs"
link="$BIN_DIR/$command"
[ -f "$target" ] || die "Missing $target"
# A real file of that name is somebody else's; say so rather than replace it.
if [ -e "$link" ] && [ ! -L "$link" ]; then
die "$link exists and is not a link. Remove it first, or use --prefix."
fi
ln -sfn "$target" "$link"
ok "$command → ${GREY}${link}${OFF}"
done
# ---------------------------------------------------------------------- PATH
case ":$PATH:" in
*":$BIN_DIR:"*)
hash -r 2>/dev/null || true
resolved="$(command -v diffyard 2>/dev/null || true)"
if [ "$resolved" = "$BIN_DIR/diffyard" ]; then
printf '\n'
if version="$("$BIN_DIR/diffyard" --version 2>/dev/null)"; then
ok "diffyard ${version} answers from anywhere"
else
die "diffyard is linked but will not run. Try: $BIN_DIR/diffyard --version"
fi
elif [ -n "$resolved" ]; then
# Another diffyard earlier on the PATH would win, and the confusion that
# causes is worth a sentence now.
printf '\n'
say "${RED}another diffyard comes first on your PATH:${OFF} $resolved"
note "the one just linked is $BIN_DIR/diffyard"
fi
;;
*)
printf '\n'
say "$BIN_DIR is not on your PATH yet. Add it:"
printf '\n %secho '"'"'export PATH="%s:$PATH"'"'"' >> ~/.bashrc%s\n' "$GREY" "$BIN_DIR" "$OFF"
note "then open a new shell, or run: source ~/.bashrc"
;;
esac
printf '\n %sTry it:%s diffyard explore https://example.com/\n\n' "$BOLD" "$OFF"