Merge branch 'fc/completion'
* fc/completion: completion: remove __git_index_file_list_filter() completion: add space after completed filename completion: add hack to enable file mode in bash < 4 completion: refactor __git_complete_index_file() completion: refactor diff_index wrappers completion: use __gitcompadd for __gitcomp_file completion; remove unuseful comments completion: document tilde expansion failure in tests completion: add file completion tests
This commit is contained in:
commit
f241c08d40
@ -252,106 +252,50 @@ __gitcomp_file ()
|
|||||||
# since tilde expansion is not applied.
|
# since tilde expansion is not applied.
|
||||||
# This means that COMPREPLY will be empty and Bash default
|
# This means that COMPREPLY will be empty and Bash default
|
||||||
# completion will be used.
|
# completion will be used.
|
||||||
COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}"))
|
__gitcompadd "$1" "${2-}" "${3-$cur}" ""
|
||||||
|
|
||||||
# Tell Bash that compspec generates filenames.
|
# use a hack to enable file mode in bash < 4
|
||||||
compopt -o filenames 2>/dev/null
|
compopt -o filenames +o nospace 2>/dev/null ||
|
||||||
|
compgen -f /non-existing-dir/ > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
__git_index_file_list_filter_compat ()
|
# Execute 'git ls-files', unless the --committable option is specified, in
|
||||||
{
|
# which case it runs 'git diff-index' to find out the files that can be
|
||||||
local path
|
# committed. It return paths relative to the directory specified in the first
|
||||||
|
# argument, and using the options specified in the second argument.
|
||||||
while read -r path; do
|
|
||||||
case "$path" in
|
|
||||||
?*/*) echo "${path%%/*}/" ;;
|
|
||||||
*) echo "$path" ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
__git_index_file_list_filter_bash ()
|
|
||||||
{
|
|
||||||
local path
|
|
||||||
|
|
||||||
while read -r path; do
|
|
||||||
case "$path" in
|
|
||||||
?*/*)
|
|
||||||
# XXX if we append a slash to directory names when using
|
|
||||||
# `compopt -o filenames`, Bash will append another slash.
|
|
||||||
# This is pretty stupid, and this the reason why we have to
|
|
||||||
# define a compatible version for this function.
|
|
||||||
echo "${path%%/*}" ;;
|
|
||||||
*)
|
|
||||||
echo "$path" ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Process path list returned by "ls-files" and "diff-index --name-only"
|
|
||||||
# commands, in order to list only file names relative to a specified
|
|
||||||
# directory, and append a slash to directory names.
|
|
||||||
__git_index_file_list_filter ()
|
|
||||||
{
|
|
||||||
# Default to Bash >= 4.x
|
|
||||||
__git_index_file_list_filter_bash
|
|
||||||
}
|
|
||||||
|
|
||||||
# Execute git ls-files, returning paths relative to the directory
|
|
||||||
# specified in the first argument, and using the options specified in
|
|
||||||
# the second argument.
|
|
||||||
__git_ls_files_helper ()
|
__git_ls_files_helper ()
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
test -n "${CDPATH+set}" && unset CDPATH
|
test -n "${CDPATH+set}" && unset CDPATH
|
||||||
# NOTE: $2 is not quoted in order to support multiple options
|
cd "$1"
|
||||||
cd "$1" && git ls-files --exclude-standard $2
|
if [ "$2" == "--committable" ]; then
|
||||||
|
git diff-index --name-only --relative HEAD
|
||||||
|
else
|
||||||
|
# NOTE: $2 is not quoted in order to support multiple options
|
||||||
|
git ls-files --exclude-standard $2
|
||||||
|
fi
|
||||||
) 2>/dev/null
|
) 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Execute git diff-index, returning paths relative to the directory
|
|
||||||
# specified in the first argument, and using the tree object id
|
|
||||||
# specified in the second argument.
|
|
||||||
__git_diff_index_helper ()
|
|
||||||
{
|
|
||||||
(
|
|
||||||
test -n "${CDPATH+set}" && unset CDPATH
|
|
||||||
cd "$1" && git diff-index --name-only --relative "$2"
|
|
||||||
) 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# __git_index_files accepts 1 or 2 arguments:
|
# __git_index_files accepts 1 or 2 arguments:
|
||||||
# 1: Options to pass to ls-files (required).
|
# 1: Options to pass to ls-files (required).
|
||||||
# Supported options are --cached, --modified, --deleted, --others,
|
|
||||||
# and --directory.
|
|
||||||
# 2: A directory path (optional).
|
# 2: A directory path (optional).
|
||||||
# If provided, only files within the specified directory are listed.
|
# If provided, only files within the specified directory are listed.
|
||||||
# Sub directories are never recursed. Path must have a trailing
|
# Sub directories are never recursed. Path must have a trailing
|
||||||
# slash.
|
# slash.
|
||||||
__git_index_files ()
|
__git_index_files ()
|
||||||
{
|
{
|
||||||
local dir="$(__gitdir)" root="${2-.}"
|
local dir="$(__gitdir)" root="${2-.}" file
|
||||||
|
|
||||||
if [ -d "$dir" ]; then
|
if [ -d "$dir" ]; then
|
||||||
__git_ls_files_helper "$root" "$1" | __git_index_file_list_filter |
|
__git_ls_files_helper "$root" "$1" |
|
||||||
sort | uniq
|
while read -r file; do
|
||||||
fi
|
case "$file" in
|
||||||
}
|
?*/*) echo "${file%%/*}" ;;
|
||||||
|
*) echo "$file" ;;
|
||||||
# __git_diff_index_files accepts 1 or 2 arguments:
|
esac
|
||||||
# 1) The id of a tree object.
|
done | sort | uniq
|
||||||
# 2) A directory path (optional).
|
|
||||||
# If provided, only files within the specified directory are listed.
|
|
||||||
# Sub directories are never recursed. Path must have a trailing
|
|
||||||
# slash.
|
|
||||||
__git_diff_index_files ()
|
|
||||||
{
|
|
||||||
local dir="$(__gitdir)" root="${2-.}"
|
|
||||||
|
|
||||||
if [ -d "$dir" ]; then
|
|
||||||
__git_diff_index_helper "$root" "$1" | __git_index_file_list_filter |
|
|
||||||
sort | uniq
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,44 +496,23 @@ __git_complete_revlist_file ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# __git_complete_index_file requires 1 argument: the options to pass to
|
# __git_complete_index_file requires 1 argument:
|
||||||
# ls-file
|
# 1: the options to pass to ls-file
|
||||||
|
#
|
||||||
|
# The exception is --committable, which finds the files appropriate commit.
|
||||||
__git_complete_index_file ()
|
__git_complete_index_file ()
|
||||||
{
|
{
|
||||||
local pfx cur_="$cur"
|
local pfx="" cur_="$cur"
|
||||||
|
|
||||||
case "$cur_" in
|
case "$cur_" in
|
||||||
?*/*)
|
?*/*)
|
||||||
pfx="${cur_%/*}"
|
pfx="${cur_%/*}"
|
||||||
cur_="${cur_##*/}"
|
cur_="${cur_##*/}"
|
||||||
pfx="${pfx}/"
|
pfx="${pfx}/"
|
||||||
|
|
||||||
__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
__gitcomp_file "$(__git_index_files "$1")" "" "$cur_"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
|
||||||
|
|
||||||
# __git_complete_diff_index_file requires 1 argument: the id of a tree
|
__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
|
||||||
# object
|
|
||||||
__git_complete_diff_index_file ()
|
|
||||||
{
|
|
||||||
local pfx cur_="$cur"
|
|
||||||
|
|
||||||
case "$cur_" in
|
|
||||||
?*/*)
|
|
||||||
pfx="${cur_%/*}"
|
|
||||||
cur_="${cur_##*/}"
|
|
||||||
pfx="${pfx}/"
|
|
||||||
|
|
||||||
__gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
__gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__git_complete_file ()
|
__git_complete_file ()
|
||||||
@ -1213,7 +1136,7 @@ _git_commit ()
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
if git rev-parse --verify --quiet HEAD >/dev/null; then
|
if git rev-parse --verify --quiet HEAD >/dev/null; then
|
||||||
__git_complete_diff_index_file "HEAD"
|
__git_complete_index_file "--committable"
|
||||||
else
|
else
|
||||||
# This is the first commit
|
# This is the first commit
|
||||||
__git_complete_index_file "--cached"
|
__git_complete_index_file "--cached"
|
||||||
@ -2702,14 +2625,6 @@ if [[ -n ${ZSH_VERSION-} ]]; then
|
|||||||
|
|
||||||
compdef _git git gitk
|
compdef _git git gitk
|
||||||
return
|
return
|
||||||
elif [[ -n ${BASH_VERSION-} ]]; then
|
|
||||||
if ((${BASH_VERSINFO[0]} < 4)); then
|
|
||||||
# compopt is not supported
|
|
||||||
__git_index_file_list_filter ()
|
|
||||||
{
|
|
||||||
__git_index_file_list_filter_compat
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__git_func_wrap ()
|
__git_func_wrap ()
|
||||||
|
@ -347,4 +347,81 @@ test_expect_success 'send-email' '
|
|||||||
test_completion "git send-email ma" "master "
|
test_completion "git send-email ma" "master "
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'complete files' '
|
||||||
|
git init tmp && cd tmp &&
|
||||||
|
test_when_finished "cd .. && rm -rf tmp" &&
|
||||||
|
|
||||||
|
echo "expected" > .gitignore &&
|
||||||
|
echo "out" >> .gitignore &&
|
||||||
|
|
||||||
|
git add .gitignore &&
|
||||||
|
test_completion "git commit " ".gitignore" &&
|
||||||
|
|
||||||
|
git commit -m ignore &&
|
||||||
|
|
||||||
|
touch new &&
|
||||||
|
test_completion "git add " "new" &&
|
||||||
|
|
||||||
|
git add new &&
|
||||||
|
git commit -a -m new &&
|
||||||
|
test_completion "git add " "" &&
|
||||||
|
|
||||||
|
git mv new modified &&
|
||||||
|
echo modify > modified &&
|
||||||
|
test_completion "git add " "modified" &&
|
||||||
|
|
||||||
|
touch untracked &&
|
||||||
|
|
||||||
|
: TODO .gitignore should not be here &&
|
||||||
|
test_completion "git rm " <<-\EOF &&
|
||||||
|
.gitignore
|
||||||
|
modified
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_completion "git clean " "untracked" &&
|
||||||
|
|
||||||
|
: TODO .gitignore should not be here &&
|
||||||
|
test_completion "git mv " <<-\EOF &&
|
||||||
|
.gitignore
|
||||||
|
modified
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mkdir dir &&
|
||||||
|
touch dir/file-in-dir &&
|
||||||
|
git add dir/file-in-dir &&
|
||||||
|
git commit -m dir &&
|
||||||
|
|
||||||
|
mkdir untracked-dir &&
|
||||||
|
|
||||||
|
: TODO .gitignore should not be here &&
|
||||||
|
test_completion "git mv modified " <<-\EOF &&
|
||||||
|
.gitignore
|
||||||
|
dir
|
||||||
|
modified
|
||||||
|
untracked
|
||||||
|
untracked-dir
|
||||||
|
EOF
|
||||||
|
|
||||||
|
test_completion "git commit " "modified" &&
|
||||||
|
|
||||||
|
: TODO .gitignore should not be here &&
|
||||||
|
test_completion "git ls-files " <<-\EOF
|
||||||
|
.gitignore
|
||||||
|
dir
|
||||||
|
modified
|
||||||
|
EOF
|
||||||
|
|
||||||
|
touch momified &&
|
||||||
|
test_completion "git add mom" "momified"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_failure 'complete with tilde expansion' '
|
||||||
|
git init tmp && cd tmp &&
|
||||||
|
test_when_finished "cd .. && rm -rf tmp" &&
|
||||||
|
|
||||||
|
touch ~/tmp/file &&
|
||||||
|
|
||||||
|
test_completion "git add ~/tmp/" "~/tmp/file"
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user