completions/git: Terminate pathspec magic

Git's pathspec system is kind of annoying:

>  A pathspec that begins with a colon : has special meaning. In the short form, the leading colon : is followed by zero or more "magic signature" letters (which optionally is terminated by another colon :), and the remainder is the pattern to match against the path. The "magic signature" consists of ASCII symbols that are neither alphanumeric, glob, regex special characters nor colon. The optional colon that terminates the "magic signature" can be omitted if the pattern begins with a character that does not belong to "magic signature" symbol set and is not a colon.

So if we complete `:/foo`, that "works" because "f" is alphanumeric
and so the "/" is the only magic character here.

If, however the filename starts with a magic character, that's used as
a magic signature.

So we do what the docs say and terminate the magic signature after the
"/" (which means "from the repo root").

Fixes #9004
This commit is contained in:
Fabian Boehm 2022-06-07 20:10:13 +02:00
parent 9238bbde65
commit 0ea6703661
2 changed files with 10 additions and 3 deletions

View file

@ -342,7 +342,11 @@ function __fish_git_files
if string match -q '../*' -- $file
or string match -q ':*' -- (commandline -ct)
set -l fromroot (builtin realpath -- $file 2>/dev/null)
and set fromroot (string replace -- "$root/" ":/" "$fromroot")
# `:` starts pathspec "magic", and the second `:` terminates it.
# `/` is the magic letter for "from repo root".
# If we didn't terminate it we'd have to escape any special chars
# (non-alphanumeric, glob or regex special characters, in whatever dialect git uses)
and set fromroot (string replace -- "$root/" ":/:" "$fromroot")
and printf '%s\t%s\n' "$fromroot" $d
end
end
@ -476,10 +480,10 @@ function __fish_git_files
end
set -a file (string join / -- $previous)
# The filename with ":/" prepended.
# The filename with ":/:" prepended.
if string match -q '../*' -- $file
or string match -q ':*' -- (commandline -ct)
set file (string replace -- "$root/" ":/" "$root/$relfile")
set file (string replace -- "$root/" ":/:" "$root/$relfile")
end
if test "$root/$relfile" = (pwd -P)/$relfile

View file

@ -40,6 +40,9 @@ touch foo
complete -C'git add '
#CHECK: foo Untracked file
complete -C'git add :'
#CHECK: :/:foo Untracked file
git config alias.s status
complete 'git s --s'
# CHECK --short