From fc3300abae8143740581481e9620e6b8a14d67e3 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Wed, 19 Aug 2026 18:22:58 +0100 Subject: [PATCH 1/4] fix: Warn when another flagsmith binary on PATH may shadow the install --- install.ps1 | 20 +++++++++++++++++++- install.sh | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/install.ps1 b/install.ps1 index 42b5f47..ef6d8ca 100644 --- a/install.ps1 +++ b/install.ps1 @@ -84,6 +84,22 @@ function Add-UserPath { return $true } +# Write-Conflicts reports other flagsmith commands on PATH that may shadow +# (or be shadowed by) the one just installed. +function Write-Conflicts { + param([string]$Target) + + $resolvedTarget = [System.IO.Path]::GetFullPath($Target) + $others = @(Get-Command -Name 'flagsmith' -All -ErrorAction SilentlyContinue | + Where-Object { $_.Source -and ([System.IO.Path]::GetFullPath($_.Source) -ne $resolvedTarget) }) + foreach ($other in $others) { + Write-Output "warning: another 'flagsmith' is on your PATH at $($other.Source)" + } + if ($others.Count -gt 0) { + Write-Output "It may shadow $Target - uninstall it first ('npm uninstall -g flagsmith-cli' removes the old npm CLI), then open a new terminal." + } +} + # Add-CiPath makes the CLI available to later steps of a GitHub Actions job. function Add-CiPath { param([string]$Dir) @@ -144,6 +160,7 @@ try { Expand-Archive -LiteralPath $zip -DestinationPath $tmp -Force New-Item -ItemType Directory -Force -Path $BinDir | Out-Null + $verb, $prep = if (Test-Path -LiteralPath (Join-Path $BinDir $ExeName)) { 'updated', 'at' } else { 'installed', 'to' } Move-Item -Force -LiteralPath (Join-Path $tmp $ExeName) -Destination (Join-Path $BinDir $ExeName) } finally { Remove-Item -Recurse -Force -LiteralPath $tmp @@ -152,7 +169,8 @@ try { $exe = Join-Path $BinDir $ExeName $installed = & $exe --version if ($LASTEXITCODE -ne 0) { throw "$exe was installed but will not run" } -Write-Output "installed $installed to $exe" +Write-Output "$verb $installed $prep $exe" +Write-Conflicts -Target $exe $pathAdded = $false if (-not $NoModifyPath) { diff --git a/install.sh b/install.sh index c07bf46..d49cdcc 100644 --- a/install.sh +++ b/install.sh @@ -166,6 +166,36 @@ end EOF } +# same_file returns 0 when both paths name the same file. -ef is not POSIX +# but every common sh has it; fall back to a plain string compare. +same_file() { + [ "$1" = "$2" ] && return 0 + [ "$1" -ef "$2" ] 2>/dev/null +} + +# warn_conflicts reports other flagsmith binaries on PATH that may shadow +# (or be shadowed by) the one just installed. +warn_conflicts() { + _target="${INSTALL_DIR}/${BIN_NAME}" + _found=0 + _seen= + _ifs_save=$IFS + IFS=: + for _dir in $PATH; do + [ -n "$_dir" ] || continue + case ":${_seen}:" in *:"${_dir}":*) continue ;; esac + _seen="${_seen}:${_dir}" + [ -x "${_dir}/${BIN_NAME}" ] || continue + same_file "${_dir}/${BIN_NAME}" "$_target" && continue + say "warning: another '${BIN_NAME}' is on your PATH at ${_dir}/${BIN_NAME}" + _found=1 + done + IFS=$_ifs_save + if [ "$_found" = 1 ]; then + say "It may shadow ${_target} — uninstall it first ('npm uninstall -g flagsmith-cli' removes the old npm CLI), then run 'hash -r' or open a new shell." + fi +} + # add_ci_path makes the CLI available to later steps of a GitHub Actions job. # GITHUB_PATH does not expand variables, so write the resolved directory. add_ci_path() { @@ -248,11 +278,18 @@ If ${VERSION} was released moments ago its archives may still be uploading — r tar -xzf "${tmp}/${archive_name}" -C "$tmp" "$BIN_NAME" mkdir -p "$INSTALL_DIR" chmod 755 "${tmp}/${BIN_NAME}" + verb=installed + preposition=to + if [ -e "${INSTALL_DIR}/${BIN_NAME}" ]; then + verb=updated + preposition=at + fi mv -f "${tmp}/${BIN_NAME}" "${INSTALL_DIR}/${BIN_NAME}" installed=$("${INSTALL_DIR}/${BIN_NAME}" --version 2>/dev/null) || err "${INSTALL_DIR}/${BIN_NAME} was installed but will not run — wrong platform?" - say "installed ${installed} to ${INSTALL_DIR}/${BIN_NAME}" + say "${verb} ${installed} ${preposition} ${INSTALL_DIR}/${BIN_NAME}" + warn_conflicts if [ "$NO_MODIFY_PATH" != 1 ]; then modify_path From 3a76bb165f43ad74a0412a586aefa3215b2a11c5 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Wed, 19 Aug 2026 18:29:22 +0100 Subject: [PATCH 2/4] fix: Quote 'at' assignment to satisfy shellcheck SC2209 --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index d49cdcc..f2b26c8 100644 --- a/install.sh +++ b/install.sh @@ -282,7 +282,7 @@ If ${VERSION} was released moments ago its archives may still be uploading — r preposition=to if [ -e "${INSTALL_DIR}/${BIN_NAME}" ]; then verb=updated - preposition=at + preposition='at' fi mv -f "${tmp}/${BIN_NAME}" "${INSTALL_DIR}/${BIN_NAME}" From 3a4bc7c7bae2a31c5ab823f8665ba216b055f298 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Wed, 19 Aug 2026 18:30:49 +0100 Subject: [PATCH 3/4] fix: Rename Write-Conflicts to Write-ConflictWarning for PSUseSingularNouns --- install.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install.ps1 b/install.ps1 index ef6d8ca..9c26370 100644 --- a/install.ps1 +++ b/install.ps1 @@ -84,9 +84,9 @@ function Add-UserPath { return $true } -# Write-Conflicts reports other flagsmith commands on PATH that may shadow +# Write-ConflictWarning reports other flagsmith commands on PATH that may shadow # (or be shadowed by) the one just installed. -function Write-Conflicts { +function Write-ConflictWarning { param([string]$Target) $resolvedTarget = [System.IO.Path]::GetFullPath($Target) @@ -170,7 +170,7 @@ $exe = Join-Path $BinDir $ExeName $installed = & $exe --version if ($LASTEXITCODE -ne 0) { throw "$exe was installed but will not run" } Write-Output "$verb $installed $prep $exe" -Write-Conflicts -Target $exe +Write-ConflictWarning -Target $exe $pathAdded = $false if (-not $NoModifyPath) { From 1a183d8c953e481708f467423ee54977b9c6ac47 Mon Sep 17 00:00:00 2001 From: Kim Gustyr Date: Wed, 19 Aug 2026 18:33:49 +0100 Subject: [PATCH 4/4] fix: Restrict conflict discovery to application and script commands --- install.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/install.ps1 b/install.ps1 index 9c26370..6a45b6f 100644 --- a/install.ps1 +++ b/install.ps1 @@ -90,10 +90,13 @@ function Write-ConflictWarning { param([string]$Target) $resolvedTarget = [System.IO.Path]::GetFullPath($Target) - $others = @(Get-Command -Name 'flagsmith' -All -ErrorAction SilentlyContinue | - Where-Object { $_.Source -and ([System.IO.Path]::GetFullPath($_.Source) -ne $resolvedTarget) }) + # Application catches flagsmith.exe and npm's flagsmith.cmd shim; + # ExternalScript catches its flagsmith.ps1 shim. Both expose .Path, and + # neither triggers module auto-loading the way an unfiltered -All can. + $others = @(Get-Command -Name 'flagsmith' -CommandType Application, ExternalScript -All -ErrorAction SilentlyContinue | + Where-Object { $_.Path -and ([System.IO.Path]::GetFullPath($_.Path) -ne $resolvedTarget) }) foreach ($other in $others) { - Write-Output "warning: another 'flagsmith' is on your PATH at $($other.Source)" + Write-Output "warning: another 'flagsmith' is on your PATH at $($other.Path)" } if ($others.Count -gt 0) { Write-Output "It may shadow $Target - uninstall it first ('npm uninstall -g flagsmith-cli' removes the old npm CLI), then open a new terminal."