-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall_pyenv.sh
More file actions
executable file
·171 lines (149 loc) · 6.01 KB
/
Copy pathinstall_pyenv.sh
File metadata and controls
executable file
·171 lines (149 loc) · 6.01 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
#!/usr/bin/env bash
set -euo pipefail
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/utils.sh"
echo -e "${BLUE}[+] Preparing pyenv installer...${NC}"
if ! utils::resolve_target_user; then
echo -e "${RED}[-] Refusing to run as root without an invoking user. Run as your user or with sudo from your account.${NC}"
exit 1
fi
echo -e "${YELLOW}[*] Target user:${NC} ${TARGET_USER}"
echo -e "${YELLOW}[*] Target home:${NC} ${TARGET_HOME}"
DEPS=(make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev \
libsqlite3-dev curl git libncursesw5-dev xz-utils tk-dev \
libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev libzstd-dev)
echo -e "${BLUE}[*] Checking for missing apt packages...${NC}"
TO_INSTALL=()
for pkg in "${DEPS[@]}"; do
if ! dpkg -s "$pkg" &>/dev/null; then
TO_INSTALL+=("$pkg")
fi
done
if [ "${#TO_INSTALL[@]}" -gt 0 ]; then
echo -e "${BLUE}[*] Installing packages:${NC} ${TO_INSTALL[*]}"
if [[ "$AS_ROOT" == true ]]; then
apt update
apt install -y "${TO_INSTALL[@]}"
else
sudo apt update
sudo apt install -y "${TO_INSTALL[@]}"
fi
echo -e "${GREEN}[+] Packages installed${NC}"
else
echo -e "${GREEN}[+] All build dependencies already present${NC}"
fi
PYENV_DIR="$TARGET_HOME/.pyenv"
PYENV_BIN="$PYENV_DIR/bin/pyenv"
if [[ -e "$PYENV_DIR" ]]; then
FOREIGN_OWNER="$(find "$PYENV_DIR" ! -user "$TARGET_USER" -print -quit 2>/dev/null || true)"
if [[ -n "$FOREIGN_OWNER" ]]; then
TARGET_GROUP="$(id -gn "$TARGET_USER")"
echo -e "${RED}[-] ${PYENV_DIR} contains files not owned by ${TARGET_USER}.${NC}" >&2
echo -e "${RED} Review them, then repair ownership once with:${NC}" >&2
echo -e "${YELLOW} sudo chown -R '${TARGET_USER}:${TARGET_GROUP}' -- '${PYENV_DIR}'${NC}" >&2
exit 1
fi
fi
if [[ -x "$PYENV_BIN" ]]; then
echo -e "${PURPLE}[*] Updating the existing pyenv installation for ${TARGET_USER}${NC}"
if [[ -x "$PYENV_DIR/plugins/pyenv-update/bin/pyenv-update" ]]; then
utils::run_as_target '"$HOME/.pyenv/bin/pyenv" update'
else
utils::run_as_target 'git -C "$HOME/.pyenv" pull --ff-only'
fi
echo -e "${GREEN}[+] pyenv update finished${NC}"
elif [[ -e "$PYENV_DIR" ]]; then
echo -e "${RED}[-] ${PYENV_DIR} exists but does not contain an executable pyenv.${NC}" >&2
echo -e "${RED} Move it aside after reviewing its installed Python versions, then rerun this script.${NC}" >&2
exit 1
else
echo -e "${PURPLE}[*] Installing pyenv via https://pyenv.run for ${TARGET_USER}${NC}"
utils::run_as_target 'curl -fsSL https://pyenv.run | bash'
echo -e "${GREEN}[+] pyenv installer finished${NC}"
fi
if [[ ! -x "$PYENV_BIN" ]]; then
echo -e "${RED}[-] pyenv installation verification failed: ${PYENV_BIN} is not executable.${NC}" >&2
exit 1
fi
PYENV_VERSION="$(utils::run_as_target '"$HOME/.pyenv/bin/pyenv" --version')"
echo -e "${GREEN}[+] Verified ${PYENV_VERSION}${NC}"
ensure_file_exists() {
local file="$1"
if [[ ! -f "$file" ]]; then
utils::exec_as_target touch -- "$file"
fi
}
configure_shell_file() {
local file="$1"
local shell_name="$2"
local enable_virtualenv="${3:-false}"
local line tmp_file last_index
local -a preserved_lines=()
ensure_file_exists "$file"
tmp_file="$(utils::exec_as_target mktemp)"
while IFS= read -r line || [[ -n "$line" ]]; do
case "$line" in
'export PYENV_ROOT="$HOME/.pyenv"' | \
'export PATH="$PYENV_ROOT/bin:$PATH"' | \
'[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' | \
'eval "$(pyenv init --path)"' | \
'eval "$(pyenv init -)"' | \
'eval "$(pyenv init - bash)"' | \
'eval "$(pyenv init - zsh)"' | \
'eval "$(pyenv virtualenv-init -)"')
continue
;;
esac
preserved_lines+=("$line")
done < "$file"
while (( ${#preserved_lines[@]} > 0 )); do
last_index=$(( ${#preserved_lines[@]} - 1 ))
[[ -z "${preserved_lines[$last_index]}" ]] || break
unset "preserved_lines[$last_index]"
done
if (( ${#preserved_lines[@]} > 0 )); then
printf '%s\n' "${preserved_lines[@]}" >> "$tmp_file"
printf '\n' >> "$tmp_file"
fi
printf '%s\n' \
'export PYENV_ROOT="$HOME/.pyenv"' \
'[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' \
"eval \"\$(pyenv init - $shell_name)\"" >> "$tmp_file"
if [[ "$enable_virtualenv" == true ]]; then
printf '%s\n' 'eval "$(pyenv virtualenv-init -)"' >> "$tmp_file"
fi
if ! utils::exec_as_target cp -- "$tmp_file" "$file"; then
utils::exec_as_target rm -f -- "$tmp_file"
return 1
fi
utils::exec_as_target rm -f -- "$tmp_file"
echo -e "${GREEN}[+] Updated $(basename "$file") for ${shell_name}${NC}"
}
TARGET_SHELL="$(getent passwd "$TARGET_USER" | cut -d: -f7)"
SHELL_NAME="${TARGET_SHELL##*/}"
ENABLE_VIRTUALENV=false
if [[ -x "$PYENV_DIR/plugins/pyenv-virtualenv/bin/pyenv-virtualenv" ]]; then
ENABLE_VIRTUALENV=true
fi
case "$SHELL_NAME" in
bash)
BASH_PROFILE="$TARGET_HOME/.profile"
for candidate in .bash_profile .bash_login .profile; do
if [[ -f "$TARGET_HOME/$candidate" ]]; then
BASH_PROFILE="$TARGET_HOME/$candidate"
break
fi
done
configure_shell_file "$TARGET_HOME/.bashrc" bash "$ENABLE_VIRTUALENV"
configure_shell_file "$BASH_PROFILE" bash false
;;
zsh)
configure_shell_file "$TARGET_HOME/.zshrc" zsh "$ENABLE_VIRTUALENV"
configure_shell_file "$TARGET_HOME/.zprofile" zsh false
;;
*)
echo -e "${YELLOW}[*] Unsupported login shell '${SHELL_NAME:-unknown}'; shell startup files were not changed.${NC}"
echo -e "${YELLOW} Configure it with: ${PYENV_BIN} init --install${NC}"
;;
esac
echo -e "${BLUE}[+] pyenv setup complete for ${TARGET_USER}${NC}"
echo -e "${BLUE} Restart with:${NC} ${YELLOW}exec \"\$SHELL\"${NC}"