Skip to content

Commit a28e911

Browse files
authored
Merge pull request #20 from devicecloud-dev/installer-conflict-detection
installers: detect shadowing dcd and auto-persist PATH on Unix
2 parents 17cf348 + 2e9b9a3 commit a28e911

2 files changed

Lines changed: 91 additions & 13 deletions

File tree

install.ps1

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,21 @@ if (-not $alreadyOnPath) {
9191
Write-Host "Installed: $(& "$InstallDir\dcd.exe" --version)"
9292
Write-Host ' Try: dcd --help'
9393
}
94+
95+
# --- warn about a conflicting (shadowing) install ---
96+
# A leftover `npm install -g @devicecloud.dev/dcd` resolves earlier on PATH than
97+
# the appended install dir, so it would keep shadowing this binary. Get-Command
98+
# reads the current session PATH (which doesn't include the registry change we
99+
# just made), so any hit here is a different, pre-existing dcd.
100+
$target = Join-Path $InstallDir 'dcd.exe'
101+
$existing = Get-Command dcd -All -ErrorAction SilentlyContinue |
102+
Where-Object { $_.Source -and ($_.Source -ine $target) } |
103+
Select-Object -First 1
104+
if ($existing) {
105+
Write-Host ''
106+
Write-Host '! Another dcd is already on your PATH:'
107+
Write-Host " $($existing.Source)"
108+
Write-Host " This is usually a previous 'npm install -g @devicecloud.dev/dcd', which"
109+
Write-Host ' can shadow this binary depending on PATH order. Remove it with:'
110+
Write-Host ' npm uninstall -g @devicecloud.dev/dcd'
111+
}

install.sh

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,42 @@ info() {
2323
printf '%s\n' "$1"
2424
}
2525

26+
# Find a dcd on PATH other than the one we just installed — usually a leftover
27+
# `npm install -g @devicecloud.dev/dcd` that can shadow this binary. Runs in a
28+
# subshell so the temporary IFS change never leaks back to the caller.
29+
find_conflicting_dcd() {
30+
(
31+
IFS=:
32+
for dir in $PATH; do
33+
[ -n "$dir" ] || continue
34+
if [ "$dir" != "$INSTALL_DIR" ] && [ -x "$dir/dcd" ]; then
35+
printf '%s\n' "$dir/dcd"
36+
exit 0
37+
fi
38+
done
39+
exit 1
40+
)
41+
}
42+
43+
# Pick the shell rc file to persist PATH into, based on the login shell.
44+
rc_file() {
45+
case "${SHELL:-}" in
46+
*zsh)
47+
printf '%s\n' "${ZDOTDIR:-$HOME}/.zshrc"
48+
;;
49+
*bash)
50+
if [ -f "$HOME/.bashrc" ]; then
51+
printf '%s\n' "$HOME/.bashrc"
52+
else
53+
printf '%s\n' "$HOME/.bash_profile"
54+
fi
55+
;;
56+
*)
57+
printf '%s\n' "$HOME/.profile"
58+
;;
59+
esac
60+
}
61+
2662
main() {
2763
DOWNLOAD_BASE="${DCD_DOWNLOAD_BASE:-https://get.devicecloud.dev}"
2864
INSTALL_DIR="${DCD_INSTALL_DIR:-$HOME/.dcd/bin}"
@@ -95,24 +131,48 @@ main() {
95131
mv "$tmp" "$INSTALL_DIR/dcd"
96132
trap - EXIT # tmp has been moved; nothing to clean up
97133

98-
# --- PATH hint ---
134+
# --- PATH setup ---
135+
path_line="export PATH=\"$INSTALL_DIR:\$PATH\""
99136
case ":$PATH:" in
100-
*":$INSTALL_DIR:"*)
137+
*":$INSTALL_DIR:"*) on_path=1 ;;
138+
*) on_path=0 ;;
139+
esac
140+
141+
info ""
142+
info "✓ Installed dcd $version to $INSTALL_DIR/dcd"
143+
144+
if [ "$on_path" -eq 0 ]; then
145+
rc=$(rc_file)
146+
if [ -f "$rc" ] && grep -Fq "$INSTALL_DIR" "$rc" 2>/dev/null; then
147+
# rc already references the dir (e.g. a re-install); don't duplicate it.
101148
info ""
102-
info "✓ Installed: $($INSTALL_DIR/dcd --version 2>/dev/null || echo "$version")"
103-
info " Try: dcd --help"
104-
;;
105-
*)
149+
info " $INSTALL_DIR is already configured in $rc."
150+
info " Restart your shell, or run: $path_line"
151+
elif printf '\n# dcd\n%s\n' "$path_line" >> "$rc" 2>/dev/null; then
106152
info ""
107-
info "✓ Installed dcd $version to $INSTALL_DIR/dcd"
153+
info " Added $INSTALL_DIR to your PATH in $rc."
154+
info " Restart your shell, or run: $path_line"
155+
else
108156
info ""
109157
info " $INSTALL_DIR is not on your PATH. Add this to your shell rc:"
110-
info " export PATH=\"$INSTALL_DIR:\$PATH\""
111-
info ""
112-
info " Then restart your shell, or run:"
113-
info " export PATH=\"$INSTALL_DIR:\$PATH\""
114-
;;
115-
esac
158+
info " $path_line"
159+
fi
160+
fi
161+
162+
# --- warn about a conflicting (shadowing) install ---
163+
if conflict=$(find_conflicting_dcd); then
164+
info ""
165+
info "! Another dcd is already on your PATH:"
166+
info " $conflict"
167+
info " This is usually a previous 'npm install -g @devicecloud.dev/dcd', which"
168+
info " can shadow this binary depending on PATH order. Remove it with:"
169+
info " npm uninstall -g @devicecloud.dev/dcd"
170+
fi
171+
172+
if [ "$on_path" -eq 1 ]; then
173+
info ""
174+
info " Try: dcd --help"
175+
fi
116176
}
117177

118178
main "$@"

0 commit comments

Comments
 (0)