Releases: Thavarshan/phpvm
Releases · Thavarshan/phpvm
v1.11.0
What's New
New Commands
phpvm exec <version> <command> [args...]— Run a command with a specific PHP version without globally switching. Uses subshell isolation so your current shell is unaffected.phpvm run <version> [script] [args...]— Shortcut forphpvm exec <version> php <script>.phpvm ls-remote [pattern]— List available PHP versions from your system package manager. Supports pattern filtering (e.g.,phpvm ls-remote 8.2).phpvm resolve <version|alias>— Resolve a version descriptor or alias to a locally installed version number.phpvm unload— Remove phpvm from the current shell session (deactivates, removes hooks, unsets all functions/variables).phpvm cache clear— Clear the phpvm cache directory.
New Features
--no-useflag on source:source phpvm.sh --no-useloads functions without auto-switching or registering the cd hook. Useful for lazy-loading setups.- Bash tab completion: Context-aware completions for commands, installed versions, and alias names. Auto-loaded when phpvm is sourced.
- Auto-set default alias on first install: The first
phpvm installnow automatically sets thedefaultalias (matches nvm behaviour). PHPVM_BINexport: After every version switch,$PHPVM_BINpoints to the active PHP binary directory.- XDG_CONFIG_HOME fallback:
PHPVM_DIRnow respects$XDG_CONFIG_HOME/phpvmwhen set.
Bug Fixes
hash -rafter version switch: Bash command hash table is now invalidated after switching, preventing stale binary resolution.phpvm_currentusesprintf: Consistent with project conventions.
Improved
phpvm listoutput: Active version marked with->arrow and green colouring. Default alias shown inline.- Help text: All commands now documented as implemented with usage examples.
Testing
- 78 BATS tests (22 new), 0 failures.
- ShellCheck clean (0 warnings).
Full Changelog: v1.10.0...v1.11.0
Compatibility
- macOS bash 3.2 fix: Replaced
caseinside$()withif/elseinls-remotebrew handler to avoid parser bug in bash 3.2.
v1.10.0
What's New
.phpvmrc Auto-Read
phpvm now reads .phpvmrc automatically when you run commands without a version argument — just like nvm reads .nvmrc:
phpvm use— reads.phpvmrc→ falls back to default alias → errors if neither existsphpvm install— reads.phpvmrcto determine which version to installphpvm exec/phpvm run— detect and report the.phpvmrcversion
.phpvmrc takes priority over the default alias.
Automatic cd Hook
When phpvm is sourced into your shell, a cd hook is now registered that automatically switches PHP versions when you enter a directory containing a .phpvmrc:
- Bash: via
PROMPT_COMMAND - Zsh: via
chpwd_functions - Gated behind
PHPVM_AUTO_USE=true(the default) - Skips switching if already on the correct version
- Silent when no
.phpvmrcis found
Internal
- New
phpvm_read_phpvmrc_version()shared helper - 5 new BATS tests for
.phpvmrcbehaviour - All 56 tests passing
v1.9.4
Fixed
- Fixed
README.MDcasing inrelease.yml: The release workflow referencedREADME.MDbut the file isREADME.md, causing CI failures on case-sensitive Linux filesystems.
Full Changelog: 1.9.3...1.9.4
v1.9.3
Fixed
- Fixed ShellCheck SC2086 in
find_phpvmrc: Double-quoted$depthand$max_depthin arithmetic comparison to prevent globbing and word splitting.
Full Changelog: 1.9.2...1.9.3
v1.9.2
Code Quality Improvements
Changed
- Namespaced global OS variables: Renamed OS_TYPE, OS_ARCH, MACOS_VERSION, MACOS_MAJOR, MACOS_MINOR, IS_WSL, WSL_VERSION, LINUX_DISTRO, and LINUX_VERSION to PHPVM_-prefixed equivalents to prevent namespace pollution when the script is sourced.
- Made .phpvmrc search depth configurable: find_phpvmrc now uses PHPVM_PHPVMRC_MAX_DEPTH environment variable (default: 25) instead of a hardcoded value.
- Replaced echo with printf in version validation: is_valid_version_format() and phpvm_normalize_version() now use printf to avoid potential misinterpretation of version strings.
- Inlined nested functions in suggest_repository_setup: Removed inner function definitions that were re-created on every call.
- Fixed word-splitting in brew_unlink_all_php: Replaced for-in-subshell pattern with a safe while-read loop.
Removed
- Removed unused PHPVM_CACHE_UPDATE_ALTERNATIVES variable.
Full Changelog: 1.9.1...1.9.2
v1.9.1
Fixed
- Fixed
phpvm_debugreturning non-zero in non-debug mode: Changed from[ test ] && cmdpattern (which returns exit code 1 when DEBUG is off) toif/then/fi, preventing silent failures inset -econtexts or when used as last statement beforereturn $?. - Fixed
phpvm_with_locklock leak on interruption: Movedphpvm_unlockbefore trap restoration so the lock is released while cleanup traps are still active, eliminating the window where an interrupt could leak the lock. - Fixed
get_php_binary_pathstdout side-effect on Linux: Capturedlinux_find_php_binaryoutput into a variable before echoing, preventing potential double output when the function's stdout mixed with the fallback path.
Changed
- Eliminated double initialization: Removed redundant
phpvm_init_if_neededcalls frominstall_php,use_php_version,phpvm_current,phpvm_which,list_installed_versions,auto_switch_php_version, anduninstall_php. Initialization is now handled centrally bymain()(viaphpvm_init_or_die) and the sourced-path entry point, avoiding duplicatedetect_system()calls (notably the expensivebrew --prefix). - Moved
package_namecomputation ininstall_php: Theget_php_package_namecall was computed but unused by most package manager branches. It is now only computed in thepacmancase arm that actually needs it.
Internal
- Version bump: Updated to v1.9.1.
- All tests passing: 51 BATS tests pass.
v1.9.0
Fixed
- Fixed error propagation in version resolution: Commands like
phpvm use latestandphpvm install latestnow correctly propagate failures fromphpvm_resolve_versioninstead of silently swallowing errors. - Fixed state consistency in
switch_to_system_php: State file (active_version=system) is now only written AFTER the switch operation succeeds, preventing state lies when brew link operations fail. - Fixed apt install/uninstall symmetry: Uninstall now removes
php${version}-cli,php${version}-common, andphp${version}-fpmpackages symmetrically with what install creates. - Fixed alias directory reliability: Alias directory creation is now required (not best-effort). If
$PHPVM_DIR/aliascannot be created, phpvm fails with a clear error message. - Fixed symlink robustness:
update_current_symlinknow usescommand -v phpto resolve the actual binary path, ensuring the symlink points to what the shell would execute. - Fixed path traversal vulnerability in alias resolution:
phpvm_resolve_versionnow validates alias names before file access, preventing path traversal attacks like../../../etc/passwd. - Fixed path traversal vulnerability in alias commands:
phpvm_aliasnow validates alias names BEFORE any file path operations. - Fixed trap restoration in sourced shells:
phpvm_with_locknow explicitly clears traps withtrap - SIGNALwhen user had no existing trap, preventing phpvm's cleanup traps from being permanently installed in the user's shell session. - Fixed init ordering for help/version commands: Moved command parsing before
phpvm_init_or_diesophpvm helpandphpvm versionwork without requiring package manager detection or system initialization. - Fixed Linux version listing accuracy: Unified all Linux package managers (apt/dnf/yum/pacman) to use
phpvm_linux_installed_versionswhich scans actual binaries, eliminating inaccurate package name listings like8.2-clior8.2-fpm. - Fixed system PHP symlink consistency: System switching now calls
update_current_symlinkto maintain consistent$PHPVM_DIR/currentsymlink behavior across all switching modes. - Fixed alias security vulnerability: Reordered validation in
phpvm_aliasto validate version format before using it in file path checks, preventing potential path traversal attacks with malicious alias targets. - Fixed yum installation strategy: Implemented proper Remi repository detection and naming conventions (
php82-php-cliformat), replacing incorrectyum install php8.2approach that would always fail. - Fixed lock PID staleness: Added explicit
lock_pid=""reset at top of eachphpvm_lockloop iteration to prevent stale PID values in error messages. - Fixed unversioned PHP formula detection: Homebrew's unversioned
phpformula is now correctly identified before any unlinking operations, preventing false version matches from system PHP. - Fixed
phpvm whichfor unversioned formulas: Correctly returns path to unversioned PHP installed asphpformula. - Fixed apt package search:
pkg_search_php()now explicitly checks forCandidate: (none)to avoid false positives fromapt-cache policy. - Fixed
echousage in input validation: Replacedecho "$var" | grepwithprintf '%s\n' "$var" | grepthroughout to prevent interpretation of strings like-n,-e, backslash escapes. - Fixed
phpvm_which()failure propagation: Now properly propagates failures fromphpvm_currentusing|| return $?. - Fixed shellcheck SC2221/SC2222 warnings: Simplified
phpvm_is_sourced()case pattern to avoid overlapping matches.
Changed
- Introduced
command_exists()helper: Replaced 40+ instances ofcommand -v X > /dev/null 2>&1with single reusable function for cleaner command availability checks. - Introduced
ensure_phpvm_dirs()function: Consolidated repeatedmkdir -p $PHPVM_DIR/Xpatterns into centralized directory creation function. - Introduced
brew_link_php_unversioned()function: Extracted duplicatebrew link php --force --overwritelogic with error handling into single reusable function. - Introduced
is_valid_version_format()function: Consolidated duplicate version regex validation pattern into single validation helper. - Added
brew_php_major_minor()helper: Reads version directly from$HOMEBREW_PREFIX/opt/php/bin/phpinstead of PATH-basedphp -r, eliminating conflicts with system PHP. - Reordered version switching flow: Now resolves target formula, then unlinks all PHP, then links resolved formula, preventing "version check breaks after unlink" bugs.
- Improved Linux binary scanning: Broadened skip patterns to prevent accidentally executing PHP helper binaries (
*fpm*,*cgi*,*dbg*,*ize*,*config*). - Ubuntu/Debian apt packages: Changed from non-existent
php8.2to actualphp8.2-cliformat used by ondrej/sury PPA. - Fedora/RHEL dnf packages: Implemented correct module stream approach instead of fictional versioned packages.
- Brew availability check: Changed from fragile
brew search | grepto stablebrew info <formula>API. - Trap preservation in
phpvm_with_lock(): Now saves and restores user's existing trap handlers instead of clobbering them. - Stale lock detection and auto-cleanup: Lock mechanism now checks if lock holder PID is still running and automatically removes stale locks.
Added
- Interactive shell guard: Auto-switch from
.phpvmrcnow only runs in interactive shells usingcase $- in *i*)pattern. - Test mode package manager bypass: Test mode now sets sandbox defaults without requiring actual brew/apt/dnf.
Internal
- Bash-only support documented: Added explicit notice that script requires bash (uses bashisms).
- Intentional symlink behavior clarified: Added comment explaining
update_current_symlink()links to resolvedphpbinary by design. - Dnf module stream workflow: Added inline documentation about RHEL/Fedora module stream management.
- Version bump: Updated to v1.9.0.
- All tests passing: 51 BATS tests pass (added 4 security tests for path traversal protection).
Full Changelog: 1.8.0...1.9.0
v1.8.0
Added
- Alias management commands: Added
phpvm aliasandphpvm unaliasfor version alias creation, listing, and removal. - Alias pattern filtering:
phpvm alias <pattern>now filters aliases by name. - Alias resolution support: Aliases now resolve in
phpvm install,phpvm use, andphpvm which. - Alias visibility:
phpvm listnow shows configured aliases. - Alias resolution in
.phpvmrc:phpvm autonow resolves aliases defined in.phpvmrc. - Latest/stable keywords:
latestandstablenow resolve to the latest installed PHP version. - Quality assurance tooling: Added ShellCheck and shfmt configuration, a QA Makefile, and a
qa.shrunner script. - BATS test suite: Added comprehensive BATS tests for core functionality and new alias behavior.
- CI quality workflow: Added a quality workflow for linting, formatting, and tests.
Changed
- Help output: Promoted alias commands to the primary usage section.
Removed
- Built-in test command: Removed
phpvm testcommand in favor of BATS test suite only.
Internal
- Alias helper utilities: Added alias listing helper and alias resolution logic.
- Test coverage: Extended BATS test suite to cover alias functionality and all core features.
Full Changelog: 1.7.0...1.8.0
v1.6.0
Added
- Smart repository detection: Added intelligent detection of missing PHP repositories on RHEL/Fedora systems with automatic suggestions for enabling Remi's repository.
- Enhanced error messaging: Implemented comprehensive error handling with actionable solutions when PHP packages are not found in default repositories.
- Repository setup guidance: Added detailed step-by-step instructions for enabling EPEL and Remi repositories on Fedora, RHEL, Rocky Linux, AlmaLinux, and CentOS systems.
Changed
- Consolidated GitHub Actions workflows: Streamlined CI/CD from 7 separate workflow files down to 3 focused workflows, eliminating duplication while maintaining comprehensive test coverage.
- Enhanced multi-distribution testing: Expanded automated testing to cover 13 Linux distributions (Ubuntu, Debian, Fedora, Rocky Linux, AlmaLinux, Arch Linux, Alpine Linux) with 4 different package managers (apt, dnf, pacman, apk).
- Improved cross-platform compatibility: Fixed package installation issues for RHEL-family distributions (Rocky/Alma Linux) and Alpine Linux in CI environments.
- Streamlined workflow organization: Reorganized tests into logical categories: syntax analysis, core functionality, PHP usage, multi-distribution compatibility, performance testing, and end-to-end integration.
- Intelligent PHP installation: Enhanced PHP installation process to check package availability before attempting installation and provide specific guidance when packages are missing.
Fixed
- Fixed coreutils package conflicts: Resolved dnf installation conflicts in Rocky Linux and AlmaLinux by adding
--allowerasingflag to handle coreutils-single vs coreutils package conflicts. - Fixed Alpine Linux container compatibility: Resolved bash availability issues in Alpine Linux containers by dynamically selecting appropriate shell (sh vs bash) for initial container startup.
- Fixed virtual package installation: Resolved apt installation failure for
awkvirtual package by explicitly installinggawkpackage instead.
Removed
- Removed emoji characters: Cleaned up all emoji usage from codebase for better terminal compatibility and professional appearance.
- Removed redundant workflow files: Eliminated duplicate testing workflows (use.yml, comprehensive-test.yml, performance-test.yml, integration-test.yml) by consolidating functionality into main test.yml.
Full Changelog: 1.5.0...1.6.0
v1.7.0
Added
- New
phpvm currentcommand: Display the currently active PHP version. Returns the version string, "system", or "none" depending on state. - New
phpvm which [version]command: Show the full path to the PHP binary for a given version. Supports all package managers (brew, apt, dnf, yum, pacman). - New
phpvm deactivatecommand: Temporarily disable phpvm management and restore the original PATH. Useful for debugging or temporarily using system defaults. - New
lsalias forlist: Addedphpvm lsas an alias forphpvm listfor convenience. - Specific exit codes: Implemented consistent exit codes across all commands for better scripting support:
0- Success1- General error2- Invalid argument or usage error3- Version not found (not available)4- Version not installed locally5- File or permission error127- Unknown command
- Exit code documentation: Added exit codes section to help output.
- PATH preservation:
phpvm usenow stores the original PATH on first activation to enable proper deactivation.
Changed
- Enhanced help output: Updated help text with new commands, examples, and exit code documentation.
- Improved error handling: Key functions now return specific exit codes instead of generic error codes.
Full Changelog: v1.6.0...1.7.0