{"thread":{"id":"28631","subject":"[PATCH 0/9] ref completion optimizations, fixes, and cleanups","startedAt":"2011-10-08T14:54:34Z","lastAt":"2011-10-16T03:29:42Z","messageCount":16,"participants":["SZEDER Gábor","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":9},"messages":[{"id":"177219","messageId":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":null,"subject":"[PATCH 0/9] ref completion optimizations, fixes, and cleanups","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:34Z","receivedAt":"2011-10-08T14:54:34Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Hi,\n\nThis series aims to improve the completion of refs & co.\n\nThis one is the most important in the series; it takes some shortcuts\nto make completing large number of refs faster (it's also faster for\ngit.git, but it's unnoticeable).\n\n  [2/9] completion: optimize refs completion\n\nThe following three make __git_refs() handle local and remote\nrepositories more consistently, and also clean up the remote-handling\ncode part of __git_refs().  They likely make things a bit faster, but\nsince the code path usually involves network communication I didn't\nrun any benchmarks.\n\n  [3/9] completion: make refs completion consistent for local and remote\n          repos\n  [4/9] completion: improve ls-remote output filtering in __git_refs()\n  [5/9] completion: support full refs from remote repositories\n\nThe following two do similar cleanups in __git_refs_remotes() than 3/9\nand 4/9 in __git_refs().\n\n  [6/9] completion: query only refs/heads/ in __git_refs_remotes()\n  [7/9] completion: improve ls-remote output filtering in\n          __git_refs_remotes()\n\nA silly while-at-it optimization; the delay eliminated by this one was\nannoying when testing 6/9 and 7/9.\n\n  [8/9] completion: fast initial completion for config 'remote.*.fetch'\n          value\n\nAnd finally remove some bitrotted code.\n\n  [9/9] completion: remove broken dead code from __git_heads() and\n          __git_tags()\n\n\nThis series is meant to be applied on the merge of master and 77653abd\n(completion: commit --fixup and --squash, 2011-10-06) from pu, and the\npatch in\n\n  Message-ID: <20111008010634.GB11561@goldbirke>\n  (http://article.gmane.org/gmane.comp.version-control.git/183131)\n\nfrom last night applied.  There will be two easily fixable conflicts\nwhen applied directly on top of current master.\n\n\nBest,\nGábor\n\n\nSZEDER Gábor (9):\n  completion: document __gitcomp()\n  completion: optimize refs completion\n  completion: make refs completion consistent for local and remote\n    repos\n  completion: improve ls-remote output filtering in __git_refs()\n  completion: support full refs from remote repositories\n  completion: query only refs/heads/ in __git_refs_remotes()\n  completion: improve ls-remote output filtering in\n    __git_refs_remotes()\n  completion: fast initial completion for config 'remote.*.fetch' value\n  completion: remove broken dead code from __git_heads() and\n    __git_tags()\n\n contrib/completion/git-completion.bash |  200 +++++++++++++++++---------------\n 1 files changed, 109 insertions(+), 91 deletions(-)\n\n-- \n1.7.7.187.ga41de\n"},{"id":"177220","messageId":"1318085683-29830-2-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 1/9] completion: document __gitcomp()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:35Z","receivedAt":"2011-10-08T14:54:35Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"I always forget which argument is which, and got tired of figuring it\nout over and over again.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |    9 +++++++--\n 1 files changed, 7 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex b36f9e70..c0fb6e15 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -485,8 +485,13 @@ _get_comp_words_by_ref ()\n fi\n fi\n \n-# __gitcomp accepts 1, 2, 3, or 4 arguments\n-# generates completion reply with compgen\n+# Generates completion reply with compgen, appending a space to possible\n+# completion words, if necessary.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word (optional).\n __gitcomp ()\n {\n \tlocal cur_=\"$cur\"\n-- \n1.7.7.187.ga41de\n"},{"id":"177221","messageId":"1318085683-29830-3-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 2/9] completion: optimize refs completion","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:36Z","receivedAt":"2011-10-08T14:54:36Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"After a unique command or option is completed, in most cases it is a\ngood thing to add a trailing a space, but sometimes it doesn't makes\nsense, e.g. when the completed word is an option taking an argument\n('--option=') or a configuration section ('core.').  Therefore the\ncompletion script uses the '-o nospace' option to prevent bash from\nautomatically appending a space to unique completions, and it has the\n__gitcomp() function to add that trailing space only when necessary.\nSee 72e5e989 (bash: Add space after unique command name is completed.,\n2007-02-04), 78d4d6a2 (bash: Support unique completion on git-config.,\n2007-02-04), and b3391775 (bash: Support unique completion when\npossible., 2007-02-04).\n\n__gitcomp() therefore iterates over all possible completion words it\ngot as argument, and checks each word whether a trailing space is\nnecessary or not.  This is ok for commands, options, etc., i.e. when\nthe number of words is relatively small, but can be noticeably slow\nfor large number of refs.  However, while options might or might not\nneed that trailing space, refs are always handled uniformly and always\nget that trailing space (or a trailing '.' for 'git config\nbranch.<head>.').  Since refs listed by __git_refs() & co. are\nseparated by newline, this allows us some optimizations with\n'compgen'.\n\nSo, add a specialized variant of __gitcomp() that only deals with\npossible completion words separated by a newline and uniformly appends\nthe trailing space to all words using 'compgen -S' (or any other\nsuffix, if specified), so no iteration over all words is done.\nConvert all callsites of __gitcomp() where it's called with refs, i.e.\nwhen it gets the output of either __git_refs(), __git_heads(),\n__git_tags(), __git_refs2(), __git_refs_remotes(), or the odd 'git\nfor-each-ref' somewhere in _git_config().  Also convert callsites\nwhere it gets other uniformly handled newline separated word lists,\ni.e. either remotes from __git_remotes(), names of set configuration\nvariables from __git_config_get_set_variables(), stashes, or commands\nand aliases.\n\nHere are some timing results for dealing with 10000 refs.\nBefore:\n\n  $ refs=\"$(__git_refs ~/tmp/git/repo-with-10k-refs/)\"\n  $ time __gitcomp \"$refs\"\n\n  real\t0m1.134s\n  user\t0m1.060s\n  sys\t0m0.130s\n\nAfter:\n\n  $ time __gitcomp_nl \"$refs\"\n\n  real\t0m0.373s\n  user\t0m0.360s\n  sys\t0m0.020s\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |  116 +++++++++++++++++++-------------\n 1 files changed, 70 insertions(+), 46 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex c0fb6e15..86de0bf4 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -512,6 +512,30 @@ __gitcomp ()\n \tesac\n }\n \n+# Generates completion reply with compgen.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words, separated by a single newline.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word (optional).\n+#    If omitted, a space is appended; if specified but empty, nothing is\n+#    appended.\n+__gitcomp_nl ()\n+{\n+\tlocal s=$'\\n' IFS=' '$'\\t'$'\\n'\n+\tlocal cur_=\"$cur\" suffix=\" \"\n+\n+\tif [ $# -gt 2 ]; then\n+\t\tcur_=\"$3\"\n+\t\tif [ $# -gt 3 ]; then\n+\t\t\tsuffix=\"$4\"\n+\t\tfi\n+\tfi\n+\n+\tIFS=$s\n+\tCOMPREPLY=($(compgen -P \"${2-}\" -S \"$suffix\" -W \"$1\" -- \"$cur_\"))\n+}\n+\n # __git_heads accepts 0 or 1 arguments (to pass to __gitdir)\n __git_heads ()\n {\n@@ -716,15 +740,15 @@ __git_complete_revlist_file ()\n \t*...*)\n \t\tpfx=\"${cur_%...*}...\"\n \t\tcur_=\"${cur_#*...}\"\n-\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\t;;\n \t*..*)\n \t\tpfx=\"${cur_%..*}..\"\n \t\tcur_=\"${cur_#*..}\"\n-\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\t;;\n \t*)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \tesac\n }\n@@ -764,7 +788,7 @@ __git_complete_remote_or_refspec ()\n \t\tc=$((++c))\n \tdone\n \tif [ -z \"$remote\" ]; then\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\treturn\n \tfi\n \tif [ $no_complete_refspec = 1 ]; then\n@@ -789,23 +813,23 @@ __git_complete_remote_or_refspec ()\n \tcase \"$cmd\" in\n \tfetch)\n \t\tif [ $lhs = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_refs2 \"$remote\")\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs2 \"$remote\")\" \"$pfx\" \"$cur_\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\tfi\n \t\t;;\n \tpull)\n \t\tif [ $lhs = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\tfi\n \t\t;;\n \tpush)\n \t\tif [ $lhs = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n \t\tfi\n \t\t;;\n \tesac\n@@ -1084,7 +1108,7 @@ _git_archive ()\n \t\treturn\n \t\t;;\n \t--remote=*)\n-\t\t__gitcomp \"$(__git_remotes)\" \"\" \"${cur##--remote=}\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\" \"\" \"${cur##--remote=}\"\n \t\treturn\n \t\t;;\n \t--*)\n@@ -1115,7 +1139,7 @@ _git_bisect ()\n \n \tcase \"$subcommand\" in\n \tbad|good|reset|skip|start)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \t*)\n \t\tCOMPREPLY=()\n@@ -1146,9 +1170,9 @@ _git_branch ()\n \t\t;;\n \t*)\n \t\tif [ $only_local_ref = \"y\" -a $has_r = \"n\" ]; then\n-\t\t\t__gitcomp \"$(__git_heads)\"\n+\t\t\t__gitcomp_nl \"$(__git_heads)\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs)\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\tfi\n \t\t;;\n \tesac\n@@ -1195,7 +1219,7 @@ _git_checkout ()\n \t\tif [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n \t\t\ttrack=''\n \t\tfi\n-\t\t__gitcomp \"$(__git_refs '' $track)\"\n+\t\t__gitcomp_nl \"$(__git_refs '' $track)\"\n \t\t;;\n \tesac\n }\n@@ -1212,7 +1236,7 @@ _git_cherry_pick ()\n \t\t__gitcomp \"--edit --no-commit\"\n \t\t;;\n \t*)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \tesac\n }\n@@ -1266,7 +1290,7 @@ _git_commit ()\n \t\t;;\n \t--reuse-message=*|--reedit-message=*|\\\n \t--fixup=*|--squash=*)\n-\t\t__gitcomp \"$(__git_refs)\" \"\" \"${cur#*=}\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"\" \"${cur#*=}\"\n \t\treturn\n \t\t;;\n \t--untracked-files=*)\n@@ -1297,7 +1321,7 @@ _git_describe ()\n \t\t\t\"\n \t\treturn\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n __git_diff_common_options=\"--stat --numstat --shortstat --summary\n@@ -1456,7 +1480,7 @@ _git_grep ()\n \t\t;;\n \tesac\n \n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_help ()\n@@ -1514,7 +1538,7 @@ _git_ls_files ()\n \n _git_ls_remote ()\n {\n-\t__gitcomp \"$(__git_remotes)\"\n+\t__gitcomp_nl \"$(__git_remotes)\"\n }\n \n _git_ls_tree ()\n@@ -1610,7 +1634,7 @@ _git_merge ()\n \t\t__gitcomp \"$__git_merge_options\"\n \t\treturn\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_mergetool ()\n@@ -1630,7 +1654,7 @@ _git_mergetool ()\n \n _git_merge_base ()\n {\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_mv ()\n@@ -1661,7 +1685,7 @@ _git_notes ()\n \t,*)\n \t\tcase \"${words[cword-1]}\" in\n \t\t--ref)\n-\t\t\t__gitcomp \"$(__git_refs)\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t\t;;\n \t\t*)\n \t\t\t__gitcomp \"$subcommands --ref\"\n@@ -1670,7 +1694,7 @@ _git_notes ()\n \t\t;;\n \tadd,--reuse-message=*|append,--reuse-message=*|\\\n \tadd,--reedit-message=*|append,--reedit-message=*)\n-\t\t__gitcomp \"$(__git_refs)\" \"\" \"${cur#*=}\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"\" \"${cur#*=}\"\n \t\t;;\n \tadd,--*|append,--*)\n \t\t__gitcomp '--file= --message= --reedit-message=\n@@ -1689,7 +1713,7 @@ _git_notes ()\n \t\t-m|-F)\n \t\t\t;;\n \t\t*)\n-\t\t\t__gitcomp \"$(__git_refs)\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t\t;;\n \t\tesac\n \t\t;;\n@@ -1717,12 +1741,12 @@ _git_push ()\n {\n \tcase \"$prev\" in\n \t--repo)\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\treturn\n \tesac\n \tcase \"$cur\" in\n \t--repo=*)\n-\t\t__gitcomp \"$(__git_remotes)\" \"\" \"${cur##--repo=}\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\" \"\" \"${cur##--repo=}\"\n \t\treturn\n \t\t;;\n \t--*)\n@@ -1760,7 +1784,7 @@ _git_rebase ()\n \n \t\treturn\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_reflog ()\n@@ -1771,7 +1795,7 @@ _git_reflog ()\n \tif [ -z \"$subcommand\" ]; then\n \t\t__gitcomp \"$subcommands\"\n \telse\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \tfi\n }\n \n@@ -1853,23 +1877,23 @@ _git_config ()\n {\n \tcase \"$prev\" in\n \tbranch.*.remote)\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\treturn\n \t\t;;\n \tbranch.*.merge)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\treturn\n \t\t;;\n \tremote.*.fetch)\n \t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.fetch}\"\n-\t\t__gitcomp \"$(__git_refs_remotes \"$remote\")\"\n+\t\t__gitcomp_nl \"$(__git_refs_remotes \"$remote\")\"\n \t\treturn\n \t\t;;\n \tremote.*.push)\n \t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.push}\"\n-\t\t__gitcomp \"$(git --git-dir=\"$(__gitdir)\" \\\n+\t\t__gitcomp_nl \"$(git --git-dir=\"$(__gitdir)\" \\\n \t\t\tfor-each-ref --format='%(refname):%(refname)' \\\n \t\t\trefs/heads)\"\n \t\treturn\n@@ -1916,7 +1940,7 @@ _git_config ()\n \t\treturn\n \t\t;;\n \t--get|--get-all|--unset|--unset-all)\n-\t\t__gitcomp \"$(__git_config_get_set_variables)\"\n+\t\t__gitcomp_nl \"$(__git_config_get_set_variables)\"\n \t\treturn\n \t\t;;\n \t*.*)\n@@ -1942,7 +1966,7 @@ _git_config ()\n \t\t;;\n \tbranch.*)\n \t\tlocal pfx=\"${cur%.*}.\" cur_=\"${cur#*.}\"\n-\t\t__gitcomp \"$(__git_heads)\" \"$pfx\" \"$cur_\" \".\"\n+\t\t__gitcomp_nl \"$(__git_heads)\" \"$pfx\" \"$cur_\" \".\"\n \t\treturn\n \t\t;;\n \tguitool.*.*)\n@@ -1971,7 +1995,7 @@ _git_config ()\n \tpager.*)\n \t\tlocal pfx=\"${cur%.*}.\" cur_=\"${cur#*.}\"\n \t\t__git_compute_all_commands\n-\t\t__gitcomp \"$__git_all_commands\" \"$pfx\" \"$cur_\"\n+\t\t__gitcomp_nl \"$__git_all_commands\" \"$pfx\" \"$cur_\"\n \t\treturn\n \t\t;;\n \tremote.*.*)\n@@ -1984,7 +2008,7 @@ _git_config ()\n \t\t;;\n \tremote.*)\n \t\tlocal pfx=\"${cur%.*}.\" cur_=\"${cur#*.}\"\n-\t\t__gitcomp \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n \t\treturn\n \t\t;;\n \turl.*.*)\n@@ -2285,7 +2309,7 @@ _git_remote ()\n \n \tcase \"$subcommand\" in\n \trename|rm|show|prune)\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\t;;\n \tupdate)\n \t\tlocal i c='' IFS=$'\\n'\n@@ -2303,7 +2327,7 @@ _git_remote ()\n \n _git_replace ()\n {\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_reset ()\n@@ -2316,7 +2340,7 @@ _git_reset ()\n \t\treturn\n \t\t;;\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_revert ()\n@@ -2327,7 +2351,7 @@ _git_revert ()\n \t\treturn\n \t\t;;\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_rm ()\n@@ -2426,7 +2450,7 @@ _git_stash ()\n \t\t\tCOMPREPLY=()\n \t\t\t;;\n \t\tshow,*|apply,*|drop,*|pop,*|branch,*)\n-\t\t\t__gitcomp \"$(git --git-dir=\"$(__gitdir)\" stash list \\\n+\t\t\t__gitcomp_nl \"$(git --git-dir=\"$(__gitdir)\" stash list \\\n \t\t\t\t\t| sed -n -e 's/:.*//p')\"\n \t\t\t;;\n \t\t*)\n@@ -2560,7 +2584,7 @@ _git_tag ()\n \t\ti=\"${words[c]}\"\n \t\tcase \"$i\" in\n \t\t-d|-v)\n-\t\t\t__gitcomp \"$(__git_tags)\"\n+\t\t\t__gitcomp_nl \"$(__git_tags)\"\n \t\t\treturn\n \t\t\t;;\n \t\t-f)\n@@ -2576,13 +2600,13 @@ _git_tag ()\n \t\t;;\n \t-*|tag)\n \t\tif [ $f = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_tags)\"\n+\t\t\t__gitcomp_nl \"$(__git_tags)\"\n \t\telse\n \t\t\tCOMPREPLY=()\n \t\tfi\n \t\t;;\n \t*)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \tesac\n }\n@@ -2635,7 +2659,7 @@ _git ()\n \t\t\t\"\n \t\t\t;;\n \t\t*)     __git_compute_porcelain_commands\n-\t\t       __gitcomp \"$__git_porcelain_commands $(__git_aliases)\" ;;\n+\t\t       __gitcomp_nl \"$__git_porcelain_commands $(__git_aliases)\" ;;\n \t\tesac\n \t\treturn\n \tfi\n-- \n1.7.7.187.ga41de\n"},{"id":"177222","messageId":"1318085683-29830-4-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 3/9] completion: make refs completion consistent for local and remote repos","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:37Z","receivedAt":"2011-10-08T14:54:37Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"For a local repository the __git_refs() completion helper function\nlists refs under 'refs/(tags|heads|remotes)/', plus some special refs\nlike HEAD and ORIG_HEAD.  For a remote repository, however, it lists\nall refs.\n\nFix this inconsistency by specifying refs filter patterns for 'git\nls-remote' to only list refs under 'refs/(tags|heads|remotes)/'.\n\nFor now this makes it impossible to complete refs outside of\n'refs/(tags|heads|remotes)/' in a remote repository, but a followup\npatch will resurrect that.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |    6 ++----\n 1 files changed, 2 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 86de0bf4..6b5dc5cd 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -615,13 +615,11 @@ __git_refs ()\n \t\tfi\n \t\treturn\n \tfi\n-\tfor i in $(git ls-remote \"$dir\" 2>/dev/null); do\n+\tfor i in $(git ls-remote \"$dir\" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null); do\n \t\tcase \"$is_hash,$i\" in\n \t\ty,*) is_hash=n ;;\n \t\tn,*^{}) is_hash=y ;;\n-\t\tn,refs/tags/*) is_hash=y; echo \"${i#refs/tags/}\" ;;\n-\t\tn,refs/heads/*) is_hash=y; echo \"${i#refs/heads/}\" ;;\n-\t\tn,refs/remotes/*) is_hash=y; echo \"${i#refs/remotes/}\" ;;\n+\t\tn,refs/*) is_hash=y; echo \"${i#refs/*/}\" ;;\n \t\tn,*) is_hash=y; echo \"$i\" ;;\n \t\tesac\n \tdone\n-- \n1.7.7.187.ga41de\n"},{"id":"177223","messageId":"1318085683-29830-5-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 4/9] completion: improve ls-remote output filtering in __git_refs()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:38Z","receivedAt":"2011-10-08T14:54:38Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"The remote-handling part of __git_refs() has a nice for loop and state\nmachine case statement to iterate over all words from the output of\n'git ls-remote' to identify object names and ref names.  Since each\nline in the output of 'git ls-remote' consists of an object name and a\nref name, we can do more effective filtering by using a while-read\nloop and letting bash's word splitting take care of object names.\nThis way the code is easier to understand and the loop will need only\nhalf the number of iterations than before.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |   14 +++++++-------\n 1 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6b5dc5cd..c6ab742d 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -579,7 +579,7 @@ __git_tags ()\n # by checkout for tracking branches\n __git_refs ()\n {\n-\tlocal i is_hash=y dir=\"$(__gitdir \"${1-}\")\" track=\"${2-}\"\n+\tlocal i hash dir=\"$(__gitdir \"${1-}\")\" track=\"${2-}\"\n \tlocal format refs\n \tif [ -d \"$dir\" ]; then\n \t\tcase \"$cur\" in\n@@ -615,12 +615,12 @@ __git_refs ()\n \t\tfi\n \t\treturn\n \tfi\n-\tfor i in $(git ls-remote \"$dir\" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null); do\n-\t\tcase \"$is_hash,$i\" in\n-\t\ty,*) is_hash=n ;;\n-\t\tn,*^{}) is_hash=y ;;\n-\t\tn,refs/*) is_hash=y; echo \"${i#refs/*/}\" ;;\n-\t\tn,*) is_hash=y; echo \"$i\" ;;\n+\tgit ls-remote \"$dir\" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \\\n+\twhile read hash i; do\n+\t\tcase \"$i\" in\n+\t\t*^{}) ;;\n+\t\trefs/*) echo \"${i#refs/*/}\" ;;\n+\t\t*) echo \"$i\" ;;\n \t\tesac\n \tdone\n }\n-- \n1.7.7.187.ga41de\n"},{"id":"177224","messageId":"1318085683-29830-6-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 5/9] completion: support full refs from remote repositories","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:39Z","receivedAt":"2011-10-08T14:54:39Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"When the __git_refs() completion helper function lists refs from a\nlocal repository, it usually lists the refs' short name, except when\nit needs to provide completion for words starting with refs, because\nin that case it lists full ref names, see 608efb87 (bash: complete\nfull refs, 2008-11-28).\n\nAdd the same functionality to the code path dealing with remote\nrepositories, too.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |   29 +++++++++++++++++++++--------\n 1 files changed, 21 insertions(+), 8 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex c6ab742d..a8d3597e 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -615,14 +615,27 @@ __git_refs ()\n \t\tfi\n \t\treturn\n \tfi\n-\tgit ls-remote \"$dir\" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \\\n-\twhile read hash i; do\n-\t\tcase \"$i\" in\n-\t\t*^{}) ;;\n-\t\trefs/*) echo \"${i#refs/*/}\" ;;\n-\t\t*) echo \"$i\" ;;\n-\t\tesac\n-\tdone\n+\tcase \"$cur\" in\n+\trefs|refs/*)\n+\t\tgit ls-remote \"$dir\" \"$cur*\" 2>/dev/null | \\\n+\t\twhile read hash i; do\n+\t\t\tcase \"$i\" in\n+\t\t\t*^{}) ;;\n+\t\t\t*) echo \"$i\" ;;\n+\t\t\tesac\n+\t\tdone\n+\t\t;;\n+\t*)\n+\t\tgit ls-remote \"$dir\" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \\\n+\t\twhile read hash i; do\n+\t\t\tcase \"$i\" in\n+\t\t\t*^{}) ;;\n+\t\t\trefs/*) echo \"${i#refs/*/}\" ;;\n+\t\t\t*) echo \"$i\" ;;\n+\t\t\tesac\n+\t\tdone\n+\t\t;;\n+\tesac\n }\n \n # __git_refs2 requires 1 argument (to pass to __git_refs)\n-- \n1.7.7.187.ga41de\n"},{"id":"177225","messageId":"1318085683-29830-7-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 6/9] completion: query only refs/heads/ in __git_refs_remotes()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:40Z","receivedAt":"2011-10-08T14:54:40Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"__git_refs_remotes() is used to provide completion for refspecs to set\n'remote.*.fetch' config variables for branches on the given remote.\nSo it's really only interested in refs under 'refs/heads/', but it\nqueries the remote for all its refs and then filters out all refs\noutside of 'refs/heads/'.\n\nLet 'git ls-remote' do the filtering.\n\nAlso remove the unused $cmd variable from __git_refs_remotes().\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |   13 +++++--------\n 1 files changed, 5 insertions(+), 8 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex a8d3597e..dc1d5e90 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -650,17 +650,14 @@ __git_refs2 ()\n # __git_refs_remotes requires 1 argument (to pass to ls-remote)\n __git_refs_remotes ()\n {\n-\tlocal cmd i is_hash=y\n-\tfor i in $(git ls-remote \"$1\" 2>/dev/null); do\n-\t\tcase \"$is_hash,$i\" in\n-\t\tn,refs/heads/*)\n+\tlocal i is_hash=y\n+\tfor i in $(git ls-remote \"$1\" 'refs/heads/*' 2>/dev/null); do\n+\t\tcase \"$is_hash\" in\n+\t\tn)\n \t\t\tis_hash=y\n \t\t\techo \"$i:refs/remotes/$1/${i#refs/heads/}\"\n \t\t\t;;\n-\t\ty,*) is_hash=n ;;\n-\t\tn,*^{}) is_hash=y ;;\n-\t\tn,refs/tags/*) is_hash=y;;\n-\t\tn,*) is_hash=y; ;;\n+\t\ty) is_hash=n ;;\n \t\tesac\n \tdone\n }\n-- \n1.7.7.187.ga41de\n"},{"id":"177226","messageId":"1318085683-29830-8-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 7/9] completion: improve ls-remote output filtering in __git_refs_remotes()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:41Z","receivedAt":"2011-10-08T14:54:41Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"This follows suit of a previous patch for __git_refs(): use a\nwhile-read loop and let bash's word splitting get rid of object names\nfrom 'git ls-remote's output.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |   13 ++++---------\n 1 files changed, 4 insertions(+), 9 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex dc1d5e90..658df3a7 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -650,15 +650,10 @@ __git_refs2 ()\n # __git_refs_remotes requires 1 argument (to pass to ls-remote)\n __git_refs_remotes ()\n {\n-\tlocal i is_hash=y\n-\tfor i in $(git ls-remote \"$1\" 'refs/heads/*' 2>/dev/null); do\n-\t\tcase \"$is_hash\" in\n-\t\tn)\n-\t\t\tis_hash=y\n-\t\t\techo \"$i:refs/remotes/$1/${i#refs/heads/}\"\n-\t\t\t;;\n-\t\ty) is_hash=n ;;\n-\t\tesac\n+\tlocal i hash\n+\tgit ls-remote \"$1\" 'refs/heads/*' 2>/dev/null | \\\n+\twhile read hash i; do\n+\t\techo \"$i:refs/remotes/$1/${i#refs/heads/}\"\n \tdone\n }\n \n-- \n1.7.7.187.ga41de\n"},{"id":"177227","messageId":"1318085683-29830-9-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 8/9] completion: fast initial completion for config 'remote.*.fetch' value","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:42Z","receivedAt":"2011-10-08T14:54:42Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"Refspecs for branches in a remote repository start with 'refs/heads/',\nso completing those refspecs with 'git config remote.origin.fetch\n<TAB>' always offers 'refs/heads/' first, because that's the unique\npart of the possible refspecs.  But it does so only after querying the\nremote with 'git ls-remote', which can take a while when the request\ngoes through some slower network to a remote server.\n\nDon't waste the user's time and offer 'refs/heads/' right away for\n'git config remote.origin.fetch <TAB>'.\n\nThe reason for putting 'refs/heads/' directly into COMPREPLY instead\nof using __gitcomp() is to avoid __gitcomp() adding a trailing space.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |    4 ++++\n 1 files changed, 4 insertions(+), 0 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 658df3a7..d7151220 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1890,6 +1890,10 @@ _git_config ()\n \tremote.*.fetch)\n \t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.fetch}\"\n+\t\tif [ -z \"$cur\" ]; then\n+\t\t\tCOMPREPLY=(\"refs/heads/\")\n+\t\t\treturn\n+\t\tfi\n \t\t__gitcomp_nl \"$(__git_refs_remotes \"$remote\")\"\n \t\treturn\n \t\t;;\n-- \n1.7.7.187.ga41de\n"},{"id":"177228","messageId":"1318085683-29830-10-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"1318085683-29830-1-git-send-email-szeder@ira.uka.de","subject":"[PATCH 9/9] completion: remove broken dead code from __git_heads() and __git_tags()","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-08T14:54:43Z","receivedAt":"2011-10-08T14:54:43Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"__git_heads() was introduced in 5de40f5 (Teach bash about\ngit-repo-config., 2006-11-27), and __git_tags() in 88e21dc (Teach bash\nabout completing arguments for git-tag, 2007-08-31).  As their name\nsuggests, __git_heads() is supposed to list only branches, and\n__git_tags() only tags.\n\nSince their introduction both of these functions consist of two\ndistinct parts.  The first part gets branches or tags, respectively,\nfrom a local repositoty using 'git for-each-ref'.  The second part\nqueries a remote repository given as argument using 'git ls-remote'.\n\nThese remote-querying parts are broken in both functions since their\nintroduction, because they list both branches and tags from the remote\nrepository.  (The 'git ls-remote' query is not limited to list only\nheads or tags, respectively, and the for loop filtering the query\nresults prints everything except dereferenced tags.)  This breakage\ncould be easily fixed by passing the '--heads' or '--tags' options or\nappropriate refs patterns to the 'git ls-remote' invocations.\n\nHowever, that no one noticed this breakage yet is probably not a\ncoincidence: neither of these two functions were used to query a\nremote repository, the remote-querying parts were dead code already\nupon thier introduction and remained dead ever since.\n\nSince those parts of code are broken, are and were never used, stop\nthe bit-rotting and remove them.\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n contrib/completion/git-completion.bash |   22 ++--------------------\n 1 files changed, 2 insertions(+), 20 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex d7151220..802b703d 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -536,42 +536,24 @@ __gitcomp_nl ()\n \tCOMPREPLY=($(compgen -P \"${2-}\" -S \"$suffix\" -W \"$1\" -- \"$cur_\"))\n }\n \n-# __git_heads accepts 0 or 1 arguments (to pass to __gitdir)\n __git_heads ()\n {\n-\tlocal cmd i is_hash=y dir=\"$(__gitdir \"${1-}\")\"\n+\tlocal dir=\"$(__gitdir)\"\n \tif [ -d \"$dir\" ]; then\n \t\tgit --git-dir=\"$dir\" for-each-ref --format='%(refname:short)' \\\n \t\t\trefs/heads\n \t\treturn\n \tfi\n-\tfor i in $(git ls-remote \"${1-}\" 2>/dev/null); do\n-\t\tcase \"$is_hash,$i\" in\n-\t\ty,*) is_hash=n ;;\n-\t\tn,*^{}) is_hash=y ;;\n-\t\tn,refs/heads/*) is_hash=y; echo \"${i#refs/heads/}\" ;;\n-\t\tn,*) is_hash=y; echo \"$i\" ;;\n-\t\tesac\n-\tdone\n }\n \n-# __git_tags accepts 0 or 1 arguments (to pass to __gitdir)\n __git_tags ()\n {\n-\tlocal cmd i is_hash=y dir=\"$(__gitdir \"${1-}\")\"\n+\tlocal dir=\"$(__gitdir)\"\n \tif [ -d \"$dir\" ]; then\n \t\tgit --git-dir=\"$dir\" for-each-ref --format='%(refname:short)' \\\n \t\t\trefs/tags\n \t\treturn\n \tfi\n-\tfor i in $(git ls-remote \"${1-}\" 2>/dev/null); do\n-\t\tcase \"$is_hash,$i\" in\n-\t\ty,*) is_hash=n ;;\n-\t\tn,*^{}) is_hash=y ;;\n-\t\tn,refs/tags/*) is_hash=y; echo \"${i#refs/tags/}\" ;;\n-\t\tn,*) is_hash=y; echo \"$i\" ;;\n-\t\tesac\n-\tdone\n }\n \n # __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments\n-- \n1.7.7.187.ga41de\n"},{"id":"177503","messageId":"7v7h497m01.fsf@alter.siamese.dyndns.org","threadId":"28631","inReplyTo":"1318085683-29830-3-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH 2/9] completion: optimize refs completion","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-13T00:50:38Z","receivedAt":"2011-10-13T00:50:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder@ira.uka.de> writes:\n\n> After a unique command or option is completed, in most cases it is a\n> good thing to add a trailing a space, but sometimes it doesn't makes\n\ns/makes/make/;\n\n> __gitcomp() therefore iterates over all possible completion words it\n> got as argument, and checks each word whether a trailing space is\n> necessary or not.  This is ok for commands, options, etc., i.e. when\n> the number of words is relatively small, but can be noticeably slow\n> for large number of refs.  However, while options might or might not\n> need that trailing space, refs are always handled uniformly and always\n> get that trailing space (or a trailing '.' for 'git config\n> branch.<head>.').\n> ...\n> So, add a specialized variant of __gitcomp() that only deals with\n> possible completion words separated by a newline and uniformly appends\n> the trailing space to all words using 'compgen -S' (or any other\n> suffix, if specified), so no iteration over all words is done.\n\ns/is done./is needed./;\n\nI think I followed your logic (very well written ;-), but feel somewhat\ndirty, as you are conflating the \"These things are separated with newlines\"\nwith \"These things do not need inspection --- they all need suffix\", which\nhas one obvious drawback --- you may find other class of words that always\nwant a SP after each of them but the source that generates such a class of\nwords may not separate the list elements with a newline.\n\nBecause a ref cannot have $IFS whitespace in its name anyway, I think you\ncan rename __gitcomp_nl to a name that conveys more clearly what it does\n(i.e. \"complete and always append suffix\"), drop the IFS fiddling from the\nfunction, and get the same optimization, no?\n"},{"id":"177535","messageId":"20111013104047.GA15379@goldbirke","threadId":"28631","inReplyTo":"7v7h497m01.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 2/9] completion: optimize refs completion","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-13T10:40:47Z","receivedAt":"2011-10-13T10:40:47Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Wed, Oct 12, 2011 at 05:50:38PM -0700, Junio C Hamano wrote:\n> SZEDER Gábor <szeder@ira.uka.de> writes:\n> \n> > After a unique command or option is completed, in most cases it is a\n> > good thing to add a trailing a space, but sometimes it doesn't makes\n> \n> s/makes/make/;\n> \n> > __gitcomp() therefore iterates over all possible completion words it\n> > got as argument, and checks each word whether a trailing space is\n> > necessary or not.  This is ok for commands, options, etc., i.e. when\n> > the number of words is relatively small, but can be noticeably slow\n> > for large number of refs.  However, while options might or might not\n> > need that trailing space, refs are always handled uniformly and always\n> > get that trailing space (or a trailing '.' for 'git config\n> > branch.<head>.').\n> > ...\n> > So, add a specialized variant of __gitcomp() that only deals with\n> > possible completion words separated by a newline and uniformly appends\n> > the trailing space to all words using 'compgen -S' (or any other\n> > suffix, if specified), so no iteration over all words is done.\n> \n> s/is done./is needed./;\n> \n> I think I followed your logic (very well written ;-)\n\nThanks; learned it around here ;)\n\n> but feel somewhat\n> dirty, as you are conflating the \"These things are separated with newlines\"\n> with \"These things do not need inspection --- they all need suffix\", which\n> has one obvious drawback --- you may find other class of words that always\n> want a SP after each of them but the source that generates such a class of\n> words may not separate the list elements with a newline.\n\nYes, there are a couple of other places where SP is uniformly needed,\nfor example completion of subcommands for bisect, notes, stash, etc.,\nmerge strategies, whitespace options, which are all separated by SP,\nor help topics, which are separated by SP, TAB, and NL.  However, it\nreally is necessary that no SP is used to separate those words, see\nbelow, so we can't use this optimization in these cases.  And since\nthe number of possible completion words in these cases is usually low,\nit doesn't worth the effort to restructure those words to not use SP\nseparator, because it doesn't really make a performance difference\nanyway.\n\n> Because a ref cannot have $IFS whitespace in its name anyway, I think you\n> can rename __gitcomp_nl to a name that conveys more clearly what it does\n> (i.e. \"complete and always append suffix\"), drop the IFS fiddling from the\n> function, and get the same optimization, no?\n\nUnfortunately, this optimization depends on the IFS fiddling, because\nwe want to append a SP.  The same IFS trick is done in __gitcomp(),\ntoo.  If we use the default IFS containing an SP and append a SP to\npossible completion words by 'compgen -S \" \"' (or by word=\"$word \", as\nin __gitcomp_1()), then that SP will be promply stripped off when\ncompgen's output is stored in the COMPREPLY array.  Using an IFS\nwithout SP keeps those SP suffixes.  Perhaps I should've mentioned\nthis explicitly in the commit message, but didn't do so because one of\nthe referenced commit messages (72e5e989 (bash: Add space after unique\ncommand name is completed., 2007-02-04)) already mentioned it briefly.\n\nBut when we use an IFS without SP, that also implies that we can't\npass words separated by SP to __gitcomp_nl(), because those words\nwon't be split at SPs anymore.  Since refs & co. are separated by NL,\nit was the obvious choice for this special-purpose IFS.  So this\noptimization can't work with the class of words mentioned above.  \n\nSo I thought that it's important to stress that this function can only\ndeal with NL separated words, hence I named it __gitcomp_nl().  But I\nsee your point about naming it after what it actually does, so I'm\nfine with __gitcomp_add_suffix() or whatever else that indicates\n\"complete and always append suffix\".\n\nWill resend in a day or two, to leave some time for other suggestions.\n\n\nBest,\nGábor\n"},{"id":"177570","messageId":"7vk4886btf.fsf@alter.siamese.dyndns.org","threadId":"28631","inReplyTo":"20111013104047.GA15379@goldbirke","subject":"Re: [PATCH 2/9] completion: optimize refs completion","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-13T17:28:12Z","receivedAt":"2011-10-13T17:28:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"SZEDER Gábor <szeder@ira.uka.de> writes:\n\n> ... If we use the default IFS containing an SP and append a SP to\n> possible completion words by 'compgen -S \" \"' (or by word=\"$word \", as\n> in __gitcomp_1()), then that SP will be promply stripped off when\n> compgen's output is stored in the COMPREPLY array.  Using an IFS\n> without SP keeps those SP suffixes.\n\nAhh, then I am perfectly fine with the \"nl\" in its name.\n\nThis is a function that unconditionally completes with trailing separator,\navoiding the cost of having to inspect each element, but the user needs to\nkeep in mind that the elements in the input must be separated with NL, so\nideally the name needs to convey both of these points---dropping \"nl\" was\na bad suggestion.\n\nThanks for a clear explanation.\n"},{"id":"177636","messageId":"20111014121609.GB2208@goldbirke","threadId":"28631","inReplyTo":"1318085683-29830-3-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH 2/9] completion: optimize refs completion","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-14T12:16:09Z","receivedAt":"2011-10-14T12:16:09Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Sat, Oct 08, 2011 at 04:54:36PM +0200, SZEDER Gábor wrote:\n> So, add a specialized variant of __gitcomp() that only deals with\n> possible completion words separated by a newline \n\n> @@ -2635,7 +2659,7 @@ _git ()\n>  \t\t\t\"\n>  \t\t\t;;\n>  \t\t*)     __git_compute_porcelain_commands\n> -\t\t       __gitcomp \"$__git_porcelain_commands $(__git_aliases)\" ;;\n> +\t\t       __gitcomp_nl \"$__git_porcelain_commands $(__git_aliases)\" ;;\n>  \t\tesac\n>  \t\treturn\n>  \tfi\n\nOops, this last hunk is wrong.\n\nI made the thinko that $__git_porcelain_commands is NL-separated and\nthe output of __git_aliases() is NL-separated, so we can pass the two\ntogether to the new __gitcomp_nl() function.  But of course not,\nbecause the SP between the two joins the last command and the first\nalias.\n\nI will resend in the evening with this hunk removed and the commit\nmessage updated.\n\n\nGábor\n"},{"id":"177722","messageId":"1318683443-1896-1-git-send-email-szeder@ira.uka.de","threadId":"28631","inReplyTo":"20111014121609.GB2208@goldbirke","subject":"[PATCH 2/9 v2] completion: optimize refs completion","fromName":"SZEDER Gábor","fromEmail":"szeder@ira.uka.de","sentAt":"2011-10-15T12:57:23Z","receivedAt":"2011-10-15T12:57:23Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"After a unique command or option is completed, in most cases it is a\ngood thing to add a trailing a space, but sometimes it doesn't make\nsense, e.g. when the completed word is an option taking an argument\n('--option=') or a configuration section ('core.').  Therefore the\ncompletion script uses the '-o nospace' option to prevent bash from\nautomatically appending a space to unique completions, and it has the\n__gitcomp() function to add that trailing space only when necessary.\nSee 72e5e989 (bash: Add space after unique command name is completed.,\n2007-02-04), 78d4d6a2 (bash: Support unique completion on git-config.,\n2007-02-04), and b3391775 (bash: Support unique completion when\npossible., 2007-02-04).\n\n__gitcomp() therefore iterates over all possible completion words it\ngot as argument, and checks each word whether a trailing space is\nnecessary or not.  This is ok for commands, options, etc., i.e. when\nthe number of words is relatively small, but can be noticeably slow\nfor large number of refs.  However, while options might or might not\nneed that trailing space, refs are always handled uniformly and always\nget that trailing space (or a trailing '.' for 'git config\nbranch.<head>.').  Since refs listed by __git_refs() & co. are\nseparated by newline, this allows us some optimizations with\n'compgen'.\n\nSo, add a specialized variant of __gitcomp() that only deals with\npossible completion words separated by a newline and uniformly appends\nthe trailing space to all words using 'compgen -S \" \"' (or any other\nsuffix, if specified), so no iteration over all words is needed.  But\nwe need to fiddle with IFS, because the default IFS containing a space\nwould cause the added space suffix to be stripped off when compgen's\noutput is stored in the COMPREPLY array.  Therefore we use only\nnewline as IFS, hence the requirement for the newline-separated\npossible completion words.\n\nConvert all callsites of __gitcomp() where it's called with refs, i.e.\nwhen it gets the output of either __git_refs(), __git_heads(),\n__git_tags(), __git_refs2(), __git_refs_remotes(), or the odd 'git\nfor-each-ref' somewhere in _git_config().  Also convert callsites\nwhere it gets other uniformly handled newline separated word lists,\ni.e. either remotes from __git_remotes(), names of set configuration\nvariables from __git_config_get_set_variables(), stashes, or commands.\n\nHere are some timing results for dealing with 10000 refs.\nBefore:\n\n  $ refs=\"$(__git_refs ~/tmp/git/repo-with-10k-refs/)\"\n  $ time __gitcomp \"$refs\"\n\n  real\t0m1.134s\n  user\t0m1.060s\n  sys\t0m0.130s\n\nAfter:\n\n  $ time __gitcomp_nl \"$refs\"\n\n  real\t0m0.373s\n  user\t0m0.360s\n  sys\t0m0.020s\n\nSigned-off-by: SZEDER Gábor <szeder@ira.uka.de>\n---\n\nOn Fri, Oct 14, 2011 at 02:16:09PM +0200, SZEDER Gábor wrote:\n> Oops, this last hunk is wrong.\n\nHere's the update with that buggy hunk removed.  I also updated the\ncomments before __gitcomp_nl() to be more explicit, and the commit\nmessage with the IFS fiddling and the grammar errors you pointed out\nearlier.\n\nThese changes don't conflict with later patches, so I resend only this\npatch but not the whole series.\n\n contrib/completion/git-completion.bash |  115 +++++++++++++++++++------------\n 1 files changed, 70 insertions(+), 45 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex c0fb6e15..daabf827 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -512,6 +512,31 @@ __gitcomp ()\n \tesac\n }\n \n+# Generates completion reply with compgen from newline-separated possible\n+# completion words by appending a space to all of them.\n+# It accepts 1 to 4 arguments:\n+# 1: List of possible completion words, separated by a single newline.\n+# 2: A prefix to be added to each possible completion word (optional).\n+# 3: Generate possible completion matches for this word (optional).\n+# 4: A suffix to be appended to each possible completion word instead of\n+#    the default space (optional).  If specified but empty, nothing is\n+#    appended.\n+__gitcomp_nl ()\n+{\n+\tlocal s=$'\\n' IFS=' '$'\\t'$'\\n'\n+\tlocal cur_=\"$cur\" suffix=\" \"\n+\n+\tif [ $# -gt 2 ]; then\n+\t\tcur_=\"$3\"\n+\t\tif [ $# -gt 3 ]; then\n+\t\t\tsuffix=\"$4\"\n+\t\tfi\n+\tfi\n+\n+\tIFS=$s\n+\tCOMPREPLY=($(compgen -P \"${2-}\" -S \"$suffix\" -W \"$1\" -- \"$cur_\"))\n+}\n+\n # __git_heads accepts 0 or 1 arguments (to pass to __gitdir)\n __git_heads ()\n {\n@@ -716,15 +741,15 @@ __git_complete_revlist_file ()\n \t*...*)\n \t\tpfx=\"${cur_%...*}...\"\n \t\tcur_=\"${cur_#*...}\"\n-\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\t;;\n \t*..*)\n \t\tpfx=\"${cur_%..*}..\"\n \t\tcur_=\"${cur_#*..}\"\n-\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\t;;\n \t*)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \tesac\n }\n@@ -764,7 +789,7 @@ __git_complete_remote_or_refspec ()\n \t\tc=$((++c))\n \tdone\n \tif [ -z \"$remote\" ]; then\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\treturn\n \tfi\n \tif [ $no_complete_refspec = 1 ]; then\n@@ -789,23 +814,23 @@ __git_complete_remote_or_refspec ()\n \tcase \"$cmd\" in\n \tfetch)\n \t\tif [ $lhs = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_refs2 \"$remote\")\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs2 \"$remote\")\" \"$pfx\" \"$cur_\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\tfi\n \t\t;;\n \tpull)\n \t\tif [ $lhs = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\tfi\n \t\t;;\n \tpush)\n \t\tif [ $lhs = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\" \"$pfx\" \"$cur_\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n+\t\t\t__gitcomp_nl \"$(__git_refs \"$remote\")\" \"$pfx\" \"$cur_\"\n \t\tfi\n \t\t;;\n \tesac\n@@ -1084,7 +1109,7 @@ _git_archive ()\n \t\treturn\n \t\t;;\n \t--remote=*)\n-\t\t__gitcomp \"$(__git_remotes)\" \"\" \"${cur##--remote=}\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\" \"\" \"${cur##--remote=}\"\n \t\treturn\n \t\t;;\n \t--*)\n@@ -1115,7 +1140,7 @@ _git_bisect ()\n \n \tcase \"$subcommand\" in\n \tbad|good|reset|skip|start)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \t*)\n \t\tCOMPREPLY=()\n@@ -1146,9 +1171,9 @@ _git_branch ()\n \t\t;;\n \t*)\n \t\tif [ $only_local_ref = \"y\" -a $has_r = \"n\" ]; then\n-\t\t\t__gitcomp \"$(__git_heads)\"\n+\t\t\t__gitcomp_nl \"$(__git_heads)\"\n \t\telse\n-\t\t\t__gitcomp \"$(__git_refs)\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\tfi\n \t\t;;\n \tesac\n@@ -1195,7 +1220,7 @@ _git_checkout ()\n \t\tif [ -n \"$(__git_find_on_cmdline \"$flags\")\" ]; then\n \t\t\ttrack=''\n \t\tfi\n-\t\t__gitcomp \"$(__git_refs '' $track)\"\n+\t\t__gitcomp_nl \"$(__git_refs '' $track)\"\n \t\t;;\n \tesac\n }\n@@ -1212,7 +1237,7 @@ _git_cherry_pick ()\n \t\t__gitcomp \"--edit --no-commit\"\n \t\t;;\n \t*)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \tesac\n }\n@@ -1266,7 +1291,7 @@ _git_commit ()\n \t\t;;\n \t--reuse-message=*|--reedit-message=*|\\\n \t--fixup=*|--squash=*)\n-\t\t__gitcomp \"$(__git_refs)\" \"\" \"${cur#*=}\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"\" \"${cur#*=}\"\n \t\treturn\n \t\t;;\n \t--untracked-files=*)\n@@ -1297,7 +1322,7 @@ _git_describe ()\n \t\t\t\"\n \t\treturn\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n __git_diff_common_options=\"--stat --numstat --shortstat --summary\n@@ -1456,7 +1481,7 @@ _git_grep ()\n \t\t;;\n \tesac\n \n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_help ()\n@@ -1514,7 +1539,7 @@ _git_ls_files ()\n \n _git_ls_remote ()\n {\n-\t__gitcomp \"$(__git_remotes)\"\n+\t__gitcomp_nl \"$(__git_remotes)\"\n }\n \n _git_ls_tree ()\n@@ -1610,7 +1635,7 @@ _git_merge ()\n \t\t__gitcomp \"$__git_merge_options\"\n \t\treturn\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_mergetool ()\n@@ -1630,7 +1655,7 @@ _git_mergetool ()\n \n _git_merge_base ()\n {\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_mv ()\n@@ -1661,7 +1686,7 @@ _git_notes ()\n \t,*)\n \t\tcase \"${words[cword-1]}\" in\n \t\t--ref)\n-\t\t\t__gitcomp \"$(__git_refs)\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t\t;;\n \t\t*)\n \t\t\t__gitcomp \"$subcommands --ref\"\n@@ -1670,7 +1695,7 @@ _git_notes ()\n \t\t;;\n \tadd,--reuse-message=*|append,--reuse-message=*|\\\n \tadd,--reedit-message=*|append,--reedit-message=*)\n-\t\t__gitcomp \"$(__git_refs)\" \"\" \"${cur#*=}\"\n+\t\t__gitcomp_nl \"$(__git_refs)\" \"\" \"${cur#*=}\"\n \t\t;;\n \tadd,--*|append,--*)\n \t\t__gitcomp '--file= --message= --reedit-message=\n@@ -1689,7 +1714,7 @@ _git_notes ()\n \t\t-m|-F)\n \t\t\t;;\n \t\t*)\n-\t\t\t__gitcomp \"$(__git_refs)\"\n+\t\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t\t;;\n \t\tesac\n \t\t;;\n@@ -1717,12 +1742,12 @@ _git_push ()\n {\n \tcase \"$prev\" in\n \t--repo)\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\treturn\n \tesac\n \tcase \"$cur\" in\n \t--repo=*)\n-\t\t__gitcomp \"$(__git_remotes)\" \"\" \"${cur##--repo=}\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\" \"\" \"${cur##--repo=}\"\n \t\treturn\n \t\t;;\n \t--*)\n@@ -1760,7 +1785,7 @@ _git_rebase ()\n \n \t\treturn\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_reflog ()\n@@ -1771,7 +1796,7 @@ _git_reflog ()\n \tif [ -z \"$subcommand\" ]; then\n \t\t__gitcomp \"$subcommands\"\n \telse\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \tfi\n }\n \n@@ -1853,23 +1878,23 @@ _git_config ()\n {\n \tcase \"$prev\" in\n \tbranch.*.remote)\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\treturn\n \t\t;;\n \tbranch.*.merge)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\treturn\n \t\t;;\n \tremote.*.fetch)\n \t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.fetch}\"\n-\t\t__gitcomp \"$(__git_refs_remotes \"$remote\")\"\n+\t\t__gitcomp_nl \"$(__git_refs_remotes \"$remote\")\"\n \t\treturn\n \t\t;;\n \tremote.*.push)\n \t\tlocal remote=\"${prev#remote.}\"\n \t\tremote=\"${remote%.push}\"\n-\t\t__gitcomp \"$(git --git-dir=\"$(__gitdir)\" \\\n+\t\t__gitcomp_nl \"$(git --git-dir=\"$(__gitdir)\" \\\n \t\t\tfor-each-ref --format='%(refname):%(refname)' \\\n \t\t\trefs/heads)\"\n \t\treturn\n@@ -1916,7 +1941,7 @@ _git_config ()\n \t\treturn\n \t\t;;\n \t--get|--get-all|--unset|--unset-all)\n-\t\t__gitcomp \"$(__git_config_get_set_variables)\"\n+\t\t__gitcomp_nl \"$(__git_config_get_set_variables)\"\n \t\treturn\n \t\t;;\n \t*.*)\n@@ -1942,7 +1967,7 @@ _git_config ()\n \t\t;;\n \tbranch.*)\n \t\tlocal pfx=\"${cur%.*}.\" cur_=\"${cur#*.}\"\n-\t\t__gitcomp \"$(__git_heads)\" \"$pfx\" \"$cur_\" \".\"\n+\t\t__gitcomp_nl \"$(__git_heads)\" \"$pfx\" \"$cur_\" \".\"\n \t\treturn\n \t\t;;\n \tguitool.*.*)\n@@ -1971,7 +1996,7 @@ _git_config ()\n \tpager.*)\n \t\tlocal pfx=\"${cur%.*}.\" cur_=\"${cur#*.}\"\n \t\t__git_compute_all_commands\n-\t\t__gitcomp \"$__git_all_commands\" \"$pfx\" \"$cur_\"\n+\t\t__gitcomp_nl \"$__git_all_commands\" \"$pfx\" \"$cur_\"\n \t\treturn\n \t\t;;\n \tremote.*.*)\n@@ -1984,7 +2009,7 @@ _git_config ()\n \t\t;;\n \tremote.*)\n \t\tlocal pfx=\"${cur%.*}.\" cur_=\"${cur#*.}\"\n-\t\t__gitcomp \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\" \"$pfx\" \"$cur_\" \".\"\n \t\treturn\n \t\t;;\n \turl.*.*)\n@@ -2285,7 +2310,7 @@ _git_remote ()\n \n \tcase \"$subcommand\" in\n \trename|rm|show|prune)\n-\t\t__gitcomp \"$(__git_remotes)\"\n+\t\t__gitcomp_nl \"$(__git_remotes)\"\n \t\t;;\n \tupdate)\n \t\tlocal i c='' IFS=$'\\n'\n@@ -2303,7 +2328,7 @@ _git_remote ()\n \n _git_replace ()\n {\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_reset ()\n@@ -2316,7 +2341,7 @@ _git_reset ()\n \t\treturn\n \t\t;;\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_revert ()\n@@ -2327,7 +2352,7 @@ _git_revert ()\n \t\treturn\n \t\t;;\n \tesac\n-\t__gitcomp \"$(__git_refs)\"\n+\t__gitcomp_nl \"$(__git_refs)\"\n }\n \n _git_rm ()\n@@ -2426,7 +2451,7 @@ _git_stash ()\n \t\t\tCOMPREPLY=()\n \t\t\t;;\n \t\tshow,*|apply,*|drop,*|pop,*|branch,*)\n-\t\t\t__gitcomp \"$(git --git-dir=\"$(__gitdir)\" stash list \\\n+\t\t\t__gitcomp_nl \"$(git --git-dir=\"$(__gitdir)\" stash list \\\n \t\t\t\t\t| sed -n -e 's/:.*//p')\"\n \t\t\t;;\n \t\t*)\n@@ -2560,7 +2585,7 @@ _git_tag ()\n \t\ti=\"${words[c]}\"\n \t\tcase \"$i\" in\n \t\t-d|-v)\n-\t\t\t__gitcomp \"$(__git_tags)\"\n+\t\t\t__gitcomp_nl \"$(__git_tags)\"\n \t\t\treturn\n \t\t\t;;\n \t\t-f)\n@@ -2576,13 +2601,13 @@ _git_tag ()\n \t\t;;\n \t-*|tag)\n \t\tif [ $f = 1 ]; then\n-\t\t\t__gitcomp \"$(__git_tags)\"\n+\t\t\t__gitcomp_nl \"$(__git_tags)\"\n \t\telse\n \t\t\tCOMPREPLY=()\n \t\tfi\n \t\t;;\n \t*)\n-\t\t__gitcomp \"$(__git_refs)\"\n+\t\t__gitcomp_nl \"$(__git_refs)\"\n \t\t;;\n \tesac\n }\n-- \n1.7.7.197.g04a3e\n"},{"id":"177761","messageId":"7vzkh1semw.fsf@alter.siamese.dyndns.org","threadId":"28631","inReplyTo":"1318683443-1896-1-git-send-email-szeder@ira.uka.de","subject":"Re: [PATCH 2/9 v2] completion: optimize refs completion","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-10-16T03:29:42Z","receivedAt":"2011-10-16T03:29:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Thanks; will replace the corresponding patch in the topic branch and\nrebuild.\n"}]}