From eb8a941b2eedf622251b2268040c4027ba747ab4 Mon Sep 17 00:00:00 2001 From: Jerome Thayananthajothy Date: Sun, 24 May 2026 17:20:30 +0530 Subject: [PATCH 1/4] =?UTF-8?q?chore:=20release=20v1.12.1=20=E2=80=94=20ad?= =?UTF-8?q?d=20self-update=20command=20and=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++ README.md | 4 +- phpvm.sh | 136 +++++++++++++++++++++++++++++++++++++++- release-notes-1.12.1.md | 19 ++++++ tests/01_core.bats | 27 ++++++++ 5 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 release-notes-1.12.1.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 598c110..928532b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Added + +- **`self-update` command:** Add `phpvm self-update` to automatically update phpvm to the latest stable release and print the updated version. + ## [v1.12.0](https://github.com/Thavarshan/phpvm/compare/v1.11.0...v1.12.0) - 2026-05-20 ### Added diff --git a/README.md b/README.md index bed90d5..0eede3f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ ```sh $ phpvm version -phpvm version 1.11.0 +phpvm version 1.12.1 PHP Version Manager for macOS and Linux Author: Jerome Thayananthajothy @@ -41,6 +41,7 @@ PHP 8.1.13 - **Run commands with a specific PHP version** without globally switching (`phpvm exec`, `phpvm run`). - **List available remote PHP versions** from your system package manager (`phpvm ls-remote`). - **Install the latest available remote PHP version** with `phpvm install latest-remote`. +- **Update phpvm in place** using `phpvm self-update` to pull the latest stable script version. - **Resolve version descriptors and aliases** to installed version numbers (`phpvm resolve`). - Auto-switch PHP versions based on project `.phpvmrc` (configurable depth via `PHPVM_PHPVMRC_MAX_DEPTH`). - Automatic directory-based switching via built-in cd hook (`PROMPT_COMMAND` for bash, `chpwd` for zsh). @@ -122,6 +123,7 @@ If the installation was successful, it should output the path to `phpvm`. | `phpvm list` or `phpvm ls` | List all installed PHP versions | | `phpvm ls-remote [pattern]` | List available remote PHP versions | | `phpvm install latest-remote` | Install the latest remote PHP version available | +| `phpvm self-update` | Update phpvm to the latest stable release | | `phpvm resolve ` | Resolve a version descriptor to an installed version | | `phpvm alias [name] [ver]` | Create, update, or list version aliases | | `phpvm unalias ` | Remove version alias | diff --git a/phpvm.sh b/phpvm.sh index 8fcdb57..d93e467 100755 --- a/phpvm.sh +++ b/phpvm.sh @@ -2,7 +2,7 @@ # phpvm - A PHP Version Manager for macOS and Linux # Author: Jerome Thayananthajothy (tjthavarshan@gmail.com) -# Version: 1.10.0 +# Version: 1.12.1 # # IMPORTANT: This script is written for bash and uses bashisms (arrays, process substitution, etc.) # For sourcing into your shell, use bash only. Zsh users should run phpvm via: @@ -11,7 +11,7 @@ # shellcheck disable=SC2155 # Allow declare and assign on same line for better readability -PHPVM_VERSION="1.12.0" +PHPVM_VERSION="1.12.1" # Test mode flag PHPVM_TEST_MODE="${PHPVM_TEST_MODE:-false}" @@ -2623,6 +2623,7 @@ Usage: phpvm alias [name] [ver] Create, update, or list version aliases phpvm unalias Remove version alias phpvm cache Manage cache directory + phpvm self-update Update phpvm to the latest stable version phpvm help Show this help message phpvm info Show system information for debugging phpvm version Show version information @@ -2678,6 +2679,129 @@ Usage: phpvm help EOF } +phpvm_get_self_update_target() { + local script_path + if [ -n "${PHPVM_SELF_UPDATE_DEST:-}" ]; then + script_path="$PHPVM_SELF_UPDATE_DEST" + else + script_path="${BASH_SOURCE[0]:-$0}" + fi + + if [ -L "$script_path" ] && command_exists readlink; then + local link + link=$(command readlink "$script_path") + if [ "${link#/}" != "$link" ]; then + script_path="$link" + else + local dir + dir=$(cd "$(dirname "$script_path")" 2> /dev/null && pwd) + script_path="$dir/$link" + fi + fi + + printf '%s +' "$script_path" +} + +phpvm_download_url_to_file() { + local url="$1" + local output="$2" + + if command_exists curl; then + command curl --fail --silent --location "$url" > "$output" + return "$?" + fi + + if command_exists wget; then + command wget --quiet --output-document="$output" "$url" + return "$?" + fi + + phpvm_err "curl or wget is required for self-update." + return "$PHPVM_EXIT_ERROR" +} + +phpvm_extract_version_from_file() { + local file="$1" + local version + + version=$(command grep -Eo 'PHPVM_VERSION="[0-9]+\.[0-9]+\.[0-9]+"' "$file" 2> /dev/null | command head -1 | command sed 's/PHPVM_VERSION="//;s/"$//') + if [ -z "$version" ]; then + return "$PHPVM_EXIT_ERROR" + fi + + printf '%s +' "$version" + return "$PHPVM_EXIT_SUCCESS" +} + +phpvm_self_update() { + local source_url="${PHPVM_SELF_UPDATE_URL:-https://raw.githubusercontent.com/Thavarshan/phpvm/main/phpvm.sh}" + local tmp_file + local remote_version + local target_script + + target_script=$(phpvm_get_self_update_target) || return "$PHPVM_EXIT_ERROR" + if [ -z "$target_script" ]; then + phpvm_err "Unable to determine phpvm script path for self-update." + return "$PHPVM_EXIT_ERROR" + fi + + tmp_file=$(mktemp) || { + phpvm_err "Failed to create temporary file for self-update." + return "$PHPVM_EXIT_FILE_ERROR" + } + + if phpvm_is_test_mode && [ -n "${PHPVM_SELF_UPDATE_TEST_SOURCE:-}" ]; then + if [ ! -f "$PHPVM_SELF_UPDATE_TEST_SOURCE" ]; then + rm -f "$tmp_file" + phpvm_err "Self-update test source not found: $PHPVM_SELF_UPDATE_TEST_SOURCE" + return "$PHPVM_EXIT_FILE_ERROR" + fi + command cp "$PHPVM_SELF_UPDATE_TEST_SOURCE" "$tmp_file" + else + if ! phpvm_download_url_to_file "$source_url" "$tmp_file"; then + rm -f "$tmp_file" + phpvm_err "Failed to download phpvm update from $source_url" + return "$PHPVM_EXIT_ERROR" + fi + fi + + remote_version=$(phpvm_extract_version_from_file "$tmp_file") || { + rm -f "$tmp_file" + phpvm_err "Failed to determine remote phpvm version." + return "$PHPVM_EXIT_ERROR" + } + + if [ "$remote_version" = "$PHPVM_VERSION" ]; then + rm -f "$tmp_file" + phpvm_echo "You are already on the latest version: v$PHPVM_VERSION." + return "$PHPVM_EXIT_SUCCESS" + fi + + phpvm_echo "Updating phpvm..." + + if [ ! -w "$target_script" ] && command_exists sudo; then + if ! run_with_sudo cp "$tmp_file" "$target_script"; then + rm -f "$tmp_file" + phpvm_err "Failed to update phpvm." + return "$PHPVM_EXIT_ERROR" + fi + else + if ! command cp "$tmp_file" "$target_script"; then + rm -f "$tmp_file" + phpvm_err "Failed to update phpvm." + return "$PHPVM_EXIT_ERROR" + fi + fi + + chmod +x "$target_script" 2> /dev/null || true + rm -f "$tmp_file" + + phpvm_echo "phpvm successfully updated to the latest version: v$remote_version." + return "$PHPVM_EXIT_SUCCESS" +} + # Print system information for debugging print_system_info() { phpvm_echo "System Information:" @@ -3283,6 +3407,10 @@ main() { print_version exit "$PHPVM_EXIT_SUCCESS" ;; + self-update) + phpvm_self_update + exit "$?" + ;; unload) phpvm_unload exit "$?" @@ -3405,6 +3533,10 @@ main() { phpvm_cache "$@" exit "$?" ;; + self-update) + phpvm_self_update + exit "$?" + ;; *) phpvm_err "Unknown command: $command" print_help diff --git a/release-notes-1.12.1.md b/release-notes-1.12.1.md new file mode 100644 index 0000000..957e631 --- /dev/null +++ b/release-notes-1.12.1.md @@ -0,0 +1,19 @@ +# Release Notes for v1.12.1 + +## Summary + +This release adds the new `phpvm self-update` command, enabling users to update phpvm to the latest stable version directly from the command line. + +## Changes + +- Added `phpvm self-update` to automatically download and install the latest stable phpvm script. +- Updated `README.md` to document the new self-update command. +- Added changelog entry for the self-update feature. + +## Notes + +Run the release creation command after pushing the branch: + +```sh +gh release create 1.12.1 --title "v1.12.1" --notes-file release-notes-1.12.1.md +``` diff --git a/tests/01_core.bats b/tests/01_core.bats index fdd730b..08537f6 100644 --- a/tests/01_core.bats +++ b/tests/01_core.bats @@ -18,6 +18,33 @@ load test_helper [[ "$output" =~ "Usage:" ]] } +@test "phpvm self-update reports already latest version" { + local remote_file="$TEST_DIR/phpvm-latest.sh" + cat > "$remote_file" <<'EOF' +#!/bin/bash +PHPVM_VERSION="1.12.1" +EOF + + run env PHPVM_TEST_MODE=true PHPVM_SELF_UPDATE_TEST_SOURCE="$remote_file" PHPVM_SELF_UPDATE_DEST="$TEST_DIR/phpvm-self-update-target.sh" bash "$BATS_TEST_DIRNAME/../phpvm.sh" self-update + [ "$status" -eq 0 ] + [[ "$output" =~ "You are already on the latest version: v1.12.1." ]] +} + +@test "phpvm self-update replaces script when newer version is available" { + local remote_file="$TEST_DIR/phpvm-updated.sh" + local target_file="$TEST_DIR/phpvm-self-update-target.sh" + cat > "$remote_file" <<'EOF' +#!/bin/bash +PHPVM_VERSION="1.12.2" +EOF + touch "$target_file" + + run env PHPVM_TEST_MODE=true PHPVM_SELF_UPDATE_TEST_SOURCE="$remote_file" PHPVM_SELF_UPDATE_DEST="$target_file" bash "$BATS_TEST_DIRNAME/../phpvm.sh" self-update + [ "$status" -eq 0 ] + [[ "$output" =~ "phpvm successfully updated to the latest version: v1.12.2." ]] + [ "$(grep -oE 'PHPVM_VERSION="[0-9]+\.[0-9]+\.[0-9]+"' "$target_file")" = "PHPVM_VERSION=\"1.12.2\"" ] +} + @test "sanitize_input rejects dangerous characters" { run sanitize_input "8.1; rm -rf /" [ "$status" -ne 0 ] From fa28523a038ad5a76a5d3aa734b4c6cae107fc9b Mon Sep 17 00:00:00 2001 From: Jerome Thayananthajothy Date: Sun, 24 May 2026 17:22:00 +0530 Subject: [PATCH 2/4] docs: fix changelog release header for v1.12.1 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 928532b..a5776f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +## [v1.12.1](https://github.com/Thavarshan/phpvm/compare/v1.12.0...v1.12.1) - 2026-05-24 + ### Added - **`self-update` command:** Add `phpvm self-update` to automatically update phpvm to the latest stable release and print the updated version. From f528d7508206e38f788917d76d7d65f5dd1aa987 Mon Sep 17 00:00:00 2001 From: Jerome Thayananthajothy Date: Sun, 24 May 2026 17:38:55 +0530 Subject: [PATCH 3/4] chore: consolidate changelog; remove per-release release-notes files --- CHANGELOG.md | 9 +++------ release-notes-1.12.0.md | 6 ------ release-notes-1.12.1.md | 19 ------------------- 3 files changed, 3 insertions(+), 31 deletions(-) delete mode 100644 release-notes-1.12.0.md delete mode 100644 release-notes-1.12.1.md diff --git a/CHANGELOG.md b/CHANGELOG.md index a5776f6..07a8e8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,9 +15,6 @@ - **`latest-remote` keyword:** Install the newest available remote PHP version directly from package manager repos with `phpvm install latest-remote`. - **`latest-available` alias:** Alias for `latest-remote`. - -### Added - - **`exec` command:** Run a command with a specific PHP version without globally switching. Executes in a subshell to isolate PATH changes from the current shell. Usage: `phpvm exec [args...]`. - **`run` command:** Sugar for `phpvm exec php