_command_offset: Restore compopts used by called command.
This fixes completions that rely on their compopts, most notably mount(8). Fixes bash-completion bug #313183.
This commit is contained in:
parent
b9a5f508e2
commit
5051b1787a
@ -1543,8 +1543,7 @@ _command()
|
|||||||
|
|
||||||
# A meta-command completion function for commands like sudo(8), which need to
|
# A meta-command completion function for commands like sudo(8), which need to
|
||||||
# first complete on a command, then complete according to that command's own
|
# first complete on a command, then complete according to that command's own
|
||||||
# completion definition - currently not quite foolproof (e.g. mount and umount
|
# completion definition.
|
||||||
# don't work properly), but still quite useful.
|
|
||||||
#
|
#
|
||||||
_command_offset()
|
_command_offset()
|
||||||
{
|
{
|
||||||
@ -1606,18 +1605,18 @@ _command_offset()
|
|||||||
$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
|
$func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# remove any \: generated by a command that doesn't
|
# restore initial compopts
|
||||||
# default to filenames or dirnames (e.g. sudo chown)
|
local opt t
|
||||||
# FIXME: I'm pretty sure this does not work!
|
while true; do
|
||||||
if [ "${cspec#*-o }" != "$cspec" ]; then
|
# FIXME: should we take "+o opt" into account?
|
||||||
cspec=${cspec#*-o }
|
t=${cspec#*-o }
|
||||||
cspec=${cspec%% *}
|
if [ "$t" == "$cspec" ]; then
|
||||||
if [[ "$cspec" != @(dir|file)names ]]; then
|
break
|
||||||
COMPREPLY=("${COMPREPLY[@]//\\\\:/:}")
|
|
||||||
else
|
|
||||||
compopt -o filenames
|
|
||||||
fi
|
fi
|
||||||
fi
|
opt=${t%% *}
|
||||||
|
compopt -o $opt
|
||||||
|
cspec=${t#$opt}
|
||||||
|
done
|
||||||
else
|
else
|
||||||
cspec=${cspec#complete}
|
cspec=${cspec#complete}
|
||||||
cspec=${cspec%%$compcmd}
|
cspec=${cspec%%$compcmd}
|
||||||
|
@ -30,7 +30,7 @@ proc setup {} {
|
|||||||
|
|
||||||
proc teardown {} {
|
proc teardown {} {
|
||||||
teardown_dummy_mnt
|
teardown_dummy_mnt
|
||||||
assert_env_unmodified
|
assert_env_unmodified {/OLDPWD/d}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -49,6 +49,13 @@ assert_complete_any "mount -t "
|
|||||||
sync_after_int
|
sync_after_int
|
||||||
|
|
||||||
|
|
||||||
|
set test "mount /dev/sda1 def should complete directory name"
|
||||||
|
assert_complete_dir "default/" "mount /dev/sda1 def" $::srcdir/fixtures/shared $test -nospace
|
||||||
|
|
||||||
|
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
|
||||||
set test "Check completing nfs mounts"
|
set test "Check completing nfs mounts"
|
||||||
set expected [list /test/path /test/path2 /second/path]
|
set expected [list /test/path /test/path2 /second/path]
|
||||||
set cmd "mount mocksrv:/"
|
set cmd "mount mocksrv:/"
|
||||||
|
@ -24,4 +24,63 @@ assert_complete_dir fixtures/ "sudo sh fix" $::srcdir "" -nospace
|
|||||||
sync_after_int
|
sync_after_int
|
||||||
|
|
||||||
|
|
||||||
|
# test that `mount` and `sudo mount` behave the same way
|
||||||
|
set test "sudo mount /dev/sda1 def should complete directory name"
|
||||||
|
assert_complete_dir "default/" "sudo mount /dev/sda1 def" $::srcdir/fixtures/shared $test -nospace
|
||||||
|
|
||||||
|
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
|
||||||
|
# Find user/group suitable for testing.
|
||||||
|
set failed_find_unique_completion 0
|
||||||
|
foreach ug {user group} {
|
||||||
|
# compgen -A is used because it's a bash builtin and available everywhere.
|
||||||
|
# The || true part prevents exec from throwing an exception if nothing is
|
||||||
|
# found (very very unlikely).
|
||||||
|
set list [split [exec bash -c "compgen -A $ug || true"] "\n"]
|
||||||
|
if {![find_unique_completion_pair $list part$ug full$ug]} {
|
||||||
|
untested "Not running complex chown tests; no suitable test $ug found."
|
||||||
|
set failed_find_unique_completion 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# These tests require an unique completion.
|
||||||
|
if {!$failed_find_unique_completion} {
|
||||||
|
assert_complete $fulluser "sudo chown $partuser"
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
assert_complete $fulluser:$fullgroup "sudo chown $fulluser:$partgroup"
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
assert_complete "dot.user:$fullgroup" "sudo chown dot.user:$partgroup"
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
foreach prefix {
|
||||||
|
"funky\\ user:" "funky.user:" "funky\\.user:" "fu\\ nky.user:"
|
||||||
|
"f\\ o\\ o\\.\\bar:" "foo\\_b\\ a\\.r\\ :"
|
||||||
|
} {
|
||||||
|
set test "Check preserve special chars in $prefix$partgroup<TAB>"
|
||||||
|
#assert_complete_into "chown $prefix$partgroup" "chown $prefix$fullgroup " $test
|
||||||
|
assert_complete $prefix$fullgroup "sudo chown $prefix$partgroup" $test
|
||||||
|
sync_after_int
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check that we give up in degenerate cases instead of spewing various junk.
|
||||||
|
|
||||||
|
assert_no_complete "sudo chown $fulluser\\\\:$partgroup"
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
assert_no_complete "sudo chown $fulluser\\\\\\:$partgroup"
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
assert_no_complete "sudo chown $fulluser\\\\\\\\:$partgroup"
|
||||||
|
sync_after_int
|
||||||
|
|
||||||
|
# Colons in user/groupnames are not usually allowed.
|
||||||
|
assert_no_complete "sudo chown foo:bar:$partgroup"
|
||||||
|
sync_after_int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
teardown
|
teardown
|
||||||
|
Loading…
x
Reference in New Issue
Block a user