summaryrefslogtreecommitdiff
path: root/contrib/completion
diff options
context:
space:
mode:
authorLibravatar SZEDER Gábor <szeder.dev@gmail.com>2017-02-03 03:48:29 +0100
committerLibravatar Junio C Hamano <gitster@pobox.com>2017-02-03 22:18:41 -0800
commitfad9484f0aebc818112fb52270ebcddc768a7573 (patch)
treefaf288e44536af8a5916c46557f225e0f4f4d80c /contrib/completion
parentcompletion: extract repository discovery from __gitdir() (diff)
downloadtgif-fad9484f0aebc818112fb52270ebcddc768a7573.tar.xz
completion: cache the path to the repository
After the previous changes in this series there are only a handful of $(__gitdir) command substitutions left in the completion script, but there is still a bit of room for improvements: 1. The command substitution involves the forking of a subshell, which has considerable overhead on some platforms. 2. There are a few cases, where this command substitution is executed more than once during a single completion, which means multiple subshells and possibly multiple 'git rev-parse' executions. __gitdir() is invoked twice while completing refs for e.g. 'git log', 'git rebase', 'gitk', or while completing remote refs for 'git fetch' or 'git push'. Both of these points can be addressed by using the __git_find_repo_path() helper function introduced in the previous commit: 1. __git_find_repo_path() stores the path to the repository in a variable instead of printing it, so the command substitution around the function can be avoided. Or rather: the command substitution should be avoided to make the new value of the variable set inside the function visible to the callers. (Yes, there is now a command substitution inside __git_find_repo_path() around each 'git rev-parse', but that's executed only if necessary, and only once per completion, see point 2. below.) 2. $__git_repo_path, the variable holding the path to the repository, is declared local in the toplevel completion functions __git_main() and __gitk_main(). Thus, once set, the path is visible in all completion functions, including all subsequent calls to __git_find_repo_path(), meaning that they wouldn't have to re-discover the path to the repository. So call __git_find_repo_path() and use $__git_repo_path instead of the $(__gitdir) command substitution to access paths in the .git directory. Turn tests checking __gitdir()'s repository discovery into tests of __git_find_repo_path() such that only the tested function changes but the expected results don't, ensuring that repo discovery keeps working as it did before. As __gitdir() is not used anymore in the completion script, mark it as deprecated and direct users' attention to __git_find_repo_path() and $__git_repo_path. Yet keep four __gitdir() tests to ensure that it handles success and failure of __git_find_repo_path() and that it still handles its optional remote argument, because users' custom completion scriptlets might depend on it. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'contrib/completion')
-rw-r--r--contrib/completion/git-completion.bash46
1 files changed, 29 insertions, 17 deletions
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 9b9526b48d..d2601aee94 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -39,6 +39,11 @@ esac
# variable.
__git_find_repo_path ()
{
+ if [ -n "$__git_repo_path" ]; then
+ # we already know where it is
+ return
+ fi
+
if [ -n "${__git_C_args-}" ]; then
__git_repo_path="$(git "${__git_C_args[@]}" \
${__git_dir:+--git-dir="$__git_dir"} \
@@ -56,6 +61,7 @@ __git_find_repo_path ()
fi
}
+# Deprecated: use __git_find_repo_path() and $__git_repo_path instead
# __gitdir accepts 0 or 1 arguments (i.e., location)
# returns location of .git repo
__gitdir ()
@@ -350,10 +356,13 @@ __git_tags ()
# 'git checkout's tracking DWIMery (optional; ignored, if set but empty).
__git_refs ()
{
- local i hash dir="$(__gitdir)" track="${2-}"
+ local i hash dir track="${2-}"
local list_refs_from=path remote="${1-}"
local format refs pfx
+ __git_find_repo_path
+ dir="$__git_repo_path"
+
if [ -z "$remote" ]; then
if [ -z "$dir" ]; then
return
@@ -458,8 +467,8 @@ __git_refs_remotes ()
__git_remotes ()
{
- local d="$(__gitdir)"
- test -d "$d/remotes" && ls -1 "$d/remotes"
+ __git_find_repo_path
+ test -d "$__git_repo_path/remotes" && ls -1 "$__git_repo_path/remotes"
__git remote
}
@@ -957,8 +966,8 @@ __git_whitespacelist="nowarn warn error error-all fix"
_git_am ()
{
- local dir="$(__gitdir)"
- if [ -d "$dir"/rebase-apply ]; then
+ __git_find_repo_path
+ if [ -d "$__git_repo_path"/rebase-apply ]; then
__gitcomp "--skip --continue --resolved --abort"
return
fi
@@ -1041,7 +1050,8 @@ _git_bisect ()
local subcommands="start bad good skip reset visualize replay log run"
local subcommand="$(__git_find_on_cmdline "$subcommands")"
if [ -z "$subcommand" ]; then
- if [ -f "$(__gitdir)"/BISECT_START ]; then
+ __git_find_repo_path
+ if [ -f "$__git_repo_path"/BISECT_START ]; then
__gitcomp "$subcommands"
else
__gitcomp "replay start"
@@ -1146,8 +1156,8 @@ _git_cherry ()
_git_cherry_pick ()
{
- local dir="$(__gitdir)"
- if [ -f "$dir"/CHERRY_PICK_HEAD ]; then
+ __git_find_repo_path
+ if [ -f "$__git_repo_path"/CHERRY_PICK_HEAD ]; then
__gitcomp "--continue --quit --abort"
return
fi
@@ -1538,10 +1548,10 @@ __git_log_date_formats="relative iso8601 rfc2822 short local default raw"
_git_log ()
{
__git_has_doubledash && return
+ __git_find_repo_path
- local g="$(__gitdir)"
local merge=""
- if [ -f "$g/MERGE_HEAD" ]; then
+ if [ -f "$__git_repo_path/MERGE_HEAD" ]; then
merge="--merge"
fi
case "$cur" in
@@ -1788,11 +1798,12 @@ _git_push ()
_git_rebase ()
{
- local dir="$(__gitdir)"
- if [ -f "$dir"/rebase-merge/interactive ]; then
+ __git_find_repo_path
+ if [ -f "$__git_repo_path"/rebase-merge/interactive ]; then
__gitcomp "--continue --skip --abort --quit --edit-todo"
return
- elif [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
+ elif [ -d "$__git_repo_path"/rebase-apply ] || \
+ [ -d "$__git_repo_path"/rebase-merge ]; then
__gitcomp "--continue --skip --abort --quit"
return
fi
@@ -2467,8 +2478,8 @@ _git_reset ()
_git_revert ()
{
- local dir="$(__gitdir)"
- if [ -f "$dir"/REVERT_HEAD ]; then
+ __git_find_repo_path
+ if [ -f "$__git_repo_path"/REVERT_HEAD ]; then
__gitcomp "--continue --quit --abort"
return
fi
@@ -2865,9 +2876,10 @@ __gitk_main ()
__git_has_doubledash && return
local __git_repo_path
- local g="$(__gitdir)"
+ __git_find_repo_path
+
local merge=""
- if [ -f "$g/MERGE_HEAD" ]; then
+ if [ -f "$__git_repo_path/MERGE_HEAD" ]; then
merge="--merge"
fi
case "$cur" in