diff --git a/README.md b/README.md index 0ab5bb6..a6e0473 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Download the archive for your platform from [GitHub Releases](https://github.com | Variable | Description | Default | |----------|-------------|---------| | `FLASHDUTY_VERSION` | Install a specific version (e.g. `v1.5.12`) | latest | -| `FLASHDUTY_INSTALL_DIR` | Install directory | `/usr/local/bin` (shell), `~\.flashduty\bin` (PowerShell) | +| `FLASHDUTY_INSTALL_DIR` | Install directory | shell: the directory of the `flashduty` already on `PATH`, else `/usr/local/bin`; PowerShell: `~\.flashduty\bin` | | `MIRROR_URL` | Release asset mirror (must be `https://`) | `https://static.flashcat.cloud/flashduty-cli` | ## Quick start diff --git a/README_zh.md b/README_zh.md index 40e7359..7e7afb1 100644 --- a/README_zh.md +++ b/README_zh.md @@ -41,7 +41,7 @@ irm https://static.flashcat.cloud/flashduty-cli/install.ps1 | iex | 变量 | 说明 | 默认值 | |------|------|--------| | `FLASHDUTY_VERSION` | 安装指定版本(如 `v1.5.12`) | 最新版 | -| `FLASHDUTY_INSTALL_DIR` | 安装目录 | `/usr/local/bin`(shell),`~\.flashduty\bin`(PowerShell) | +| `FLASHDUTY_INSTALL_DIR` | 安装目录 | shell:`PATH` 上已有 `flashduty` 所在目录,没有则 `/usr/local/bin`;PowerShell:`~\.flashduty\bin` | | `MIRROR_URL` | 下载镜像地址(必须是 `https://`) | `https://static.flashcat.cloud/flashduty-cli` | ## 快速上手 diff --git a/install.sh b/install.sh index ee7527e..5d2e0ed 100755 --- a/install.sh +++ b/install.sh @@ -4,7 +4,8 @@ # # Environment: # FLASHDUTY_VERSION Install a specific version (e.g. v0.1.2). Default: latest. -# FLASHDUTY_INSTALL_DIR Install directory. Default: /usr/local/bin. +# FLASHDUTY_INSTALL_DIR Install directory. Default: the directory of the +# flashduty already on PATH, else /usr/local/bin. # INSTALLED_NAME Installed command name. Default: flashduty. # MIRROR_URL Fetch release assets from this https mirror prefix. # Default: https://static.flashcat.cloud/flashduty-cli. @@ -18,7 +19,15 @@ set -e REPO="flashcatcloud/flashduty-cli" BINARY="flashduty-cli" INSTALLED_NAME="${INSTALLED_NAME:-flashduty}" -INSTALL_DIR="${FLASHDUTY_INSTALL_DIR:-/usr/local/bin}" +# Default to the directory of the copy the shell already runs, so an upgrade +# replaces it instead of landing behind it on PATH. Fresh installs use +# /usr/local/bin. +existing=$(command -v "${INSTALLED_NAME}" 2>/dev/null || true) +case "${existing}" in + /*) default_dir=$(dirname -- "${existing}") ;; + *) default_dir="/usr/local/bin" ;; +esac +INSTALL_DIR="${FLASHDUTY_INSTALL_DIR:-${default_dir}}" # By default release downloads are fetched from the Flashcat CDN. Set MIRROR_URL # to another prefix to override, or to an empty string to force GitHub fallback. @@ -230,6 +239,12 @@ EOF # --- main --- main() { + # flashduty-runner stages its own bundled copy; replacing it would desync the + # runner from the CLI it was built and verified against. + if [ "${FLASHDUTY_MANAGED_BY_RUNNER:-}" = "1" ]; then + fail "flashduty is managed by flashduty-runner; upgrade the runner instead" + fi + need_cmd uname need_cmd tar need_cmd curl @@ -316,12 +331,15 @@ main() { info "Installed to ${INSTALL_DIR}/${INSTALLED_NAME}" - # Warn if install dir is not in PATH - case ":${PATH}:" in - *":${INSTALL_DIR}:"*) ;; - *) info "WARNING: ${INSTALL_DIR} is not in your PATH. Add it with:" - info " export PATH=\"${INSTALL_DIR}:\$PATH\"" ;; - esac + # Warn unless the shell now runs the binary just installed. + active=$(command -v "${INSTALLED_NAME}" 2>/dev/null || true) + if [ -z "${active}" ]; then + info "WARNING: ${INSTALL_DIR} is not in your PATH. Add it with:" + info " export PATH=\"${INSTALL_DIR}:\$PATH\"" + elif [ "$(dirname -- "${active}")" != "${INSTALL_DIR%/}" ]; then + info "WARNING: your shell runs ${active}, not this install." + info " Remove that copy, or put ${INSTALL_DIR} ahead of it on PATH." + fi # Best-effort shell completion; never fail the install over it. BIN="${INSTALL_DIR}/${INSTALLED_NAME}" diff --git a/tests/install_sh_sudo_test.sh b/tests/install_sh_sudo_test.sh index b1a0428..8710ceb 100644 --- a/tests/install_sh_sudo_test.sh +++ b/tests/install_sh_sudo_test.sh @@ -93,7 +93,7 @@ run_install() { home_dir="$1" install_dir="$2" out_file="$3" - env PATH="${FAKE_BIN}:$PATH" \ + env PATH="${FAKE_BIN}:${EXTRA_PATH:+${EXTRA_PATH}:}$PATH" \ HOME="${home_dir}" \ SHELL=/bin/false \ FLASHDUTY_VERSION=v9.9.9 \ @@ -186,7 +186,76 @@ test_tty_prompts_for_interactive_sudo() { assert_file_missing "${home_dir}/.local/bin/flashduty" } +# A stale copy earlier on PATH: with no FLASHDUTY_INSTALL_DIR the upgrade must +# replace it in place rather than install a shadowed copy elsewhere. +make_existing_copy() { + mkdir -p "$1" + printf '#!/bin/sh\necho "old flashduty"\n' > "$1/flashduty" + chmod +x "$1/flashduty" +} + +test_replaces_copy_already_on_path() { + SUDO_LOG="${TMP_DIR}/sudo-existing.log" + export SUDO_LOG + : > "${SUDO_LOG}" + home_dir="${TMP_DIR}/home-existing" + existing_dir="${TMP_DIR}/existing-bin" + out_file="${TMP_DIR}/existing.out" + mkdir -p "${home_dir}" + make_existing_copy "${existing_dir}" + + # Trailing slash: dash's `command -v` then reports "