Skip to content

Commit 7d04ff6

Browse files
authored
Merge pull request #17 from Thavarshan/feature/latest-remote-install
feat: add latest-remote install keyword
2 parents a1b5e9a + d93d6d0 commit 7d04ff6

5 files changed

Lines changed: 147 additions & 82 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
## [Unreleased]
44

5+
### Added
6+
7+
- **`latest-remote` keyword:** Install the newest available remote PHP version directly from package manager repos with `phpvm install latest-remote`.
8+
- **`latest-available` alias:** Alias for `latest-remote`.
9+
510
## [v1.11.0](https://github.com/Thavarshan/phpvm/compare/v1.10.0...v1.11.0) - 2026-04-13
611

712
### Added

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ PHP 8.1.13
4040
- Seamlessly switch between installed PHP versions.
4141
- **Run commands with a specific PHP version** without globally switching (`phpvm exec`, `phpvm run`).
4242
- **List available remote PHP versions** from your system package manager (`phpvm ls-remote`).
43+
- **Install the latest available remote PHP version** with `phpvm install latest-remote`.
4344
- **Resolve version descriptors and aliases** to installed version numbers (`phpvm resolve`).
4445
- Auto-switch PHP versions based on project `.phpvmrc` (configurable depth via `PHPVM_PHPVMRC_MAX_DEPTH`).
4546
- Automatic directory-based switching via built-in cd hook (`PROMPT_COMMAND` for bash, `chpwd` for zsh).
@@ -120,6 +121,7 @@ If the installation was successful, it should output the path to `phpvm`.
120121
| `phpvm auto` | Auto-switch based on `.phpvmrc` file |
121122
| `phpvm list` or `phpvm ls` | List all installed PHP versions |
122123
| `phpvm ls-remote [pattern]` | List available remote PHP versions |
124+
| `phpvm install latest-remote` | Install the latest remote PHP version available |
123125
| `phpvm resolve <version\|alias>` | Resolve a version descriptor to an installed version |
124126
| `phpvm alias [name] [ver]` | Create, update, or list version aliases |
125127
| `phpvm unalias <name>` | Remove version alias |

phpvm.sh

Lines changed: 105 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
# shellcheck disable=SC2155 # Allow declare and assign on same line for better readability
1313

14-
PHPVM_VERSION="1.11.0"
14+
PHPVM_VERSION="1.12.0"
1515

1616
# Test mode flag
1717
PHPVM_TEST_MODE="${PHPVM_TEST_MODE:-false}"
@@ -1016,6 +1016,17 @@ phpvm_resolve_version() {
10161016
fi
10171017
fi
10181018

1019+
if [ "$input" = "latest-remote" ] || [ "$input" = "latest-available" ]; then
1020+
if resolved=$(phpvm_get_latest_remote_version); then
1021+
printf '%s\n' "$resolved"
1022+
return 0
1023+
else
1024+
phpvm_err "No remote PHP versions found."
1025+
phpvm_warn "List available versions with: phpvm ls-remote"
1026+
return "$PHPVM_EXIT_NOT_FOUND"
1027+
fi
1028+
fi
1029+
10191030
# SECURITY: Only check alias file if input passes alias name validation
10201031
# This prevents path traversal attacks like "../../../etc/passwd"
10211032
if phpvm_validate_alias_name "$input" && [ -f "$PHPVM_DIR/alias/$input" ]; then
@@ -1092,6 +1103,95 @@ phpvm_get_latest_installed_version() {
10921103
return 1
10931104
}
10941105

1106+
# Get available remote PHP versions from package manager repositories
1107+
phpvm_get_remote_versions() {
1108+
local pattern="$1"
1109+
local remote_versions=""
1110+
1111+
if phpvm_is_test_mode; then
1112+
remote_versions="7.4
1113+
8.0
1114+
8.1
1115+
8.2
1116+
8.3
1117+
8.4"
1118+
else
1119+
case "$PKG_MANAGER" in
1120+
brew)
1121+
remote_versions=$(
1122+
brew formulae 2> /dev/null | command grep -E '^php(@[0-9]+\.[0-9]+)?$' | while IFS= read -r formula; do
1123+
if [ "$formula" = "php" ]; then
1124+
printf '%s\n' "$(brew_php_major_minor 2> /dev/null || printf '%s' 'latest')"
1125+
else
1126+
printf '%s\n' "${formula#php@}"
1127+
fi
1128+
done | command sort -t. -k1,1n -k2,2n
1129+
)
1130+
;;
1131+
apt)
1132+
remote_versions=$(
1133+
apt-cache search '^php[0-9]' 2> /dev/null |
1134+
command grep -oE 'php[0-9]+\.[0-9]+-cli' |
1135+
command sed 's/php//;s/-cli//' |
1136+
command sort -t. -k1,1n -k2,2n -u
1137+
)
1138+
;;
1139+
dnf)
1140+
remote_versions=$(
1141+
dnf module list php 2> /dev/null |
1142+
command grep -oE '[0-9]+\.[0-9]+' |
1143+
command sort -t. -k1,1n -k2,2n -u
1144+
)
1145+
;;
1146+
yum)
1147+
remote_versions=$(
1148+
yum list available 'php*-cli' 2> /dev/null |
1149+
command grep -oE 'php[0-9]+-php-cli' |
1150+
command sed 's/php//;s/-php-cli//' |
1151+
command sed 's/\([0-9]\)\([0-9]\)/\1.\2/' |
1152+
command sort -t. -k1,1n -k2,2n -u
1153+
)
1154+
;;
1155+
pacman)
1156+
remote_versions=$(
1157+
pacman -Ss '^php' 2> /dev/null |
1158+
command grep -oE 'php[0-9]*\s+[0-9]+\.[0-9]+' |
1159+
command grep -oE '[0-9]+\.[0-9]+' |
1160+
command sort -t. -k1,1n -k2,2n -u
1161+
)
1162+
;;
1163+
*)
1164+
return 1
1165+
;;
1166+
esac
1167+
fi
1168+
1169+
if [ -n "$pattern" ] && [ -n "$remote_versions" ]; then
1170+
remote_versions=$(printf '%s\n' "$remote_versions" | command grep -F "$pattern" || true)
1171+
fi
1172+
1173+
printf '%s\n' "$remote_versions"
1174+
}
1175+
1176+
# Get latest available remote PHP version
1177+
phpvm_get_latest_remote_version() {
1178+
local remote_versions
1179+
local latest
1180+
1181+
remote_versions=$(phpvm_get_remote_versions) || return 1
1182+
if [ -z "$remote_versions" ]; then
1183+
return 1
1184+
fi
1185+
1186+
latest=$(printf '%s\n' "$remote_versions" | phpvm_latest_from_list)
1187+
if [ -n "$latest" ]; then
1188+
printf '%s\n' "$latest"
1189+
return 0
1190+
fi
1191+
1192+
return 1
1193+
}
1194+
10951195
# Check if Remi repository is available/enabled for RHEL/Fedora systems
10961196
check_remi_repository() {
10971197
# Check if Remi repository is installed
@@ -2530,6 +2630,8 @@ Usage:
25302630
Version Arguments:
25312631
X.Y or X.Y.Z Specific PHP version (e.g., 8.1 or 8.1.15)
25322632
latest Latest installed version (not latest available)
2633+
latest-remote Latest remote version available via package manager
2634+
latest-available Alias for 'latest-remote'
25332635
stable Alias for 'latest' (latest installed)
25342636
system System default PHP
25352637
<alias-name> Any user-defined alias (e.g., 'default', 'prod')
@@ -2879,89 +2981,10 @@ phpvm_ls_remote() {
28792981
local pattern="${1:-}"
28802982
local remote_versions=""
28812983

2882-
# In test mode, return a hardcoded list for testing
2883-
if phpvm_is_test_mode; then
2884-
remote_versions="7.4
2885-
8.0
2886-
8.1
2887-
8.2
2888-
8.3
2889-
8.4"
2890-
if [ -n "$pattern" ]; then
2891-
remote_versions=$(printf '%s\n' "$remote_versions" | command grep -F "$pattern")
2892-
fi
2893-
if [ -z "$remote_versions" ]; then
2894-
phpvm_warn "No PHP versions found matching '$pattern'."
2895-
return "$PHPVM_EXIT_NOT_FOUND"
2896-
fi
2897-
phpvm_echo "Available remote PHP versions:"
2898-
printf '%s\n' "$remote_versions" | while IFS= read -r v; do
2899-
printf ' %s\n' "$v"
2900-
done
2901-
return "$PHPVM_EXIT_SUCCESS"
2902-
fi
2903-
2904-
phpvm_echo "Querying available PHP versions from $PKG_MANAGER..."
2905-
2906-
case "$PKG_MANAGER" in
2907-
brew)
2908-
# List all php formulae from Homebrew
2909-
remote_versions=$(
2910-
brew formulae 2> /dev/null | command grep -E '^php(@[0-9]+\.[0-9]+)?$' | while IFS= read -r formula; do
2911-
if [ "$formula" = "php" ]; then
2912-
printf '%s\n' "$(brew_php_major_minor 2> /dev/null || printf '%s\n' 'latest')"
2913-
else
2914-
printf '%s\n' "${formula#php@}"
2915-
fi
2916-
done | command sort -t. -k1,1n -k2,2n
2917-
)
2918-
;;
2919-
apt)
2920-
# List PHP versions available from apt repositories
2921-
remote_versions=$(
2922-
apt-cache search '^php[0-9]' 2> /dev/null |
2923-
command grep -oE 'php[0-9]+\.[0-9]+-cli' |
2924-
command sed 's/php//;s/-cli//' |
2925-
command sort -t. -k1,1n -k2,2n -u
2926-
)
2927-
;;
2928-
dnf)
2929-
# List PHP module streams available via dnf
2930-
remote_versions=$(
2931-
dnf module list php 2> /dev/null |
2932-
command grep -oE '[0-9]+\.[0-9]+' |
2933-
command sort -t. -k1,1n -k2,2n -u
2934-
)
2935-
;;
2936-
yum)
2937-
# List Remi PHP packages available via yum
2938-
remote_versions=$(
2939-
yum list available 'php*-cli' 2> /dev/null |
2940-
command grep -oE 'php[0-9]+-php-cli' |
2941-
command sed 's/php//;s/-php-cli//' |
2942-
command sed 's/\([0-9]\)\([0-9]\)/\1.\2/' |
2943-
command sort -t. -k1,1n -k2,2n -u
2944-
)
2945-
;;
2946-
pacman)
2947-
# List PHP packages available via pacman
2948-
remote_versions=$(
2949-
pacman -Ss '^php' 2> /dev/null |
2950-
command grep -oE 'php[0-9]*\s+[0-9]+\.[0-9]+' |
2951-
command grep -oE '[0-9]+\.[0-9]+' |
2952-
command sort -t. -k1,1n -k2,2n -u
2953-
)
2954-
;;
2955-
*)
2984+
remote_versions=$(phpvm_get_remote_versions "$pattern") || {
29562985
phpvm_err "ls-remote is not supported for package manager: $PKG_MANAGER"
29572986
return "$PHPVM_EXIT_ERROR"
2958-
;;
2959-
esac
2960-
2961-
# Apply pattern filter if given
2962-
if [ -n "$pattern" ] && [ -n "$remote_versions" ]; then
2963-
remote_versions=$(printf '%s\n' "$remote_versions" | command grep -F "$pattern")
2964-
fi
2987+
}
29652988

29662989
if [ -z "$remote_versions" ]; then
29672990
if [ -n "$pattern" ]; then

release-notes-1.12.0.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# v1.12.0 Release Notes
2+
3+
## Added
4+
5+
- Add `latest-remote` keyword for `phpvm install`, allowing users to install the newest available PHP version from remote package manager repositories.
6+
- Add `latest-available` alias for `latest-remote`.
7+
8+
## Details
9+
10+
- `phpvm install latest-remote`
11+
- `phpvm install latest-available`
12+
13+
## Notes
14+
15+
- This feature works with existing package manager support for Homebrew, apt, dnf, yum, and pacman.
16+
- It complements `phpvm ls-remote`, which lists available remote versions.
17+
- In test mode, the remote version list is simulated for coverage.

tests/02_features.bats

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ load test_helper
4949
[[ ! "$output" =~ "7.4" ]]
5050
}
5151

52+
@test "phpvm install latest-remote installs newest available PHP version" {
53+
run install_php "latest-remote"
54+
[ "$status" -eq 0 ]
55+
[[ "$output" =~ "Installing PHP 8.4" ]]
56+
[[ "$output" =~ "PHP 8.4 installed." ]]
57+
phpvm_test_php_installed "8.4"
58+
[ "$?" -eq 0 ]
59+
}
60+
61+
@test "phpvm install latest-available also installs newest available remote PHP" {
62+
run install_php "latest-available"
63+
[ "$status" -eq 0 ]
64+
[[ "$output" =~ "Installing PHP 8.4" ]]
65+
[[ "$output" =~ "PHP 8.4 installed." ]]
66+
phpvm_test_php_installed "8.4"
67+
[ "$?" -eq 0 ]
68+
}
69+
5270
# --- resolve command ---
5371

5472
@test "phpvm resolve returns installed version" {

0 commit comments

Comments
 (0)