{"thread":{"id":"22941","subject":"[PATCH] bash-completion: Support running with set -u in bash 4.0","startedAt":"2010-03-06T18:16:55Z","lastAt":"2010-03-06T20:17:53Z","messageCount":3,"participants":["Jonathan Nieder","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"136320","messageId":"20100306181655.GA2261@progeny.tock","threadId":"22941","inReplyTo":null,"subject":"[PATCH] bash-completion: Support running with set -u in bash 4.0","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-03-06T18:16:55Z","receivedAt":"2010-03-06T18:16:55Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"From: Thomas Nilsson <thomas.nilsson@unixangst.com>\nDate: Tue, 23 Feb 2010 12:13:00 +0100\n\nStarting with bash 4.0-beta, under \"set -u\" semantics, accessing\nundefined local variables is now an error.  Some user environments\nenable this setting in the interactive shell, with unpleasant results:\n\n knirch@traktor:~/source/external/git (master)$ set -o unset\n bash: w: unbound variable\n knirch@traktor:~/source/external/git$ git ^Ibash: command: unbound variable\n bash: w: unbound variable\n knirch@traktor:~/source/external/git$\n bash: w: unbound variable\n knirch@traktor:~/source/external/git$\n\nMost of these variables should be bound to \"\".  In contexts where the\ncompletion functions should access an undefined variable, accessing a\ndefault empty string (as in \"${1-}\" instead of \"$1\") is a reasonable\nway to cope, as it silences the undefined variable error while still\nsupplying an empty string.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\nSent by Thomas to <http://bugs.debian.org/571087> (thanks!).  One\nmight use 'set -u' in an interactive shell while manually\nsingle-stepping through a shell script, perhaps.\n\n contrib/completion/git-completion.bash |   16 ++++++++--------\n 1 files changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex fe93747..d97467e 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -84,8 +84,8 @@ __git_ps1 ()\n {\n \tlocal g=\"$(__gitdir)\"\n \tif [ -n \"$g\" ]; then\n-\t\tlocal r\n-\t\tlocal b\n+\t\tlocal r=\"\"\n+\t\tlocal b=\"\"\n \t\tif [ -f \"$g/rebase-merge/interactive\" ]; then\n \t\t\tr=\"|REBASE-i\"\n \t\t\tb=\"$(cat \"$g/rebase-merge/head-name\")\"\n@@ -127,11 +127,11 @@ __git_ps1 ()\n \t\t\t}\n \t\tfi\n \n-\t\tlocal w\n-\t\tlocal i\n-\t\tlocal s\n-\t\tlocal u\n-\t\tlocal c\n+\t\tlocal w=\"\"\n+\t\tlocal i=\"\"\n+\t\tlocal s=\"\"\n+\t\tlocal u=\"\"\n+\t\tlocal c=\"\"\n \n \t\tif [ \"true\" = \"$(git rev-parse --is-inside-git-dir 2>/dev/null)\" ]; then\n \t\t\tif [ \"true\" = \"$(git rev-parse --is-bare-repository 2>/dev/null)\" ]; then\n@@ -2181,7 +2181,7 @@ _git ()\n \t\tc=$((++c))\n \tdone\n \n-\tif [ -z \"$command\" ]; then\n+\tif [ -z \"${command-}\" ]; then\n \t\tcase \"${COMP_WORDS[COMP_CWORD]}\" in\n \t\t--*)   __gitcomp \"\n \t\t\t--paginate\n-- \n1.7.0\n"},{"id":"136336","messageId":"7vtystfdu5.fsf@alter.siamese.dyndns.org","threadId":"22941","inReplyTo":"20100306181655.GA2261@progeny.tock","subject":"Re: [PATCH] bash-completion: Support running with set -u in bash 4.0","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-03-06T19:29:54Z","receivedAt":"2010-03-06T19:29:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jonathan Nieder <jrnieder@gmail.com> writes:\n\n> From: Thomas Nilsson <thomas.nilsson@unixangst.com>\n> Date: Tue, 23 Feb 2010 12:13:00 +0100\n>\n> Starting with bash 4.0-beta, under \"set -u\" semantics, accessing\n> undefined local variables is now an error.  Some user environments\n> enable this setting in the interactive shell, with unpleasant results:\n\nUnfortunate but necessary, it seems.\n\n> @@ -2181,7 +2181,7 @@ _git ()\n>  \t\tc=$((++c))\n>  \tdone\n>  \n> -\tif [ -z \"$command\" ]; then\n> +\tif [ -z \"${command-}\" ]; then\n>  \t\tcase \"${COMP_WORDS[COMP_CWORD]}\" in\n>  \t\t--*)   __gitcomp \"\n>  \t\t\t--paginate\n\nWhy not this patch, instead of the above hunk?\n\nAlso if we initialize __git_dir with an empty string on the same line, I\nthink we can lose \"${__git_dir-}\" ugliness in __gitdir () function.\n\n contrib/completion/git-completion.bash |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex fe93747..3a65156 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2167,7 +2167,7 @@ _git_tag ()\n \n _git ()\n {\n-\tlocal i c=1 command __git_dir\n+\tlocal i c=1 command=\"\" __git_dir\n \n \twhile [ $c -lt $COMP_CWORD ]; do\n \t\ti=\"${COMP_WORDS[c]}\"\n"},{"id":"136321","messageId":"20100306201753.GA4704@progeny.tock","threadId":"22941","inReplyTo":"7vtystfdu5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH] bash-completion: Support running with set -u in bash 4.0","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-03-06T20:17:53Z","receivedAt":"2010-03-06T20:17:53Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Junio C Hamano wrote:\n> Jonathan Nieder <jrnieder@gmail.com> writes:\n\n>> @@ -2181,7 +2181,7 @@ _git ()\n>>  \t\tc=$((++c))\n>>  \tdone\n>>  \n>> -\tif [ -z \"$command\" ]; then\n>> +\tif [ -z \"${command-}\" ]; then\n>>  \t\tcase \"${COMP_WORDS[COMP_CWORD]}\" in\n>>  \t\t--*)   __gitcomp \"\n>>  \t\t\t--paginate\n>\n> Why not this patch, instead of the above hunk?\n\nMy mistake.  The original patch was as you suggest, then I changed it\nto the above to make it follow the style of surrounding code.\n\nIf one makes it a goal to lose the ${foo-} lines:\n\n - In __gitdir, [ -z \"${1-}\" ] should be [ $# -eq 0 ]\n - In __gitdir callers, \"${1-}\" should be replaced by \"$@\"\n - In _git, __git_dir should be initialized to \"\"\n - In _gitk and __git_ps1, __git_dir should be made local and\n   initialized (independent bugfix)\n - In __git_ps1, the code examining $GIT_PS1_DESCRIBE_STYLE\n   should be protected by an if [ -n \"${GIT_PS1_DESCRIBE_STYLE:+set}\" ]\n - The checks for GIT_PS1_SHOWDIRTYSTATE and GIT_PS1_SHOWUNTRACKEDFILES\n   would also be adjusted\n - __gitcomp should get some local variables set to \"\" and then\n   conditionally set to its arguments\n - \"${1-}\" in __git_heads and __git_tags should be \"$dir\"\n\nThese look like good things to do anyway.  Assuming your change\nhas already been made, the follow-up patch would look something\nlike this.\n\n-- %< --\nSubject: bash-completion: Avoid using uninitialized values\n\nThe \"${var-}\" idiom is obscure and makes it easy to hide uses of\nvalues not initialized by the completion script that could have leaked\nfrom the user’s environment.\n\nUntested.  The only intentional change in functionality from this\npatch is that __git_dir has been made local to _gitk() and __git_ps1.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n contrib/completion/git-completion.bash |   52 +++++++++++++++++++++-----------\n 1 files changed, 34 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2682f52..e291d8d 100755\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -63,8 +63,8 @@ esac\n # returns location of .git repo\n __gitdir ()\n {\n-\tif [ -z \"${1-}\" ]; then\n-\t\tif [ -n \"${__git_dir-}\" ]; then\n+\tif [ $# -eq 0 ]; then\n+\t\tif [ -n \"$__git_dir\" ]; then\n \t\t\techo \"$__git_dir\"\n \t\telif [ -d .git ]; then\n \t\t\techo .git\n@@ -82,6 +82,7 @@ __gitdir ()\n # returns text to add to bash PS1 prompt (includes branch name)\n __git_ps1 ()\n {\n+\tlocal __git_dir=\"\"\n \tlocal g=\"$(__gitdir)\"\n \tif [ -n \"$g\" ]; then\n \t\tlocal r=\"\"\n@@ -108,18 +109,20 @@ __git_ps1 ()\n \t\t\tfi\n \n \t\t\tb=\"$(git symbolic-ref HEAD 2>/dev/null)\" || {\n-\n-\t\t\t\tb=\"$(\n-\t\t\t\tcase \"${GIT_PS1_DESCRIBE_STYLE-}\" in\n+\t\t\t\tif [ -z \"${GIT_PS1_DESCRIBE_STYLE:+set}\" ] ||\n+\t\t\t\t\t[ \"$GIT_PS1_DESCRIBE_STYLE\" = default ]; then\n+\t\t\t\t\tb=$(git describe --exact-match HEAD 2>/dev/null)\n+\t\t\t\telse b=$(case \"$GIT_PS1_DESCRIBE_STYLE\" in\n \t\t\t\t(contains)\n \t\t\t\t\tgit describe --contains HEAD ;;\n \t\t\t\t(branch)\n \t\t\t\t\tgit describe --contains --all HEAD ;;\n \t\t\t\t(describe)\n \t\t\t\t\tgit describe HEAD ;;\n-\t\t\t\t(* | default)\n+\t\t\t\t(*)\n \t\t\t\t\tgit describe --exact-match HEAD ;;\n-\t\t\t\tesac 2>/dev/null)\" ||\n+\t\t\t\tesac 2>/dev/null)\n+\t\t\t\tfi ||\n \n \t\t\t\tb=\"$(cut -c1-7 \"$g/HEAD\" 2>/dev/null)...\" ||\n \t\t\t\tb=\"unknown\"\n@@ -140,7 +143,7 @@ __git_ps1 ()\n \t\t\t\tb=\"GIT_DIR!\"\n \t\t\tfi\n \t\telif [ \"true\" = \"$(git rev-parse --is-inside-work-tree 2>/dev/null)\" ]; then\n-\t\t\tif [ -n \"${GIT_PS1_SHOWDIRTYSTATE-}\" ]; then\n+\t\t\tif [ -n \"${GIT_PS1_SHOWDIRTYSTATE:+set}\" ]; then\n \t\t\t\tif [ \"$(git config --bool bash.showDirtyState)\" != \"false\" ]; then\n \t\t\t\t\tgit diff --no-ext-diff --quiet --exit-code || w=\"*\"\n \t\t\t\t\tif git rev-parse --quiet --verify HEAD >/dev/null; then\n@@ -150,11 +153,11 @@ __git_ps1 ()\n \t\t\t\t\tfi\n \t\t\t\tfi\n \t\t\tfi\n-\t\t\tif [ -n \"${GIT_PS1_SHOWSTASHSTATE-}\" ]; then\n+\t\t\tif [ -n \"${GIT_PS1_SHOWSTASHSTATE:+set}\" ]; then\n \t\t\t        git rev-parse --verify refs/stash >/dev/null 2>&1 && s=\"$\"\n \t\t\tfi\n \n-\t\t\tif [ -n \"${GIT_PS1_SHOWUNTRACKEDFILES-}\" ]; then\n+\t\t\tif [ -n \"${GIT_PS1_SHOWUNTRACKEDFILES:+set}\" ]; then\n \t\t\t   if [ -n \"$(git ls-files --others --exclude-standard)\" ]; then\n \t\t\t      u=\"%\"\n \t\t\t   fi\n@@ -183,18 +186,30 @@ __gitcomp_1 ()\n # generates completion reply with compgen\n __gitcomp ()\n {\n+\tlocal replies=\"\"\n+\tlocal pfx=\"\"\n \tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n+\tlocal sfx=\"\"\n+\tif [ $# -gt 3 ]; then\n+\t\tsfx=$4\n+\tfi\n \tif [ $# -gt 2 ]; then\n \t\tcur=\"$3\"\n \tfi\n+\tif [ $# -gt 1 ]; then\n+\t\tpfx=$2\n+\tfi\n+\tif [ $# -gt 0 ]; then\n+\t\treplies=$1\n+\tfi\n \tcase \"$cur\" in\n \t--*=)\n \t\tCOMPREPLY=()\n \t\t;;\n \t*)\n \t\tlocal IFS=$'\\n'\n-\t\tCOMPREPLY=($(compgen -P \"${2-}\" \\\n-\t\t\t-W \"$(__gitcomp_1 \"${1-}\" \"${4-}\")\" \\\n+\t\tCOMPREPLY=($(compgen -P \"$pfx\" \\\n+\t\t\t-W \"$(__gitcomp_1 \"$replies\" \"$sfx\")\" \\\n \t\t\t-- \"$cur\"))\n \t\t;;\n \tesac\n@@ -203,13 +218,13 @@ __gitcomp ()\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 cmd i is_hash=y 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+\tfor i in $(git ls-remote \"$dir\" 2>/dev/null); do\n \t\tcase \"$is_hash,$i\" in\n \t\ty,*) is_hash=n ;;\n \t\tn,*^{}) is_hash=y ;;\n@@ -222,13 +237,13 @@ __git_heads ()\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 cmd i is_hash=y 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+\tfor i in $(git ls-remote \"$dir\" 2>/dev/null); do\n \t\tcase \"$is_hash,$i\" in\n \t\ty,*) is_hash=n ;;\n \t\tn,*^{}) is_hash=y ;;\n@@ -241,7 +256,7 @@ __git_tags ()\n # __git_refs accepts 0 or 1 arguments (to pass to __gitdir)\n __git_refs ()\n {\n-\tlocal i is_hash=y dir=\"$(__gitdir \"${1-}\")\"\n+\tlocal i is_hash=y dir=\"$(__gitdir \"$@\")\"\n \tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\" format refs\n \tif [ -d \"$dir\" ]; then\n \t\tcase \"$cur\" in\n@@ -2167,7 +2182,7 @@ _git_tag ()\n \n _git ()\n {\n-\tlocal i c=1 command=\"\" __git_dir\n+\tlocal i c=1 command=\"\" __git_dir=\"\"\n \n \twhile [ $c -lt $COMP_CWORD ]; do\n \t\ti=\"${COMP_WORDS[c]}\"\n@@ -2265,6 +2280,7 @@ _gitk ()\n {\n \t__git_has_doubledash && return\n \n+\tlocal __git_dir=\"\"\n \tlocal cur=\"${COMP_WORDS[COMP_CWORD]}\"\n \tlocal g=\"$(__gitdir)\"\n \tlocal merge=\"\"\n-- \n1.7.0\n"}]}