Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion scripts/install.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -648,7 +648,46 @@ rc_lists_dir() {
{
n = 0
if ($0 ~ /(^|[^A-Za-z_])fish_add_path([^A-Za-z_]|$)/) {
for (i = 1; i <= NF; i++) if ($i !~ /^-/ && $i !~ /fish_add_path/) cand[++n] = $i
# Parse quotes instead of field-splitting. We WRITE
# fish_add_path "$PREFIX", so a prefix containing spaces became
# two whitespace fields here and never matched -- the installer
# then appended a second block and claimed it had added a PATH
# entry that was already present. The sibling reader further up
# already keeps the remainder intact; this now agrees with it.
# Tokenise the argument list, honouring quotes. Three things
# this has to get right, each of which broke a previous
# attempt (cli#439):
# * FIRST occurrence of the command, via index() -- a greedy
# /^.*fish_add_path/ strips through an inline comment that
# mentions it and loses the real argument;
# * quoted arguments are ONE path, spaces included, because we
# write fish_add_path "$PREFIX";
# * fish_add_path takes MULTIPLE directories, so parsing must
# continue past the first closing quote.
at = index($0, "fish_add_path")
rest = substr($0, at + 13)
while (length(rest) > 0) {
sub(/^[[:space:]]+/, "", rest)
if (length(rest) == 0) break
ch = substr(rest, 1, 1)
if (ch == "#") break # trailing comment
if (ch == "\"" || ch == "\047") {
body = substr(rest, 2)
close_at = index(body, ch)
if (close_at > 0) {
cand[++n] = substr(body, 1, close_at - 1)
rest = substr(body, close_at + 1)
} else { # unterminated quote
cand[++n] = body
rest = ""
}
} else {
sp = match(rest, /[[:space:]]/)
tok = (sp > 0) ? substr(rest, 1, sp - 1) : rest
rest = (sp > 0) ? substr(rest, sp) : ""
if (tok !~ /^-/) cand[++n] = tok # skip flags
}
}
} else if ($0 ~ /(^|[^A-Za-z_])[Pp][Aa][Tt][Hh][+]?=/) {
value = $0
sub(/^[^=]*=/, "", value)
Expand Down
60 changes: 60 additions & 0 deletions scripts/tests/install-verify.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -469,6 +469,66 @@ for spec in "zsh:.zshrc:export PATH=" "fish:.config/fish/config.fish:fish_add_pa
drop_sandbox
done

# -- 16. a fish prefix containing spaces is recognised as already listed ------
# We WRITE `fish_add_path "$PREFIX"`, so rc_lists_dir must parse the quotes
# rather than field-split: it used to see two whitespace fields, match neither,
# append a second block, and report adding an entry that was already present.
for quote_style in double single; do
make_sandbox yes
RC="$HOMEDIR/.config/fish/config.fish"
mkdir -p "$(dirname "$RC")"
SPACED="$SBX/my tools/bin"
mkdir -p "$SPACED"
if [ "$quote_style" = double ]; then
printf 'fish_add_path "%s"\n' "$SPACED" > "$RC"
else
printf "fish_add_path '%s'\n" "$SPACED" > "$RC"
fi
before=$(cat "$RC")
FAKE_SHELL=/bin/fish COSIGN_RESULT=0 run_installer_at "$SPACED" >/dev/null 2>&1
if [ "$(cat "$RC")" = "$before" ]; then
ok "fish: $quote_style-quoted prefix with spaces seen as already listed"
else
bad "fish: $quote_style-quoted prefix with spaces not matched (rc rewritten)"; sed 's/^/ /' "$RC"
fi
drop_sandbox
done

# -- 17. an inline comment that mentions fish_add_path must not defeat the match
# A greedy strip through the LAST `fish_add_path` on the line would leave the
# comment text as the "path" and miss the real argument (Bugbot, cli#439).
make_sandbox yes
RC="$HOMEDIR/.config/fish/config.fish"
mkdir -p "$(dirname "$RC")"
printf 'fish_add_path "%s" # set by fish_add_path\n' "$SBX/s1" > "$RC"
mkdir -p "$SBX/s1"
before=$(cat "$RC")
FAKE_SHELL=/bin/fish COSIGN_RESULT=0 run_installer_at "$SBX/s1" >/dev/null 2>&1
if [ "$(cat "$RC")" = "$before" ]; then
ok "fish: inline comment naming fish_add_path does not break the match"
else
bad "fish: inline comment naming fish_add_path broke the match (rc rewritten)"; sed 's/^/ /' "$RC"
fi
drop_sandbox

# -- 18. the prefix is the SECOND quoted arg on a multi-path fish line --------
# fish_add_path accepts several directories. Parsing that stopped at the first
# closing quote missed a later one, appended a redundant block, and reported a
# PATH add that was already there (Bugbot, cli#439).
make_sandbox yes
RC="$HOMEDIR/.config/fish/config.fish"
mkdir -p "$(dirname "$RC")"
mkdir -p "$SBX/other" "$SBX/s1"
printf 'fish_add_path "%s" "%s"\n' "$SBX/other" "$SBX/s1" > "$RC"
before=$(cat "$RC")
FAKE_SHELL=/bin/fish COSIGN_RESULT=0 run_installer_at "$SBX/s1" >/dev/null 2>&1
if [ "$(cat "$RC")" = "$before" ]; then
ok "fish: prefix as the second quoted arg is seen as already listed"
else
bad "fish: second quoted arg was not matched (rc rewritten)"; sed 's/^/ /' "$RC"
fi
drop_sandbox

echo
echo "install-verify: $PASS passed, $FAIL failed"
[ "$FAIL" -eq 0 ]
Loading