Speed up bash completion loading

Since git is not used in each and every interactive xterm, it
seems best to load completion support with cold caches and then
load each needed thing lazily.  This has most of the speed
advantage of pre-generating everything at build time, without the
complication of figuring out at build time what commands will be
available at run time.

On this slow laptop, this decreases the time to load
git-completion.bash from about 500 ms to about 175 ms.

Suggested-by: Kirill Smelkov <kirr@mns.spb.ru>
Acked-by: Shawn O. Pearce <spearce@spearce.org>
Cc: Stephen Boyd <bebarino@gmail.com>
Cc: SZEDER Gábor <szeder@ira.uka.de>
Cc: Sverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Jonathan Nieder 2009-11-17 18:49:10 -06:00 committed by Junio C Hamano
parent 78d553b7d7
commit eaa4e6ee2a

View File

@ -21,13 +21,7 @@
# 2) Added the following line to your .bashrc: # 2) Added the following line to your .bashrc:
# source ~/.git-completion.sh # source ~/.git-completion.sh
# #
# 3) You may want to make sure the git executable is available # 3) Consider changing your PS1 to also show the current branch:
# in your PATH before this script is sourced, as some caching
# is performed while the script loads. If git isn't found
# at source time then all lookups will be done on demand,
# which may be slightly slower.
#
# 4) Consider changing your PS1 to also show the current branch:
# PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' # PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
# #
# The argument to __git_ps1 will be displayed only if you # The argument to __git_ps1 will be displayed only if you
@ -324,12 +318,8 @@ __git_remotes ()
done done
} }
__git_merge_strategies () __git_list_merge_strategies ()
{ {
if [ -n "${__git_merge_strategylist-}" ]; then
echo "$__git_merge_strategylist"
return
fi
git merge -s help 2>&1 | git merge -s help 2>&1 |
sed -n -e '/[Aa]vailable strategies are: /,/^$/{ sed -n -e '/[Aa]vailable strategies are: /,/^$/{
s/\.$// s/\.$//
@ -339,8 +329,17 @@ __git_merge_strategies ()
p p
}' }'
} }
__git_merge_strategylist=
__git_merge_strategylist=$(__git_merge_strategies 2>/dev/null) __git_merge_strategies=
# 'git merge -s help' (and thus detection of the merge strategy
# list) fails, unfortunately, if run outside of any git working
# tree. __git_merge_strategies is set to the empty string in
# that case, and the detection will be repeated the next time it
# is needed.
__git_compute_merge_strategies ()
{
: ${__git_merge_strategies:=$(__git_list_merge_strategies)}
}
__git_complete_file () __git_complete_file ()
{ {
@ -474,27 +473,24 @@ __git_complete_remote_or_refspec ()
__git_complete_strategy () __git_complete_strategy ()
{ {
__git_compute_merge_strategies
case "${COMP_WORDS[COMP_CWORD-1]}" in case "${COMP_WORDS[COMP_CWORD-1]}" in
-s|--strategy) -s|--strategy)
__gitcomp "$(__git_merge_strategies)" __gitcomp "$__git_merge_strategies"
return 0 return 0
esac esac
local cur="${COMP_WORDS[COMP_CWORD]}" local cur="${COMP_WORDS[COMP_CWORD]}"
case "$cur" in case "$cur" in
--strategy=*) --strategy=*)
__gitcomp "$(__git_merge_strategies)" "" "${cur##--strategy=}" __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
return 0 return 0
;; ;;
esac esac
return 1 return 1
} }
__git_all_commands () __git_list_all_commands ()
{ {
if [ -n "${__git_all_commandlist-}" ]; then
echo "$__git_all_commandlist"
return
fi
local i IFS=" "$'\n' local i IFS=" "$'\n'
for i in $(git help -a|egrep '^ [a-zA-Z0-9]') for i in $(git help -a|egrep '^ [a-zA-Z0-9]')
do do
@ -504,17 +500,18 @@ __git_all_commands ()
esac esac
done done
} }
__git_all_commandlist=
__git_all_commandlist="$(__git_all_commands 2>/dev/null)"
__git_porcelain_commands () __git_all_commands=
__git_compute_all_commands ()
{
: ${__git_all_commands:=$(__git_list_all_commands)}
}
__git_list_porcelain_commands ()
{ {
if [ -n "${__git_porcelain_commandlist-}" ]; then
echo "$__git_porcelain_commandlist"
return
fi
local i IFS=" "$'\n' local i IFS=" "$'\n'
for i in "help" $(__git_all_commands) __git_compute_all_commands
for i in "help" $__git_all_commands
do do
case $i in case $i in
*--*) : helper pattern;; *--*) : helper pattern;;
@ -595,8 +592,13 @@ __git_porcelain_commands ()
esac esac
done done
} }
__git_porcelain_commandlist=
__git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)" __git_porcelain_commands=
__git_compute_porcelain_commands ()
{
__git_compute_all_commands
: ${__git_porcelain_commands:=$(__git_list_porcelain_commands)}
}
__git_aliases () __git_aliases ()
{ {
@ -1081,7 +1083,8 @@ _git_help ()
return return
;; ;;
esac esac
__gitcomp "$(__git_all_commands) __git_compute_all_commands
__gitcomp "$__git_all_commands
attributes cli core-tutorial cvs-migration attributes cli core-tutorial cvs-migration
diffcore gitk glossary hooks ignore modules diffcore gitk glossary hooks ignore modules
repository-layout tutorial tutorial-2 repository-layout tutorial tutorial-2
@ -1427,7 +1430,8 @@ _git_config ()
return return
;; ;;
pull.twohead|pull.octopus) pull.twohead|pull.octopus)
__gitcomp "$(__git_merge_strategies)" __git_compute_merge_strategies
__gitcomp "$__git_merge_strategies"
return return
;; ;;
color.branch|color.diff|color.interactive|\ color.branch|color.diff|color.interactive|\
@ -1528,7 +1532,8 @@ _git_config ()
pager.*) pager.*)
local pfx="${cur%.*}." local pfx="${cur%.*}."
cur="${cur#*.}" cur="${cur#*.}"
__gitcomp "$(__git_all_commands)" "$pfx" "$cur" __git_compute_all_commands
__gitcomp "$__git_all_commands" "$pfx" "$cur"
return return
;; ;;
remote.*.*) remote.*.*)
@ -2125,7 +2130,8 @@ _git ()
--help --help
" "
;; ;;
*) __gitcomp "$(__git_porcelain_commands) $(__git_aliases)" ;; *) __git_compute_porcelain_commands
__gitcomp "$__git_porcelain_commands $(__git_aliases)" ;;
esac esac
return return
fi fi