mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
Git Bash hands native Bun C:/ paths while gstack-hook-check looked them up as /c/, so every TypeScript hook was refused and team-mode auto-update held every release since 1.91.31. The checker maps Bun's paths back to the shell spelling, the auto-updater lets the incoming release's own checker decide (installed checker only as a fallback, hook-check-unavailable when neither verifies), and docs/troubleshooting.md gives stuck installs one recovery command. /gstack-upgrade and /spec guards use the --show-prefix root check, gstack-wtree treats drive-letter --git-path answers as absolute, and setup refuses to replace a runtime root that is or contains its own checkout, Kiro's in-place root included (#3084), with --status suggesting the move. New sourced helper bin/gstack-path-spelling.sh and TS twin lib/path-spelling.ts. Co-authored-by: yuriysan <63948747+yuriysan@users.noreply.github.com> Co-authored-by: y$un_ <3579304+szsunyuan@users.noreply.github.com> Co-authored-by: Frederik Reventlow <267160539+dmfrede@users.noreply.github.com> Co-authored-by: skleinbe-ny <226563731+skleinbe-ny@users.noreply.github.com> Co-authored-by: bkermen <184220642+bkermen@users.noreply.github.com> Co-authored-by: Drew Jankowski <3200063+andrewkjankowski@users.noreply.github.com>
88 lines
3.1 KiB
Bash
88 lines
3.1 KiB
Bash
# shellcheck shell=bash
|
|
# gstack-path-spelling.sh — sourced helper: one spelling for paths on Windows
|
|
# shells. Git Bash (MSYS) spells a drive path /c/x, native programs (git.exe,
|
|
# bun.exe) answer C:/x or C:\x, and MSYS converts /c/x arguments to C:/x before
|
|
# a native program starts. Comparing two spellings as strings is the bug class
|
|
# behind #3088, #3100 and #3101. TS twin: lib/path-spelling.ts.
|
|
#
|
|
# gstack_path_shell PATH Git Bash's drive spelling (/c/x) of an absolute
|
|
# PATH, mount aliases such as /tmp resolved through
|
|
# their drive path; unchanged outside Windows shells
|
|
# gstack_path_native PATH the native spelling (C:/x) on Windows shells;
|
|
# unchanged elsewhere
|
|
# gstack_path_same A B true when A and B name the same file: filesystem
|
|
# identity when both exist, else equal shell
|
|
# spellings
|
|
# gstack_path_absolute PATH true when PATH is absolute in any spelling (/x,
|
|
# C:/x, C:\x): Git for Windows answers C:/x
|
|
# gstack_path_within PATH DIR
|
|
# true when the existing DIR is PATH or one of its
|
|
# ancestors, by gstack_path_same on each ancestor
|
|
# of the absolute PATH
|
|
#
|
|
# No side effects beyond the _GSTACK_PS_* variables; safe under set -u.
|
|
|
|
case "$(uname -s 2>/dev/null)" in
|
|
MINGW*|MSYS*) _GSTACK_PS_KIND=msys ;;
|
|
CYGWIN*) _GSTACK_PS_KIND=cygwin ;;
|
|
*) _GSTACK_PS_KIND=posix ;;
|
|
esac
|
|
|
|
gstack_path_shell() {
|
|
case "$_GSTACK_PS_KIND" in
|
|
posix) printf '%s\n' "$1"; return 0 ;;
|
|
cygwin) cygpath -u "$1" 2>/dev/null || printf '%s\n' "$1"; return 0 ;;
|
|
esac
|
|
_gps_p=$(cygpath -am "$1" 2>/dev/null) || _gps_p=""
|
|
[ -n "$_gps_p" ] || _gps_p=$1
|
|
_gps_p=$(printf '%s' "$_gps_p" | tr '\\' '/')
|
|
case "$_gps_p" in
|
|
[A-Za-z]:|[A-Za-z]:/*)
|
|
_gps_d=$(printf '%s' "${_gps_p%%:*}" | tr '[:upper:]' '[:lower:]')
|
|
_gps_p="/$_gps_d${_gps_p#?:}" ;;
|
|
esac
|
|
printf '%s\n' "$_gps_p"
|
|
}
|
|
|
|
gstack_path_native() {
|
|
case "$_GSTACK_PS_KIND" in
|
|
posix) printf '%s\n' "$1"; return 0 ;;
|
|
esac
|
|
_gpn_p=$(cygpath -am "$1" 2>/dev/null) || _gpn_p=""
|
|
if [ -z "$_gpn_p" ]; then
|
|
_gpn_p=$(printf '%s' "$1" | tr '\\' '/')
|
|
case "$_gpn_p" in
|
|
/[A-Za-z]|/[A-Za-z]/*)
|
|
_gpn_d=$(printf '%s' "${_gpn_p:1:1}" | tr '[:lower:]' '[:upper:]')
|
|
_gpn_p="$_gpn_d:${_gpn_p:2}"
|
|
[ -n "${_gpn_p#?:}" ] || _gpn_p="$_gpn_p/" ;;
|
|
esac
|
|
fi
|
|
printf '%s\n' "$_gpn_p"
|
|
}
|
|
|
|
gstack_path_same() {
|
|
if { [ -e "$1" ] || [ -L "$1" ]; } && { [ -e "$2" ] || [ -L "$2" ]; }; then
|
|
[ "$1" -ef "$2" ]
|
|
return
|
|
fi
|
|
[ "$(gstack_path_shell "$1")" = "$(gstack_path_shell "$2")" ]
|
|
}
|
|
|
|
gstack_path_absolute() {
|
|
case "$1" in /*|[A-Za-z]:[\\/]*) return 0 ;; esac
|
|
return 1
|
|
}
|
|
|
|
gstack_path_within() {
|
|
[ -e "$2" ] || return 1
|
|
_gpw_p=$1
|
|
while [ -n "$_gpw_p" ]; do
|
|
gstack_path_same "$_gpw_p" "$2" && return 0
|
|
case "$_gpw_p" in /|[A-Za-z]:|[A-Za-z]:/) return 1 ;; esac
|
|
_gpw_p=${_gpw_p%/}
|
|
case "$_gpw_p" in */*) _gpw_p=${_gpw_p%/*}; [ -n "$_gpw_p" ] || _gpw_p=/ ;; *) return 1 ;; esac
|
|
done
|
|
return 1
|
|
}
|