├── bin ├── phpenv └── phpenv-install-all-darwin ├── .github └── FUNDING.yml ├── test ├── run ├── libexec │ └── phpenv-echo ├── global.bats ├── commands.bats ├── version-file-write.bats ├── completions.bats ├── version.bats ├── --version.bats ├── version-origin.bats ├── version-file.bats ├── version-name.bats ├── version-file-read.bats ├── exec.bats ├── help.bats ├── test_helper.bash ├── versions.bats └── which.bats ├── .gitignore ├── libexec ├── phpenv-root ├── phpenv-shims ├── phpenv-configure ├── phpenv-version-file-write ├── phpenv-version ├── phpenv-version-origin ├── phpenv-version-file-read ├── phpenv-completions ├── phpenv---version ├── phpenv-whence ├── phpenv-version-name ├── phpenv-version-file ├── phpenv-prefix ├── phpenv-exec ├── phpenv-commands ├── phpenv-sh-shell ├── phpenv-global ├── phpenv-hooks ├── phpenv-versions ├── phpenv ├── phpenv-local ├── phpenv-which ├── phpenv-init ├── phpenv-rehash └── phpenv-help ├── completions ├── phpenv.zsh ├── phpenv.bash └── phpenv.fish ├── LICENSE └── README.md /bin/phpenv: -------------------------------------------------------------------------------- 1 | ../libexec/phpenv -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [madumlao] 2 | liberapay: phpenv 3 | -------------------------------------------------------------------------------- /test/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | exec bats ${CI:+--tap} "${@:-test}" 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /plugins 3 | /shims 4 | /version 5 | /versions 6 | /lib 7 | /var 8 | -------------------------------------------------------------------------------- /libexec/phpenv-root: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Display the root directory where versions and shims are kept 3 | echo $PHPENV_ROOT 4 | -------------------------------------------------------------------------------- /test/libexec/phpenv-echo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: phpenv echo [-F] VAR 3 | 4 | if [[ $1 == -F* ]]; then 5 | sep="${1:2}" 6 | echo "${!2}" | tr "${sep:-:}" $'\n' 7 | else 8 | echo "${!1}" 9 | fi 10 | -------------------------------------------------------------------------------- /completions/phpenv.zsh: -------------------------------------------------------------------------------- 1 | if [[ ! -o interactive ]]; then 2 | return 3 | fi 4 | 5 | compctl -K _phpenv phpenv 6 | 7 | _phpenv() { 8 | local words completions 9 | read -cA words 10 | 11 | if [ "${#words}" -eq 2 ]; then 12 | completions="$(phpenv commands)" 13 | else 14 | completions="$(phpenv completions ${words[2,-1]})" 15 | fi 16 | 17 | reply=("${(ps:\n:)completions}") 18 | } 19 | -------------------------------------------------------------------------------- /libexec/phpenv-shims: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: List existing phpenv shims 3 | # Usage: phpenv shims [--short] 4 | 5 | set -e 6 | [ -n "$PHPENV_DEBUG" ] && set -x 7 | 8 | # Provide phpenv completions 9 | if [ "$1" = "--complete" ]; then 10 | echo --short 11 | exit 12 | fi 13 | 14 | for command in "${PHPENV_ROOT}/shims/"*; do 15 | if [ "$1" = "--short" ]; then 16 | echo "${command##*/}" 17 | else 18 | echo "$command" 19 | fi 20 | done | sort 21 | -------------------------------------------------------------------------------- /completions/phpenv.bash: -------------------------------------------------------------------------------- 1 | _phpenv() { 2 | COMPREPLY=() 3 | local word="${COMP_WORDS[COMP_CWORD]}" 4 | 5 | if [ "$COMP_CWORD" -eq 1 ]; then 6 | COMPREPLY=( $(compgen -W "$(phpenv commands)" -- "$word") ) 7 | else 8 | local words=("${COMP_WORDS[@]}") 9 | unset words[0] 10 | unset words[$COMP_CWORD] 11 | local completions=$(phpenv completions "${words[@]}") 12 | COMPREPLY=( $(compgen -W "$completions" -- "$word") ) 13 | fi 14 | } 15 | 16 | complete -F _phpenv phpenv 17 | -------------------------------------------------------------------------------- /libexec/phpenv-configure: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Edit the current PHP's php.ini configuration file at location 3 | 4 | set -e 5 | [ -n "$PHPENV_DEBUG" ] && set -x 6 | 7 | if [ "$VISUAL" ]; then 8 | cmd="$VISUAL" 9 | fi 10 | 11 | if ! [ "$cmd" ] && [ "$EDITOR" ]; then 12 | cmd="$EDITOR" 13 | fi 14 | 15 | if ! [ "$cmd" ] && type vim >/dev/null 2>&1; then 16 | cmd="vim" 17 | fi 18 | 19 | if ! [ "$cmd" ]; then 20 | cmd="vi" 21 | fi 22 | 23 | "$cmd" "$(php --ini|grep Loaded|awk '{print $NF}')" 24 | -------------------------------------------------------------------------------- /libexec/phpenv-version-file-write: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: phpenv version-file-write 3 | 4 | set -e 5 | [ -n "$PHPENV_DEBUG" ] && set -x 6 | 7 | PHPENV_VERSION_FILE="$1" 8 | PHPENV_VERSION="$2" 9 | 10 | if [ -z "$PHPENV_VERSION" ] || [ -z "$PHPENV_VERSION_FILE" ]; then 11 | phpenv-help --usage version-file-write >&2 12 | exit 1 13 | fi 14 | 15 | # Make sure the specified version is installed. 16 | phpenv-prefix "$PHPENV_VERSION" >/dev/null 17 | 18 | # Write the version out to disk. 19 | echo "$PHPENV_VERSION" > "$PHPENV_VERSION_FILE" 20 | -------------------------------------------------------------------------------- /libexec/phpenv-version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Show the current PHP version and its origin 3 | # 4 | # Shows the currently selected PHP version and how it was 5 | # selected. To obtain only the version string, use `phpenv 6 | # version-name'. 7 | 8 | set -e 9 | [ -n "$PHPENV_DEBUG" ] && set -x 10 | 11 | version_name="$(phpenv-version-name)" 12 | version_origin="$(phpenv-version-origin)" 13 | 14 | if [ "$version_origin" = "${PHPENV_ROOT}/version" ] && [ ! -e "$version_origin" ]; then 15 | echo "$version_name" 16 | else 17 | echo "$version_name (set by $version_origin)" 18 | fi 19 | -------------------------------------------------------------------------------- /libexec/phpenv-version-origin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Explain how the current PHP version is set 3 | set -e 4 | [ -n "$PHPENV_DEBUG" ] && set -x 5 | 6 | unset PHPENV_VERSION_ORIGIN 7 | 8 | IFS=$'\n' read -d '' -r -a scripts <<<"$(phpenv-hooks version-origin)" || true 9 | for script in "${scripts[@]}"; do 10 | # shellcheck disable=SC1090 11 | source "$script" 12 | done 13 | 14 | if [ -n "$PHPENV_VERSION_ORIGIN" ]; then 15 | echo "$PHPENV_VERSION_ORIGIN" 16 | elif [ -n "$PHPENV_VERSION" ]; then 17 | echo "PHPENV_VERSION environment variable" 18 | else 19 | phpenv-version-file 20 | fi 21 | -------------------------------------------------------------------------------- /libexec/phpenv-version-file-read: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: phpenv version-file-read 3 | set -e 4 | [ -n "$PHPENV_DEBUG" ] && set -x 5 | 6 | VERSION_FILE="$1" 7 | 8 | if [ -s "$VERSION_FILE" ]; then 9 | # Read the first word from the specified version file. Avoid reading it whole. 10 | IFS="${IFS}"$'\r' 11 | read -n 1024 -d "" -r version _ <"$VERSION_FILE" || : 12 | 13 | if [ "$version" = ".." ] || [[ $version == */* ]]; then 14 | echo "phpenv: invalid version in \`$VERSION_FILE'" >&2 15 | elif [ -n "$version" ]; then 16 | echo "$version" 17 | exit 18 | fi 19 | fi 20 | 21 | exit 1 22 | -------------------------------------------------------------------------------- /completions/phpenv.fish: -------------------------------------------------------------------------------- 1 | function __fish_phpenv_needs_command 2 | set cmd (commandline -opc) 3 | if [ (count $cmd) -eq 1 -a $cmd[1] = 'phpenv' ] 4 | return 0 5 | end 6 | return 1 7 | end 8 | 9 | function __fish_phpenv_using_command 10 | set cmd (commandline -opc) 11 | if [ (count $cmd) -gt 1 ] 12 | if [ $argv[1] = $cmd[2] ] 13 | return 0 14 | end 15 | end 16 | return 1 17 | end 18 | 19 | complete -f -c phpenv -n '__fish_phpenv_needs_command' -a '(phpenv commands)' 20 | for cmd in (phpenv commands) 21 | complete -f -c phpenv -n "__fish_phpenv_using_command $cmd" -a "(phpenv completions $cmd)" 22 | end 23 | -------------------------------------------------------------------------------- /libexec/phpenv-completions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: phpenv completions [...] 3 | 4 | set -e 5 | [ -n "$PHPENV_DEBUG" ] && set -x 6 | 7 | COMMAND="$1" 8 | if [ -z "$COMMAND" ]; then 9 | phpenv-help --usage completions >&2 10 | exit 1 11 | fi 12 | 13 | # Provide phpenv completions 14 | if [ "$COMMAND" = "--complete" ]; then 15 | exec phpenv-commands 16 | fi 17 | 18 | COMMAND_PATH="$(type -P "phpenv-$COMMAND" "phpenv-sh-$COMMAND" | head -n1)" 19 | 20 | # --help is provided automatically 21 | echo --help 22 | 23 | if grep -iE "^([#%]|--|//) provide phpenv completions" "$COMMAND_PATH" >/dev/null; then 24 | shift 25 | exec "$COMMAND_PATH" --complete "$@" 26 | fi 27 | -------------------------------------------------------------------------------- /libexec/phpenv---version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Display the version of phpenv 3 | # 4 | # Displays the version number of this phpenv release, including the 5 | # current revision from git, if available. 6 | # 7 | # The format of the git revision is: 8 | # -- 9 | # where `num_commits` is the number of commits since `version` was 10 | # tagged. 11 | 12 | set -e 13 | [ -n "$PHPENV_DEBUG" ] && set -x 14 | 15 | version="1.0.0" 16 | git_revision="" 17 | 18 | if cd "${BASH_SOURCE%/*}" 2>/dev/null && git remote -v 2>/dev/null | grep -q phpenv; then 19 | git_revision="$(git describe --tags HEAD 2>/dev/null || true)" 20 | git_revision="${git_revision#v}" 21 | fi 22 | 23 | echo "phpenv ${git_revision:-$version}" 24 | -------------------------------------------------------------------------------- /test/global.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "default" { 6 | run phpenv-global 7 | assert_success 8 | assert_output "system" 9 | } 10 | 11 | @test "read PHPENV_ROOT/version" { 12 | mkdir -p "$PHPENV_ROOT" 13 | echo "1.2.3" > "$PHPENV_ROOT/version" 14 | run phpenv-global 15 | assert_success 16 | assert_output "1.2.3" 17 | } 18 | 19 | @test "set PHPENV_ROOT/version" { 20 | mkdir -p "$PHPENV_ROOT/versions/1.2.3" 21 | run phpenv-global "1.2.3" 22 | assert_success 23 | run phpenv-global 24 | assert_success "1.2.3" 25 | } 26 | 27 | @test "fail setting invalid PHPENV_ROOT/version" { 28 | mkdir -p "$PHPENV_ROOT" 29 | run phpenv-global "1.2.3" 30 | assert_failure "phpenv: version \`1.2.3' not installed" 31 | } 32 | -------------------------------------------------------------------------------- /test/commands.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "commands" { 6 | run phpenv-commands 7 | assert_success 8 | assert_line "init" 9 | assert_line "rehash" 10 | assert_line "shell" 11 | refute_line "sh-shell" 12 | assert_line "echo" 13 | } 14 | 15 | @test "commands --sh" { 16 | run phpenv-commands --sh 17 | assert_success 18 | refute_line "init" 19 | assert_line "shell" 20 | } 21 | 22 | @test "commands in path with spaces" { 23 | path="${PHPENV_TEST_DIR}/my commands" 24 | cmd="${path}/phpenv-sh-hello" 25 | mkdir -p "$path" 26 | touch "$cmd" 27 | chmod +x "$cmd" 28 | 29 | PATH="${path}:$PATH" run phpenv-commands --sh 30 | assert_success 31 | assert_line "hello" 32 | } 33 | 34 | @test "commands --no-sh" { 35 | run phpenv-commands --no-sh 36 | assert_success 37 | assert_line "init" 38 | refute_line "shell" 39 | } 40 | -------------------------------------------------------------------------------- /test/version-file-write.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | setup() { 6 | mkdir -p "$PHPENV_TEST_DIR" 7 | cd "$PHPENV_TEST_DIR" 8 | } 9 | 10 | @test "invocation without 2 arguments prints usage" { 11 | run phpenv-version-file-write 12 | assert_failure "Usage: phpenv version-file-write " 13 | run phpenv-version-file-write "one" "" 14 | assert_failure 15 | } 16 | 17 | @test "setting nonexistent version fails" { 18 | assert [ ! -e ".php-version" ] 19 | run phpenv-version-file-write ".php-version" "7.4.33" 20 | assert_failure "phpenv: version \`7.4.33' not installed" 21 | assert [ ! -e ".php-version" ] 22 | } 23 | 24 | @test "writes value to arbitrary file" { 25 | mkdir -p "${PHPENV_ROOT}/versions/7.4.33" 26 | assert [ ! -e "my-version" ] 27 | run phpenv-version-file-write "${PWD}/my-version" "7.4.33" 28 | assert_success "" 29 | assert [ "$(cat my-version)" = "7.4.33" ] 30 | } 31 | -------------------------------------------------------------------------------- /libexec/phpenv-whence: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: List all PHP versions that contain the given executable 3 | # Usage: phpenv whence [--path] 4 | 5 | set -e 6 | [ -n "$PHPENV_DEBUG" ] && set -x 7 | 8 | # Provide phpenv completions 9 | if [ "$1" = "--complete" ]; then 10 | echo --path 11 | exec phpenv shims --short 12 | fi 13 | 14 | if [ "$1" = "--path" ]; then 15 | print_paths="1" 16 | shift 17 | else 18 | print_paths="" 19 | fi 20 | 21 | whence() { 22 | local command="$1" 23 | phpenv-versions --bare | while read version; do 24 | path="$(phpenv-prefix "$version")/bin/${command}" 25 | if [ -x "$path" ]; then 26 | [ "$print_paths" ] && echo "$path" || echo "$version" 27 | fi 28 | done 29 | } 30 | 31 | PHPENV_COMMAND="$1" 32 | if [ -z "$PHPENV_COMMAND" ]; then 33 | phpenv-help --usage whence >&2 34 | exit 1 35 | fi 36 | 37 | result="$(whence "$PHPENV_COMMAND")" 38 | [ -n "$result" ] && echo "$result" 39 | -------------------------------------------------------------------------------- /libexec/phpenv-version-name: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Show the current PHP version 3 | set -e 4 | [ -n "$PHPENV_DEBUG" ] && set -x 5 | 6 | if [ -z "$PHPENV_VERSION" ]; then 7 | PHPENV_VERSION_FILE="$(phpenv-version-file)" 8 | PHPENV_VERSION="$(phpenv-version-file-read "$PHPENV_VERSION_FILE" || true)" 9 | fi 10 | 11 | IFS=$'\n' read -d '' -r -a scripts <<<"$(phpenv-hooks version-name)" || true 12 | for script in "${scripts[@]}"; do 13 | # shellcheck disable=SC1090 14 | source "$script" 15 | done 16 | 17 | if [ -z "$PHPENV_VERSION" ] || [ "$PHPENV_VERSION" = "system" ]; then 18 | echo "system" 19 | exit 20 | fi 21 | 22 | version_exists() { 23 | local version="$1" 24 | [ -d "${PHPENV_ROOT}/versions/${version}" ] 25 | } 26 | 27 | if version_exists "$PHPENV_VERSION"; then 28 | echo "$PHPENV_VERSION" 29 | elif version_exists "${PHPENV_VERSION#php-}"; then 30 | echo "${PHPENV_VERSION#php-}" 31 | else 32 | echo "phpenv: version \`$PHPENV_VERSION' is not installed (set by $(phpenv-version-origin))" >&2 33 | exit 1 34 | fi 35 | -------------------------------------------------------------------------------- /libexec/phpenv-version-file: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: phpenv version-file [] 3 | # Summary: Detect the file that sets the current phpenv version 4 | # 5 | # Detects and prints the location of a `.php-version` file that sets the 6 | # version for the current working directory. If no file found, this prints 7 | # the location of the global version file, even if that file does 8 | # not exist. 9 | 10 | set -e 11 | [ -n "$PHPENV_DEBUG" ] && set -x 12 | 13 | target_dir="$1" 14 | 15 | find_local_version_file() { 16 | local root="$1" 17 | while ! [[ "$root" =~ ^//[^/]*$ ]]; do 18 | if [ -s "${root}/.php-version" ]; then 19 | echo "${root}/.php-version" 20 | return 0 21 | fi 22 | [ -n "$root" ] || break 23 | root="${root%/*}" 24 | done 25 | return 1 26 | } 27 | 28 | if [ -n "$target_dir" ]; then 29 | find_local_version_file "$target_dir" 30 | else 31 | find_local_version_file "$PHPENV_DIR" || { 32 | [ "$PHPENV_DIR" != "$PWD" ] && find_local_version_file "$PWD" 33 | } || echo "${PHPENV_ROOT}/version" 34 | fi 35 | -------------------------------------------------------------------------------- /libexec/phpenv-prefix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Display prefix for a PHP version 3 | # Usage: phpenv prefix [] 4 | # 5 | # Displays the directory where a PHP version is installed. If no 6 | # version is given, `phpenv prefix' displays the location of the 7 | # currently selected version. 8 | 9 | set -e 10 | [ -n "$PHPENV_DEBUG" ] && set -x 11 | 12 | # Provide phpenv completions 13 | if [ "$1" = "--complete" ]; then 14 | echo system 15 | exec phpenv-versions --bare 16 | fi 17 | 18 | if [ -n "$1" ]; then 19 | export PHPENV_VERSION="$1" 20 | elif [ -z "$PHPENV_VERSION" ]; then 21 | PHPENV_VERSION="$(phpenv-version-name)" 22 | fi 23 | 24 | if [ "$PHPENV_VERSION" = "system" ]; then 25 | PHP_PATH="$(phpenv-which php)" 26 | PHP_PATH="${PHP_PATH%/*}" 27 | echo "${PHP_PATH%/bin}" 28 | exit 29 | fi 30 | 31 | PHPENV_PREFIX_PATH="${PHPENV_ROOT}/versions/${PHPENV_VERSION}" 32 | if [ ! -d "$PHPENV_PREFIX_PATH" ]; then 33 | echo "phpenv: version \`${PHPENV_VERSION}' not installed" >&2 34 | exit 1 35 | fi 36 | 37 | echo "$PHPENV_PREFIX_PATH" 38 | -------------------------------------------------------------------------------- /test/completions.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | create_command() { 6 | bin="${PHPENV_TEST_DIR}/bin" 7 | mkdir -p "$bin" 8 | echo "$2" > "${bin}/$1" 9 | chmod +x "${bin}/$1" 10 | } 11 | 12 | @test "command with no completion support" { 13 | create_command "phpenv-hello" "#!$BASH 14 | echo hello" 15 | run phpenv-completions hello 16 | assert_success "--help" 17 | } 18 | 19 | @test "command with completion support" { 20 | create_command "phpenv-hello" "#!$BASH 21 | # Provide phpenv completions 22 | if [[ \$1 = --complete ]]; then 23 | echo hello 24 | else 25 | exit 1 26 | fi" 27 | run phpenv-completions hello 28 | assert_success 29 | assert_output < [...] 6 | # 7 | # Runs an executable by first preparing PATH so that the selected PHP 8 | # version's `bin' directory is at the front. 9 | # 10 | # For example, if the currently selected PHP version is 1.9.3-p327: 11 | # phpenv exec bundle install 12 | # 13 | # is equivalent to: 14 | # PATH="$PHPENV_ROOT/versions/1.9.3-p327/bin:$PATH" bundle install 15 | 16 | set -e 17 | [ -n "$PHPENV_DEBUG" ] && set -x 18 | 19 | # Provide phpenv completions 20 | if [ "$1" = "--complete" ]; then 21 | exec phpenv-shims --short 22 | fi 23 | 24 | PHPENV_VERSION="$(phpenv-version-name)" 25 | PHPENV_COMMAND="$1" 26 | 27 | if [ -z "$PHPENV_COMMAND" ]; then 28 | phpenv-help --usage exec >&2 29 | exit 1 30 | fi 31 | 32 | export PHPENV_VERSION 33 | PHPENV_COMMAND_PATH="$(phpenv-which "$PHPENV_COMMAND")" 34 | PHPENV_BIN_PATH="${PHPENV_COMMAND_PATH%/*}" 35 | 36 | for script in $(phpenv-hooks exec); do 37 | source "$script" 38 | done 39 | 40 | shift 1 41 | if [ "$PHPENV_VERSION" != "system" ]; then 42 | export PATH="${PHPENV_BIN_PATH}:${PATH}" 43 | fi 44 | exec -a "$PHPENV_COMMAND" "$PHPENV_COMMAND_PATH" "$@" 45 | -------------------------------------------------------------------------------- /test/version.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | create_version() { 6 | mkdir -p "${PHPENV_ROOT}/versions/$1" 7 | } 8 | 9 | setup() { 10 | mkdir -p "$PHPENV_TEST_DIR" 11 | cd "$PHPENV_TEST_DIR" 12 | } 13 | 14 | @test "no version selected" { 15 | assert [ ! -d "${PHPENV_ROOT}/versions" ] 16 | run phpenv-version 17 | assert_success "system" 18 | } 19 | 20 | @test "set by PHPENV_VERSION" { 21 | create_version "8.1.16" 22 | PHPENV_VERSION=8.1.16 run phpenv-version 23 | assert_success "8.1.16 (set by PHPENV_VERSION environment variable)" 24 | } 25 | 26 | @test "set by local file" { 27 | create_version "8.1.16" 28 | cat > ".php-version" <<<"8.1.16" 29 | run phpenv-version 30 | assert_success "8.1.16 (set by ${PWD}/.php-version)" 31 | } 32 | 33 | @test "set by global file" { 34 | create_version "8.1.16" 35 | cat > "${PHPENV_ROOT}/version" <<<"8.1.16" 36 | run phpenv-version 37 | assert_success "8.1.16 (set by ${PHPENV_ROOT}/version)" 38 | } 39 | 40 | @test "prefer local over global file" { 41 | create_version "8.1.16" 42 | create_version "8.4.0" 43 | cat > ".php-version" <<<"8.1.16" 44 | cat > "${PHPENV_ROOT}/version" <<<"8.4.0" 45 | run phpenv-version 46 | assert_success "8.1.16 (set by ${PWD}/.php-version)" 47 | } 48 | -------------------------------------------------------------------------------- /test/--version.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | export GIT_DIR="${PHPENV_TEST_DIR}/.git" 6 | 7 | setup() { 8 | mkdir -p "$HOME" 9 | git config --global user.name "Tester" 10 | git config --global user.email "tester@test.local" 11 | cd "$PHPENV_TEST_DIR" 12 | } 13 | 14 | git_commit() { 15 | git commit --quiet --allow-empty -m "empty" 16 | } 17 | 18 | @test "default version" { 19 | assert [ ! -e "$PHPENV_ROOT" ] 20 | run phpenv---version 21 | assert_success 22 | [[ $output == "phpenv "?.?.? ]] 23 | } 24 | 25 | @test "doesn't read version from non-phpenv repo" { 26 | git init 27 | git remote add origin https://github.com/homebrew/homebrew.git 28 | git_commit 29 | git tag v1.0 30 | 31 | run phpenv---version 32 | assert_success 33 | [[ $output == "phpenv "?.?.? ]] 34 | } 35 | 36 | @test "reads version from git repo" { 37 | git init 38 | git remote add origin https://github.com/phpenv/phpenv.git 39 | git_commit 40 | git tag v0.4.1 41 | git_commit 42 | git_commit 43 | 44 | run phpenv---version 45 | assert_success "phpenv 0.4.1-2-g$(git rev-parse --short HEAD)" 46 | } 47 | 48 | @test "prints default version if no tags in git repo" { 49 | git init 50 | git remote add origin https://github.com/phpenv/phpenv.git 51 | git_commit 52 | 53 | run phpenv---version 54 | [[ $output == "phpenv "?.?.? ]] 55 | } 56 | -------------------------------------------------------------------------------- /libexec/phpenv-commands: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: List all available phpenv commands 3 | # Usage: phpenv commands [--sh|--no-sh] 4 | # 5 | # List names of all phpenv commands, including 3rd-party ones found in the 6 | # PATH or in phpenv plugins. With `--sh`, list only shell commands. 7 | # 8 | # This functionality is mainly meant for scripting. To see usage help for 9 | # phpenv, run `phpenv help`. 10 | 11 | set -e 12 | [ -n "$PHPENV_DEBUG" ] && set -x 13 | 14 | # Provide phpenv completions 15 | if [ "$1" = "--complete" ]; then 16 | echo --sh 17 | echo --no-sh 18 | exit 19 | fi 20 | 21 | exclude_shell= 22 | command_prefix="phpenv-" 23 | 24 | if [ "$1" = "--sh" ]; then 25 | command_prefix="phpenv-sh-" 26 | shift 27 | elif [ "$1" = "--no-sh" ]; then 28 | exclude_shell=1 29 | shift 30 | fi 31 | 32 | shopt -s nullglob 33 | 34 | { 35 | PATH_remain="$PATH" 36 | # traverse PATH to find "phpenv-" prefixed commands 37 | while true; do 38 | path="${PATH_remain%%:*}" 39 | if [ -n "$path" ]; then 40 | for phpenv_command in "${path}/${command_prefix}"*; do 41 | phpenv_command="${phpenv_command##*phpenv-}" 42 | if [[ -z $exclude_shell || $phpenv_command != sh-* ]]; then 43 | echo "${phpenv_command##sh-}" 44 | fi 45 | done 46 | fi 47 | [[ $PATH_remain == *:* ]] || break 48 | PATH_remain="${PATH_remain#*:}" 49 | done 50 | } | sort | uniq 51 | -------------------------------------------------------------------------------- /libexec/phpenv-sh-shell: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Set or show the shell-specific PHP version 4 | # 5 | # Usage: phpenv shell 6 | # phpenv shell --unset 7 | # 8 | # Sets a shell-specific PHP version by setting the `PHPENV_VERSION' 9 | # environment variable in your shell. This version overrides local 10 | # application-specific versions and the global version. 11 | # 12 | # should be a string matching a PHP version known to phpenv. 13 | # The special version string `system' will use your default system PHP. 14 | # Run `phpenv versions' for a list of available PHP versions. 15 | 16 | set -e 17 | [ -n "$PHPENV_DEBUG" ] && set -x 18 | 19 | # Provide phpenv completions 20 | if [ "$1" = "--complete" ]; then 21 | echo --unset 22 | echo system 23 | exec phpenv-versions --bare 24 | fi 25 | 26 | version="$1" 27 | 28 | if [ "$version" = "--unset" ]; then 29 | echo "unset PHPENV_VERSION" 2>/dev/null 30 | PHPENV_VERSION=""; version="" 31 | fi 32 | 33 | 34 | if [ -z "$version" ]; then 35 | if [ -z "$PHPENV_VERSION" ]; then 36 | echo "phpenv: no shell-specific version configured" >&2 37 | exit 1 38 | else 39 | echo "echo \"\$PHPENV_VERSION\"" 40 | exit 41 | fi 42 | fi 43 | 44 | # Make sure the specified version is installed. 45 | if phpenv-prefix "$version" >/dev/null; then 46 | echo "export PHPENV_VERSION=\"${version}\"" 47 | echo "$version" >&2 48 | else 49 | echo "return 1" 50 | exit 1 51 | fi 52 | -------------------------------------------------------------------------------- /libexec/phpenv-global: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Set or show the global PHP version and update the Apache apxs 4 | # library link 5 | # 6 | # Usage: phpenv global 7 | # phpenv global --unset 8 | # 9 | # Sets the global PHP version. You can override the global version at 10 | # any time by setting a directory-specific version with `phpenv local' 11 | # or by setting the `PHPENV_VERSION' environment variable. 12 | # 13 | # should be a string matching a PHP version known to phpenv. 14 | # The special version string `system' will use your default system PHP. 15 | # Run `phpenv versions' for a list of available PHP versions. 16 | 17 | set -e 18 | [ -n "$PHPENV_DEBUG" ] && set -x 19 | 20 | # Provide phpenv completions 21 | if [ "$1" = "--complete" ]; then 22 | echo system --unset 23 | exec phpenv-versions --bare 24 | fi 25 | 26 | PHPENV_VERSION="$1" 27 | PHPENV_VERSION_FILE="${PHPENV_ROOT}/version" 28 | 29 | if [ "$1" == "--unset" ]; then 30 | rm -f "$PHPENV_VERSION_FILE" 31 | PHPENV_VERSION="" 32 | fi 33 | 34 | if [ -n "$PHPENV_VERSION" ]; then 35 | phpenv-version-file-write "$PHPENV_VERSION_FILE" "$PHPENV_VERSION" 36 | else 37 | PHPENV_VERSION=$(phpenv-version-file-read "$PHPENV_VERSION_FILE") || 38 | PHPENV_VERSION=$(phpenv-version-file-read "${PHPENV_ROOT}/global") || 39 | PHPENV_VERSION=$(phpenv-version-file-read "${PHPENV_ROOT}/default") || 40 | PHPENV_VERSION=system 41 | fi 42 | 43 | echo ${PHPENV_VERSION} 44 | -------------------------------------------------------------------------------- /libexec/phpenv-hooks: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: List hook scripts for a given phpenv command 3 | # Usage: phpenv hooks 4 | 5 | set -e 6 | [ -n "$PHPENV_DEBUG" ] && set -x 7 | 8 | # Provide phpenv completions 9 | if [ "$1" = "--complete" ]; then 10 | echo exec 11 | echo rehash 12 | echo which 13 | exit 14 | fi 15 | 16 | PHPENV_COMMAND="$1" 17 | if [ -z "$PHPENV_COMMAND" ]; then 18 | phpenv-help --usage hooks >&2 19 | exit 1 20 | fi 21 | 22 | #PHPENV_COMMAND_HOOK="$2" 23 | #if [ -z "$PHPENV_COMMAND_HOOK" ]; then 24 | # PHPENV_COMMAND_HOOK="*" 25 | #fi 26 | 27 | resolve_link() { 28 | $(type -p greadlink readlink | head -1) $1 29 | } 30 | 31 | realpath() { 32 | local cwd="$(pwd)" 33 | local base="$(basename $1)" 34 | local path="$1" 35 | 36 | while [ -n "$path" ]; do 37 | cd "${path%/*}" 38 | local name="${path##*/}" 39 | path="$(resolve_link "$name" || true)" 40 | done 41 | 42 | echo "$(pwd)/$base" 43 | cd "$cwd" 44 | } 45 | 46 | shopt -s nullglob 47 | for path in ${PHPENV_HOOK_PATH//:/$'\n'}; do 48 | for script in $path/"$PHPENV_COMMAND"/*.bash; do 49 | echo $(realpath $script) 50 | done 51 | done 52 | # 53 | #for path in ${PHPENV_HOOK_PATH//:/$'\n'}; do 54 | # files="${path}/${PHPENV_COMMAND}/${PHPENV_COMMAND_HOOK}.bash" 55 | # for script in $files; do 56 | # if [ "$PHPENV_COMMAND_HOOK" != "*" ] && [ -x $script ]; then 57 | # exec "$script" 58 | # elif [ -f $script ]; then 59 | # echo $(realpath $script) 60 | # fi 61 | # done 62 | #done 63 | shopt -u nullglob 64 | -------------------------------------------------------------------------------- /test/version-origin.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | setup() { 6 | mkdir -p "$PHPENV_TEST_DIR" 7 | cd "$PHPENV_TEST_DIR" 8 | } 9 | 10 | @test "reports global file even if it doesn't exist" { 11 | assert [ ! -e "${PHPENV_ROOT}/version" ] 12 | run phpenv-version-origin 13 | assert_success "${PHPENV_ROOT}/version" 14 | } 15 | 16 | @test "detects global file" { 17 | mkdir -p "$PHPENV_ROOT" 18 | touch "${PHPENV_ROOT}/version" 19 | run phpenv-version-origin 20 | assert_success "${PHPENV_ROOT}/version" 21 | } 22 | 23 | @test "detects PHPENV_VERSION" { 24 | PHPENV_VERSION=1 run phpenv-version-origin 25 | assert_success "PHPENV_VERSION environment variable" 26 | } 27 | 28 | @test "detects local file" { 29 | echo "system" > .php-version 30 | run phpenv-version-origin 31 | assert_success "${PWD}/.php-version" 32 | } 33 | 34 | @test "reports from hook" { 35 | create_hook version-origin test.bash <<<"PHPENV_VERSION_ORIGIN=plugin" 36 | 37 | PHPENV_VERSION=1 run phpenv-version-origin 38 | assert_success "plugin" 39 | } 40 | 41 | @test "carries original IFS within hooks" { 42 | create_hook version-origin hello.bash <&2 23 | exit 1 24 | ;; 25 | esac 26 | done 27 | 28 | canonicalize_dir() { 29 | { cd "$1" && pwd -P 30 | } 2>/dev/null || echo "$1" 31 | } 32 | 33 | versions_dir="${PHPENV_ROOT}/versions" 34 | if [ -n "$skip_aliases" ]; then 35 | versions_dir="$(canonicalize_dir "$versions_dir")" 36 | fi 37 | 38 | list_versions() { 39 | local path 40 | local target 41 | shopt -s nullglob 42 | for path in "$versions_dir"/*; do 43 | if [ -d "$path" ]; then 44 | if [ -n "$skip_aliases" ] && [ -L "$path" ]; then 45 | target="$(canonicalize_dir "$path")" 46 | [ "${target%/*}" != "$versions_dir" ] || continue 47 | fi 48 | echo "${path##*/}" 49 | fi 50 | done 51 | shopt -u nullglob 52 | } 53 | 54 | if [ -n "$bare" ]; then 55 | list_versions 56 | exit 0 57 | fi 58 | 59 | sort_versions() { 60 | sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z.\1/; s/$/.z/; G; s/\n/ /' | \ 61 | LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}' 62 | } 63 | 64 | versions="$( 65 | if PHPENV_VERSION=system phpenv-which php >/dev/null 2>&1; then 66 | echo system 67 | fi 68 | list_versions | sort_versions 69 | )" 70 | 71 | if [ -z "$versions" ]; then 72 | echo "Warning: no PHP detected on the system" >&2 73 | exit 1 74 | fi 75 | 76 | current_version="$(phpenv-version-name || true)" 77 | while read -r version; do 78 | if [ "$version" == "$current_version" ]; then 79 | echo "* $(phpenv-version 2>/dev/null)" 80 | else 81 | echo " $version" 82 | fi 83 | done <<<"$versions" 84 | -------------------------------------------------------------------------------- /libexec/phpenv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | export -n CDPATH 4 | 5 | if [ "$1" = "--debug" ]; then 6 | export PHPENV_DEBUG=1 7 | shift 8 | fi 9 | 10 | if [ -n "$PHPENV_DEBUG" ]; then 11 | export PS4='+ [${BASH_SOURCE##*/}:${LINENO}] ' 12 | set -x 13 | fi 14 | 15 | resolve_link() { 16 | $(type -p greadlink readlink | head -1) "$1" 17 | } 18 | 19 | abs_dirname() { 20 | local cwd="$(pwd)" 21 | local path="$1" 22 | 23 | while [ -n "$path" ]; do 24 | cd "${path%/*}" 25 | local name="${path##*/}" 26 | path="$(resolve_link "$name" || true)" 27 | done 28 | 29 | pwd 30 | cd "$cwd" 31 | } 32 | 33 | if [ -z "${PHPENV_ROOT}" ]; then 34 | PHPENV_ROOT="${HOME}/.phpenv" 35 | else 36 | PHPENV_ROOT="${PHPENV_ROOT%/}" 37 | fi 38 | export PHPENV_ROOT 39 | 40 | if [ -z "${PHPENV_DIR}" ]; then 41 | PHPENV_DIR="$(pwd)" 42 | else 43 | cd "$PHPENV_DIR" 2>/dev/null || { 44 | echo "phpenv: cannot change working directory to \`$PHPENV_DIR'" 45 | exit 1 46 | } >&2 47 | PHPENV_DIR="$(pwd)" 48 | cd "$OLDPWD" 49 | fi 50 | export PHPENV_DIR 51 | 52 | 53 | shopt -s nullglob 54 | 55 | bin_path="$(abs_dirname "$0")" 56 | for plugin_bin in "${PHPENV_ROOT}/plugins/"*/bin; do 57 | bin_path="${bin_path}:${plugin_bin}" 58 | done 59 | export PATH="${bin_path}:${PATH}" 60 | 61 | hook_path="${PHPENV_HOOK_PATH}:${PHPENV_ROOT}/phpenv.d:/usr/local/etc/phpenv.d:/etc/phpenv.d:/usr/lib/phpenv/hooks" 62 | for plugin_hook in "${PHPENV_ROOT}/plugins/"*/etc/phpenv.d; do 63 | hook_path="${hook_path}:${plugin_hook}" 64 | done 65 | export PHPENV_HOOK_PATH="$hook_path" 66 | 67 | shopt -u nullglob 68 | 69 | command="$1" 70 | if [[ "$2" = "--help" || "$2" = "-h" ]]; then 71 | phpenv-help "$command" >&2 72 | exit 1 73 | fi 74 | 75 | case "$command" in 76 | "" | "-h" | "--help" ) 77 | echo -e "$(phpenv-help)" >&2 78 | ;; 79 | "-v" ) 80 | exec phpenv---version 81 | ;; 82 | * ) 83 | command_path="$(command -v "phpenv-$command" || true)" 84 | if [ -z "$command_path" ]; then 85 | echo "phpenv: no such command \`$command'" >&2 86 | exit 1 87 | fi 88 | 89 | shift 1 90 | exec "$command_path" "$@" 91 | ;; 92 | esac 93 | -------------------------------------------------------------------------------- /libexec/phpenv-local: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Set or show the local application-specific PHP version 4 | # 5 | # Usage: phpenv local 6 | # phpenv local --unset 7 | # 8 | # Sets the local application-specific PHP version by writing the 9 | # version name to a file named `.php-version'. 10 | # 11 | # When you run a PHP command, phpenv will look for a `.php-version' 12 | # file in the current directory and each parent directory. If no such 13 | # file is found in the tree, phpenv will use the global PHP version 14 | # specified with `phpenv global'. A version specified with the 15 | # `PHPENV_VERSION' environment variable takes precedence over local 16 | # and global versions. 17 | # 18 | # For backwards compatibility, phpenv will also read version 19 | # specifications from `.phpenv-version' files, but a `.php-version' 20 | # file in the same directory takes precedence. 21 | # 22 | # should be a string matching a PHP version known to phpenv. 23 | # The special version string `system' will use your default system PHP. 24 | # Run `phpenv versions' for a list of available PHP versions. 25 | 26 | set -e 27 | [ -n "$PHPENV_DEBUG" ] && set -x 28 | 29 | # Provide phpenv completions 30 | if [ "$1" = "--complete" ]; then 31 | echo --unset 32 | echo system 33 | exec phpenv-versions --bare 34 | fi 35 | 36 | PHPENV_VERSION="$1" 37 | 38 | if [ "$PHPENV_VERSION" = "--unset" ]; then 39 | rm -f .php-version .phpenv-version 40 | PHPENV_VERSION="" 41 | elif [ -n "$PHPENV_VERSION" ]; then 42 | if [ "$(PHPENV_VERSION= phpenv-version-origin)" -ef .phpenv-version ]; then 43 | rm -f .phpenv-version 44 | { echo "phpenv: removed existing \`.phpenv-version' file and migrated" 45 | echo " local version specification to \`.php-version' file" 46 | } >&2 47 | fi 48 | phpenv-version-file-write .php-version "$PHPENV_VERSION" 49 | echo "$PHPENV_VERSION" >&2 50 | fi 51 | if [ -z "$PHPENV_VERSION" ]; then 52 | phpenv-version-file-read .php-version || 53 | phpenv-version-file-read .phpenv-version || 54 | { echo "phpenv: no local version configured for this directory" 55 | exit 1 56 | } >&2 57 | fi 58 | -------------------------------------------------------------------------------- /test/version-file.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | setup() { 6 | mkdir -p "$PHPENV_TEST_DIR" 7 | cd "$PHPENV_TEST_DIR" 8 | } 9 | 10 | create_file() { 11 | mkdir -p "$(dirname "$1")" 12 | echo "system" > "$1" 13 | } 14 | 15 | @test "detects global 'version' file" { 16 | create_file "${PHPENV_ROOT}/version" 17 | run phpenv-version-file 18 | assert_success "${PHPENV_ROOT}/version" 19 | } 20 | 21 | @test "prints global file if no version files exist" { 22 | assert [ ! -e "${PHPENV_ROOT}/version" ] 23 | assert [ ! -e ".php-version" ] 24 | run phpenv-version-file 25 | assert_success "${PHPENV_ROOT}/version" 26 | } 27 | 28 | @test "in current directory" { 29 | create_file ".php-version" 30 | run phpenv-version-file 31 | assert_success "${PHPENV_TEST_DIR}/.php-version" 32 | } 33 | 34 | @test "in parent directory" { 35 | create_file ".php-version" 36 | mkdir -p project 37 | cd project 38 | run phpenv-version-file 39 | assert_success "${PHPENV_TEST_DIR}/.php-version" 40 | } 41 | 42 | @test "topmost file has precedence" { 43 | create_file ".php-version" 44 | create_file "project/.php-version" 45 | cd project 46 | run phpenv-version-file 47 | assert_success "${PHPENV_TEST_DIR}/project/.php-version" 48 | } 49 | 50 | @test "PHPENV_DIR has precedence over PWD" { 51 | create_file "widget/.php-version" 52 | create_file "project/.php-version" 53 | cd project 54 | PHPENV_DIR="${PHPENV_TEST_DIR}/widget" run phpenv-version-file 55 | assert_success "${PHPENV_TEST_DIR}/widget/.php-version" 56 | } 57 | 58 | @test "PWD is searched if PHPENV_DIR yields no results" { 59 | mkdir -p "widget/blank" 60 | create_file "project/.php-version" 61 | cd project 62 | PHPENV_DIR="${PHPENV_TEST_DIR}/widget/blank" run phpenv-version-file 63 | assert_success "${PHPENV_TEST_DIR}/project/.php-version" 64 | } 65 | 66 | @test "finds version file in target directory" { 67 | create_file "project/.php-version" 68 | run phpenv-version-file "${PWD}/project" 69 | assert_success "${PHPENV_TEST_DIR}/project/.php-version" 70 | } 71 | 72 | @test "fails when no version file in target directory" { 73 | run phpenv-version-file "$PWD" 74 | assert_failure "" 75 | } 76 | -------------------------------------------------------------------------------- /libexec/phpenv-which: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Display the full path to an executable 4 | # 5 | # Usage: phpenv which 6 | # 7 | # Displays the full path to the executable that phpenv will invoke when 8 | # you run the given command. 9 | 10 | set -e 11 | [ -n "$PHPENV_DEBUG" ] && set -x 12 | 13 | # Provide phpenv completions 14 | if [ "$1" = "--complete" ]; then 15 | exec phpenv shims --short 16 | fi 17 | 18 | expand_path() { 19 | if [ ! -d "$1" ]; then 20 | return 1 21 | fi 22 | 23 | local cwd="$(pwd)" 24 | cd "$1" 25 | pwd 26 | cd "$cwd" 27 | } 28 | 29 | remove_from_path() { 30 | local path_to_remove="$(expand_path "$1")" 31 | local result="" 32 | 33 | if [ -z "$path_to_remove" ]; then 34 | echo "${PATH}" 35 | return 36 | fi 37 | 38 | local paths 39 | IFS=: paths=($PATH) 40 | 41 | for path in "${paths[@]}"; do 42 | path="$(expand_path "$path" || true)" 43 | if [ -n "$path" ] && [ "$path" != "$path_to_remove" ]; then 44 | result="${result}${path}:" 45 | fi 46 | done 47 | 48 | echo "${result%:}" 49 | } 50 | 51 | PHPENV_VERSION="$(phpenv-version-name)" 52 | PHPENV_COMMAND="$1" 53 | 54 | if [ -z "$PHPENV_COMMAND" ]; then 55 | phpenv-help --usage which >&2 56 | exit 1 57 | fi 58 | 59 | if [ "$PHPENV_VERSION" = "system" ]; then 60 | PATH="$(remove_from_path "${PHPENV_ROOT}/shims")" 61 | PHPENV_COMMAND_PATH="$(command -v "$PHPENV_COMMAND" || true)" 62 | else 63 | PHPENV_COMMAND_PATH="${PHPENV_ROOT}/versions/${PHPENV_VERSION}/bin/${PHPENV_COMMAND}" 64 | if ! [ -x "$PHPENV_COMMAND_PATH" ]; then 65 | PHPENV_COMMAND_PATH="${PHPENV_ROOT}/versions/${PHPENV_VERSION}/sbin/${PHPENV_COMMAND}" 66 | fi 67 | fi 68 | 69 | for script in $(phpenv-hooks which); do 70 | source "$script" 71 | done 72 | 73 | if [ -x "$PHPENV_COMMAND_PATH" ]; then 74 | echo "$PHPENV_COMMAND_PATH" 75 | else 76 | echo "phpenv: $PHPENV_COMMAND: command not found" >&2 77 | 78 | versions="$(phpenv-whence "$PHPENV_COMMAND" || true)" 79 | if [ -n "$versions" ]; then 80 | { echo 81 | echo "The \`$1' command exists in these PHP versions:" 82 | echo "$versions" | sed 's/^/ /g' 83 | echo 84 | } >&2 85 | fi 86 | 87 | exit 127 88 | fi 89 | -------------------------------------------------------------------------------- /test/version-name.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | create_version() { 6 | mkdir -p "${PHPENV_ROOT}/versions/$1" 7 | } 8 | 9 | setup() { 10 | mkdir -p "$PHPENV_TEST_DIR" 11 | cd "$PHPENV_TEST_DIR" 12 | } 13 | 14 | @test "no version selected" { 15 | assert [ ! -d "${PHPENV_ROOT}/versions" ] 16 | run phpenv-version-name 17 | assert_success "system" 18 | } 19 | 20 | @test "system version is not checked for existence" { 21 | PHPENV_VERSION=system run phpenv-version-name 22 | assert_success "system" 23 | } 24 | 25 | @test "PHPENV_VERSION can be overridden by hook" { 26 | create_version "7.4.33" 27 | create_version "8.1.16" 28 | create_hook version-name test.bash <<<"PHPENV_VERSION=8.1.16" 29 | 30 | PHPENV_VERSION=7.4.33 run phpenv-version-name 31 | assert_success "8.1.16" 32 | } 33 | 34 | @test "carries original IFS within hooks" { 35 | create_hook version-name hello.bash < ".php-version" <<<"7.4.33" 51 | run phpenv-version-name 52 | assert_success "7.4.33" 53 | 54 | PHPENV_VERSION=8.1.16 run phpenv-version-name 55 | assert_success "8.1.16" 56 | } 57 | 58 | @test "local file has precedence over global" { 59 | create_version "7.4.33" 60 | create_version "8.1.16" 61 | 62 | cat > "${PHPENV_ROOT}/version" <<<"7.4.33" 63 | run phpenv-version-name 64 | assert_success "7.4.33" 65 | 66 | cat > ".php-version" <<<"8.1.16" 67 | run phpenv-version-name 68 | assert_success "8.1.16" 69 | } 70 | 71 | @test "missing version" { 72 | PHPENV_VERSION=1.2 run phpenv-version-name 73 | assert_failure "phpenv: version \`1.2' is not installed (set by PHPENV_VERSION environment variable)" 74 | } 75 | 76 | @test "version with prefix in name" { 77 | create_version "7.4.33" 78 | cat > ".php-version" <<<"php-7.4.33" 79 | run phpenv-version-name 80 | assert_success 81 | assert_output "7.4.33" 82 | } 83 | -------------------------------------------------------------------------------- /test/version-file-read.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | setup() { 6 | mkdir -p "${PHPENV_TEST_DIR}/myproject" 7 | cd "${PHPENV_TEST_DIR}/myproject" 8 | } 9 | 10 | @test "fails without arguments" { 11 | run phpenv-version-file-read 12 | assert_failure "" 13 | } 14 | 15 | @test "fails for invalid file" { 16 | run phpenv-version-file-read "non-existent" 17 | assert_failure "" 18 | } 19 | 20 | @test "fails for blank file" { 21 | echo > my-version 22 | run phpenv-version-file-read my-version 23 | assert_failure "" 24 | } 25 | 26 | @test "reads simple version file" { 27 | cat > my-version <<<"8.1.16" 28 | run phpenv-version-file-read my-version 29 | assert_success "8.1.16" 30 | } 31 | 32 | @test "ignores leading spaces" { 33 | cat > my-version <<<" 8.1.16" 34 | run phpenv-version-file-read my-version 35 | assert_success "8.1.16" 36 | } 37 | 38 | @test "reads only the first word from file" { 39 | cat > my-version <<<"8.1.16-p194@tag 7.4.33 hi" 40 | run phpenv-version-file-read my-version 41 | assert_success "8.1.16-p194@tag" 42 | } 43 | 44 | @test "loads only the first line in file" { 45 | cat > my-version < my-version < my-version 64 | run phpenv-version-file-read my-version 65 | assert_success "7.4.33" 66 | } 67 | 68 | @test "ignores carriage returns" { 69 | cat > my-version <<< $'8.1.16\r' 70 | run phpenv-version-file-read my-version 71 | assert_success "8.1.16" 72 | } 73 | 74 | @test "prevents directory traversal" { 75 | cat > my-version <<<".." 76 | run phpenv-version-file-read my-version 77 | assert_failure "phpenv: invalid version in \`my-version'" 78 | 79 | cat > my-version <<<"../foo" 80 | run phpenv-version-file-read my-version 81 | assert_failure "phpenv: invalid version in \`my-version'" 82 | } 83 | 84 | @test "disallows path segments in version string" { 85 | cat > my-version <<<"foo/bar" 86 | run phpenv-version-file-read my-version 87 | assert_failure "phpenv: invalid version in \`my-version'" 88 | } 89 | -------------------------------------------------------------------------------- /test/exec.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | create_executable() { 6 | name="${1?}" 7 | shift 1 8 | bin="${PHPENV_ROOT}/versions/${PHPENV_VERSION}/bin" 9 | mkdir -p "$bin" 10 | { if [ $# -eq 0 ]; then cat - 11 | else echo "$@" 12 | fi 13 | } | sed -Ee '1s/^ +//' > "${bin}/$name" 14 | chmod +x "${bin}/$name" 15 | } 16 | 17 | @test "fails with invalid version" { 18 | export PHPENV_VERSION="2.0" 19 | run phpenv-exec php -v 20 | assert_failure "phpenv: version \`2.0' is not installed (set by PHPENV_VERSION environment variable)" 21 | } 22 | 23 | @test "fails with invalid version set from file" { 24 | mkdir -p "$PHPENV_TEST_DIR" 25 | cd "$PHPENV_TEST_DIR" 26 | echo 1.9 > .php-version 27 | run phpenv-exec rspec 28 | assert_failure "phpenv: version \`1.9' is not installed (set by $PWD/.php-version)" 29 | } 30 | 31 | @test "completes with names of executables" { 32 | export PHPENV_VERSION="2.0" 33 | create_executable "php" "#!/bin/sh" 34 | create_executable "phar" "#!/bin/sh" 35 | 36 | phpenv-rehash 37 | run phpenv-completions exec 38 | assert_success 39 | assert_output <" { 82 | export PHPENV_VERSION="2.0" 83 | 84 | # emulate `php -S' behavior 85 | create_executable "php" </dev/null; then 91 | \$BASH "\$found" 92 | else 93 | echo "php: no PHP script found in input (LoadError)" >&2 94 | exit 1 95 | fi 96 | else 97 | echo 'php 2.0 (phpenv test)' 98 | fi 99 | SH 100 | 101 | create_executable "phar" <])" 4 | 5 | set -e 6 | [ -n "$PHPENV_DEBUG" ] && set -x 7 | 8 | print="" 9 | no_rehash="" 10 | for args in "$@" 11 | do 12 | if [ "$args" = "-" ]; then 13 | print=1 14 | shift 15 | fi 16 | 17 | if [ "$args" = "--no-rehash" ]; then 18 | no_rehash=1 19 | shift 20 | fi 21 | done 22 | 23 | shell="$1" 24 | if [ -z "$shell" ]; then 25 | shell="$(basename "$SHELL")" 26 | fi 27 | 28 | resolve_link() { 29 | $(type -p greadlink readlink | head -1) $1 30 | } 31 | 32 | abs_dirname() { 33 | local cwd="$(pwd)" 34 | local path="$1" 35 | 36 | while [ -n "$path" ]; do 37 | cd "${path%/*}" 38 | local name="${path##*/}" 39 | path="$(resolve_link "$name" || true)" 40 | done 41 | 42 | pwd 43 | cd "$cwd" 44 | } 45 | 46 | root="$(abs_dirname "$0")/.." 47 | 48 | if [ -z "$print" ]; then 49 | case "$shell" in 50 | bash ) 51 | profile='~/.bash_profile' 52 | ;; 53 | zsh ) 54 | profile='~/.zshrc' 55 | ;; 56 | ksh ) 57 | profile='~/.profile' 58 | ;; 59 | fish ) 60 | profile='~/.config/fish/config.fish' 61 | ;; 62 | * ) 63 | profile='your profile' 64 | ;; 65 | esac 66 | 67 | { echo "# Load phpenv automatically by adding" 68 | echo "# the following to ${profile}:" 69 | echo 70 | case "$shell" in 71 | fish ) 72 | echo 'status --is-interactive; and source (phpenv init -|psub)' 73 | ;; 74 | * ) 75 | echo 'eval "$(phpenv init -)"' 76 | ;; 77 | esac 78 | echo 79 | } >&2 80 | 81 | exit 1 82 | fi 83 | 84 | mkdir -p "${PHPENV_ROOT}/"{shims,versions} 85 | 86 | case "$shell" in 87 | fish ) 88 | echo "set -gx PATH '${PHPENV_ROOT}/shims' \$PATH" 89 | ;; 90 | * ) 91 | echo 'export PATH="'${PHPENV_ROOT}'/shims:${PATH}"' 92 | ;; 93 | esac 94 | 95 | case "$shell" in 96 | bash | zsh | fish ) 97 | echo "source \"$root/completions/phpenv.${shell}\"" 98 | ;; 99 | esac 100 | 101 | if [ -z "$no_rehash" ]; then 102 | echo 'phpenv rehash 2>/dev/null' 103 | fi 104 | 105 | commands=(`phpenv-commands --sh`) 106 | case "$shell" in 107 | fish ) 108 | cat < /dev/null || { \ 8 | echo "Please install homebrew, see: http://mxcl.github.com/homebrew/"; exit 1; \ 9 | } 10 | [[ "/usr/local" != "$(brew --prefix)" ]] && { \ 11 | echo "For now we expect the brew --prefix to be /usr/local"; \ 12 | echo "but yours is $(brew --prefix)."; \ 13 | echo "Please create an issue to have this resolved."; exit 1; \ 14 | } 15 | 16 | PHPENV_ROOT="$(dirname ~/.phpenv/bin)" 17 | #Install dependencies 18 | echo "Installing PHP build dependencies..." 19 | echo "ERROR: Something already installed is a good thing" 20 | echo 21 | #flex 2.5.4 formula patch 22 | grep -q 2.5.4 /usr/local/Library/Formula/flex.rb || \ 23 | patch /usr/local/Library/Formula/flex.rb ${PHPENV_ROOT}/patches/homebrew-flex.diff 24 | 25 | brew install \ 26 | flex curl expat freetds freetype gettext gmp imap-uw jpeg libevent libiconv libmagic \ 27 | libmemcached libpng libvpx libxml2 libxslt mariadb mcrypt mhash net-snmp oniguruma \ 28 | openssl pcre readline tidy unixodbc zlib autoconf213 autoconf ccache httpd 29 | 30 | #install libxml2 2.7.8 31 | cd /usr/local 32 | git checkout 497b13a /usr/local/Library/Formula/libxml2.rb 33 | brew install libxml2 34 | git checkout HEAD /usr/local/Library/Formula/libxml2.rb 35 | cd - &> /dev/null 36 | #make sure we are on the latest version though 37 | brew switch libxml2 $(brew versions libxml2|awk '{if (NR==1) print $1}') 38 | 39 | #Use ccache 40 | export PATH=/usr/local/opt/ccache/libexec:$PATH 41 | 42 | #Add our php module to the new apache httpd.conf 43 | grep -q php5_module /usr/local/opt/httpd/etc/apache2/httpd.conf || { \ 44 | awk -v phpenv="${PHPENV_ROOT}" '/^LoadModule/{ 45 | if (!done) { 46 | print "LoadModule php5_module "phpenv"/lib/libphp5.so"; done=1; 47 | } 48 | }; 49 | {print $0;}' /usr/local/opt/httpd/etc/apache2/httpd.conf > /usr/local/opt/httpd/etc/apache2/httpd.tmp && \ 50 | mv /usr/local/opt/httpd/etc/apache2/httpd.{tmp,conf}; \ 51 | } 52 | echo 53 | echo "Fetching the latest releases to see what is available..." 54 | echo "If this is the first time you use phpenv we have to clone" 55 | echo "the php-src repo first, please be patient..." 56 | RELEASES=$(phpenv install --releases 2>/dev/null) 57 | 58 | LATEST=(\ 59 | "$(echo "${RELEASES}"| grep --color=never php-5.5| head -n 1)" \ 60 | "$(echo "${RELEASES}"| grep --color=never php-5.4| head -n 1)" \ 61 | "$(echo "${RELEASES}"| grep --color=never php-5.3| head -n 1)" \ 62 | "$(echo "${RELEASES}"| grep --color=never php-5.2| head -n 1)" \ 63 | ) 64 | echo "These are the latest releases, we will install them now:" 65 | echo 66 | echo "${LATEST[@]}" 67 | echo 68 | for release in "${LATEST[@]}"; do 69 | echo "Cleaning the build environment..." 70 | phpenv install --deep-clean &> /dev/null; 71 | echo "Running: phpenv install ${release} ${1}"; 72 | phpenv install ${release} ${1} || { \ 73 | echo "Ok that didn't work, please open an issue for this."; exit 1; \ 74 | } 75 | done 76 | -------------------------------------------------------------------------------- /test/help.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | @test "without args shows summary of common commands" { 6 | run phpenv-help 7 | assert_success 8 | assert_line "Usage: phpenv [...]" 9 | assert_line "Commands to manage available PHP versions:" 10 | } 11 | 12 | @test "usage flag" { 13 | run phpenv-help --usage 14 | assert_success 15 | assert_output "Usage: phpenv [...]" 16 | } 17 | 18 | @test "invalid command" { 19 | run phpenv-help hello 20 | assert_failure "phpenv: no such command \`hello'" 21 | } 22 | 23 | @test "shows help for a specific command" { 24 | mkdir -p "${PHPENV_TEST_DIR}/bin" 25 | cat > "${PHPENV_TEST_DIR}/bin/phpenv-hello" < 28 | # Summary: Says "hello" to you, from phpenv 29 | # This command is useful for saying hello. 30 | echo hello 31 | SH 32 | 33 | run phpenv-help hello 34 | assert_success 35 | assert_output < 37 | 38 | This command is useful for saying hello. 39 | SH 40 | } 41 | 42 | @test "replaces missing extended help with summary text" { 43 | mkdir -p "${PHPENV_TEST_DIR}/bin" 44 | cat > "${PHPENV_TEST_DIR}/bin/phpenv-hello" < 47 | # Summary: Says "hello" to you, from phpenv 48 | echo hello 49 | SH 50 | 51 | run phpenv-help hello 52 | assert_success 53 | assert_output < 55 | 56 | Says "hello" to you, from phpenv 57 | SH 58 | } 59 | 60 | @test "extracts only usage" { 61 | mkdir -p "${PHPENV_TEST_DIR}/bin" 62 | cat > "${PHPENV_TEST_DIR}/bin/phpenv-hello" < 65 | # Summary: Says "hello" to you, from phpenv 66 | # This extended help won't be shown. 67 | echo hello 68 | SH 69 | 70 | run phpenv-help --usage hello 71 | assert_success "Usage: phpenv hello " 72 | } 73 | 74 | @test "empty usage section" { 75 | mkdir -p "${PHPENV_TEST_DIR}/bin" 76 | cat > "${PHPENV_TEST_DIR}/bin/phpenv-hello" < "${PHPENV_TEST_DIR}/bin/phpenv-hello" < 91 | # phpenv hi [everybody] 92 | # phpenv hola --translate 93 | # Summary: Says "hello" to you, from phpenv 94 | # Help text. 95 | echo hello 96 | SH 97 | 98 | run phpenv-help hello 99 | assert_success 100 | assert_output < 102 | phpenv hi [everybody] 103 | phpenv hola --translate 104 | 105 | Help text. 106 | SH 107 | } 108 | 109 | @test "multiline extended help section" { 110 | mkdir -p "${PHPENV_TEST_DIR}/bin" 111 | cat > "${PHPENV_TEST_DIR}/bin/phpenv-hello" < 114 | # Summary: Says "hello" to you, from phpenv 115 | # This is extended help text. 116 | # It can contain multiple lines. 117 | # 118 | # And paragraphs. 119 | 120 | echo hello 121 | SH 122 | 123 | run phpenv-help hello 124 | assert_success 125 | assert_output < 127 | 128 | This is extended help text. 129 | It can contain multiple lines. 130 | 131 | And paragraphs. 132 | SH 133 | } 134 | -------------------------------------------------------------------------------- /test/test_helper.bash: -------------------------------------------------------------------------------- 1 | unset PHPENV_VERSION 2 | unset PHPENV_DIR 3 | 4 | # guard against executing this block twice due to bats internals 5 | if [ -z "$PHPENV_TEST_DIR" ]; then 6 | PHPENV_TEST_DIR="${BATS_TMPDIR}/phpenv" 7 | export PHPENV_TEST_DIR="$(mktemp -d "${PHPENV_TEST_DIR}.XXX" 2>/dev/null || echo "$PHPENV_TEST_DIR")" 8 | 9 | export PHPENV_ROOT="${PHPENV_TEST_DIR}/root" 10 | export HOME="${PHPENV_TEST_DIR}/home" 11 | export PHPENV_HOOK_PATH="${PHPENV_ROOT}/phpenv.d" 12 | 13 | PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin 14 | PATH="${PHPENV_TEST_DIR}/bin:$PATH" 15 | PATH="${BATS_TEST_DIRNAME}/../libexec:$PATH" 16 | PATH="${BATS_TEST_DIRNAME}/libexec:$PATH" 17 | PATH="${PHPENV_ROOT}/shims:$PATH" 18 | export PATH 19 | 20 | for xdg_var in `env 2>/dev/null | grep ^XDG_ | cut -d= -f1`; do unset "$xdg_var"; done 21 | unset xdg_var 22 | fi 23 | 24 | teardown() { 25 | rm -rf "$PHPENV_TEST_DIR" 26 | } 27 | 28 | flunk() { 29 | { if [ "$#" -eq 0 ]; then cat - 30 | else echo "$@" 31 | fi 32 | } | sed "s:${PHPENV_TEST_DIR}:TEST_DIR:g" >&2 33 | return 1 34 | } 35 | 36 | assert_success() { 37 | if [ "$status" -ne 0 ]; then 38 | flunk "command failed with exit status $status" 39 | elif [ "$#" -gt 0 ]; then 40 | assert_output "$1" 41 | fi 42 | } 43 | 44 | assert_failure() { 45 | if [ "$status" -eq 0 ]; then 46 | flunk "expected failed exit status" 47 | elif [ "$#" -gt 0 ]; then 48 | assert_output "$1" 49 | fi 50 | } 51 | 52 | assert_equal() { 53 | if [ "$1" != "$2" ]; then 54 | { echo "expected: $1" 55 | echo "actual: $2" 56 | } | flunk 57 | fi 58 | } 59 | 60 | assert_output() { 61 | local expected 62 | if [ $# -eq 0 ]; then expected="$(cat -)" 63 | else expected="$1" 64 | fi 65 | assert_equal "$expected" "$output" 66 | } 67 | 68 | assert_line() { 69 | if [ "$1" -ge 0 ] 2>/dev/null; then 70 | assert_equal "$2" "${lines[$1]}" 71 | else 72 | local line 73 | for line in "${lines[@]}"; do 74 | if [ "$line" = "$1" ]; then return 0; fi 75 | done 76 | flunk "expected line \`$1'" 77 | fi 78 | } 79 | 80 | refute_line() { 81 | if [ "$1" -ge 0 ] 2>/dev/null; then 82 | local num_lines="${#lines[@]}" 83 | if [ "$1" -lt "$num_lines" ]; then 84 | flunk "output has $num_lines lines" 85 | fi 86 | else 87 | local line 88 | for line in "${lines[@]}"; do 89 | if [ "$line" = "$1" ]; then 90 | flunk "expected to not find line \`$line'" 91 | fi 92 | done 93 | fi 94 | } 95 | 96 | assert() { 97 | if ! "$@"; then 98 | flunk "failed: $@" 99 | fi 100 | } 101 | 102 | # Output a modified PATH that ensures that the given executable is not present, 103 | # but in which system utils necessary for phpenv operation are still available. 104 | path_without() { 105 | local exe="$1" 106 | local path=":${PATH}:" 107 | local found alt util 108 | for found in $(type -aP "$exe"); do 109 | found="${found%/*}" 110 | if [ "$found" != "${PHPENV_ROOT}/shims" ]; then 111 | alt="${PHPENV_TEST_DIR}/$(echo "${found#/}" | tr '/' '-')" 112 | mkdir -p "$alt" 113 | for util in bash head cut readlink greadlink sed sort awk; do 114 | if [ -x "${found}/$util" ]; then 115 | ln -s "${found}/$util" "${alt}/$util" 116 | fi 117 | done 118 | path="${path/:${found}:/:${alt}:}" 119 | fi 120 | done 121 | path="${path#:}" 122 | echo "${path%:}" 123 | } 124 | 125 | create_hook() { 126 | mkdir -p "${PHPENV_HOOK_PATH}/$1" 127 | touch "${PHPENV_HOOK_PATH}/$1/$2" 128 | if [ ! -t 0 ]; then 129 | cat > "${PHPENV_HOOK_PATH}/$1/$2" 130 | fi 131 | } 132 | -------------------------------------------------------------------------------- /test/versions.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | 3 | load test_helper 4 | 5 | create_version() { 6 | mkdir -p "${PHPENV_ROOT}/versions/$1" 7 | } 8 | 9 | setup() { 10 | mkdir -p "$PHPENV_TEST_DIR" 11 | cd "$PHPENV_TEST_DIR" 12 | } 13 | 14 | stub_system_php() { 15 | local stub="${PHPENV_TEST_DIR}/bin/php" 16 | mkdir -p "$(dirname "$stub")" 17 | touch "$stub" && chmod +x "$stub" 18 | } 19 | 20 | @test "no versions installed" { 21 | stub_system_php 22 | assert [ ! -d "${PHPENV_ROOT}/versions" ] 23 | run phpenv-versions 24 | assert_success "* system" 25 | } 26 | 27 | @test "not even system php available" { 28 | PATH="$(path_without php)" run phpenv-versions 29 | assert_failure 30 | assert_output "Warning: no PHP detected on the system" 31 | } 32 | 33 | @test "bare output no versions installed" { 34 | assert [ ! -d "${PHPENV_ROOT}/versions" ] 35 | run phpenv-versions --bare 36 | assert_success "" 37 | } 38 | 39 | @test "single version installed" { 40 | stub_system_php 41 | create_version "8.4" 42 | run phpenv-versions 43 | assert_success 44 | assert_output < "${PHPENV_ROOT}/version" <<<"8.1.16" 104 | run phpenv-versions 105 | assert_success 106 | assert_output < ".php-version" <<<"8.1.16" 118 | run phpenv-versions 119 | assert_success 120 | assert_output < "${PHPENV_ROOT}/version" <<<"7.4.33" 120 | create_executable "7.4.33" "php" 121 | 122 | mkdir -p "$PHPENV_TEST_DIR" 123 | cd "$PHPENV_TEST_DIR" 124 | 125 | PHPENV_VERSION='' run phpenv-which php 126 | assert_success "${PHPENV_ROOT}/versions/7.4.33/bin/php" 127 | } 128 | -------------------------------------------------------------------------------- /libexec/phpenv-rehash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Summary: Rehash phpenv shims (run this after installing executables) 3 | 4 | set -e 5 | [ -n "$PHPENV_DEBUG" ] && set -x 6 | 7 | SHIM_PATH="${PHPENV_ROOT}/shims" 8 | PROTOTYPE_SHIM_PATH="${SHIM_PATH}/.phpenv-shim" 9 | 10 | # Create the shims directory if it doesn't already exist. 11 | mkdir -p "$SHIM_PATH" 12 | 13 | # Ensure only one instance of phpenv-rehash is running at a time by 14 | # setting the shell's `noclobber` option and attempting to write to 15 | # the prototype shim file. If the file already exists, print a warning 16 | # to stderr and exit with a non-zero status. 17 | set -o noclobber 18 | { echo > "$PROTOTYPE_SHIM_PATH" 19 | } 2>/dev/null || 20 | { echo "phpenv: cannot rehash: $PROTOTYPE_SHIM_PATH exists" 21 | exit 1 22 | } >&2 23 | set +o noclobber 24 | 25 | # If we were able to obtain a lock, register a trap to clean up the 26 | # prototype shim when the process exits. 27 | trap remove_prototype_shim EXIT 28 | 29 | remove_prototype_shim() { 30 | rm -f "$PROTOTYPE_SHIM_PATH" 31 | } 32 | 33 | # The prototype shim file is a script that re-execs itself, passing 34 | # its filename and any arguments to `phpenv exec`. This file is 35 | # hard-linked for every executable and then removed. The linking 36 | # technique is fast, uses less disk space than unique files, and also 37 | # serves as a locking mechanism. 38 | create_prototype_shim() { 39 | cat > "$PROTOTYPE_SHIM_PATH" </dev/null 2>&1; then 71 | for shim in *; do rm -f "$shim"; done 72 | fi 73 | break 74 | done 75 | } 76 | 77 | # The basename of each argument passed to `make_shims` will be 78 | # registered for installation as a shim. In this way, plugins may call 79 | # `make_shims` with a glob to register many shims at once. 80 | make_shims() { 81 | local shims="$@" 82 | 83 | for file in $shims; do 84 | local shim="${file##*/}" 85 | register_shim "$shim" 86 | done 87 | } 88 | 89 | # Create an empty array for the list of registered shims and an empty 90 | # string to use as a search index. 91 | registered_shims=() 92 | registered_shims_index="" 93 | 94 | # We will keep track of shims registered for installation with the 95 | # global `registered_shims` array and with a global search index 96 | # string. The array will let us iterate over all registered shims. The 97 | # index string will let us quickly check whether a shim with the given 98 | # name has been registered or not. 99 | register_shim() { 100 | local shim="$@" 101 | registered_shims["${#registered_shims[@]}"]="$shim" 102 | registered_shims_index="$registered_shims_index/$shim/" 103 | } 104 | 105 | # To install all the registered shims, we iterate over the 106 | # `registered_shims` array and create a link if one does not already 107 | # exist. 108 | install_registered_shims() { 109 | local shim 110 | for shim in "${registered_shims[@]}"; do 111 | [ -e "$shim" ] || ln -f "$PROTOTYPE_SHIM_PATH" "$shim" 112 | done 113 | } 114 | 115 | # Once the registered shims have been installed, we make a second pass 116 | # over the contents of the shims directory. Any file that is present 117 | # in the directory but has not been registered as a shim should be 118 | # removed. 119 | remove_stale_shims() { 120 | local shim 121 | for shim in *; do 122 | if [[ "$registered_shims_index" != *"/$shim/"* ]]; then 123 | rm -f "$shim" 124 | fi 125 | done 126 | } 127 | 128 | 129 | # Change to the shims directory. 130 | cd "$SHIM_PATH" 131 | shopt -s nullglob 132 | 133 | # Create the prototype shim, then register shims for all known 134 | # executables. 135 | create_prototype_shim 136 | remove_outdated_shims 137 | make_shims ../versions/*/*bin/* 138 | 139 | # Restore the previous working directory. 140 | cd "$OLDPWD" 141 | 142 | # Allow plugins to register shims. 143 | for script in $(phpenv-hooks rehash); do 144 | source "$script" 145 | done 146 | 147 | # Change back to the shims directory to install the registered shims 148 | # and remove stale shims. 149 | cd "$SHIM_PATH" 150 | install_registered_shims 151 | remove_stale_shims 152 | -------------------------------------------------------------------------------- /libexec/phpenv-help: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Summary: Display help for a command 4 | # 5 | # Usage: phpenv help [--usage] COMMAND 6 | # 7 | # Parses and displays help contents from a command's source file. 8 | # 9 | # A command is considered documented if it starts with a comment block 10 | # that has a `Summary:' or `Usage:' section. Usage instructions can 11 | # span multiple lines as long as subsequent lines are indented. 12 | # The remainder of the comment block is displayed as extended 13 | # documentation. 14 | 15 | set -e 16 | [ -n "$PHPENV_DEBUG" ] && set -x 17 | 18 | # Provide phpenv completions 19 | if [ "$1" = "--complete" ]; then 20 | echo --usage 21 | exec phpenv-commands 22 | fi 23 | 24 | command_path() { 25 | local command="$1" 26 | type -P phpenv-"$command" phpenv-sh-"$command" | head -n1 27 | } 28 | 29 | extract_initial_comment_block() { 30 | sed -ne " 31 | /^#/ !{ 32 | q 33 | } 34 | 35 | s/^#$/# / 36 | 37 | /^# / { 38 | s/^# // 39 | p 40 | } 41 | " 42 | } 43 | 44 | collect_documentation() { 45 | local awk 46 | awk="$(type -P gawk)" || awk="$(type -P awk)" || true 47 | if [ -z "$awk" ]; then 48 | echo "phpenv: cannot find awk" >&2 49 | return 1 50 | fi 51 | 52 | # shellcheck disable=SC2016 53 | "$awk" ' 54 | /^Summary:/ { 55 | summary = substr($0, 10) 56 | next 57 | } 58 | 59 | /^Usage:/ { 60 | reading_usage = 1 61 | usage = usage "\n" $0 62 | next 63 | } 64 | 65 | /^( *$| )/ && reading_usage { 66 | usage = usage "\n" $0 67 | next 68 | } 69 | 70 | { 71 | reading_usage = 0 72 | help = help "\n" $0 73 | } 74 | 75 | function escape(str) { 76 | gsub(/[`\\$"]/, "\\\\&", str) 77 | return str 78 | } 79 | 80 | function trim(str) { 81 | sub(/^\n*/, "", str) 82 | sub(/\n*$/, "", str) 83 | return str 84 | } 85 | 86 | END { 87 | if (usage || summary) { 88 | print "summary=\"" escape(summary) "\"" 89 | print "usage=\"" escape(trim(usage)) "\"" 90 | print "help=\"" escape(trim(help)) "\"" 91 | } 92 | } 93 | ' 94 | } 95 | 96 | documentation_for() { 97 | local filename 98 | filename="$(command_path "$1")" 99 | if [ -n "$filename" ]; then 100 | extract_initial_comment_block < "$filename" | collect_documentation 101 | fi 102 | } 103 | 104 | print_summary() { 105 | local command="$1" 106 | local summary usage help 107 | eval "$(documentation_for "$command")" 108 | 109 | if [ -n "$summary" ]; then 110 | printf " %-9s %s\n" "$command" "$summary" 111 | fi 112 | } 113 | 114 | print_summaries() { 115 | for command; do 116 | print_summary "$command" 117 | done 118 | } 119 | 120 | print_help() { 121 | local command="$1" 122 | local summary usage help 123 | eval "$(documentation_for "$command")" 124 | [ -n "$help" ] || help="$summary" 125 | 126 | if [ -n "$usage" ] || [ -n "$summary" ]; then 127 | if [ -n "$usage" ]; then 128 | echo "$usage" 129 | else 130 | echo "Usage: phpenv ${command}" 131 | fi 132 | if [ -n "$help" ]; then 133 | echo 134 | echo "$help" 135 | echo 136 | fi 137 | else 138 | echo "Sorry, this command isn't documented yet." >&2 139 | return 1 140 | fi 141 | } 142 | 143 | print_usage() { 144 | local command="$1" 145 | local summary usage help 146 | eval "$(documentation_for "$command")" 147 | if [ -n "$usage" ]; then 148 | echo "$usage" 149 | else 150 | echo "Usage: phpenv ${command}" 151 | fi 152 | } 153 | 154 | if [ "$1" = "--complete-commands" ]; then 155 | command_prefix="${2:-}" 156 | seen=() 157 | shopt -s nullglob 158 | PATH_remain="$PATH" 159 | # traverse PATH to find "phpenv-" prefixed commands 160 | while true; do 161 | path="${PATH_remain%%:*}" 162 | if [ -n "$path" ]; then 163 | for phpenv_command in "${path}/phpenv-"*; do 164 | command_name="${phpenv_command##*/}" 165 | command_name="${command_name#phpenv-}" 166 | command_name="${command_name#sh-}" 167 | [[ $command_name == "${command_prefix}"* ]] || continue 168 | [[ " ${seen[*]} " != *" ${command_name} "* ]] || continue 169 | seen+=("$command_name") 170 | summary="" 171 | eval "$(extract_initial_comment_block < "$phpenv_command" | collect_documentation)" 172 | [ -n "$summary" ] || continue 173 | printf "%s:%s\n" "$command_name" "$summary" 174 | done 175 | fi 176 | [[ $PATH_remain == *:* ]] || break 177 | PATH_remain="${PATH_remain#*:}" 178 | done 179 | exit 0 180 | fi 181 | 182 | unset usage 183 | if [ "$1" = "--usage" ]; then 184 | usage="1" 185 | shift 186 | fi 187 | 188 | if [ -z "$1" ] || [ "$1" == "phpenv" ]; then 189 | echo "Usage: phpenv [...]" 190 | [ -n "$usage" ] && exit 191 | echo 192 | echo "Commands to manage available PHP versions:" 193 | print_summaries versions install uninstall rehash 194 | echo 195 | echo "Commands to view or change the current PHP version:" 196 | print_summaries version local global shell 197 | echo 198 | echo "See \`phpenv help ' for information on a specific command." 199 | echo "For full documentation, see: https://github.com/phpenv/phpenv#readme" 200 | else 201 | command="$1" 202 | if [ -n "$(command_path "$command")" ]; then 203 | if [ -n "$usage" ]; then 204 | print_usage "$command" 205 | else 206 | print_help "$command" 207 | fi 208 | else 209 | echo "phpenv: no such command \`$command'" >&2 210 | exit 1 211 | fi 212 | fi 213 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## phpenv - PHP multi-version installation and management for humans. 2 | 3 | ### Key features: 4 | 5 | My name is phpenv. I was designed for humans, to help simplify the management 6 | of multiple PHP custom build installations. 7 | 8 | I was originally inspired by the outstanding work of 9 | [rbenv][rbenv-url] and [ruby-build][ruby-build-url] 10 | with a whole bunch of PHP centric additions 11 | to help you build your first release, simplify managing and working 12 | with diffirent releases and keep you building new release after new 13 | release like there's nothing to it. 14 | 15 | You are a PHP developer, like we are, and you not only have to have the 16 | latest and freshest interpreter to spin your scripts but you also care to 17 | see what how they get treated when submitted to older interpretations. 18 | Ever wondered why you can't run a PHP app on your own development machine? Well 19 | you just found the answer doing when taken for a ride building PHP 20 | on their dev machines. Easily customize your configuration options and even 21 | build pecl extensions into PHP or manually afterwards. Configure and install 22 | custom builds of the same PHP release version directly from the PHP source 23 | code repository kept in your local `.phpenv` folder. 24 | 25 | ## How It Works 26 | 27 | After phpenv injects itself into your PATH at installation time, any invocation 28 | of `php`, `php-fpm`, or other PHP-related executable will first activate phpenv. 29 | Then, phpenv scans the current project directory for a file named `.php-version`. 30 | If found, that file determines the version of PHP that should be used within that 31 | directory. phpenv then looks up that PHP version among those installed under 32 | `~/.phpenv/versions/`. 33 | 34 | phpenv expects each version to be a directory resulting from a PHP installation. 35 | This means each directory has its own binaries, libraries, config files, man pages. 36 | For example, each version has its own `php`, `php-fpm`, `pecl`, `pyrus`, `php.ini`. 37 | phpenv detects which version to run for your project then calls the appropriate file. 38 | 39 | You can choose the PHP version for your project with, for example: 40 | 41 | ```sh 42 | cd Projects/my-php-project 43 | # choose PHP 8.3.13 44 | phpenv local 8.3.13 45 | ``` 46 | 47 | Doing so will update the `.php-version` file in the current directory with the 48 | version that you've chosen. A different project of yours that is another directory 49 | might be using a different version of PHP altogether - phpenv will seamlessly 50 | transition from one PHP version to another when you cd into the project directory. 51 | 52 | Finally, almost every aspect of phpenv's mechanism is customizable via plugins 53 | written in bash. 54 | 55 | ## Installation 56 | 57 | ### Basic GitHub Checkout 58 | For a more automated install, you can use [phpenv-installer][phpenv-installer-url]. 59 | If you prefer a manual approach, follow the steps below. 60 | 61 | This will get you going with the latest version of phpenv and make it 62 | easy to fork and contribute any changes back upstream. 63 | 64 | 1. Check out phpenv into `~/.phpenv`. 65 | 66 | ```sh 67 | git clone https://github.com/phpenv/phpenv.git ~/.phpenv 68 | ``` 69 | 70 | 2. Add `~/.phpenv/bin` to your `$PATH` for access to the `phpenv` 71 | command-line utility. 72 | 73 | The `$PATH` variable is typically set in your shell initialization file. 74 | Common examples: 75 | - if you are using bash, check if `~/.bash_profile` exists. 76 | - if you are using another shell, check your specific shell configuration. 77 | - if the above do not exist, shells will typically default to `~/.profile` 78 | 79 | Assuming that your shell initialization is in `~/.profile`, then 80 | 81 | ```sh 82 | echo 'export PATH="$HOME/.phpenv/bin:$PATH"' >> ~/.profile 83 | ``` 84 | 85 | 3. Add phpenv init to your shell to enable shims and autocompletion. 86 | 87 | ```sh 88 | echo 'eval "$(phpenv init -)"' >> ~/.profile 89 | ``` 90 | 91 | 4. Restart your shell so the path changes take effect. You can now 92 | begin using phpenv. 93 | 94 | ```sh 95 | exec $SHELL -l 96 | ``` 97 | 98 | 5. (Optional) Install php-build into it and any php. (See [php-build][php-build-url] home) 99 | 100 | ```sh 101 | git clone https://github.com/php-build/php-build $(phpenv root)/plugins/php-build 102 | phpenv install 103 | ``` 104 | 105 | 6. (Optional) Rebuild the shim binaries. You should do this any time you install 106 | a new PHP binary. 107 | 108 | ```sh 109 | phpenv rehash 110 | ``` 111 | 112 | ### Upgrading 113 | 114 | If you've installed phpenv using the instructions above, you can 115 | upgrade your installation at any time using git. 116 | 117 | To upgrade to the latest development version of phpenv, use `git pull`: 118 | 119 | ```sh 120 | cd ~/.phpenv && git pull 121 | ``` 122 | 123 | ### php-build configuration 124 | By default, php-build will compile PHP with a default set of options specified by: 125 | - php-build [default configure options][php-build-default-configure-opts-url] 126 | - per-version configure options in the PHP build definition. For example, in [7.4.13](https://github.com/php-build/php-build/blob/master/share/php-build/definitions/7.4.13) 127 | - configure options specified in environment variables. See [the man page](https://github.com/php-build/php-build/blob/master/man/php-build.1.ronn) for details. 128 | 129 | Typically, if you need to specify how PHP is built on your system, you can add configure options in the `PHP_BUILD_CONFIGURE_OPTS` variable, and add PHP extensions in the `PHP_BUILD_INSTALL_EXTENSION` variable. 130 | 131 | ### Webserver Setup 132 | #### PHP-FPM 133 | The preferred way of connecting phpenv applications is by using php-fpm after building php. Your webserver can then be configured to connect to the php-fpm instance. In this approach, php will run as the permissions of the invoking user, which is not necessarily as the web server. 134 | 135 | php-fpm can be started in one of the following ways: 136 | - using an init script: by running `~/.phpenv/versions/$VERSION/etc/init.d/php-fpm` 137 | - using systemd: by installing `~/.phpenv/versions/$VERSION/etc/systemd/system/php-fpm.service` 138 | - using an init script: by writing your own custom init script 139 | - using systemd: by writing your own custom systemd unit 140 | - manually: by running `php-fpm (8)` and supplying command-line arguments 141 | 142 | By default, php-fpm comes with a configuration file under `~/.phpenv/versions/$VERSION/etc/php-fpm.conf`, which it will look for when run. This configures php-fpm to listen on `localhost:9000` when started. You may edit or replace this file, or supply a different configuration file using the `--fpm-config` (`-y`) command line argument. 143 | 144 | Instructions for connecting different webservers to php-fpm: 145 | - for Apache, see the [apache wiki article][apache-wiki-phpfpm] 146 | - for NGINX, see the [nginx wiki article][nginx-wiki-phpfpm] 147 | 148 | #### Apache SAPI 149 | Alternatively, you may still use the Apache php module by configuring [php-build][php-build-url] to build the libphp.so apache extension (directions to follow). libphp.so can then be found by apache under the `~/.phpenv/versions/$VERSION/libexec` folder. This file can be used for Apache's `LoadModule php5_module` directive and requires Apache to restart when changed. 150 | 151 | ### Neckbeard Configuration 152 | 153 | Skip this section unless you must know what every line in your shell 154 | profile is doing. 155 | 156 | `phpenv init` is the only command that crosses the line of loading 157 | extra commands into your shell. Here's what `phpenv init` actually does: 158 | 159 | 1. Sets up your shims path. This is the only requirement for phpenv to 160 | function properly. You could also do this by hand by prepending 161 | `~/.phpenv/shims` to your `$PATH`. 162 | 163 | 2. Installs autocompletion. This is entirely optional but pretty 164 | useful. Sourcing `~/.phpenv/completions/phpenv.bash` will set that 165 | up. There is also a `~/.phpenv/completions/phpenv.zsh` for Zsh 166 | users. 167 | 168 | 3. Rehashes shims. From time to time you'll need to rebuild your 169 | shim files. Doing this on init makes sure everything is up to 170 | date. You can always run `phpenv rehash` manually. 171 | 172 | 4. Installs the sh dispatcher. This bit is also optional, but allows 173 | phpenv and plugins to change variables in your current shell, making 174 | commands like `phpenv shell` possible. The sh dispatcher doesn't do 175 | anything crazy like override `cd` or hack your shell prompt, but if 176 | for some reason you need `phpenv` to be a real script rather than a 177 | shell function, you can safely skip it. 178 | 179 | Run `phpenv init -` for yourself to see exactly what happens under the 180 | hood. 181 | 182 | ## Usage 183 | 184 | Like `git`, the `phpenv` command delegates to subcommands based on its 185 | first argument. The most common subcommands are: 186 | 187 | ### phpenv help 188 | 189 | Show the usage and useful help. When you are in trouble, do this ;) 190 | 191 | ```sh 192 | phpenv help 193 | phpenv help 194 | ``` 195 | 196 | ### phpenv install 197 | 198 | [php-build][php-build-url] is a phpenv-compatible plugin that builds and installs php. To be able to use phpenv install, download and install the php-build plugin as described in step 5. of the install instructions above. 199 | 200 | Before running phpenv install, make sure the development versions needed to build php are installed in your system. In particular, if you want to build the apache extension, make sure that apache2-dev (or your OS's equivalent) is installed. 201 | 202 | ### phpenv global 203 | 204 | Sets the global version of PHP to be used in all shells by writing 205 | the version name to the `~/.phpenv/version` file. This version can be 206 | overridden by a per-project `.phpenv-version` file, or by setting the 207 | `PHPENV_VERSION` environment variable. 208 | 209 | ```sh 210 | phpenv global 5.4.0 211 | ``` 212 | 213 | The special version name `system` tells phpenv to use the system PHP 214 | (detected by searching your `$PATH`). 215 | 216 | When run without a version number, `phpenv global` reports the 217 | currently configured global version. 218 | 219 | ### phpenv local 220 | 221 | Sets a local per-project PHP version by writing the version name to 222 | a `.phpenv-version` file in the current directory. This version 223 | overrides the global, and can be overridden itself by setting the 224 | `PHPENV_VERSION` environment variable or with the `phpenv shell` 225 | command. 226 | 227 | ```sh 228 | phpenv local 5.3.8 229 | ``` 230 | 231 | When run without a version number, `phpenv local` reports the currently 232 | configured local version. You can also unset the local version: 233 | 234 | ```sh 235 | phpenv local --unset 236 | ``` 237 | 238 | ### phpenv shell 239 | 240 | Sets a shell-specific PHP version by setting the `PHPENV_VERSION` 241 | environment variable in your shell. This version overrides both 242 | project-specific versions and the global version. 243 | 244 | ```sh 245 | phpenv shell 5.3.9 246 | ``` 247 | 248 | When run without a version number, `phpenv shell` reports the current 249 | value of `PHPENV_VERSION`. You can also unset the shell version: 250 | 251 | ```sh 252 | phpenv shell --unset 253 | ``` 254 | 255 | Note that you'll need phpenv's shell integration enabled (step 3 of 256 | the installation instructions) in order to use this command. If you 257 | prefer not to use shell integration, you may simply set the 258 | `PHPENV_VERSION` variable yourself: 259 | 260 | ```sh 261 | export PHPENV_VERSION=5.3.13 262 | ``` 263 | 264 | ### phpenv versions 265 | 266 | Lists all PHP versions known to phpenv, and shows an asterisk next to 267 | the currently active version. 268 | 269 | ```sh 270 | $ phpenv versions 271 | 5.2.8 272 | 5.3.13 273 | * 5.4.0 (set by /YOUR-USERNAME/.phpenv/global) 274 | ``` 275 | 276 | ### phpenv version 277 | 278 | Displays the currently active PHP version, along with information on 279 | how it was set. 280 | 281 | ```sh 282 | $ phpenv version 283 | 5.4.0 (set by /YOUR-USERNAME/.phpenv/version) 284 | ``` 285 | 286 | ### phpenv rehash 287 | 288 | Installs shims for all PHP binaries known to phpenv (i.e., 289 | `~/.phpenv/versions/*/bin/*`). Run this command after you install a new 290 | version of PHP. 291 | 292 | ```sh 293 | phpenv rehash 294 | ``` 295 | 296 | ### phpenv which 297 | 298 | Displays the full path to the binary that phpenv will execute when you 299 | run the given command. 300 | 301 | ```sh 302 | $ phpenv which pyrus 303 | /YOUR-USERNAME/.phpenv/versions/5.4.0/bin/pyrus 304 | ``` 305 | 306 | ## Environment variables 307 | 308 | You can affect how phpenv operates with the following settings: 309 | 310 | name | default | description 311 | -----|---------|------------ 312 | `PHPENV_VERSION`| | Specifies the PHP version to be used.
Also see [`phpenv shell`](#phpenv-shell) 313 | `PHPENV_ROOT` | `~/.phpenv` | Defines the directory under which PHP versions and shims reside.
Also see [`phpenv root`](#phpenv-root) 314 | `PHPENV_DEBUG` | | Outputs debug information.
Also as `phpenv --debug ` 315 | `PHPENV_HOOK_PATH` | | Colon-separated list of paths searched for phpenv hooks. 316 | `PHPENV_DIR` | `$PWD` | Directory to start searching for `.php-version` files. 317 | 318 | ### Uninstalling phpenv 319 | 320 | The simplicity of phpenv makes it easy to temporarily disable it, or uninstall from the system. 321 | 322 | 1. To **disable** phpenv managing your PHP versions, simply comment or remove the `phpenv init` line from your shell startup configuration. This will remove phpenv shims directory from PATH, and future invocations like `php` will execute the system PHP version, bypassing phpenv completely. 323 | 324 | While disabled, `phpenv` will still be accessible on the command line, but your PHP projects won't be affected by version switching. 325 | 326 | 2. To completely **uninstall** phpenv, perform step (1) and then remove the phpenv root directory. This will **delete all PHP versions** that were installd under `` `phpenv root`/versions/ `. 327 | 328 | ## Development 329 | 330 | The phpenv source code is [hosted on GitHub][phpenv-url]. It's clean, modular, 331 | and easy to understand (thanks to the rbenv project), even if you're not a 332 | shell hacker. 333 | 334 | Tests are executed using [Bats][bats-url] 335 | 336 | ```sh 337 | bats test 338 | bats test/.bats 339 | ``` 340 | 341 | This project is basically a clone (Read: "search and replace") of the rbenv 342 | project. It's in need of love and support. If you're interested in improving it 343 | please feel free to fork, submit [pull requests][phpenv-prs] and file bugs on the [issue 344 | tracker][phpenv-issues]. 345 | 346 | 347 | ### License 348 | 349 | (The MIT license) 350 | 351 | Copyright (c) 2012 Dominic Giglio\ 352 | Copyright (c) 2013 Nick Lombard\ 353 | Copyright (c) 2015 madumlao 354 | 355 | Permission is hereby granted, free of charge, to any person obtaining 356 | a copy of this software and associated documentation files (the 357 | "Software"), to deal in the Software without restriction, including 358 | without limitation the rights to use, copy, modify, merge, publish, 359 | distribute, sublicense, and/or sell copies of the Software, and to 360 | permit persons to whom the Software is furnished to do so, subject to 361 | the following conditions: 362 | 363 | The above copyright notice and this permission notice shall be 364 | included in all copies or substantial portions of the Software. 365 | 366 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 367 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 368 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 369 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 370 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 371 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 372 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 373 | 374 | [original-url]: https://github.com/phpenv/phpenv 375 | [php-build-url]: https://github.com/php-build/php-build 376 | [php-build-default-configure-opts-url]: https://github.com/php-build/php-build/blob/master/share/php-build/default_configure_options 377 | [phpenv-url]: https://github.com/phpenv/phpenv 378 | [phpenv-issues]: https://github.com/phpenv/phpenv/issues 379 | [phpenv-installer-url]: https://github.com/phpenv/phpenv-installer 380 | [phpenv-prs]: https://github.com/phpenv/phpenv/pulls 381 | [rbenv-url]: https://github.com/rbenv/rbenv 382 | [ruby-build-url]: https://github.com/rbenv/ruby-build 383 | [apache-wiki-phpfpm]: https://wiki.apache.org/httpd/PHP-FPM 384 | [nginx-wiki-phpfpm]: https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/ 385 | [bats-url]: https://github.com/bats-core/bats-core 386 | --------------------------------------------------------------------------------