Skip to content

Commit 81d7607

Browse files
authored
Provide an env.sh file that can be sourced, automatically update shell profile config file to source it (#53)
1 parent 4654041 commit 81d7607

9 files changed

+299
-41
lines changed

install/swiftly-install.sh

Lines changed: 115 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,20 @@
1212
# to store platform information, downloaded toolchains, and other state required to manage
1313
# the toolchains.
1414
#
15+
# After installation, the script will create $SWIFTLY_HOME_DIR/env.sh, which can be sourced
16+
# to properly set up the environment variables required to run swiftly. Unless --no-modify-profile
17+
# was specified, the script will also update ~/.profile, ~/.bash_profile, ~/.bash_login, or ~/.zprofile,
18+
# depending on the value of $SHELL and the existence of the files, to source the env.sh file on login.
19+
# This will ensure that future logins will automatically configure SWIFTLY_HOME_DIR, SWIFTLY_BIN_DIR,
20+
# and PATH.
21+
#
1522
# Unless the --disable-confirmation flag is set, this script will allow the runner to
1623
# configure either of those two directory paths.
1724
#
1825
# curl is required to run this script.
1926

2027
set -o errexit
28+
shopt -s extglob
2129

2230
has_command () {
2331
command -v "$1" > /dev/null
@@ -40,8 +48,33 @@ read_input_with_default () {
4048
fi
4149
}
4250

51+
# Replaces the actual path to $HOME at the beginning of the provided string argument with
52+
# the string "$HOME". This is used when printing to stdout.
53+
# e.g. "home/user/.local/bin" => "$HOME/.local/bin"
54+
replace_home_path () {
55+
if [[ "$1" =~ ^"$HOME"(/|$) ]]; then
56+
echo "\$HOME${1#$HOME}"
57+
else
58+
echo "$1"
59+
fi
60+
}
61+
62+
# Replaces the string "$HOME" or "~" in the argument with the actual value of $HOME.
63+
# e.g. "$HOME/.local/bin" => "/home/user/.local/bin"
64+
# e.g. "~/.local/bin" => "/home/user/.local/bin"
65+
expand_home_path () {
66+
echo "${1/#@(~|\$HOME)/$HOME}"
67+
}
68+
69+
# Prints the provided argument using the terminal's bold text effect.
70+
bold () {
71+
echo "$(tput bold)$1$(tput sgr0)"
72+
}
73+
4374
SWIFTLY_INSTALL_VERSION="0.1.0"
4475

76+
MODIFY_PROFILE="true"
77+
4578
for arg in "$@"; do
4679
case "$arg" in
4780
"--help" | "-h")
@@ -54,6 +87,8 @@ USAGE:
5487
5588
FLAGS:
5689
-y, --disable-confirmation Disable confirmation prompt.
90+
--no-modify-profile Do not attempt to modify the profile file to set environment
91+
variables (e.g. PATH) on login.
5792
-h, --help Prints help information.
5893
--version Prints version information.
5994
EOF
@@ -64,6 +99,10 @@ EOF
6499
DISABLE_CONFIRMATION="true"
65100
;;
66101

102+
"--no-modify-profile")
103+
MODIFY_PROFILE="false"
104+
;;
105+
67106
"--version")
68107
echo "$SWIFTLY_INSTALL_VERSION"
69108
exit 0
@@ -172,6 +211,23 @@ JSON_OUT=$(cat <<EOF
172211
EOF
173212
)
174213

214+
PROFILE_FILE="$HOME/.profile"
215+
case "$SHELL" in
216+
*"zsh")
217+
PROFILE_FILE="$HOME/.zprofile"
218+
;;
219+
*"bash")
220+
# Order derived from:
221+
# https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Bash-Startup-Files
222+
if [[ -f "$HOME/.bash_profile" ]]; then
223+
PROFILE_FILE="$HOME/.bash_profile"
224+
elif [[ -f "$HOME/.bash_login" ]]; then
225+
PROFILE_FILE="$HOME/.bash_login"
226+
fi
227+
;;
228+
*)
229+
esac
230+
175231
echo "This script will install swiftly, a Swift toolchain installer and manager."
176232
echo ""
177233

@@ -182,30 +238,53 @@ DEFAULT_BIN_DIR="$HOME/.local/bin"
182238
BIN_DIR="${SWIFTLY_BIN_DIR:-$DEFAULT_BIN_DIR}"
183239

184240
while [ -z "$DISABLE_CONFIRMATION" ]; do
185-
echo "swiftly data and configuration files directory: $HOME_DIR"
186-
echo "swiftly executables installation directory: $BIN_DIR"
241+
echo "Current installation options:"
242+
echo ""
243+
printf " %40s: $(bold $(replace_home_path $HOME_DIR))\n" "Data and configuration files directory"
244+
printf " %40s: $(bold $(replace_home_path $BIN_DIR))\n" "Executables installation directory"
245+
printf " %40s: $(bold $MODIFY_PROFILE)\n" "Modify login config ($(replace_home_path $PROFILE_FILE))"
187246
echo ""
188247
echo "Select one of the following:"
189248
echo "1) Proceed with the installation (default)"
190-
echo "2) Customize the installation paths"
249+
echo "2) Customize the installation"
191250
echo "3) Cancel"
192251

193252
read_input_with_default "1"
194253
case "$READ_INPUT_RETURN" in
195254
# Just hitting enter will proceed with the default installation.
196255
"1" | "1)")
197-
echo ""
198256
break
199257
;;
200258

201259
"2" | "2)")
202-
echo "Enter the swiftly data and configuration files directory (default $HOME_DIR): "
260+
echo "Enter the swiftly data and configuration files directory (default $(replace_home_path $HOME_DIR)): "
203261
read_input_with_default "$HOME_DIR"
204-
HOME_DIR="${READ_INPUT_RETURN/#~/$HOME}"
262+
HOME_DIR="$(expand_home_path $READ_INPUT_RETURN)"
205263

206-
echo "Enter the swiftly binary installation directory (default $BIN_DIR): "
264+
echo "Enter the swiftly executables installation directory (default $(replace_home_path $BIN_DIR)): "
207265
read_input_with_default "$BIN_DIR"
208-
BIN_DIR="${READ_INPUT_RETURN/#~/$HOME}"
266+
BIN_DIR="$(expand_home_path $READ_INPUT_RETURN)"
267+
268+
if [[ "$MODIFY_PROFILE" == "true" ]]; then
269+
MODIFY_PROFILE_PROMPT="(Y/n)"
270+
else
271+
MODIFY_PROFILE_PROMPT="(y/N)"
272+
fi
273+
echo "Modify login config ($(replace_home_path $PROFILE_FILE))? $MODIFY_PROFILE_PROMPT"
274+
read_input_with_default "$MODIFY_PROFILE"
275+
276+
case "$READ_INPUT_RETURN" in
277+
"y" | "Y")
278+
MODIFY_PROFILE="true"
279+
;;
280+
281+
"n" | "N")
282+
MODIFY_PROFILE="false"
283+
;;
284+
285+
*)
286+
;;
287+
esac
209288
;;
210289

211290
*)
@@ -217,9 +296,9 @@ done
217296

218297
if [[ -d "$HOME_DIR" ]]; then
219298
if [[ "$DISABLE_CONFIRMATION" == "true" ]]; then
220-
echo "Overwriting existing swiftly installation at $HOME_DIR"
299+
echo "Overwriting existing swiftly installation at $(replace_home_path $HOME_DIR)"
221300
else
222-
echo "Existing swiftly installation detected at $HOME_DIR, overwrite? (Y/n)"
301+
echo "Existing swiftly installation detected at $(replace_home_path $HOME_DIR), overwrite? (Y/n)"
223302

224303
while [[ true ]]; do
225304
read_input_with_default "y"
@@ -259,35 +338,42 @@ curl \
259338

260339
chmod +x "$BIN_DIR/swiftly"
261340

262-
echo ""
263-
264-
echo "swiftly executable written to $BIN_DIR/swiftly"
265-
266341
echo "$JSON_OUT" > "$HOME_DIR/config.json"
267342

268-
echo "swiftly data files written to $HOME_DIR"
269-
270343
# Verify the downloaded executable works. The script will exit if this fails due to errexit.
271344
SWIFTLY_HOME_DIR="$HOME_DIR" SWIFTLY_BIN_DIR="$BIN_DIR" "$BIN_DIR/swiftly" --version > /dev/null
272345

273346
echo ""
274347
echo "swiftly has been succesfully installed!"
275-
if ! has_command "swiftly" ; then
276-
echo "You may have to restart your shell or add $BIN_DIR \
277-
to your PATH in order to access swiftly from the shell."
348+
echo ""
349+
350+
ENV_OUT=$(cat <<EOF
351+
export SWIFTLY_HOME_DIR="$(replace_home_path $HOME_DIR)"
352+
export SWIFTLY_BIN_DIR="$(replace_home_path $BIN_DIR)"
353+
if [[ ":\$PATH:" != *":\$SWIFTLY_BIN_DIR:"* ]]; then
354+
export PATH="\$SWIFTLY_BIN_DIR:\$PATH"
278355
fi
356+
EOF
357+
)
279358

280-
if [[ "$HOME_DIR" != "$DEFAULT_HOME_DIR" ]]; then
281-
echo ""
282-
echo "To ensure swiftly can properly find its data and configuration files, set the \$SWIFTLY_HOME_DIR \
283-
environment variable to $HOME_DIR before using swiftly."
359+
echo "$ENV_OUT" > "$HOME_DIR/env.sh"
360+
361+
if [[ "$MODIFY_PROFILE" == "true" ]]; then
362+
SOURCE_LINE=". $(replace_home_path $HOME_DIR)/env.sh"
363+
364+
# Only append the line if it isn't in .profile already.
365+
if [[ ! -f "$PROFILE_FILE" ]] || [[ ! "$(cat $PROFILE_FILE)" =~ "$SOURCE_LINE" ]]; then
366+
echo "$SOURCE_LINE" >> "$PROFILE_FILE"
367+
fi
284368
fi
285369

286-
if [[ "$BIN_DIR" != "$DEFAULT_BIN_DIR" ]]; then
370+
if ! has_command "swiftly" || [[ "$HOME_DIR" != "$DEFAULT_HOME_DIR" || "$BIN_DIR" != "$DEFAULT_BIN_DIR" ]] ; then
371+
echo "Once you log in again, swiftly should be accessible from your PATH."
372+
echo "To begin using swiftly from your current shell, first run the following command:"
373+
echo ""
374+
echo " . $(replace_home_path $HOME_DIR)/env.sh"
287375
echo ""
288-
echo "To ensure swiftly installs Swift tooclhain executables to the configured location, set the \$SWIFTLY_BIN_DIR \
289-
environment variable to $BIN_DIR before using swiftly."
376+
echo "Then to install the latest version of Swift, run 'swiftly install latest'"
377+
else
378+
echo "To install the latest version of Swift, run 'swiftly install latest'"
290379
fi
291-
292-
echo ""
293-
echo "To install the latest version of Swift, run 'swiftly install latest'"

install/tests/custom-home-install.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
3+
# Tests that custom install paths that include the string "$HOME" are expanded properly.
4+
# WARNING: this test makes changes to the local filesystem and is intended to be run in a containerized environment.
5+
6+
set -o errexit
7+
source ./test-util.sh
8+
9+
export CUSTOM_HOME_DIR_NAME="home-substitution-test-home"
10+
export CUSTOM_HOME_DIR="$HOME/$CUSTOM_HOME_DIR_NAME"
11+
export CUSTOM_BIN_DIR="$CUSTOM_HOME_DIR/bin"
12+
13+
cp "$HOME/.profile" "$HOME/.profile.bak"
14+
15+
cleanup () {
16+
rm -r "$CUSTOM_HOME_DIR"
17+
mv "$HOME/.profile.bak" "$HOME/.profile"
18+
}
19+
trap cleanup EXIT
20+
21+
# Make sure that the "~" character is handled properly.
22+
printf "2\n\$HOME/${CUSTOM_HOME_DIR_NAME}\n\$HOME/${CUSTOM_HOME_DIR_NAME}/bin\ny\n1\n" | ./swiftly-install.sh
23+
24+
# .profile should be updated to update PATH and SWIFTLY_HOME_DIR/SWIFTLY_BIN_DIR.
25+
bash --login -c "swiftly --version"
26+
27+
. "$CUSTOM_HOME_DIR/env.sh"
28+
29+
if ! has_command "swiftly" ; then
30+
test_fail "Can't find swiftly on the PATH"
31+
fi
32+
33+
if [[ "$SWIFTLY_HOME_DIR" != "$CUSTOM_HOME_DIR" ]]; then
34+
test_fail "SWIFTLY_HOME_DIR ($SWIFTLY_HOME_DIR) did not equal $CUSTOM_HOME_DIR"
35+
fi
36+
37+
if [[ "$SWIFTLY_BIN_DIR" != "$CUSTOM_BIN_DIR" ]]; then
38+
test_fail "SWIFTLY_BIN_DIR ($SWIFTLY_BIN_DIR) did not equal $CUSTOM_BIN_DIR"
39+
fi
40+
41+
if [[ ! -d "$CUSTOM_HOME_DIR/toolchains" ]]; then
42+
test_fail "the toolchains directory was not created in SWIFTLY_HOME_DIR"
43+
fi
44+
45+
test_pass

install/tests/custom-install.sh

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ export CUSTOM_HOME_DIR="$(pwd)custom-test-home"
1010
export CUSTOM_BIN_DIR="$CUSTOM_HOME_DIR/bin"
1111
export PATH="$CUSTOM_BIN_DIR:$PATH"
1212

13+
cp "$HOME/.profile" "$HOME/.profile.bak"
1314
cleanup () {
1415
set +o errexit
1516

17+
mv "$HOME/.profile.bak" "$HOME/.profile"
18+
1619
if has_command "swiftly" ; then
1720
swiftly uninstall -y latest > /dev/null
1821
fi
@@ -21,15 +24,25 @@ cleanup () {
2124
}
2225
trap cleanup EXIT
2326

24-
printf "2\n$CUSTOM_HOME_DIR\n$CUSTOM_BIN_DIR\n1\n" | ./swiftly-install.sh
27+
printf "2\n$CUSTOM_HOME_DIR\n$CUSTOM_BIN_DIR\ny\n1\n" | ./swiftly-install.sh
28+
29+
# .profile should be updated to update PATH and SWIFTLY_HOME_DIR/SWIFTLY_BIN_DIR.
30+
bash --login -c "swiftly --version"
2531

26-
export SWIFTLY_HOME_DIR="$CUSTOM_HOME_DIR"
27-
export SWIFTLY_BIN_DIR="$CUSTOM_BIN_DIR"
32+
. "$CUSTOM_HOME_DIR/env.sh"
2833

2934
if ! has_command "swiftly" ; then
3035
test_fail "Can't find swiftly on the PATH"
3136
fi
3237

38+
if [[ "$SWIFTLY_HOME_DIR" != "$CUSTOM_HOME_DIR" ]]; then
39+
test_fail "SWIFTLY_HOME_DIR ($SWIFTLY_HOME_DIR) did not equal $CUSTOM_HOME_DIR"
40+
fi
41+
42+
if [[ "$SWIFTLY_BIN_DIR" != "$CUSTOM_BIN_DIR" ]]; then
43+
test_fail "SWIFTLY_BIN_DIR ($SWIFTLY_BIN_DIR) did not equal $CUSTOM_BIN_DIR"
44+
fi
45+
3346
if [[ ! -d "$CUSTOM_HOME_DIR/toolchains" ]]; then
3447
test_fail "the toolchains directory was not created in SWIFTLY_HOME_DIR"
3548
fi

install/tests/custom-tilde-install.sh

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,35 @@ source ./test-util.sh
99
export CUSTOM_HOME_DIR_NAME="tilde-substitution-test-home"
1010
export CUSTOM_HOME_DIR="$HOME/$CUSTOM_HOME_DIR_NAME"
1111
export CUSTOM_BIN_DIR="$CUSTOM_HOME_DIR/bin"
12-
export PATH="$CUSTOM_BIN_DIR:$PATH"
12+
13+
cp "$HOME/.profile" "$HOME/.profile.bak"
1314

1415
cleanup () {
1516
rm -r "$CUSTOM_HOME_DIR"
17+
mv "$HOME/.profile.bak" "$HOME/.profile"
1618
}
1719
trap cleanup EXIT
1820

1921
# Make sure that the "~" character is handled properly.
20-
printf "2\n~/${CUSTOM_HOME_DIR_NAME}\n~/${CUSTOM_HOME_DIR_NAME}/bin\n1\n" | ./swiftly-install.sh
22+
printf "2\n~/${CUSTOM_HOME_DIR_NAME}\n~/${CUSTOM_HOME_DIR_NAME}/bin\ny\n1\n" | ./swiftly-install.sh
23+
24+
# .profile should be updated to update PATH and SWIFTLY_HOME_DIR/SWIFTLY_BIN_DIR.
25+
bash --login -c "swiftly --version"
26+
27+
. "$CUSTOM_HOME_DIR/env.sh"
2128

2229
if ! has_command "swiftly" ; then
2330
test_fail "Can't find swiftly on the PATH"
2431
fi
2532

33+
if [[ "$SWIFTLY_HOME_DIR" != "$CUSTOM_HOME_DIR" ]]; then
34+
test_fail "SWIFTLY_HOME_DIR ($SWIFTLY_HOME_DIR) did not equal $CUSTOM_HOME_DIR"
35+
fi
36+
37+
if [[ "$SWIFTLY_BIN_DIR" != "$CUSTOM_BIN_DIR" ]]; then
38+
test_fail "SWIFTLY_BIN_DIR ($SWIFTLY_BIN_DIR) did not equal $CUSTOM_BIN_DIR"
39+
fi
40+
2641
if [[ ! -d "$CUSTOM_HOME_DIR/toolchains" ]]; then
2742
test_fail "the toolchains directory was not created in SWIFTLY_HOME_DIR"
2843
fi

install/tests/default-install.sh

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,29 @@
66
set -o errexit
77
source ./test-util.sh
88

9+
cp "$HOME/.profile" "$HOME/.profile.bak"
10+
911
cleanup () {
12+
set +o errexit
13+
14+
mv "$HOME/.profile.bak" "$HOME/.profile"
15+
1016
if has_command "swiftly" ; then
1117
swiftly uninstall -y latest > /dev/null
1218
fi
1319

1420
rm -r "$HOME/.local/share/swiftly"
15-
rm -r "$HOME/.local/bin/swiftly"
21+
rm "$HOME/.local/bin/swiftly"
1622
}
1723
trap cleanup EXIT
1824

19-
export PATH="$HOME/.local/bin:$PATH"
20-
2125
echo "1" | ./swiftly-install.sh
2226

27+
# .profile should be updated to update PATH.
28+
bash --login -c "swiftly --version"
29+
30+
. "$HOME/.local/share/swiftly/env.sh"
31+
2332
if ! has_command "swiftly" ; then
2433
test_fail "Can't find swiftly on the PATH"
2534
fi

0 commit comments

Comments
 (0)