-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathphpvm.sh
executable file
Β·369 lines (332 loc) Β· 10.5 KB
/
phpvm.sh
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
#!/bin/sh
# phpvm - A PHP Version Manager for macOS and Linux
PHPVM_DIR="$HOME/.phpvm"
PHPVM_VERSIONS_DIR="$PHPVM_DIR/versions"
PHPVM_ACTIVE_VERSION_FILE="$PHPVM_DIR/active_version"
PHPVM_CURRENT_SYMLINK="$PHPVM_DIR/current"
DEBUG=false # Set to true to enable debug logs
# Create the required directory structure
create_directories() {
mkdir -p "$PHPVM_VERSIONS_DIR" || {
echo "Error: Failed to create directory $PHPVM_VERSIONS_DIR" >&2
exit 1
}
}
# ANSI color codes
RED=$(printf '\033[31m')
GREEN=$(printf '\033[32m')
YELLOW=$(printf '\033[33m')
RESET=$(printf '\033[0m')
# Output functions
phpvm_echo() { printf "%s%s%s\n" "$GREEN" "$*" "$RESET"; }
phpvm_err() { printf "%sError: %s%s\n" "$RED" "$*" "$RESET" >&2; }
phpvm_warn() { printf "%sWarning: %s%s\n" "$YELLOW" "$*" "$RESET" >&2; }
phpvm_debug() { [ "$DEBUG" = "true" ] && echo "Debug: $*"; }
# Detect the system's package manager and OS
detect_system() {
if [ "$(uname)" = "Darwin" ]; then
PKG_MANAGER="brew"
if ! command -v brew >/dev/null 2>&1; then
phpvm_err "Homebrew is not installed. Please install Homebrew first."
exit 1
fi
HOMEBREW_PREFIX="/opt/homebrew"
PHP_BIN_PATH="$HOMEBREW_PREFIX/bin"
return 0
fi
# Detect Linux package manager
if command -v apt-get >/dev/null 2>&1; then
PKG_MANAGER="apt"
PHP_BIN_PATH="/usr/bin"
elif command -v dnf >/dev/null 2>&1; then
PKG_MANAGER="dnf"
PHP_BIN_PATH="/usr/bin"
elif command -v yum >/dev/null 2>&1; then
PKG_MANAGER="yum"
PHP_BIN_PATH="/usr/bin"
elif command -v pacman >/dev/null 2>&1; then
PKG_MANAGER="pacman"
PHP_BIN_PATH="/usr/bin"
elif command -v brew >/dev/null 2>&1; then
PKG_MANAGER="brew"
# Detect Linuxbrew path
if [ -d "/home/linuxbrew/.linuxbrew" ]; then
HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew"
elif [ -d "$HOME/.linuxbrew" ]; then
HOMEBREW_PREFIX="$HOME/.linuxbrew"
else
HOMEBREW_PREFIX="/usr/local" # Fallback location
fi
PHP_BIN_PATH="$HOMEBREW_PREFIX/bin"
else
phpvm_err "No supported package manager found (apt, dnf, yum, pacman, or brew)."
exit 1
fi
}
# Install PHP using the detected package manager
install_php() {
version="$1"
[ -z "$version" ] && {
phpvm_err "No PHP version specified for installation."
return 1
}
phpvm_echo "Installing PHP $version..."
case "$PKG_MANAGER" in
brew)
if ! brew install php@"$version"; then
phpvm_warn "php@$version is not available in Homebrew. Trying latest version..."
if ! brew install php; then
phpvm_err "Failed to install PHP."
return 1
fi
fi
;;
apt)
# Check if we need sudo
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
else
SUDO=""
fi
$SUDO apt-get update
if ! $SUDO apt-get install -y php"$version"; then
phpvm_err "Failed to install PHP $version. Package php$version may not exist."
return 1
fi
;;
dnf | yum)
# Check if we need sudo
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
else
SUDO=""
fi
if ! $SUDO $PKG_MANAGER install -y php"$version"; then
# Try with full version format for some repos
if ! $SUDO $PKG_MANAGER install -y php-"$version".0; then
phpvm_err "Failed to install PHP $version. Package php$version may not exist."
return 1
fi
fi
;;
pacman)
# Check if we need sudo
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
else
SUDO=""
fi
$SUDO pacman -Sy
if ! $SUDO pacman -S --noconfirm php"$version"; then
phpvm_err "Failed to install PHP $version. Package php$version may not exist."
return 1
fi
;;
esac
phpvm_echo "PHP $version installed."
return 0
}
# Helper function to get the installed PHP version
get_installed_php_version() {
phpvm_debug "Getting installed PHP version..."
if command -v php-config >/dev/null 2>&1; then
php-config --version
else
php -v | awk '/^PHP/ {print $2}'
fi
}
use_php_version() {
version="$1"
[ -z "$version" ] && {
phpvm_err "No PHP version specified to switch."
return 1
}
phpvm_echo "Switching to PHP $version..."
case "$PKG_MANAGER" in
brew)
phpvm_debug "Unlinking any existing PHP version..."
brew unlink php >/dev/null 2>&1 || phpvm_warn "Failed to unlink current PHP version."
if [ -d "$HOMEBREW_PREFIX/Cellar/php@$version" ]; then
phpvm_debug "Linking PHP $version..."
brew link php@"$version" --force --overwrite || {
phpvm_err "Failed to link PHP $version."
return 1
}
elif [ -d "$HOMEBREW_PREFIX/Cellar/php" ]; then
installed_version=$(get_installed_php_version)
if [ "$installed_version" = "$version" ]; then
phpvm_echo "Using PHP $version installed as 'php'."
else
phpvm_err "PHP version $version is not installed. Installed version: $installed_version"
return 1
fi
else
phpvm_err "PHP version $version is not installed."
return 1
fi
;;
apt | dnf | yum | pacman)
# For Linux package managers, we use update-alternatives if available
if command -v update-alternatives >/dev/null 2>&1; then
# Check if we need sudo
if [ "$(id -u)" -ne 0 ]; then
SUDO="sudo"
else
SUDO=""
fi
if [ -f "/usr/bin/php$version" ]; then
$SUDO update-alternatives --set php "/usr/bin/php$version" || {
phpvm_err "Failed to switch to PHP $version using update-alternatives."
return 1
}
else
phpvm_err "PHP binary for version $version not found at /usr/bin/php$version"
return 1
fi
else
phpvm_err "update-alternatives command not found. Cannot switch PHP versions on this system."
return 1
fi
;;
esac
phpvm_debug "Updating symlink to PHP $version..."
rm -f "$PHPVM_CURRENT_SYMLINK"
ln -s "$PHP_BIN_PATH/php" "$PHPVM_CURRENT_SYMLINK" || {
phpvm_err "Failed to update symlink."
return 1
}
echo "$version" >"$PHPVM_ACTIVE_VERSION_FILE" || {
phpvm_err "Failed to write active version."
return 1
}
phpvm_echo "Switched to PHP $version."
return 0
}
auto_switch_php_version() {
current_dir="$PWD"
found=0
depth=0
max_depth=5
while [ "$current_dir" != "/" ] && [ $depth -lt $max_depth ]; do
if [ -f "$current_dir/.phpvmrc" ]; then
if ! version=$(tr -d '[:space:]' <"$current_dir/.phpvmrc"); then
phpvm_err "Failed to read $current_dir/.phpvmrc"
return 1
fi
if [ -n "$version" ]; then
phpvm_echo "Auto-switching to PHP $version (from $current_dir/.phpvmrc)"
if ! use_php_version "$version"; then
phpvm_err "Failed to switch to PHP $version from $current_dir/.phpvmrc"
return 1
fi
else
phpvm_warn "No valid PHP version found in $current_dir/.phpvmrc."
return 1
fi
found=1
break
fi
current_dir=$(dirname "$current_dir")
depth=$((depth + 1))
done
if [ $found -eq 0 ]; then
phpvm_warn "No .phpvmrc file found in the current or parent directories."
return 1
fi
return 0
}
list_installed_versions() {
phpvm_echo "Installed PHP versions:"
case "$PKG_MANAGER" in
brew)
if [ -d "$HOMEBREW_PREFIX/Cellar" ]; then
for dir in "$HOMEBREW_PREFIX/Cellar/php"*; do
if [ -d "$dir" ]; then
base_name=$(basename "$dir")
if [ "$base_name" = "php" ]; then
version=$(get_installed_php_version)
echo " $version (latest)"
else
# Extract version from [email protected] format
version=${base_name#php@}
echo " $version"
fi
fi
done
fi
;;
apt)
dpkg -l | grep -E '^ii +php[0-9]+\.[0-9]+' | awk '{print " " $2}' | sed 's/^ php//'
;;
dnf | yum)
$PKG_MANAGER list installed | grep -E 'php[0-9]+\.' | awk '{print " " $1}' | sed 's/^ php//'
;;
pacman)
pacman -Q | grep '^php' | awk '{print " " $1}' | sed 's/^ php//'
;;
esac
echo ""
if [ -f "$PHPVM_ACTIVE_VERSION_FILE" ]; then
active_version=$(cat "$PHPVM_ACTIVE_VERSION_FILE")
phpvm_echo "Active version: $active_version"
else
phpvm_warn "No active PHP version set."
fi
}
print_help() {
cat <<EOF
phpvm - PHP Version Manager
Usage:
phpvm install <version> Install specified PHP version
phpvm use <version> Switch to specified PHP version
phpvm auto Auto-switch based on .phpvmrc file
phpvm list List installed PHP versions
phpvm help Show this help message
Examples:
phpvm install 8.1 Install PHP 8.1
phpvm use 7.4 Switch to PHP 7.4
phpvm auto Auto-switch based on current directory
EOF
}
main() {
create_directories
detect_system
if [ "$#" -eq 0 ]; then
phpvm_err "No command provided."
print_help
exit 1
fi
command="$1"
shift
case "$command" in
use)
if [ "$#" -eq 0 ]; then
phpvm_err "Missing PHP version argument for 'use' command."
exit 1
fi
use_php_version "$@"
;;
install)
if [ "$#" -eq 0 ]; then
phpvm_err "Missing PHP version argument for 'install' command."
exit 1
fi
install_php "$@"
;;
auto)
auto_switch_php_version
;;
list)
list_installed_versions
;;
help)
print_help
;;
*)
phpvm_err "Unknown command: $command"
print_help
exit 1
;;
esac
}
main "$@"