diff --git a/README.md b/README.md index 64da4a0..6805b30 100644 --- a/README.md +++ b/README.md @@ -165,10 +165,10 @@ Already-loaded extensions are reported as `already ON` and skipped. On Linux, ex ### Composer ```bash -phpvm composer # installs composer.phar + shim into the active PHP version's bin dir +phpvm composer # installs a single global composer that follows the active PHP version ``` -The installer signature is verified against `composer.github.io/installer.sig` (SHA-384) before execution. Composer lives **inside the active PHP version's directory** — switch versions with `phpvm use ` then re-run `phpvm composer` for that version. +The installer signature is verified against `composer.github.io/installer.sig` (SHA-384) before execution. Composer is installed **once** — `composer.phar` in `~/.phpvm/` and a shim in `~/.phpvm/bin/` (on PATH) that runs whatever PHP is active. Switch versions with `phpvm use ` and the same `composer` keeps working; no need to re-run `phpvm composer`. (Composer 2.x requires PHP ≥ 7.2.5, so an extremely old active version won't run the latest composer.) ### Fix `php.ini` extension_dir @@ -239,7 +239,8 @@ phpvm/ │ └── 8.1.29/ ├── current -> versions/8.3.0 (junction on Windows, symlink on Linux) ├── cache/ # Linux: cached source tarballs -├── bin/ # Windows: phpvm.cmd + phpvm.ps1 shim +├── composer.phar # global Composer (follows the active version) +├── bin/ # on PATH: composer shim (+ phpvm.cmd / phpvm.ps1 on Windows) ├── phpvm.ps1 # Windows: main script └── phpvm.sh # Linux: main script (sourced in .bashrc) ``` diff --git a/linux/install.sh b/linux/install.sh index abda429..6cee393 100644 --- a/linux/install.sh +++ b/linux/install.sh @@ -6,7 +6,7 @@ set -e -PHPVM_VERSION="1.8.0" +PHPVM_VERSION="1.8.1" PHPVM_DIR="${PHPVM_DIR:-$HOME/.phpvm}" PHPVM_REPO="https://raw.githubusercontent.com/devhardiyanto/phpvm/main" diff --git a/linux/phpvm.sh b/linux/phpvm.sh index d239036..5802726 100644 --- a/linux/phpvm.sh +++ b/linux/phpvm.sh @@ -10,10 +10,11 @@ # phpvm use 8.3.0 # ============================================================================== -PHPVM_VERSION="1.8.0" +PHPVM_VERSION="1.8.1" PHPVM_DIR="${PHPVM_DIR:-$HOME/.phpvm}" PHPVM_VERSIONS="$PHPVM_DIR/versions" PHPVM_CURRENT="$PHPVM_DIR/current" +PHPVM_BIN="$PHPVM_DIR/bin" # global shims (composer) — always on PATH PHPVM_CACHE="$PHPVM_DIR/cache" PHPVM_LOG="$PHPVM_DIR/build.log" PHPVM_UPDATE_URL="https://raw.githubusercontent.com/devhardiyanto/phpvm/main/version.txt" @@ -76,16 +77,27 @@ _phpvm_check_update() { _phpvm_init() { - mkdir -p "$PHPVM_VERSIONS" "$PHPVM_CACHE" + mkdir -p "$PHPVM_VERSIONS" "$PHPVM_CACHE" "$PHPVM_BIN" } # ── PATH management ─────────────────────────────────────────────────────────── -# Sets $PHPVM_CURRENT/bin as the first entry in PATH +# Order: $PHPVM_BIN (global shims like composer) before $PHPVM_CURRENT/bin so a +# global composer always wins over any stale per-version shim; both ahead of the +# rest of PATH. `php`, `pecl`, etc. still resolve from the active version's bin. _phpvm_use_path() { local bin="$PHPVM_CURRENT/bin" # Remove any existing phpvm path entries PATH=$(echo "$PATH" | tr ':' '\n' | grep -v "$PHPVM_DIR" | paste -sd ':') - export PATH="$bin:$PATH" + export PATH="$PHPVM_BIN:$bin:$PATH" +} + +# Ensure $PHPVM_BIN is on PATH even when no version is active yet, so the global +# `composer` shim is reachable (and gives a clean error) regardless. +_phpvm_ensure_bin_path() { + case ":$PATH:" in + *":$PHPVM_BIN:"*) ;; + *) export PATH="$PHPVM_BIN:$PATH" ;; + esac } # ── Auto-switch (.phpvmrc) ──────────────────────────────────────────────────── @@ -890,22 +902,22 @@ phpvm_ext() { } # ============================================================================== -# COMPOSER (one composer.phar per active PHP version) +# COMPOSER (one global composer that follows the active PHP version) # ============================================================================== phpvm_composer() { local cur cur=$(_phpvm_current_version) [[ -z "$cur" ]] && { _err "No active PHP version. Run: phpvm use "; return 1; } - local php_root="$PHPVM_VERSIONS/$cur" - local php_bin="$php_root/bin/php" + local php_bin="$PHPVM_VERSIONS/$cur/bin/php" [[ ! -x "$php_bin" ]] && { _err "php binary not found: $php_bin"; return 1; } - local phar="$php_root/bin/composer.phar" - local shim="$php_root/bin/composer" + local phar="$PHPVM_DIR/composer.phar" + local shim="$PHPVM_BIN/composer" if [[ -x "$shim" && -f "$phar" ]]; then _warn "Composer already installed at $shim" + _dim "It follows your active PHP version automatically." _dim "Run: composer --version" return 0 fi @@ -946,8 +958,8 @@ phpvm_composer() { _ok "Hash verified." _step "Installing Composer ..." - mkdir -p "$php_root/bin" - (cd "$php_root/bin" && "$php_bin" "$tmp" --quiet --filename=composer.phar) || { + mkdir -p "$PHPVM_BIN" + (cd "$PHPVM_DIR" && "$php_bin" "$tmp" --quiet --filename=composer.phar) || { _err "Composer installer failed." rm -f "$tmp" return 1 @@ -956,21 +968,21 @@ phpvm_composer() { [[ ! -f "$phar" ]] && { _err "composer.phar not created at $phar"; return 1; } - # POSIX shim — works in bash/zsh/sh. + # POSIX shim — execs the *current* PHP, so composer tracks `phpvm use` + # without reinstalling. Works in bash/zsh/sh. cat > "$shim" </dev/null | sed 's/^/ /' echo "" - _dim "Note: composer is installed inside the PHP $cur bin dir." - _dim "After 'phpvm use ', re-run 'phpvm composer' for that version." + _dim "Composer follows your active PHP version — no need to re-run after 'phpvm use'." } # ============================================================================== @@ -1280,9 +1292,12 @@ phpvm() { # Tests / external sourcing can set PHPVM_NO_INIT=1 to skip the source-time # side effects below (PATH manipulation + hook registration). if [[ -z "${PHPVM_NO_INIT:-}" ]]; then - # Auto-activate current version if set (on shell load) + # Auto-activate current version if set (on shell load); otherwise still make + # sure the global shim dir is on PATH. if [[ -L "$PHPVM_CURRENT" ]]; then _phpvm_use_path + else + _phpvm_ensure_bin_path fi # Register .phpvmrc auto-switch hook if user opted in. diff --git a/tests/linux/commands.bats b/tests/linux/commands.bats index 6063f14..fb0a900 100644 --- a/tests/linux/commands.bats +++ b/tests/linux/commands.bats @@ -69,14 +69,14 @@ PHPEOF [[ "$output" == *"No active PHP version"* ]] } -@test "composer: no-op when shim + phar already present" { +@test "composer: no-op when global shim + phar already present" { _fake_php_install 8.3.0 - local bin="$PHPVM_VERSIONS/8.3.0/bin" - touch "$bin/composer.phar" - cat > "$bin/composer" <<'EOF' + mkdir -p "$PHPVM_BIN" + touch "$PHPVM_DIR/composer.phar" + cat > "$PHPVM_BIN/composer" <<'EOF' #!/usr/bin/env sh EOF - chmod +x "$bin/composer" + chmod +x "$PHPVM_BIN/composer" run phpvm_composer [ "$status" -eq 0 ] [[ "$output" == *"already installed"* ]] diff --git a/version.txt b/version.txt index 27f9cd3..a8fdfda 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.8.0 +1.8.1 diff --git a/windows/install.ps1 b/windows/install.ps1 index 78af709..3973957 100644 --- a/windows/install.ps1 +++ b/windows/install.ps1 @@ -7,7 +7,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" -$PHPVM_VERSION = "1.8.0" +$PHPVM_VERSION = "1.8.1" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $PHPVM_BIN = "$PHPVM_DIR\bin" diff --git a/windows/phpvm.ps1 b/windows/phpvm.ps1 index f966343..3f4145b 100644 --- a/windows/phpvm.ps1 +++ b/windows/phpvm.ps1 @@ -15,7 +15,7 @@ Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" # -- Constants ----------------------------------------------------------------- -$PHPVM_VERSION = "1.8.0" +$PHPVM_VERSION = "1.8.1" $PHPVM_DIR = if ($env:PHPVM_DIR) { $env:PHPVM_DIR } else { "$env:USERPROFILE\.phpvm" } $VERSIONS_DIR = "$PHPVM_DIR\versions" $CURRENT_LINK = "$PHPVM_DIR\current" @@ -1122,13 +1122,15 @@ function Invoke-Composer { Write-Warn "openssl enabled. If Composer install fails, restart terminal first then re-run 'phpvm composer'." } - # One composer per PHP version dir; switch versions -> re-run `phpvm composer`. - $phpRoot = Split-Path $info.Exe -Parent - $composerPhar = "$phpRoot\composer.phar" - $composerBat = "$phpRoot\composer.bat" + # One global composer that follows the active PHP version: the phar lives in + # $PHPVM_DIR and the shim sits in $PHPVM_BIN (already on PATH) and calls + # whatever `php` resolves to. + $composerPhar = "$PHPVM_DIR\composer.phar" + $composerBat = "$PHPVM_BIN\composer.bat" if (Test-Path $composerBat) { Write-Warn "Composer already installed at $composerBat" + Write-Dim "It follows your active PHP version automatically." Write-Dim "Run: composer --version" return } @@ -1157,8 +1159,9 @@ function Invoke-Composer { Write-Ok "Hash verified." Write-Step "Installing Composer ..." - Push-Location $phpRoot - & $info.Exe $installerFile --quiet + if (-not (Test-Path $PHPVM_BIN)) { New-Item -ItemType Directory -Path $PHPVM_BIN -Force | Out-Null } + Push-Location $PHPVM_DIR + & $info.Exe $installerFile --quiet --filename composer.phar Pop-Location if (-not (Test-Path $composerPhar)) { @@ -1169,20 +1172,20 @@ function Invoke-Composer { Remove-Item $installerFile -Force - # Shim so `composer` works from CMD + PowerShell without PATH gymnastics. + # Shim in $PHPVM_BIN (on PATH) calls `php` from PATH - i.e. the active + # version - so composer follows `phpvm use` without reinstalling. $bat = @" @echo off -php "%~dp0composer.phar" %* +php "$composerPhar" %* "@ $bat | Set-Content $composerBat -Encoding ASCII - Write-Ok "Composer installed!" + Write-Ok "Composer installed (global)!" Write-Ok " phar : $composerPhar" Write-Ok " shim : $composerBat" Write-Host "" - & $info.Exe "$phpRoot\composer.phar" --version | ForEach-Object { Write-Host " $_" } + & $info.Exe $composerPhar --version | ForEach-Object { Write-Host " $_" } Write-Host "" - Write-Dim "Note: composer.bat is inside the PHP version folder." - Write-Dim "If you switch PHP version, run 'phpvm composer' again for that version." + Write-Dim "Composer follows your active PHP version - no need to re-run after 'phpvm use'." } function Show-Help {