{"thread":{"id":"61830","subject":"[PATCH 1/8] git-prompt: use here-doc instead of here-string","startedAt":"2024-07-23T19:18:31Z","lastAt":"2024-08-28T20:34:41Z","messageCount":80,"participants":["Avi Halachmi (:avih) via GitGitGadget","Avi Halachmi via GitGitGadget","Junio C Hamano","brian m. carlson","avih","Patrick Steinhardt","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"499184","messageId":"9ce5ddadf0bb13229461d67451094a373348771e.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 1/8] git-prompt: use here-doc instead of here-string","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:19Z","receivedAt":"2024-07-23T19:18:31Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nHere-documend is standard, and works in all shells.\n\nBoth here-string and here-doc add final newline, which is important\nin this case, because $output is without final newline, but we do\nwant \"read\" to succeed on the last line as well.\n\nShells which support here-string:\n- bash, zsh, mksh, ksh93, yash (non-posix-mode).\n\nshells which don't, and got fixed:\n- ash-derivatives (dash, free/net bsd sh, busybox-ash).\n- pdksh, openbsd sh.\n- All Schily Bourne shell variants.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5330e769a72..ebf2e30d684 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -137,7 +137,9 @@ __git_ps1_show_upstream ()\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n \t\tesac\n-\tdone <<< \"$output\"\n+\tdone <<-OUTPUT\n+\t\t$output\n+\tOUTPUT\n \n \t# parse configuration values\n \tlocal option\n-- \ngitgitgadget\n\n"},{"id":"499186","messageId":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":null,"subject":"[PATCH 0/8] git-prompt: support more shells","fromName":"Avi Halachmi via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:18Z","receivedAt":"2024-07-23T19:18:31Z","isPatch":true,"sender":{"key":"name:Avi Halachmi","avatar":null},"body":"Before this patchset only bash and zsh were supported.\n\nAfter this patchset, the following shells work: bash, zsh, dash (since at\nleast 0.5.8), free/net bsd sh, busybox-ash, mksh, openbsd sh, pdksh(!),\nSchily extended Bourne sh (bosh), yash.\n\nThe code should now be almost posix-compliant, with one big exception\n(\"local\" variables in functions) which is not simple to fix.\n\nShells which don't work, likely only due to missing \"local\": ksh93[u+m],\nSchily minimal posix Bourne sh (pbosh), yash-posix-mode.\n\nMost changes are trivial, like changing [[...]] to [...], with one exception\n(git-prompt: don't use shell arrays) which changes few lines.\n\nTested with and without colors, with diversions from upstream, in git-svn\nrepos, and more, but I'm not considering it full coverage.\n\n * avih\n\nAvi Halachmi (:avih) (8):\n  git-prompt: use here-doc instead of here-string\n  git-prompt: fix uninitialized variable\n  git-prompt: don't use shell arrays\n  git-prompt: replace [[...]] with standard code\n  git-prompt: add some missing quotes\n  git-prompt: add fallback for shells without $'...'\n  git-prompt: ta-da! document usage in other shells\n  git-prompt: support custom 0-width PS1 markers\n\n contrib/completion/git-prompt.sh | 196 +++++++++++++++++++++----------\n 1 file changed, 131 insertions(+), 65 deletions(-)\n\n\nbase-commit: d19b6cd2dd72dc811f19df4b32c7ed223256c3ee\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1750%2Favih%2Fprompt-compat-v1\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1750/avih/prompt-compat-v1\nPull-Request: https://github.com/git/git/pull/1750\n-- \ngitgitgadget\n"},{"id":"499185","messageId":"680ecb524040c64f886c4e484a64f0d17b512e27.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 2/8] git-prompt: fix uninitialized variable","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:20Z","receivedAt":"2024-07-23T19:18:32Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nFirst use is in the form:  local var; ...; var=$var$whatever...\n\nIf the variable was unset (as bash and others do after \"local x\"),\nthen it would error if set -u is in effect.\n\nAlso, many shells inherit the existing value after \"local var\"\nwithout init, but in this case it's unlikely to have a prior value.\n\nNow we initialize it.\n\n(local var= is enough, but local var=\"\" is the custom in this file)\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex ebf2e30d684..4cc2cf91bb6 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,7 +116,7 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern count n\n+\tlocal svn_remote svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n \n \tsvn_remote=()\n-- \ngitgitgadget\n\n"},{"id":"499187","messageId":"7e994eae7bc3dfa021262410c801ddb124ce24f1.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 3/8] git-prompt: don't use shell arrays","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:21Z","receivedAt":"2024-07-23T19:18:35Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nArrays only existed in the svn-upstream code, used to:\n- Keep a list of svn remotes.\n- Convert commit msg to array of words, extract the 2nd-to-last word.\n\nExcept bash/zsh, nearly all shells failed load on syntax errors here.\n\nNow:\n- The svn remotes are a list of newline-terminated values.\n- The 2nd-to-last word is extracted using standard shell substrings.\n- All shells can digest the svn-upstream code.\n\nWhile using shell field splitting to extract the word is simple, and\ndoesn't even need non-standard code, e.g. set -- $(git log -1 ...),\nit would have the same issues as the old array code: it depends on IFS\nwhich we don't control, and it's subject to glob-expansion, e.g. if\nthe message happens to include * or **/* (as this commit message just\ndid), then the array could get huge. This was not great.\n\nNow it uses standard shell substrings, and we know the exact delimiter\nto expect, because it's the match from our grep just one line earlier.\n\nThe new word extraction code also fixes svn-upstream in zsh, because\npreviously it used arr[len-2], but because in zsh, unlike bash, array\nsubscripts are 1-based, it incorrectly extracted the 3rd-to-last word.\nsymptom: missing upstream status in a git-svn repo: u=, u+N-M, etc.\n\nThe breakage in zsh is surprising, because it was last touched by\n  commit d0583da838 (prompt: fix show upstream with svn and zsh),\nclaiming to fix exactly that. However, it only mentions syntax fixes.\nIt's unclear if behavior was fixed too. But it was broken, now fixed.\n\nNote LF=$'\\n' and then using $LF instead of $'\\n' few times.\nA future commit will add fallback for shells without $'...', so this\nwould be the only line to touch instead of replacing every $'\\n' .\n\nShells which could run the previous array code:\n- bash\n\nShells which have arrays but were broken anyway:\n- zsh: 1-based subscript\n- ksh93: no \"local\" (the new code can't fix this part...)\n- mksh, openbsd sh, pdksh: failed load on syntax error: \"for ((...))\".\n\nMore shells which Failed to load due to syntax error:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne shell, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 48 ++++++++++++++++++++------------\n 1 file changed, 30 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4cc2cf91bb6..75c3a813fda 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,10 +116,10 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern=\"\" count n\n+\tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n+\tlocal LF=$'\\n'\n \n-\tsvn_remote=()\n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n \twhile read -r key value; do\n@@ -132,7 +132,7 @@ __git_ps1_show_upstream ()\n \t\t\tfi\n \t\t\t;;\n \t\tsvn-remote.*.url)\n-\t\t\tsvn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n+\t\t\tsvn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n \t\t\tsvn_url_pattern=\"$svn_url_pattern\\\\|$value\"\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n@@ -156,25 +156,37 @@ __git_ps1_show_upstream ()\n \tcase \"$upstream_type\" in\n \tgit)    upstream_type=\"@{upstream}\" ;;\n \tsvn*)\n-\t\t# get the upstream from the \"git-svn-id: ...\" in a commit message\n-\t\t# (git-svn uses essentially the same procedure internally)\n-\t\tlocal -a svn_upstream\n-\t\tsvn_upstream=($(git log --first-parent -1 \\\n-\t\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null))\n-\t\tif [[ 0 -ne ${#svn_upstream[@]} ]]; then\n-\t\t\tsvn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}\n-\t\t\tsvn_upstream=${svn_upstream%@*}\n-\t\t\tlocal n_stop=\"${#svn_remote[@]}\"\n-\t\t\tfor ((n=1; n <= n_stop; n++)); do\n-\t\t\t\tsvn_upstream=${svn_upstream#${svn_remote[$n]}}\n-\t\t\tdone\n+\t\t# successful svn-upstream resolution:\n+\t\t# - get the list of configured svn-remotes ($svn_remotes set above)\n+\t\t# - get the last commit which seems from one of our svn-remotes\n+\t\t# - confirm that it is from one of the svn-remotes\n+\t\t# - use $GIT_SVN_ID if set, else \"git-svn\"\n \n-\t\t\tif [[ -z \"$svn_upstream\" ]]; then\n+\t\t# get upstream from \"git-svn-id: UPSTRM@N HASH\" in a commit message\n+\t\t# (git-svn uses essentially the same procedure internally)\n+\t\tlocal svn_upstream=\"$(\n+\t\t\tgit log --first-parent -1 \\\n+\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null\n+\t\t)\"\n+\n+\t\tif [ -n \"$svn_upstream\" ]; then\n+\t\t\t# extract the URI, assuming --grep matched the last line\n+\t\t\tsvn_upstream=${svn_upstream##*$LF}  # last line\n+\t\t\tsvn_upstream=${svn_upstream#*: }    # UPSTRM@N HASH\n+\t\t\tsvn_upstream=${svn_upstream%@*}     # UPSTRM\n+\n+\t\t\tcase ${LF}${svn_remotes} in\n+\t\t\t*\"${LF}${svn_upstream}${LF}\"*)\n+\t\t\t\t# grep indeed matched the last line - it's our remote\n \t\t\t\t# default branch name for checkouts with no layout:\n \t\t\t\tupstream_type=${GIT_SVN_ID:-git-svn}\n-\t\t\telse\n+\t\t\t\t;;\n+\t\t\t*)\n+\t\t\t\t# the commit message includes one of our remotes, but\n+\t\t\t\t# it's not at the last line. is $svn_upstream junk?\n \t\t\t\tupstream_type=${svn_upstream#/}\n-\t\t\tfi\n+\t\t\t\t;;\n+\t\t\tesac\n \t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n-- \ngitgitgadget\n\n"},{"id":"499188","messageId":"232340902a1feeafe526528eb88b8d0814d11545.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 4/8] git-prompt: replace [[...]] with standard code","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:22Z","receivedAt":"2024-07-23T19:18:36Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe existing [[...]] tests were either already valid as standard [...]\ntests, or only required minimal retouch:\n\nNotes:\n\n- [[...]] doesn't do field splitting and glob expansion, so $var\n  or $(cmd...) don't need quoting, but [... does need quotes.\n\n- [[ X == Y ]] when Y is a string is same as [ X = Y ], but if Y is\n  a pattern, then we need:  case X in Y)... ; esac  .\n\n- [[ ... && ... ]] was replaced with [ ... ] && [ ... ] .\n\n- [[ -o <zsh-option> ]] requires [[...]], so put it in \"eval\" and only\n  eval it in zsh, so other shells would not abort on syntax error\n  (posix says [[ has unspecified results, shells allowed to reject it)\n\n- ((x++)) was changed into x=$((x+1))  (yeah, not [[...]] ...)\n\nShells which accepted the previous forms:\n- bash, zsh, ksh93, mksh, openbsd sh, pdksh.\n\nShells which didn't, and now can process it:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne sh, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 30 ++++++++++++++++--------------\n 1 file changed, 16 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 75c3a813fda..4781261f868 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -126,7 +126,7 @@ __git_ps1_show_upstream ()\n \t\tcase \"$key\" in\n \t\tbash.showupstream)\n \t\t\tGIT_PS1_SHOWUPSTREAM=\"$value\"\n-\t\t\tif [[ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]]; then\n+\t\t\tif [ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]; then\n \t\t\t\tp=\"\"\n \t\t\t\treturn\n \t\t\tfi\n@@ -187,14 +187,14 @@ __git_ps1_show_upstream ()\n \t\t\t\tupstream_type=${svn_upstream#/}\n \t\t\t\t;;\n \t\t\tesac\n-\t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n+\t\telif [ \"svn+git\" = \"$upstream_type\" ]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n \t\t;;\n \tesac\n \n \t# Find how many commits we are ahead/behind our upstream\n-\tif [[ -z \"$legacy\" ]]; then\n+\tif [ -z \"$legacy\" ]; then\n \t\tcount=\"$(git rev-list --count --left-right \\\n \t\t\t\t\"$upstream_type\"...HEAD 2>/dev/null)\"\n \telse\n@@ -206,8 +206,8 @@ __git_ps1_show_upstream ()\n \t\t\tfor commit in $commits\n \t\t\tdo\n \t\t\t\tcase \"$commit\" in\n-\t\t\t\t\"<\"*) ((behind++)) ;;\n-\t\t\t\t*)    ((ahead++))  ;;\n+\t\t\t\t\"<\"*) behind=$((behind+1)) ;;\n+\t\t\t\t*)    ahead=$((ahead+1))   ;;\n \t\t\t\tesac\n \t\t\tdone\n \t\t\tcount=\"$behind\t$ahead\"\n@@ -217,7 +217,7 @@ __git_ps1_show_upstream ()\n \tfi\n \n \t# calculate the result\n-\tif [[ -z \"$verbose\" ]]; then\n+\tif [ -z \"$verbose\" ]; then\n \t\tcase \"$count\" in\n \t\t\"\") # no upstream\n \t\t\tp=\"\" ;;\n@@ -243,7 +243,7 @@ __git_ps1_show_upstream ()\n \t\t*)\t    # diverged from upstream\n \t\t\tupstream=\"|u+${count#*\t}-${count%\t*}\" ;;\n \t\tesac\n-\t\tif [[ -n \"$count\" && -n \"$name\" ]]; then\n+\t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n \t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n@@ -265,7 +265,7 @@ __git_ps1_show_upstream ()\n # their own color.\n __git_ps1_colorize_gitstring ()\n {\n-\tif [[ -n ${ZSH_VERSION-} ]]; then\n+\tif [ -n \"${ZSH_VERSION-}\" ]; then\n \t\tlocal c_red='%F{red}'\n \t\tlocal c_green='%F{green}'\n \t\tlocal c_lblue='%F{blue}'\n@@ -417,7 +417,7 @@ __git_ps1 ()\n \t# incorrect.)\n \t#\n \tlocal ps1_expanded=yes\n-\t[ -z \"${ZSH_VERSION-}\" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no\n+\t[ -z \"${ZSH_VERSION-}\" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no\n \t[ -z \"${BASH_VERSION-}\" ] || shopt -q promptvars || ps1_expanded=no\n \n \tlocal repo_info rev_parse_exit_code\n@@ -502,11 +502,13 @@ __git_ps1 ()\n \t\t\t\t\treturn $exit\n \t\t\t\tfi\n \n-\t\t\t\tif [[ $head == \"ref: \"* ]]; then\n+\t\t\t\tcase $head in\n+\t\t\t\t\"ref: \"*)\n \t\t\t\t\thead=\"${head#ref: }\"\n-\t\t\t\telse\n+\t\t\t\t\t;;\n+\t\t\t\t*)\n \t\t\t\t\thead=\"\"\n-\t\t\t\tfi\n+\t\t\t\tesac\n \t\t\t\t;;\n \t\t\t*)\n \t\t\t\thead=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n@@ -542,8 +544,8 @@ __git_ps1 ()\n \tfi\n \n \tlocal conflict=\"\" # state indicator for unresolved conflicts\n-\tif [[ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" == \"yes\" ]] &&\n-\t   [[ $(git ls-files --unmerged 2>/dev/null) ]]; then\n+\tif [ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" = \"yes\" ] &&\n+\t   [ \"$(git ls-files --unmerged 2>/dev/null)\" ]; then\n \t\tconflict=\"|CONFLICT\"\n \tfi\n \n-- \ngitgitgadget\n\n"},{"id":"499189","messageId":"4f77b7eb7f1110e47201b8c97c34a0cbcd14e24f.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 5/8] git-prompt: add some missing quotes","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:23Z","receivedAt":"2024-07-23T19:18:36Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe issues which this commit fixes are unlikely to be broken\nin real life, but the fixes improve correctness, and would prevent\nbugs in some uncommon cases, such as weird IFS values.\n\nListing some portability guideline here for future reference.\n\nI'm leaving it to someone else to decide whether to include\nit in the file itself, place is as a new file, or not.\n\n---------\n\nThe command \"local\" is non standard, but is allowed in this file:\n- Quote initialization if it can expand (local x=\"$y\"). See below.\n- Don't assume initial value after \"local x\". Either initialize it\n  (local x=..), or set before first use (local x;.. x=..; <use $x>).\n  (between shells, \"local x\" can unset x, or inherit it, or do x= )\n\nOther non-standard features beyond \"local\" are to be avoided.\n\nUse the standard \"test\" - [...] instead of non-standard [[...]] .\n\n--------\n\nQuotes (some portability things, but mainly general correctness):\n\nQuotes prevent tilde-expansion of some unquoted literal tildes (~).\nIf the expansion is undesirable, quotes would ensure that.\n  Tilds expanded: a=~user:~/ ;  echo ~user ~/dir\n  not expanded:   t=\"~\"; a=${t}user  b=\\~foo~;  echo \"~user\" $t/dir\n\nBut the main reason for quoting is to prevent IFS field splitting\n(which also coalesces IFS chars) and glob expansion after parameter\nexpansion or command substitution.\n\nIn _command-arguments_, expanded/substituted values must be quoted:\n  Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n  Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n\nStill in _agumemts_, no need to quote non-expandable values:\n  Good:                 local x=   y=yes;   echo OK\n  OK, but not required: local x=\"\" y=\"yes\"; echo \"OK\"\nBut completely empty (NULL) arguments must be quoted:\n  foo \"\"   is not the same as:   foo\n\nAssignments in simple commands - with or without an actual command,\ndon't need quoting becase there's no IFS split or glob expansion:\n  Good:   s=* a=$b c=$(cmd...)${x# foo }${y-   } [cmd ...]\n  It's also OK to use double quotes, but not required.\n\nThis behavior (no IFS/glob) is called \"assignment context\", and\n\"local\" does not behave with assignment context in some shells,\nhence we require quotes when using \"local\" - for compatibility.\n\nFirst value in 'case...' doesn't IFS-split/glob, doesn't need quotes:\n  Good:       case  * $foo $(cmd...)  in ... ; esac\n  identical:  case \"* $foo $(cmd...)\" in ... ; esac\n\nNested quotes in command substitution are fine, often necessary:\n  Good: echo \"$(foo... \"$x\" \"$(bar ...)\")\"\n\nNested quotes in substring ops are legal, and sometimes needed\nto prevent interpretation as a pattern, but not the most readable:\n  Legal:  foo \"${x#*\"$y\" }\"\n\nNested quotes in \"maybe other value\" subst are invalid, unnecessary:\n  Good:  local x=\"${y- }\";   foo \"${z:+ $a }\"\n  Bad:   local x=\"${y-\" \"}\"; foo \"${z:+\" $a \"}\"\nOuter/inner quotes in \"maybe other value\" have different use cases:\n  \"${x-$y}\"  always one quoted arg: \"$x\" if x is set, else \"$y\".\n  ${x+\"$x\"}  one quoted arg \"$x\" if x is set, else no arg at all.\n  Unquoted $x is similar to the second case, but it would get split\n  into few arguments if it includes any of the IFS chars.\n\nAssignments don't need the outer quotes, and the braces delimit the\nvalue, so nested quotes can be avoided, for readability:\n  a=$(foo \"$x\")  a=${x#*\"$y\" }  c=${y- };  bar \"$a\" \"$b\" \"$c\"\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4781261f868..5d7f236fe48 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -246,7 +246,7 @@ __git_ps1_show_upstream ()\n \t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n-\t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\t\t\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t\t\tupstream=\"$upstream \\${__git_ps1_upstream_name}\"\n \t\t\telse\n \t\t\t\tupstream=\"$upstream ${__git_ps1_upstream_name}\"\n@@ -278,12 +278,12 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n \t\tlocal c_clear=$'\\001\\e[0m\\002'\n \tfi\n-\tlocal bad_color=$c_red\n-\tlocal ok_color=$c_green\n+\tlocal bad_color=\"$c_red\"\n+\tlocal ok_color=\"$c_green\"\n \tlocal flags_color=\"$c_lblue\"\n \n \tlocal branch_color=\"\"\n-\tif [ $detached = no ]; then\n+\tif [ \"$detached\" = no ]; then\n \t\tbranch_color=\"$ok_color\"\n \telse\n \t\tbranch_color=\"$bad_color\"\n@@ -360,7 +360,7 @@ __git_sequencer_status ()\n __git_ps1 ()\n {\n \t# preserve exit status\n-\tlocal exit=$?\n+\tlocal exit=\"$?\"\n \tlocal pcmode=no\n \tlocal detached=no\n \tlocal ps1pc_start='\\u@\\h:\\w '\n@@ -379,7 +379,7 @@ __git_ps1 ()\n \t\t;;\n \t\t0|1)\tprintf_format=\"${1:-$printf_format}\"\n \t\t;;\n-\t\t*)\treturn $exit\n+\t\t*)\treturn \"$exit\"\n \t\t;;\n \tesac\n \n@@ -427,7 +427,7 @@ __git_ps1 ()\n \trev_parse_exit_code=\"$?\"\n \n \tif [ -z \"$repo_info\" ]; then\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal short_sha=\"\"\n@@ -449,7 +449,7 @@ __git_ps1 ()\n \t   [ \"$(git config --bool bash.hideIfPwdIgnored)\" != \"false\" ] &&\n \t   git check-ignore -q .\n \tthen\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal sparse=\"\"\n@@ -499,7 +499,7 @@ __git_ps1 ()\n \t\t\tcase \"$ref_format\" in\n \t\t\tfiles)\n \t\t\t\tif ! __git_eread \"$g/HEAD\" head; then\n-\t\t\t\t\treturn $exit\n+\t\t\t\t\treturn \"$exit\"\n \t\t\t\tfi\n \n \t\t\t\tcase $head in\n@@ -597,10 +597,10 @@ __git_ps1 ()\n \t\tfi\n \tfi\n \n-\tlocal z=\"${GIT_PS1_STATESEPARATOR-\" \"}\"\n+\tlocal z=\"${GIT_PS1_STATESEPARATOR- }\"\n \n \tb=${b##refs/heads/}\n-\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t__git_ps1_branch_name=$b\n \t\tb=\"\\${__git_ps1_branch_name}\"\n \tfi\n@@ -612,7 +612,7 @@ __git_ps1 ()\n \tlocal f=\"$h$w$i$s$u$p\"\n \tlocal gitstring=\"$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}\"\n \n-\tif [ $pcmode = yes ]; then\n+\tif [ \"$pcmode\" = yes ]; then\n \t\tif [ \"${__git_printf_supports_v-}\" != yes ]; then\n \t\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n \t\telse\n@@ -623,5 +623,5 @@ __git_ps1 ()\n \t\tprintf -- \"$printf_format\" \"$gitstring\"\n \tfi\n \n-\treturn $exit\n+\treturn \"$exit\"\n }\n-- \ngitgitgadget\n\n"},{"id":"499190","messageId":"1c1b58e20cab6b4989b140282353073165f0067e.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:24Z","receivedAt":"2024-07-23T19:18:37Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\n$'...' is new in POSIX (2024), and some shells support it in recent\nversions, while others have had it for decades (bash, zsh, ksh93).\n\nHowever, there are still enough shells which don't support it, and\nit's cheap to provide a fallback for them, so let's do that instead\nof dismissing it as \"it's compliant\".\n\nshells where $'...' works:\n- bash, zsh, ksh93, mksh, busybox-ash, dash master, free/net bsd sh.\n\nshells where it doesn't work, but the new fallback works:\n- all dash releases (up to 0.5.12), older versions of free/net bsd sh,\n  openbsd sh, pdksh, all Schily Bourne sh variants, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 52 +++++++++++++++++++++-----------\n 1 file changed, 34 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5d7f236fe48..bbc16417ac9 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -111,6 +111,17 @@\n __git_printf_supports_v=\n printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n \n+__git_SOH=$'\\1' __git_STX=$'\\2' __git_ESC=$'\\33'\n+__git_LF=$'\\n' __git_CRLF=$'\\r\\n'\n+\n+if [ $'\\101' != A ]; then  # fallback for shells without $'...'\n+   __git_CRLF=$(printf \"\\r\\n\\1\\2\\33\")  # CR LF SOH STX ESC\n+   __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}\n+   __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}\n+   __git_SOH=${__git_CRLF#??};   __git_CRLF=${__git_CRLF%?}\n+   __git_LF=${__git_CRLF#?}\n+fi\n+\n # stores the divergence from upstream in $p\n # used by GIT_PS1_SHOWUPSTREAM\n __git_ps1_show_upstream ()\n@@ -118,7 +129,7 @@ __git_ps1_show_upstream ()\n \tlocal key value\n \tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n-\tlocal LF=$'\\n'\n+\tlocal LF=\"$__git_LF\"\n \n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n@@ -271,12 +282,16 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue='%F{blue}'\n \t\tlocal c_clear='%f'\n \telse\n-\t\t# Using \\001 and \\002 around colors is necessary to prevent\n-\t\t# issues with command line editing/browsing/completion!\n-\t\tlocal c_red=$'\\001\\e[31m\\002'\n-\t\tlocal c_green=$'\\001\\e[32m\\002'\n-\t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n-\t\tlocal c_clear=$'\\001\\e[0m\\002'\n+\t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n+\t\t# which bash/readline identify while calculating the prompt\n+\t\t# on-screen width - to exclude 0-screen-width esc sequences.\n+\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${__git_STX}\"\n+\n+\t\tlocal c_red=\"${c_pre}31${c_post}\"\n+\t\tlocal c_green=\"${c_pre}32${c_post}\"\n+\t\tlocal c_lblue=\"${c_pre}1;34${c_post}\"\n+\t\tlocal c_clear=\"${c_pre}0${c_post}\"\n \tfi\n \tlocal bad_color=\"$c_red\"\n \tlocal ok_color=\"$c_green\"\n@@ -312,7 +327,7 @@ __git_ps1_colorize_gitstring ()\n # variable, in that order.\n __git_eread ()\n {\n-\ttest -r \"$1\" && IFS=$'\\r\\n' read -r \"$2\" <\"$1\"\n+\ttest -r \"$1\" && IFS=$__git_CRLF read -r \"$2\" <\"$1\"\n }\n \n # see if a cherry-pick or revert is in progress, if the user has committed a\n@@ -430,19 +445,20 @@ __git_ps1 ()\n \t\treturn \"$exit\"\n \tfi\n \n+\tlocal LF=\"$__git_LF\"\n \tlocal short_sha=\"\"\n \tif [ \"$rev_parse_exit_code\" = \"0\" ]; then\n-\t\tshort_sha=\"${repo_info##*$'\\n'}\"\n-\t\trepo_info=\"${repo_info%$'\\n'*}\"\n+\t\tshort_sha=\"${repo_info##*$LF}\"\n+\t\trepo_info=\"${repo_info%$LF*}\"\n \tfi\n-\tlocal ref_format=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_worktree=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal bare_repo=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_gitdir=\"${repo_info##*$'\\n'}\"\n-\tlocal g=\"${repo_info%$'\\n'*}\"\n+\tlocal ref_format=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_worktree=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal bare_repo=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_gitdir=\"${repo_info##*$LF}\"\n+\tlocal g=\"${repo_info%$LF*}\"\n \n \tif [ \"true\" = \"$inside_worktree\" ] &&\n \t   [ -n \"${GIT_PS1_HIDE_IF_PWD_IGNORED-}\" ] &&\n-- \ngitgitgadget\n\n"},{"id":"499191","messageId":"4a086ffc36033301095665530ab8f45cd1c4af36.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 7/8] git-prompt: ta-da! document usage in other shells","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:25Z","receivedAt":"2024-07-23T19:18:39Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWith one big exception, git-prompt.sh should now be both almost posix\ncompliant, and also compatible with most (posix-ish) shells.\n\nThat exception is the use of \"local\" vars in functions, which happens\nextensively in the current code, and is not simple to replace with\nposix compliant code (but also not impossible).\n\nLuckily, almost all shells support \"local\" as used by the current\ncode, with the notable exception of ksh93[u+m], but also the Schily\nminimal posix sh (pbosh), and yash in posix mode.\n\nSee assessment below that \"local\" is likely the only blocker in those.\n\nSo except mainly ksh93, git-prompt.sh now works in most shells:\n- bash, zsh, dash since at least 0.5.8, free/net bsd sh, busybox-ash,\n  mksh, openbsd sh, pdksh(!), Schily extended Bourne sh (bosh), yash.\n\nwhich is quite nice.\n\nAs an anecdote, replacing the 1st line in __git_ps1() (local exit=$?)\nwith these 2 makes it work in all tested shells, even without \"local\":\n\n  # handles only 0/1 args for simplicity. needs +5 LOC for any $#\n  __git_e=$?; local exit=\"$__git_e\" 2>/dev/null ||\n    {(eval 'local() { export \"$@\"; }'; __git_ps1 \"$@\"); return \"$__git_e\"; }\n\nExplanation:\n\n  If the shell doesn't have the command \"local\", define our own\n  function \"local\" which instead does plain (global) assignents.\n  Then use __git_ps1 in a subshell to not clober the caller's vars.\n\n  This happens to work because currently there are no name conflicts\n  (shadow) at the code, initial value is not assumed (i.e. always\n  doing either 'local x=...'  or 'local x;...  x=...'), and assigned\n  initial values are quoted (local x=\"$y\"), preventing word split and\n  glob expansion (i.e. assignment context is not assumed).\n\n  The last two (always init, quote values) seem to be enough to use\n  \"local\" portably if supported, and otherwise shells indeed differ.\n\n  Uses \"eval\", else shells with \"local\" may reject it during parsing.\n  We don't need \"export\", but it's smaller than writing our own loop.\n\nWhile cute, this approach is not really sustainable because all the\nvars become global, which is hard to maintain without conflicts\n(but hey, it currently has no conflicts - without even trying...).\n\nHowever, regardless of being an anecdote, it provides some support to\nthe assessment that \"local\" is the only blocker in those shells.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 33 ++++++++++++++++++++++++++++++--\n 1 file changed, 31 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex bbc16417ac9..5787eca28db 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -8,8 +8,8 @@\n # To enable:\n #\n #    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).\n-#    2) Add the following line to your .bashrc/.zshrc:\n-#        source ~/.git-prompt.sh\n+#    2) Add the following line to your .bashrc/.zshrc/.profile:\n+#        . ~/.git-prompt.sh   # dot path/to/this-file\n #    3a) Change your PS1 to call __git_ps1 as\n #        command-substitution:\n #        Bash: PS1='[\\u@\\h \\W$(__git_ps1 \" (%s)\")]\\$ '\n@@ -30,6 +30,8 @@\n #        Optionally, you can supply a third argument with a printf\n #        format string to finetune the output of the branch status\n #\n+#    See notes below about compatibility with other shells.\n+#\n # The repository status will be displayed only if you are currently in a\n # git repository. The %s token is the placeholder for the shown status.\n #\n@@ -106,6 +108,33 @@\n # directory is set up to be ignored by git, then set\n # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the\n # repository level by setting bash.hideIfPwdIgnored to \"false\".\n+#\n+# Conpatibility with other shells (beyond bash/zsh):\n+#\n+#    We require posix-ish shell plus \"local\" support, which is most\n+#    shells (even pdksh), but excluding ksh93 (because no \"local\").\n+#\n+#    Prompt integration might differ between shells, but the gist is\n+#    to load it once on shell init with '. path/to/git-prompt.sh',\n+#    set GIT_PS1* vars once as needed, and either place $(__git_ps1..)\n+#    inside PS1 once (0/1 args), or, before each prompt is displayed,\n+#    call __git_ps1 (2/3 args) which sets PS1 with the status embedded.\n+#\n+#    Many shells support the 1st method of command substitution,\n+#    though some might need to first enable cmd substitution in PS1.\n+#\n+#    When using colors, each escape sequence is wrapped between byte\n+#    values 1 and 2 (control chars SOH, STX, respectively), which are\n+#    invisible at the output, but for bash/readline they mark 0-width\n+#    strings (SGR color sequences) when calculating the on-screen\n+#    prompt width, to maintain correct input editing at the prompt.\n+#\n+#    Currently there's no support for different markers, so if editing\n+#    behaves weird when using colors in __git_ps1, then the solution\n+#    is either to disable colors, or, in some shells which only care\n+#    about the width of the last prompt line (e.g. busybox-ash),\n+#    ensure the git output is not at the last line, maybe like so:\n+#      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n __git_printf_supports_v=\n-- \ngitgitgadget\n\n"},{"id":"499192","messageId":"f241c3ae1e405c04c51d8853b9415f428b06c535.1721762306.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH 8/8] git-prompt: support custom 0-width PS1 markers","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-07-23T19:18:26Z","receivedAt":"2024-07-23T19:18:41Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWhen using colors, the shell needs to identify 0-width substrings\nin PS1 - such as color escape sequences - when calculating the\non-screen width of the prompt.\n\nUntil now, we used the form %F{<color>} in zsh - which it knows is\n0-width, or otherwise use standard SGR esc sequences wrapped between\nbyte values 1 and 2 (SOH, STX) as 0-width start/end markers, which\nbash/readline identify as such.\n\nBut now that more shells are supported, the standard SGR sequences\ntypically work, but the SOH/STX markers might not be identified.\n\nThis commit adds support for vars GIT_PS1_COLOR_{PRE,POST} which\nset custom 0-width markers or disable the markers.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 19 ++++++++++++-------\n 1 file changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5787eca28db..60df5cb94fe 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -129,11 +129,16 @@\n #    strings (SGR color sequences) when calculating the on-screen\n #    prompt width, to maintain correct input editing at the prompt.\n #\n-#    Currently there's no support for different markers, so if editing\n-#    behaves weird when using colors in __git_ps1, then the solution\n-#    is either to disable colors, or, in some shells which only care\n-#    about the width of the last prompt line (e.g. busybox-ash),\n-#    ensure the git output is not at the last line, maybe like so:\n+#    To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE\n+#    and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not\n+#    use markers. For instance, some shells support '\\[' and '\\]' as\n+#    start/end markers in PS1 - when invoking __git_ps1 with 3/4 args,\n+#    but it may or may not work in command substitution mode. YMMV.\n+#\n+#    If the shell doesn't support 0-width markers and editing behaves\n+#    incorrectly when using colors in __git_ps1, then, other than\n+#    disabling color, it might be solved using multi-line prompt,\n+#    where the git status is not at the last line, e.g.:\n #      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n@@ -314,8 +319,8 @@ __git_ps1_colorize_gitstring ()\n \t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n \t\t# which bash/readline identify while calculating the prompt\n \t\t# on-screen width - to exclude 0-screen-width esc sequences.\n-\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n-\t\tlocal c_post=\"m${__git_STX}\"\n+\t\tlocal c_pre=\"${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${GIT_PS1_COLOR_POST-$__git_STX}\"\n \n \t\tlocal c_red=\"${c_pre}31${c_post}\"\n \t\tlocal c_green=\"${c_pre}32${c_post}\"\n-- \ngitgitgadget\n"},{"id":"499194","messageId":"xmqqjzhb28yc.fsf@gitster.g","threadId":"61830","inReplyTo":"4f77b7eb7f1110e47201b8c97c34a0cbcd14e24f.1721762306.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 5/8] git-prompt: add some missing quotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-07-23T19:40:27Z","receivedAt":"2024-07-23T19:40:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avi Halachmi (:avih) via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n>\n> The issues which this commit fixes are unlikely to be broken\n> in real life, but the fixes improve correctness, and would prevent\n> bugs in some uncommon cases, such as weird IFS values.\n>\n> Listing some portability guideline here for future reference.\n>\n> I'm leaving it to someone else to decide whether to include\n> it in the file itself, place is as a new file, or not.\n\nCheck Documentation/CodingGuidelines; I think we have something to\nsay about local var=\"val\" construct to help dash.\n\nWe allowed liberal uses of bash-ism in this file, as it was\ninitially written for bash anyway.  If we were rewriting the prompt\nscripts to be usable by other shells, great.  But then we'd want to\nmake sure it adheres to existing coding guidelines we have.\n\n\n"},{"id":"499196","messageId":"xmqqy15rzwi5.fsf@gitster.g","threadId":"61830","inReplyTo":"1c1b58e20cab6b4989b140282353073165f0067e.1721762306.git.gitgitgadget@gmail.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-07-23T20:25:22Z","receivedAt":"2024-07-23T20:25:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avi Halachmi (:avih) via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n>\n> $'...' is new in POSIX (2024), and some shells support it in recent\n> versions, while others have had it for decades (bash, zsh, ksh93).\n\nI will not look at this series futher during the current development\ncycle that is about to conclude, but ...\n\n> +__git_SOH=$'\\1' __git_STX=$'\\2' __git_ESC=$'\\33'\n> +__git_LF=$'\\n' __git_CRLF=$'\\r\\n'\n> +\n> +if [ $'\\101' != A ]; then  # fallback for shells without $'...'\n> +   __git_CRLF=$(printf \"\\r\\n\\1\\2\\33\")  # CR LF SOH STX ESC\n> +   __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}\n> +   __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}\n> +   __git_SOH=${__git_CRLF#??};   __git_CRLF=${__git_CRLF%?}\n> +   __git_LF=${__git_CRLF#?}\n> +fi\n\n... given that these are not used literally in-place but are always\nreferred to by their __git_BYTE names, if we are making this script\nportable across shells to the same degree as other shell scripts\nfollowing our coding guidelines, I would prefer to see it done\nwithout any \"fallback\".\n\n$(printf '\\r') would work with bash, zsh and ksh93, too, and one\ntime assignment to these variables is not going to be performance\ncritical.  Just forbid use of $'\\octal' notation in the coding\nguidelines document, and implement just one variant.\n\nPerhaps we should spell more things out that you wrote in some of\nyour proposed log messages more explicitly.  I think these have been\nrules we have followed (grep for them in *.sh files outside\ncontrib/) but I did not find mention in the guidelines document.\n\nThanks.\n\n Documentation/CodingGuidelines | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git c/Documentation/CodingGuidelines w/Documentation/CodingGuidelines\nindex 1d92b2da03..bb058fcc87 100644\n--- c/Documentation/CodingGuidelines\n+++ w/Documentation/CodingGuidelines\n@@ -107,6 +107,8 @@ For shell scripts specifically (not exhaustive):\n \n  - We do not use Process Substitution <(list) or >(list).\n \n+ - We do not use Dollar-Single-Quotes $'<octal>' notation.\n+\n  - Do not write control structures on a single line with semicolon.\n    \"then\" should be on the next line for if statements, and \"do\"\n    should be on the next line for \"while\" and \"for\".\n@@ -140,7 +142,8 @@ For shell scripts specifically (not exhaustive):\n \tsort >actual &&\n \t...\n \n- - We prefer \"test\" over \"[ ... ]\".\n+ - We prefer \"test\" over \"[ ... ]\".  Never use \"[[ ... ]]\" unless in a\n+   script only meant for bash.\n \n  - We do not write the noiseword \"function\" in front of shell\n    functions.\n\n"},{"id":"499208","messageId":"ZqAzpYuTrK6L-uyN@tapette.crustytoothpaste.net","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"Re: [PATCH 0/8] git-prompt: support more shells","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2024-07-23T22:50:13Z","receivedAt":"2024-07-23T22:50:21Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2024-07-23 at 19:18:18, Avi Halachmi via GitGitGadget wrote:\n> Before this patchset only bash and zsh were supported.\n> \n> After this patchset, the following shells work: bash, zsh, dash (since at\n> least 0.5.8), free/net bsd sh, busybox-ash, mksh, openbsd sh, pdksh(!),\n> Schily extended Bourne sh (bosh), yash.\n> \n> The code should now be almost posix-compliant, with one big exception\n> (\"local\" variables in functions) which is not simple to fix.\n\nWe explicitly allow `local` in our coding guidelines.  As a side note,\nDebian requires it of all shells that can be used as `/bin/sh`.\n\n> Shells which don't work, likely only due to missing \"local\": ksh93[u+m],\n> Schily minimal posix Bourne sh (pbosh), yash-posix-mode.\n\nksh93u+m is planning on adding local in a future revision.\n-- \nbrian m. carlson (they/them or he/him)\nToronto, Ontario, CA\n"},{"id":"499214","messageId":"332605494.478904.1721782074981@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqjzhb28yc.fsf@gitster.g","subject":"Re: [PATCH 5/8] git-prompt: add some missing quotes","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-24T00:47:54Z","receivedAt":"2024-07-24T01:08:12Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Tuesday, July 23, 2024 at 10:40:30 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n\nThanks for the quick reply, and aplogies for my delayed reply.\n\nI replied at the github PR https://github.com/git/git/pull/1750\nand didn't realize GitGitGadget doesn't forward it to the list.\nThen I accidentally sent email with HTML. 3rd time the charm...\n\n>> Listing some portability guideline here for future reference.\n>>\n>> I'm leaving it to someone else to decide whether to include\n>> it in the file itself, place is as a new file, or not.\n\n> Check Documentation/CodingGuidelines; I think we have something to\n> say about local var=\"val\" construct to help dash.\n\nI wasn't aware of this file, but I should have searched for it before\nposting. Thanks for the pointer.\n\nAs far as I can tell CodingGuidelines and my guideline align perfectly\non every subject which both mention, down to nuances like that quoted\ninitial value in \"local\", though each also has few subjects which the\nother doesn't.\n\n> ... If we were rewriting the prompt\n> scripts to be usable by other shells, great.  But then we'd want to\n> make sure it adheres to existing coding guidelines we have.\n\nNot sure how many prompt scripts there are, but if you're referring\nto the scripts at contrib/completion then only git-prompt.sh is\napplicable in many shells and would gain by being portable. The\nothers are shell-specific, so I wouldn't think they need be portable.\n\nAs for git-prompt.sh, as far as I can tell, after this patchset, this\nfile adheres to CodingGuidelines completely as far as correctness and\ncompatibility go.\n\nHowever, regardless of not being aware of CodingGuidelines, the goal\nof this patchset was to improve compatibility and correctness, and I\nwouldn't have chosen or felt comfortable to included style changes\n(\"'then' in new line\" can have also portability implications, though\nnot in the many shells which I tested).\n\nSo no change in terms of style, it still diverges from the guidelines.\n\nShall I add a commit which fixes style issues?\n"},{"id":"499215","messageId":"1542063589.2363688.1721786934049@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqy15rzwi5.fsf@gitster.g","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-24T02:08:54Z","receivedAt":"2024-07-24T02:09:02Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":"\nOn Tuesday, July 23, 2024 at 11:25:29 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n\n> > $'...' is new in POSIX (2024), and some shells support it in recent\n> > versions, while others have had it for decades (bash, zsh, ksh93).\n\n> I will not look at this series futher during the current development\n> cycle that is about to conclude, but ...\n\nThanks. I'm happy to continue whenever others have the bandwidth.\n\n> > +__git_SOH=$'\\1' __git_STX=$'\\2' __git_ESC=$'\\33'\n> > +__git_LF=$'\\n' __git_CRLF=$'\\r\\n'\n> > +\n> > +if [ $'\\101' != A ]; then  # fallback for shells without $'...'\n> > +  __git_CRLF=$(printf \"\\r\\n\\1\\2\\33\")  # CR LF SOH STX ESC\n> > +  __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}\n> > +  __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}\n> > +  __git_SOH=${__git_CRLF#??};  __git_CRLF=${__git_CRLF%?}\n> > +  __git_LF=${__git_CRLF#?}\n> > +fi\n\n> ... I would prefer to see it done without any \"fallback\".\n\nThat's fair. I'll change it.\n\n> $(printf '\\r') would work with bash, zsh and ksh93, too, and one\n> time assignment to these variables is not going to be performance\n> critical.\n\nGenerally true, and also mostly non-generally as far as performace\ngoes, though personally I'd prefer to avoid command substitution in\nthis context if possible, as even a single one can have non-negligible\nimpact in (very) hot scripts.\n\nBut it would still be very small, and doesn't matter with this file.\n\n> Just forbid use of $'\\octal' notation in the coding\n> guidelines document, and implement just one variant.\n\nAgreed, and the CodingGuidelines patch LGTM.\n\nHowever, off the top of my head I wouldn't know how this variant\nshould look like. This one printf and splitting it later is a bit\nmeh to be used in every script which needs control literals, but\nI also don't have anything cleaner off the top of my head.\n\n> Perhaps we should spell more things out that you wrote in some of\n> your proposed log messages more explicitly.  I think these have been\n> rules we have followed (grep for them in *.sh files outside\n> contrib/) but I did not find mention in the guidelines document.\n\nIf I can help with this, let me know how.\n\n> Thanks.\n\nMy pleasure.\n"},{"id":"499216","messageId":"992128710.1986532.1721788902932@mail.yahoo.com","threadId":"61830","inReplyTo":"ZqAzpYuTrK6L-uyN@tapette.crustytoothpaste.net","subject":"Re: [PATCH 0/8] git-prompt: support more shells","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-24T02:41:42Z","receivedAt":"2024-07-24T02:41:46Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Wednesday, July 24, 2024 at 01:50:16 AM GMT+3, brian m. carlson <sandals@crustytoothpaste.net> wrote:\n\n> We explicitly allow `local` in our coding guidelines.\n\nYeah. I missed the guidelines initially, but I got to the same\nconclusion with git-prompt.sh - to allow only \"local\" exception.\n\n> As a side note,\n> Debian requires it of all shells that can be used as `/bin/sh`.\n\nI wasn't aware of that, but it does makes sense to me.\n \n> ksh93u+m is planning on adding local in a future revision.\n\nThat's nice. I did try to check whether it's planned, and request if\nit wasn't, but I didn't find the future plans (but also didn't try\ntoo hard). Though I think they're still doing bug fixes for the\nforseeable future, which is also great. Looking forward to it.\n\nHowever, while they do have typeset (in non-posix 'function foo()...),\nit has syntactic scope and not dynamic like with \"local\", so it\nwouldn't be a trivial mapping to an existing functionality.\n\n\"local\" is so useful, and with minimal application restrictions it's\nalready effectively portable with very few exceptions, but ksh93[u+m]\nis indeed one of the notable ones.\n\nI think was a missed opportinity that POSIX 2024 didn't include \"local\"\n(I know it was discussed).\n\nIt is possible to implement the functionality compliantly and even\nwith reasonable syntax, no tricks, and very good performance, but it's\nnot the same as being officially supported.\n"},{"id":"499273","messageId":"xmqq7cdazu4a.fsf@gitster.g","threadId":"61830","inReplyTo":"992128710.1986532.1721788902932@mail.yahoo.com","subject":"Re: [PATCH 0/8] git-prompt: support more shells","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-07-24T15:29:09Z","receivedAt":"2024-07-24T15:29:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n>  On Wednesday, July 24, 2024 at 01:50:16 AM GMT+3, brian m. carlson <sandals@crustytoothpaste.net> wrote:\n>\n>> We explicitly allow `local` in our coding guidelines.\n>\n> Yeah. I missed the guidelines initially, but I got to the same\n> conclusion with git-prompt.sh - to allow only \"local\" exception.\n\nIt is a bit more nuanced than that, though.  Here is what we say:\n\n - Even though \"local\" is not part of POSIX, we make heavy use of it\n   in our test suite.  We do not use it in scripted Porcelains, and\n   hopefully nobody starts using \"local\" before all shells that matter\n   support it (notably, ksh from AT&T Research does not support it yet).\n\nFor the purpose of git-prompt, I think it should be OK (without\n\"local\", it is harder, if not impossible, to clobber end-user's\nshell variable namespace with various temporaries we need to use\nduring prompt computation) to declare that we now support shells\nother than bash and zsh as long as they are reasonably POSIX and\nsupport \"local\" that is dynamic.\n\n> That's nice. I did try to check whether it's planned, and request if\n> it wasn't, but I didn't find the future plans (but also didn't try\n> too hard). Though I think they're still doing bug fixes for the\n> forseeable future, which is also great. Looking forward to it.\n\nDo we know what kind of \"local\" is ksh93 adding?  The same as their\n\"typeset\" that is not dynamic?  That is so different from what others\ndo and scripts expect to be all that useful, I am afraid.\n\n"},{"id":"499287","messageId":"xmqqjzhavhk8.fsf@gitster.g","threadId":"61830","inReplyTo":"xmqq7cdazu4a.fsf@gitster.g","subject":"Re: [PATCH 0/8] git-prompt: support more shells","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-07-24T17:13:59Z","receivedAt":"2024-07-24T17:14:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> For the purpose of git-prompt, I think it should be OK (without\n> \"local\", it is harder, if not impossible, to clobber end-user's\n> shell variable namespace with various temporaries we need to use\n> during prompt computation) to declare that we now support shells\n> other than bash and zsh as long as they are reasonably POSIX and\n> support \"local\" that is dynamic.\n\n\"to clobber\" -> \"to avoid clobbering\", sorry for the noise.\n"},{"id":"499289","messageId":"2104161937.2499137.1721840883913@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqq7cdazu4a.fsf@gitster.g","subject":"Re: [PATCH 0/8] git-prompt: support more shells","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-24T17:08:03Z","receivedAt":"2024-07-24T17:30:06Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Wednesday, July 24, 2024 at 06:29:12 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> It is a bit more nuanced than that, though.  Here is what we say:\n>\n> - Even though \"local\" is not part of POSIX, we make heavy use of it\n>   in our test suite.  We do not use it in scripted Porcelains, and\n>   hopefully nobody starts using \"local\" before all shells that matter\n>   support it (notably, ksh from AT&T Research does not support it yet).\n>\n> For the purpose of git-prompt, I think it should be OK ...\n> to declare that we now support shells\n> other than bash and zsh as long as they are reasonably POSIX and\n> support \"local\" that is dynamic.\n\nI have to admit I missed \"in our test suite\".\nRight, so no \"local\" in Porcelains, but yes in the test suite.\n\nBut yes, agreed, because it supports so many more shells.\nThe commit \"git-prompt: ta-da! document..\" does document it.\n\n> (without\n> \"local\", it is harder, if not impossible, to clobber end-user's\n> shell variable namespace with various temporaries we need to use\n> during prompt computation)\n\nIt actually is technically possible with git-prompt.sh, with 1 LOC.\nSee the \"anecdote\" at end of the same \"ta-da!\" commit message which\ndoes exactly that. Though for obvious reason we can't really do that.\n\n> Do we know what kind of \"local\" is ksh93 adding?  The same as their\n> \"typeset\" that is not dynamic?  That is so different from what others\n> do and scripts expect to be all that useful, I am afraid.\n\nI would think it has to be similar enough to other shells, or else it\ncreates a compatibility nightmare IMO. But that's a guess.\n\nSomewhat off topic, so apologies if this shouldn't be here:\n\nAs for the Porcelains, I have to assume that it can be unpleasant\nto maintain big scripts without \"local\". Would there be an interest\nin adding a facility with the same semantics as \"local\", but posix\ncompliant (and also posix-ish shells), for use in Porcelains?\n\nIt's not a drop-in replacement, but the syntax is reasonable IMO:\n\n    locals myfunc x y\n    _myfunc () {\n        echo \"$? $1 $2\"\n        x=1 y=2\n        return 33\n    }\n\n    x=x; unset y\n    (exit 42) || myfunc foo bar\n    echo \"$? $x ${y-unset}\"\n\nPrints:\n    42 foo bar\n    33 x unset\n\n\"locals myfunc x y\" creates a wrapper function \"myfunc\" which saves\nthe state of $x and $y, calls _myfunc \"$@\", then restores the state\n(and propagates the initial and final $? appropriately). Recursion is\nsupported, the wrapper doesn't create additional variables, and no\nsubshells are used at the wrapper (also not at \"locals\").\n\nThe implementation of \"locals\" is small (10-20 LOC), but we can't\nexpect scripts to embed it, so it would need to be sourced (dot).\n\nIf there is interest in such thing, let me know, and I can submit\na patch (independent of this patchset) to adds such file which\ncan then be sourced by other scripts in order to use \"locals\".\n\nUnrelated, and it might not mean much, but I did want to thank you\nfor maintaining git all those years.\n\n"},{"id":"499330","messageId":"1106076396.2672924.1721906849141@mail.yahoo.com","threadId":"61830","inReplyTo":"1542063589.2363688.1721786934049@mail.yahoo.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-25T11:27:29Z","receivedAt":"2024-07-25T11:38:14Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Wednesday, July 24, 2024 at 05:08:54 AM GMT+3, avih <avihpit@yahoo.com> wrote:\n> On Tuesday, July 23, 2024 at 11:25:29 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n> > >\n> > > +__git_SOH=$'\\1' __git_STX=$'\\2' __git_ESC=$'\\33'\n> > > +__git_LF=$'\\n' __git_CRLF=$'\\r\\n'\n> > > +\n> > > +if [ $'\\101' != A ]; then  # fallback for shells without $'...'\n> > > +  __git_CRLF=$(printf \"\\r\\n\\1\\2\\33\")  # CR LF SOH STX ESC\n> > > +  __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}\n> > > +  __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}\n> > > +  __git_SOH=${__git_CRLF#??};  __git_CRLF=${__git_CRLF%?}\n> > > +  __git_LF=${__git_CRLF#?}\n> > > +fi\n>\n> > ... I would prefer to see it done without any \"fallback\".\n> > Just forbid use of $'\\octal' notation in the coding\n> > guidelines document, and implement just one variant.\n>\n> ... off the top of my head I wouldn't know how this variant\n> should look like. This one printf and splitting it later is a bit\n> meh to be used in every script which needs control literals, but\n> I also don't have anything cleaner off the top of my head.\n\nI think I misinterpreted the scope of \"variant\". I thought it meant,\nacross scripts which need to use $'...', but now I realize it meant\nbetween using $'...' and using the fallback in this patch.\n\nSo mainly as a general solution, but also applicable to this patch,\nbelow is my best generalized solution so far, so that scripts don't\nhave to reinvent the wheel with this \"string strip dance\" above,\nbut I'm not too happy with it, mainly due to the gotcha that single\nquotes in the value break the world (escape the \"eval\").\n\nSo unless others prefer this solution or have other ideas, I think\nit's best to keep the existing \"strip dance\" which the patch already\nhas, but make it the only variant instead of being a fallback.\n\nGeneralized solution (without namespace-ification):\n\n    # assign_as_fmt NAME=FMT ...  -->  NAME=$(printf FMT) ...\n    # - works also if the output ends in newline\n    # - NAME must be a valid var name\n    # - FMT _must_ not include/output single quotes (escapes eval)\n    # - best used like $'..':  x=$'\\r\\n'  ->  assign_as_fmt x='\\r\\n'\n    #   (which also avoids accidental single quotes, but not '\\047')\n    assign_as_fmt () {\n        # accumulate \" NAME='FMT'\" from each \"NAME=FMT\"\n        fmt=  # ignore non-locality for now\n        while [ \"${1+x}\" ]; do\n            fmt=\"$fmt ${1%%=*}='${1#*=}'\"\n            shift\n        done\n        eval \"$(printf \"$fmt\")\"  # FMTs become values, eval'ed\n    }\n\n    assign_as_fmt \\\n        __git_SOH='\\1' __git_STX='\\2' __git_ESC='\\33' \\\n        __git_LF='\\n' __git_CRLF='\\r\\n'\n\n"},{"id":"499342","messageId":"258254527.2690084.1721914093743@mail.yahoo.com","threadId":"61830","inReplyTo":"1106076396.2672924.1721906849141@mail.yahoo.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-25T13:28:13Z","receivedAt":"2024-07-25T14:40:24Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Thursday, July 25, 2024 at 02:27:29 PM GMT+3, avih <avihpit@yahoo.com> wrote:\n>\n> So mainly as a general solution, but also applicable to this patch,\n> below is my best generalized solution so far, so that scripts don't\n> have to reinvent the wheel with this \"string strip dance\" above,\n> but I'm not too happy with it, mainly due to the gotcha that single\n> quotes in the value break the world (escape the \"eval\").\n\nPardon the noise.\n\nTo summarize the options to replace $'...' portably, like:\n\n    __git_SOH=$'\\1' __git_STX=$'\\2' __git_ESC=$'\\33'\n    __git_LF=$'\\n' __git_CRLF=$'\\r\\n'\n\nThe current patch has this, which is not fun and not scalable:\n\n   __git_CRLF=$(printf \"\\r\\n\\1\\2\\33\")  # CR LF SOH STX ESC\n   __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}\n   __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}\n   __git_SOH=${__git_CRLF#??};   __git_CRLF=${__git_CRLF%?}\n   __git_LF=${__git_CRLF#?}\n\nIf performance is not important, this works (with care about \\n):\n\n   __git_LF=$(printf \"\\nx\"); __git_LF=${__git_LF%x}\n   __git_STX=$(printf '\\1')\n   ...\n\nA previous message suggested this, which has a beautiful API,\nbut it requires an additional non-tiny function, and it also\nhides a great risk of escaping \"eval\":\n\n    assign_as_fmt () {\n        # hides the usage of \"eval\"\n        ...\n    }\n\n    assign_as_fmt \\\n        __git_SOH='\\1' __git_STX='\\2' __git_ESC='\\33' \\\n        __git_LF='\\n' __git_CRLF='\\r\\n'\n\nBut then I figured there's another option, which is reasonably\nreadable, scalable, small without additional functions, but still\nrequires some care, though the risk is not hidden and easy to avoid:\n\nIt's basically what the function does, but without a function:\n(double quotes required only if it ends in \\n, or for uniformity)\n\n    # doubel-check to ensure the printf output is valid shell input\n    eval \"$(printf '\n        __git_SOH=\"\\1\" __git_STX=\"\\2\" __git_ESC=\"\\33\"\n        __git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n    ')\"\n\nI think it strikes the best balance between the options, both\nfor this patch, and possibly also as a general recomendation.\n\nSo unless there are objections or better suggestions, this is\nwhat I currently prefer for this patch.\n"},{"id":"499358","messageId":"xmqqwml9igux.fsf@gitster.g","threadId":"61830","inReplyTo":"1106076396.2672924.1721906849141@mail.yahoo.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-07-25T16:19:50Z","receivedAt":"2024-07-25T16:19:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n> Generalized solution (without namespace-ification):\n\nI think you are over-engineering this.  We do not have immediate\nneed for such facility to be used by other scripts.  On the other\nhand, we know exactly what git-prompt wants to see available, and\nyou already implemented them.\n\nSo just losing \"make assignment asuming $'blah' works, and then\nreassign based on what printf gave us\" and always using the printf\nthing is what we want to see here.\n\n>     assign_as_fmt \\\n>         __git_SOH='\\1' __git_STX='\\2' __git_ESC='\\33' \\\n>         __git_LF='\\n' __git_CRLF='\\r\\n'\n\nAre you sure that everybody's implementation of printf(1) is happy\nwith \\d and \\dd?  I am an old timer who learnt in a distant past to\nalways spell octals as \\ddd without omitting any leading 0-digit,\nbecause some was unhappy.\n\nThanks.\n"},{"id":"499359","messageId":"xmqqsevxignu.fsf@gitster.g","threadId":"61830","inReplyTo":"258254527.2690084.1721914093743@mail.yahoo.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-07-25T16:24:05Z","receivedAt":"2024-07-25T16:24:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n>     eval \"$(printf '\n>         __git_SOH=\"\\1\" __git_STX=\"\\2\" __git_ESC=\"\\33\"\n>         __git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n>     ')\"\n>\n> I think it strikes the best balance between the options, both\n> for this patch, and possibly also as a general recomendation.\n>\n> So unless there are objections or better suggestions, this is\n> what I currently prefer for this patch.\n\nModulo my superstition against \\d and \\dd, the above does look\nvery readable and hard to break.\n\nThanks.\n"},{"id":"499376","messageId":"511935853.2797881.1721937799082@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqsevxignu.fsf@gitster.g","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-07-25T20:03:19Z","receivedAt":"2024-07-25T20:15:08Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Thursday, July 25, 2024 at 07:19:56 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n> I think you are over-engineering this.  We do not have immediate\n> need for such facility to be used by other scripts.  On the other\n> hand, we know exactly what git-prompt wants to see available, and\n> you already implemented them.\n\nYes. It was a misunderstanding on my part, and it was overengineered.\n\nBut because I initially misinterpreted your statement as\n\"disallow $'...' at the guidelines, and we need to find one variant\n(form) to use\", it got me thinking, because I wasn't very happy with\nthe existing form at the patch either.\n\nAnd it did eventually lead to a solution we both liked. I'm OK taking\nthat road, but next time I should probably wait a bit more before\ngoing pulic with half-baked ideas.\n\n> So just losing \"make assignment asuming $'blah' works, and then\n> reassign based on what printf gave us\" and always using the printf\n> thing is what we want to see here.\n\nYes.\n\n> Are you sure that everybody's implementation of printf(1) is happy\n> with \\d and \\dd?  I am an old timer who learnt in a distant past to\n> always spell octals as \\ddd without omitting any leading 0-digit,\n> because some was unhappy.\n\nIf I knew who \"everybody\" is, then maybe.\n\nBut \"learned in the distant past\" does carry weight, as do existing\npractices. However, there seem to be almost no cases in non - /t/...\nfiles, and most of them are in git-prompt.sh.\n\nIn test scripts though, it's a mixed bag. I think in decreasing order\nof popularity:\n- Always use \\ddd form.\n- Allow less than 3 if it begins with 0, like \\01, and many \\0 .\n- Yes, \\1 or \\4 are fine (there are not many of those).\n\nI'll use the \\ddd form you because you prefer it and it does seem the\nmost popular (I think also outside of git codebase), and even if only\nfor being bullet-proof against following '0'-'7' chars at the string.\n\nBut back to the question of how much I'm sure, then I'm sure there\nare exceptions, but I couldn't find one yet.\n\nIt works in all the shell-builtin-printf I have access to (~ 20),\nas well as gnu /bin/printf. Obviously there are many common ancestors\nthere (esp. ash and pdksh), but they are still different codebases,\nand others don't share code with those, like ksh, bash, Schily, yash.\n\nAs a cute data point, this printf statement, copy-pasted into a 1981\nBSD 2.11 running on PDP11, prints the exact output as it does today:\n\n    printf 'a=\"\\1\" b=\"\\2\" c=\"\\33\" d=\"\\n\" e=\"\\r\\n\"' | od -c\n\nhttps://skn.noip.me/pdp11/pdp11.html  (\"boot RP1\", user root, no pass)\n\nOn Thursday, July 25, 2024 at 07:24:08 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n> avih <avihpit@yahoo.com> writes:\n> >    eval \"$(printf '\n> >        __git_SOH=\"\\1\" __git_STX=\"\\2\" __git_ESC=\"\\33\"\n> >        __git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n> >    ')\"\n>\n> Modulo my superstition against \\d and \\dd, the above does look\n> very readable and hard to break.\n\nThanks.\n\n"},{"id":"500930","messageId":"2007960310.4114358.1723658954502@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqy15rzwi5.fsf@gitster.g","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-14T18:09:14Z","receivedAt":"2024-08-14T18:39:48Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Tuesday, July 23, 2024 at 11:25:29 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n> > From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n> >\n> > $'...' is new in POSIX (2024), and some shells support it in recent\n> > versions, while others have had it for decades (bash, zsh, ksh93).\n>\n> I will not look at this series futher during the current development\n> cycle that is about to conclude, but ...\n\nPing\n\nReminder: I'll update this part to not-use $'...' and without\nfallback, but I'm currently waiting for comments on the other parts\nas well before I update this patch.\n\n- avih\n\n\n"},{"id":"500936","messageId":"xmqqfrr6yk73.fsf@gitster.g","threadId":"61830","inReplyTo":"2007960310.4114358.1723658954502@mail.yahoo.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-14T19:32:16Z","receivedAt":"2024-08-14T19:32:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n>  On Tuesday, July 23, 2024 at 11:25:29 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n>> > From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n>> >\n>> > $'...' is new in POSIX (2024), and some shells support it in recent\n>> > versions, while others have had it for decades (bash, zsh, ksh93).\n>>\n>> I will not look at this series futher during the current development\n>> cycle that is about to conclude, but ...\n>\n> Ping\n>\n> Reminder: I'll update this part to not-use $'...' and without\n> fallback, but I'm currently waiting for comments on the other parts\n> as well before I update this patch.\n\nPing for others.  I do not recall having much other things to say on\nthe series.\n\nThanks.\n\n"},{"id":"500947","messageId":"12887914.4232362.1723695432887@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqfrr6yk73.fsf@gitster.g","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-15T04:17:12Z","receivedAt":"2024-08-15T04:57:45Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Wednesday, August 14, 2024 at 10:32:19 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n>> avih <avihpit@yahoo.com> writes:\n>>>  On Tuesday, July 23, 2024 at 11:25:29 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n>>> I will not look at this series futher during the current development\n>>> cycle that is about to conclude, but ...\n>>\n>> Ping\n>>\n>> Reminder: I'll update this part to not-use $'...' and without\n>> fallback, but I'm currently waiting for comments on the other parts\n>> as well before I update this patch.\n>\n> Ping for others.  I do not recall having much other things to say on\n> the series.\n\nNot sure I understand.\n\nShall I ping the other 7 parts individually?\n\nOr shall I go ahead and post the updated part 6/8 (and rebased\nparts 7 and 8 trivially)\n\nSlightly off topic, git-prompt.sh was not modified in master since\nI submitted the series, so no need to rebase the series, right?\n\n\n"},{"id":"500994","messageId":"xmqqy14yuf9r.fsf@gitster.g","threadId":"61830","inReplyTo":"12887914.4232362.1723695432887@mail.yahoo.com","subject":"Re: [PATCH 6/8] git-prompt: add fallback for shells without $'...'","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-15T12:44:32Z","receivedAt":"2024-08-15T12:44:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n>>> Ping\n>>>\n>>> Reminder: I'll update this part to not-use $'...' and without\n>>> fallback, but I'm currently waiting for comments on the other parts\n>>> as well before I update this patch.\n>>\n>> Ping for others.  I do not recall having much other things to say on\n>> the series.\n>\n> Not sure I understand.\n>\n> Shall I ping the other 7 parts individually?\n\nNo, I pinged other folks, who are reading git@vger.kernel.org, to\ngive their reviews, because the prompt script is not exactly my area\nof expertise.  I commented on it only because nobody else did, and\nbecause I care about portability while keeping the complexity level\ndown.  Other aspects of the series are better reviewed by others,\nnot by me.\n\nIf you have updated series, resending the whole series with as v2\n(e.g. [PATCH v2 1/8]..[PATCH v2 8/8], if there is no change in the\nnumber of patches) would be good.\n\nTHanks.\n"},{"id":"500995","messageId":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.git.git.1721762306.gitgitgadget@gmail.com","subject":"[PATCH v2 0/8] git-prompt: support more shells v2","fromName":"Avi Halachmi via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:05Z","receivedAt":"2024-08-15T13:14:17Z","isPatch":true,"sender":{"key":"name:Avi Halachmi","avatar":null},"body":"This addresses review comment on part 6/8 (git-prompt: add fallback for\nshells without $'...') which requested to use one form for all shells\ninstead $'...' where supported and a fallback otherwise.\n\nParts 7/8 and 8/8 are rebased trivially on top of updated part 6/8.\n\nUsing the GitGitGadget github interface, so I don't know whether it will\nsend only the 3 updated patches, or all 8 as v2.\n\nPotential followups which this series does not address:\n\n * A comment on part 6/8 suggested to add to CodingGuidelines some of the\n   guidelines in the commit messages, without being specific, likely\n   referring to part 5/8 (git-prompt: add some missing quotes).\n\n * The same comment to 6/8 posted a suggested patch to CodingGuidelines to\n   disallow bashism [[...]], and disallow $'...' - which is comliant (POSIX\n   2024) but not supported in all shells.\n\nAvi Halachmi (:avih) (8):\n  git-prompt: use here-doc instead of here-string\n  git-prompt: fix uninitialized variable\n  git-prompt: don't use shell arrays\n  git-prompt: replace [[...]] with standard code\n  git-prompt: add some missing quotes\n  git-prompt: don't use shell $'...'\n  git-prompt: ta-da! document usage in other shells\n  git-prompt: support custom 0-width PS1 markers\n\n contrib/completion/git-prompt.sh | 191 ++++++++++++++++++++-----------\n 1 file changed, 126 insertions(+), 65 deletions(-)\n\n\nbase-commit: d19b6cd2dd72dc811f19df4b32c7ed223256c3ee\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1750%2Favih%2Fprompt-compat-v2\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1750/avih/prompt-compat-v2\nPull-Request: https://github.com/git/git/pull/1750\n\nRange-diff vs v1:\n\n 1:  9ce5ddadf0b = 1:  9ce5ddadf0b git-prompt: use here-doc instead of here-string\n 2:  680ecb52404 = 2:  680ecb52404 git-prompt: fix uninitialized variable\n 3:  7e994eae7bc = 3:  7e994eae7bc git-prompt: don't use shell arrays\n 4:  232340902a1 = 4:  232340902a1 git-prompt: replace [[...]] with standard code\n 5:  4f77b7eb7f1 = 5:  4f77b7eb7f1 git-prompt: add some missing quotes\n 6:  1c1b58e20ca ! 6:  363b7015763 git-prompt: add fallback for shells without $'...'\n     @@ Metadata\n      Author: Avi Halachmi (:avih) <avihpit@yahoo.com>\n      \n       ## Commit message ##\n     -    git-prompt: add fallback for shells without $'...'\n     +    git-prompt: don't use shell $'...'\n      \n          $'...' is new in POSIX (2024), and some shells support it in recent\n          versions, while others have had it for decades (bash, zsh, ksh93).\n      \n          However, there are still enough shells which don't support it, and\n     -    it's cheap to provide a fallback for them, so let's do that instead\n     -    of dismissing it as \"it's compliant\".\n     +    it's cheap to use an alternative form which works in all shells,\n     +    so let's do that instead of dismissing it as \"it's compliant\".\n     +\n     +    It was agreed to use one form rather than $'...' where supported and\n     +    fallback otherwise.\n      \n          shells where $'...' works:\n          - bash, zsh, ksh93, mksh, busybox-ash, dash master, free/net bsd sh.\n     @@ contrib/completion/git-prompt.sh\n       __git_printf_supports_v=\n       printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n       \n     -+__git_SOH=$'\\1' __git_STX=$'\\2' __git_ESC=$'\\33'\n     -+__git_LF=$'\\n' __git_CRLF=$'\\r\\n'\n     -+\n     -+if [ $'\\101' != A ]; then  # fallback for shells without $'...'\n     -+   __git_CRLF=$(printf \"\\r\\n\\1\\2\\33\")  # CR LF SOH STX ESC\n     -+   __git_ESC=${__git_CRLF#????}; __git_CRLF=${__git_CRLF%?}\n     -+   __git_STX=${__git_CRLF#???};  __git_CRLF=${__git_CRLF%?}\n     -+   __git_SOH=${__git_CRLF#??};   __git_CRLF=${__git_CRLF%?}\n     -+   __git_LF=${__git_CRLF#?}\n     -+fi\n     ++# like __git_SOH=$'\\001' etc but works also in shells without $'...'\n     ++eval \"$(printf '\n     ++\t__git_SOH=\"\\001\" __git_STX=\"\\002\" __git_ESC=\"\\033\"\n     ++\t__git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n     ++')\"\n      +\n       # stores the divergence from upstream in $p\n       # used by GIT_PS1_SHOWUPSTREAM\n 7:  4a086ffc360 = 7:  4aa75cdb5dd git-prompt: ta-da! document usage in other shells\n 8:  f241c3ae1e4 = 8:  e71ddcd2232 git-prompt: support custom 0-width PS1 markers\n\n-- \ngitgitgadget\n"},{"id":"500996","messageId":"9ce5ddadf0bb13229461d67451094a373348771e.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 1/8] git-prompt: use here-doc instead of here-string","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:06Z","receivedAt":"2024-08-15T13:14:18Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nHere-documend is standard, and works in all shells.\n\nBoth here-string and here-doc add final newline, which is important\nin this case, because $output is without final newline, but we do\nwant \"read\" to succeed on the last line as well.\n\nShells which support here-string:\n- bash, zsh, mksh, ksh93, yash (non-posix-mode).\n\nshells which don't, and got fixed:\n- ash-derivatives (dash, free/net bsd sh, busybox-ash).\n- pdksh, openbsd sh.\n- All Schily Bourne shell variants.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5330e769a72..ebf2e30d684 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -137,7 +137,9 @@ __git_ps1_show_upstream ()\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n \t\tesac\n-\tdone <<< \"$output\"\n+\tdone <<-OUTPUT\n+\t\t$output\n+\tOUTPUT\n \n \t# parse configuration values\n \tlocal option\n-- \ngitgitgadget\n\n"},{"id":"500997","messageId":"680ecb524040c64f886c4e484a64f0d17b512e27.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 2/8] git-prompt: fix uninitialized variable","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:07Z","receivedAt":"2024-08-15T13:14:19Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nFirst use is in the form:  local var; ...; var=$var$whatever...\n\nIf the variable was unset (as bash and others do after \"local x\"),\nthen it would error if set -u is in effect.\n\nAlso, many shells inherit the existing value after \"local var\"\nwithout init, but in this case it's unlikely to have a prior value.\n\nNow we initialize it.\n\n(local var= is enough, but local var=\"\" is the custom in this file)\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex ebf2e30d684..4cc2cf91bb6 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,7 +116,7 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern count n\n+\tlocal svn_remote svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n \n \tsvn_remote=()\n-- \ngitgitgadget\n\n"},{"id":"500998","messageId":"7e994eae7bc3dfa021262410c801ddb124ce24f1.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 3/8] git-prompt: don't use shell arrays","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:08Z","receivedAt":"2024-08-15T13:14:19Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nArrays only existed in the svn-upstream code, used to:\n- Keep a list of svn remotes.\n- Convert commit msg to array of words, extract the 2nd-to-last word.\n\nExcept bash/zsh, nearly all shells failed load on syntax errors here.\n\nNow:\n- The svn remotes are a list of newline-terminated values.\n- The 2nd-to-last word is extracted using standard shell substrings.\n- All shells can digest the svn-upstream code.\n\nWhile using shell field splitting to extract the word is simple, and\ndoesn't even need non-standard code, e.g. set -- $(git log -1 ...),\nit would have the same issues as the old array code: it depends on IFS\nwhich we don't control, and it's subject to glob-expansion, e.g. if\nthe message happens to include * or **/* (as this commit message just\ndid), then the array could get huge. This was not great.\n\nNow it uses standard shell substrings, and we know the exact delimiter\nto expect, because it's the match from our grep just one line earlier.\n\nThe new word extraction code also fixes svn-upstream in zsh, because\npreviously it used arr[len-2], but because in zsh, unlike bash, array\nsubscripts are 1-based, it incorrectly extracted the 3rd-to-last word.\nsymptom: missing upstream status in a git-svn repo: u=, u+N-M, etc.\n\nThe breakage in zsh is surprising, because it was last touched by\n  commit d0583da838 (prompt: fix show upstream with svn and zsh),\nclaiming to fix exactly that. However, it only mentions syntax fixes.\nIt's unclear if behavior was fixed too. But it was broken, now fixed.\n\nNote LF=$'\\n' and then using $LF instead of $'\\n' few times.\nA future commit will add fallback for shells without $'...', so this\nwould be the only line to touch instead of replacing every $'\\n' .\n\nShells which could run the previous array code:\n- bash\n\nShells which have arrays but were broken anyway:\n- zsh: 1-based subscript\n- ksh93: no \"local\" (the new code can't fix this part...)\n- mksh, openbsd sh, pdksh: failed load on syntax error: \"for ((...))\".\n\nMore shells which Failed to load due to syntax error:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne shell, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 48 ++++++++++++++++++++------------\n 1 file changed, 30 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4cc2cf91bb6..75c3a813fda 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,10 +116,10 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern=\"\" count n\n+\tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n+\tlocal LF=$'\\n'\n \n-\tsvn_remote=()\n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n \twhile read -r key value; do\n@@ -132,7 +132,7 @@ __git_ps1_show_upstream ()\n \t\t\tfi\n \t\t\t;;\n \t\tsvn-remote.*.url)\n-\t\t\tsvn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n+\t\t\tsvn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n \t\t\tsvn_url_pattern=\"$svn_url_pattern\\\\|$value\"\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n@@ -156,25 +156,37 @@ __git_ps1_show_upstream ()\n \tcase \"$upstream_type\" in\n \tgit)    upstream_type=\"@{upstream}\" ;;\n \tsvn*)\n-\t\t# get the upstream from the \"git-svn-id: ...\" in a commit message\n-\t\t# (git-svn uses essentially the same procedure internally)\n-\t\tlocal -a svn_upstream\n-\t\tsvn_upstream=($(git log --first-parent -1 \\\n-\t\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null))\n-\t\tif [[ 0 -ne ${#svn_upstream[@]} ]]; then\n-\t\t\tsvn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}\n-\t\t\tsvn_upstream=${svn_upstream%@*}\n-\t\t\tlocal n_stop=\"${#svn_remote[@]}\"\n-\t\t\tfor ((n=1; n <= n_stop; n++)); do\n-\t\t\t\tsvn_upstream=${svn_upstream#${svn_remote[$n]}}\n-\t\t\tdone\n+\t\t# successful svn-upstream resolution:\n+\t\t# - get the list of configured svn-remotes ($svn_remotes set above)\n+\t\t# - get the last commit which seems from one of our svn-remotes\n+\t\t# - confirm that it is from one of the svn-remotes\n+\t\t# - use $GIT_SVN_ID if set, else \"git-svn\"\n \n-\t\t\tif [[ -z \"$svn_upstream\" ]]; then\n+\t\t# get upstream from \"git-svn-id: UPSTRM@N HASH\" in a commit message\n+\t\t# (git-svn uses essentially the same procedure internally)\n+\t\tlocal svn_upstream=\"$(\n+\t\t\tgit log --first-parent -1 \\\n+\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null\n+\t\t)\"\n+\n+\t\tif [ -n \"$svn_upstream\" ]; then\n+\t\t\t# extract the URI, assuming --grep matched the last line\n+\t\t\tsvn_upstream=${svn_upstream##*$LF}  # last line\n+\t\t\tsvn_upstream=${svn_upstream#*: }    # UPSTRM@N HASH\n+\t\t\tsvn_upstream=${svn_upstream%@*}     # UPSTRM\n+\n+\t\t\tcase ${LF}${svn_remotes} in\n+\t\t\t*\"${LF}${svn_upstream}${LF}\"*)\n+\t\t\t\t# grep indeed matched the last line - it's our remote\n \t\t\t\t# default branch name for checkouts with no layout:\n \t\t\t\tupstream_type=${GIT_SVN_ID:-git-svn}\n-\t\t\telse\n+\t\t\t\t;;\n+\t\t\t*)\n+\t\t\t\t# the commit message includes one of our remotes, but\n+\t\t\t\t# it's not at the last line. is $svn_upstream junk?\n \t\t\t\tupstream_type=${svn_upstream#/}\n-\t\t\tfi\n+\t\t\t\t;;\n+\t\t\tesac\n \t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n-- \ngitgitgadget\n\n"},{"id":"500999","messageId":"232340902a1feeafe526528eb88b8d0814d11545.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 4/8] git-prompt: replace [[...]] with standard code","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:09Z","receivedAt":"2024-08-15T13:14:20Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe existing [[...]] tests were either already valid as standard [...]\ntests, or only required minimal retouch:\n\nNotes:\n\n- [[...]] doesn't do field splitting and glob expansion, so $var\n  or $(cmd...) don't need quoting, but [... does need quotes.\n\n- [[ X == Y ]] when Y is a string is same as [ X = Y ], but if Y is\n  a pattern, then we need:  case X in Y)... ; esac  .\n\n- [[ ... && ... ]] was replaced with [ ... ] && [ ... ] .\n\n- [[ -o <zsh-option> ]] requires [[...]], so put it in \"eval\" and only\n  eval it in zsh, so other shells would not abort on syntax error\n  (posix says [[ has unspecified results, shells allowed to reject it)\n\n- ((x++)) was changed into x=$((x+1))  (yeah, not [[...]] ...)\n\nShells which accepted the previous forms:\n- bash, zsh, ksh93, mksh, openbsd sh, pdksh.\n\nShells which didn't, and now can process it:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne sh, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 30 ++++++++++++++++--------------\n 1 file changed, 16 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 75c3a813fda..4781261f868 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -126,7 +126,7 @@ __git_ps1_show_upstream ()\n \t\tcase \"$key\" in\n \t\tbash.showupstream)\n \t\t\tGIT_PS1_SHOWUPSTREAM=\"$value\"\n-\t\t\tif [[ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]]; then\n+\t\t\tif [ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]; then\n \t\t\t\tp=\"\"\n \t\t\t\treturn\n \t\t\tfi\n@@ -187,14 +187,14 @@ __git_ps1_show_upstream ()\n \t\t\t\tupstream_type=${svn_upstream#/}\n \t\t\t\t;;\n \t\t\tesac\n-\t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n+\t\telif [ \"svn+git\" = \"$upstream_type\" ]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n \t\t;;\n \tesac\n \n \t# Find how many commits we are ahead/behind our upstream\n-\tif [[ -z \"$legacy\" ]]; then\n+\tif [ -z \"$legacy\" ]; then\n \t\tcount=\"$(git rev-list --count --left-right \\\n \t\t\t\t\"$upstream_type\"...HEAD 2>/dev/null)\"\n \telse\n@@ -206,8 +206,8 @@ __git_ps1_show_upstream ()\n \t\t\tfor commit in $commits\n \t\t\tdo\n \t\t\t\tcase \"$commit\" in\n-\t\t\t\t\"<\"*) ((behind++)) ;;\n-\t\t\t\t*)    ((ahead++))  ;;\n+\t\t\t\t\"<\"*) behind=$((behind+1)) ;;\n+\t\t\t\t*)    ahead=$((ahead+1))   ;;\n \t\t\t\tesac\n \t\t\tdone\n \t\t\tcount=\"$behind\t$ahead\"\n@@ -217,7 +217,7 @@ __git_ps1_show_upstream ()\n \tfi\n \n \t# calculate the result\n-\tif [[ -z \"$verbose\" ]]; then\n+\tif [ -z \"$verbose\" ]; then\n \t\tcase \"$count\" in\n \t\t\"\") # no upstream\n \t\t\tp=\"\" ;;\n@@ -243,7 +243,7 @@ __git_ps1_show_upstream ()\n \t\t*)\t    # diverged from upstream\n \t\t\tupstream=\"|u+${count#*\t}-${count%\t*}\" ;;\n \t\tesac\n-\t\tif [[ -n \"$count\" && -n \"$name\" ]]; then\n+\t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n \t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n@@ -265,7 +265,7 @@ __git_ps1_show_upstream ()\n # their own color.\n __git_ps1_colorize_gitstring ()\n {\n-\tif [[ -n ${ZSH_VERSION-} ]]; then\n+\tif [ -n \"${ZSH_VERSION-}\" ]; then\n \t\tlocal c_red='%F{red}'\n \t\tlocal c_green='%F{green}'\n \t\tlocal c_lblue='%F{blue}'\n@@ -417,7 +417,7 @@ __git_ps1 ()\n \t# incorrect.)\n \t#\n \tlocal ps1_expanded=yes\n-\t[ -z \"${ZSH_VERSION-}\" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no\n+\t[ -z \"${ZSH_VERSION-}\" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no\n \t[ -z \"${BASH_VERSION-}\" ] || shopt -q promptvars || ps1_expanded=no\n \n \tlocal repo_info rev_parse_exit_code\n@@ -502,11 +502,13 @@ __git_ps1 ()\n \t\t\t\t\treturn $exit\n \t\t\t\tfi\n \n-\t\t\t\tif [[ $head == \"ref: \"* ]]; then\n+\t\t\t\tcase $head in\n+\t\t\t\t\"ref: \"*)\n \t\t\t\t\thead=\"${head#ref: }\"\n-\t\t\t\telse\n+\t\t\t\t\t;;\n+\t\t\t\t*)\n \t\t\t\t\thead=\"\"\n-\t\t\t\tfi\n+\t\t\t\tesac\n \t\t\t\t;;\n \t\t\t*)\n \t\t\t\thead=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n@@ -542,8 +544,8 @@ __git_ps1 ()\n \tfi\n \n \tlocal conflict=\"\" # state indicator for unresolved conflicts\n-\tif [[ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" == \"yes\" ]] &&\n-\t   [[ $(git ls-files --unmerged 2>/dev/null) ]]; then\n+\tif [ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" = \"yes\" ] &&\n+\t   [ \"$(git ls-files --unmerged 2>/dev/null)\" ]; then\n \t\tconflict=\"|CONFLICT\"\n \tfi\n \n-- \ngitgitgadget\n\n"},{"id":"501000","messageId":"4f77b7eb7f1110e47201b8c97c34a0cbcd14e24f.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 5/8] git-prompt: add some missing quotes","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:10Z","receivedAt":"2024-08-15T13:14:21Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe issues which this commit fixes are unlikely to be broken\nin real life, but the fixes improve correctness, and would prevent\nbugs in some uncommon cases, such as weird IFS values.\n\nListing some portability guideline here for future reference.\n\nI'm leaving it to someone else to decide whether to include\nit in the file itself, place is as a new file, or not.\n\n---------\n\nThe command \"local\" is non standard, but is allowed in this file:\n- Quote initialization if it can expand (local x=\"$y\"). See below.\n- Don't assume initial value after \"local x\". Either initialize it\n  (local x=..), or set before first use (local x;.. x=..; <use $x>).\n  (between shells, \"local x\" can unset x, or inherit it, or do x= )\n\nOther non-standard features beyond \"local\" are to be avoided.\n\nUse the standard \"test\" - [...] instead of non-standard [[...]] .\n\n--------\n\nQuotes (some portability things, but mainly general correctness):\n\nQuotes prevent tilde-expansion of some unquoted literal tildes (~).\nIf the expansion is undesirable, quotes would ensure that.\n  Tilds expanded: a=~user:~/ ;  echo ~user ~/dir\n  not expanded:   t=\"~\"; a=${t}user  b=\\~foo~;  echo \"~user\" $t/dir\n\nBut the main reason for quoting is to prevent IFS field splitting\n(which also coalesces IFS chars) and glob expansion after parameter\nexpansion or command substitution.\n\nIn _command-arguments_, expanded/substituted values must be quoted:\n  Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n  Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n\nStill in _agumemts_, no need to quote non-expandable values:\n  Good:                 local x=   y=yes;   echo OK\n  OK, but not required: local x=\"\" y=\"yes\"; echo \"OK\"\nBut completely empty (NULL) arguments must be quoted:\n  foo \"\"   is not the same as:   foo\n\nAssignments in simple commands - with or without an actual command,\ndon't need quoting becase there's no IFS split or glob expansion:\n  Good:   s=* a=$b c=$(cmd...)${x# foo }${y-   } [cmd ...]\n  It's also OK to use double quotes, but not required.\n\nThis behavior (no IFS/glob) is called \"assignment context\", and\n\"local\" does not behave with assignment context in some shells,\nhence we require quotes when using \"local\" - for compatibility.\n\nFirst value in 'case...' doesn't IFS-split/glob, doesn't need quotes:\n  Good:       case  * $foo $(cmd...)  in ... ; esac\n  identical:  case \"* $foo $(cmd...)\" in ... ; esac\n\nNested quotes in command substitution are fine, often necessary:\n  Good: echo \"$(foo... \"$x\" \"$(bar ...)\")\"\n\nNested quotes in substring ops are legal, and sometimes needed\nto prevent interpretation as a pattern, but not the most readable:\n  Legal:  foo \"${x#*\"$y\" }\"\n\nNested quotes in \"maybe other value\" subst are invalid, unnecessary:\n  Good:  local x=\"${y- }\";   foo \"${z:+ $a }\"\n  Bad:   local x=\"${y-\" \"}\"; foo \"${z:+\" $a \"}\"\nOuter/inner quotes in \"maybe other value\" have different use cases:\n  \"${x-$y}\"  always one quoted arg: \"$x\" if x is set, else \"$y\".\n  ${x+\"$x\"}  one quoted arg \"$x\" if x is set, else no arg at all.\n  Unquoted $x is similar to the second case, but it would get split\n  into few arguments if it includes any of the IFS chars.\n\nAssignments don't need the outer quotes, and the braces delimit the\nvalue, so nested quotes can be avoided, for readability:\n  a=$(foo \"$x\")  a=${x#*\"$y\" }  c=${y- };  bar \"$a\" \"$b\" \"$c\"\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4781261f868..5d7f236fe48 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -246,7 +246,7 @@ __git_ps1_show_upstream ()\n \t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n-\t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\t\t\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t\t\tupstream=\"$upstream \\${__git_ps1_upstream_name}\"\n \t\t\telse\n \t\t\t\tupstream=\"$upstream ${__git_ps1_upstream_name}\"\n@@ -278,12 +278,12 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n \t\tlocal c_clear=$'\\001\\e[0m\\002'\n \tfi\n-\tlocal bad_color=$c_red\n-\tlocal ok_color=$c_green\n+\tlocal bad_color=\"$c_red\"\n+\tlocal ok_color=\"$c_green\"\n \tlocal flags_color=\"$c_lblue\"\n \n \tlocal branch_color=\"\"\n-\tif [ $detached = no ]; then\n+\tif [ \"$detached\" = no ]; then\n \t\tbranch_color=\"$ok_color\"\n \telse\n \t\tbranch_color=\"$bad_color\"\n@@ -360,7 +360,7 @@ __git_sequencer_status ()\n __git_ps1 ()\n {\n \t# preserve exit status\n-\tlocal exit=$?\n+\tlocal exit=\"$?\"\n \tlocal pcmode=no\n \tlocal detached=no\n \tlocal ps1pc_start='\\u@\\h:\\w '\n@@ -379,7 +379,7 @@ __git_ps1 ()\n \t\t;;\n \t\t0|1)\tprintf_format=\"${1:-$printf_format}\"\n \t\t;;\n-\t\t*)\treturn $exit\n+\t\t*)\treturn \"$exit\"\n \t\t;;\n \tesac\n \n@@ -427,7 +427,7 @@ __git_ps1 ()\n \trev_parse_exit_code=\"$?\"\n \n \tif [ -z \"$repo_info\" ]; then\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal short_sha=\"\"\n@@ -449,7 +449,7 @@ __git_ps1 ()\n \t   [ \"$(git config --bool bash.hideIfPwdIgnored)\" != \"false\" ] &&\n \t   git check-ignore -q .\n \tthen\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal sparse=\"\"\n@@ -499,7 +499,7 @@ __git_ps1 ()\n \t\t\tcase \"$ref_format\" in\n \t\t\tfiles)\n \t\t\t\tif ! __git_eread \"$g/HEAD\" head; then\n-\t\t\t\t\treturn $exit\n+\t\t\t\t\treturn \"$exit\"\n \t\t\t\tfi\n \n \t\t\t\tcase $head in\n@@ -597,10 +597,10 @@ __git_ps1 ()\n \t\tfi\n \tfi\n \n-\tlocal z=\"${GIT_PS1_STATESEPARATOR-\" \"}\"\n+\tlocal z=\"${GIT_PS1_STATESEPARATOR- }\"\n \n \tb=${b##refs/heads/}\n-\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t__git_ps1_branch_name=$b\n \t\tb=\"\\${__git_ps1_branch_name}\"\n \tfi\n@@ -612,7 +612,7 @@ __git_ps1 ()\n \tlocal f=\"$h$w$i$s$u$p\"\n \tlocal gitstring=\"$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}\"\n \n-\tif [ $pcmode = yes ]; then\n+\tif [ \"$pcmode\" = yes ]; then\n \t\tif [ \"${__git_printf_supports_v-}\" != yes ]; then\n \t\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n \t\telse\n@@ -623,5 +623,5 @@ __git_ps1 ()\n \t\tprintf -- \"$printf_format\" \"$gitstring\"\n \tfi\n \n-\treturn $exit\n+\treturn \"$exit\"\n }\n-- \ngitgitgadget\n\n"},{"id":"501001","messageId":"363b7015763a0203771780d3af63eea903228d43.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 6/8] git-prompt: don't use shell $'...'","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:11Z","receivedAt":"2024-08-15T13:14:22Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\n$'...' is new in POSIX (2024), and some shells support it in recent\nversions, while others have had it for decades (bash, zsh, ksh93).\n\nHowever, there are still enough shells which don't support it, and\nit's cheap to use an alternative form which works in all shells,\nso let's do that instead of dismissing it as \"it's compliant\".\n\nIt was agreed to use one form rather than $'...' where supported and\nfallback otherwise.\n\nshells where $'...' works:\n- bash, zsh, ksh93, mksh, busybox-ash, dash master, free/net bsd sh.\n\nshells where it doesn't work, but the new fallback works:\n- all dash releases (up to 0.5.12), older versions of free/net bsd sh,\n  openbsd sh, pdksh, all Schily Bourne sh variants, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 47 ++++++++++++++++++++------------\n 1 file changed, 29 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5d7f236fe48..c3dd38f847c 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -111,6 +111,12 @@\n __git_printf_supports_v=\n printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n \n+# like __git_SOH=$'\\001' etc but works also in shells without $'...'\n+eval \"$(printf '\n+\t__git_SOH=\"\\001\" __git_STX=\"\\002\" __git_ESC=\"\\033\"\n+\t__git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n+')\"\n+\n # stores the divergence from upstream in $p\n # used by GIT_PS1_SHOWUPSTREAM\n __git_ps1_show_upstream ()\n@@ -118,7 +124,7 @@ __git_ps1_show_upstream ()\n \tlocal key value\n \tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n-\tlocal LF=$'\\n'\n+\tlocal LF=\"$__git_LF\"\n \n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n@@ -271,12 +277,16 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue='%F{blue}'\n \t\tlocal c_clear='%f'\n \telse\n-\t\t# Using \\001 and \\002 around colors is necessary to prevent\n-\t\t# issues with command line editing/browsing/completion!\n-\t\tlocal c_red=$'\\001\\e[31m\\002'\n-\t\tlocal c_green=$'\\001\\e[32m\\002'\n-\t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n-\t\tlocal c_clear=$'\\001\\e[0m\\002'\n+\t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n+\t\t# which bash/readline identify while calculating the prompt\n+\t\t# on-screen width - to exclude 0-screen-width esc sequences.\n+\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${__git_STX}\"\n+\n+\t\tlocal c_red=\"${c_pre}31${c_post}\"\n+\t\tlocal c_green=\"${c_pre}32${c_post}\"\n+\t\tlocal c_lblue=\"${c_pre}1;34${c_post}\"\n+\t\tlocal c_clear=\"${c_pre}0${c_post}\"\n \tfi\n \tlocal bad_color=\"$c_red\"\n \tlocal ok_color=\"$c_green\"\n@@ -312,7 +322,7 @@ __git_ps1_colorize_gitstring ()\n # variable, in that order.\n __git_eread ()\n {\n-\ttest -r \"$1\" && IFS=$'\\r\\n' read -r \"$2\" <\"$1\"\n+\ttest -r \"$1\" && IFS=$__git_CRLF read -r \"$2\" <\"$1\"\n }\n \n # see if a cherry-pick or revert is in progress, if the user has committed a\n@@ -430,19 +440,20 @@ __git_ps1 ()\n \t\treturn \"$exit\"\n \tfi\n \n+\tlocal LF=\"$__git_LF\"\n \tlocal short_sha=\"\"\n \tif [ \"$rev_parse_exit_code\" = \"0\" ]; then\n-\t\tshort_sha=\"${repo_info##*$'\\n'}\"\n-\t\trepo_info=\"${repo_info%$'\\n'*}\"\n+\t\tshort_sha=\"${repo_info##*$LF}\"\n+\t\trepo_info=\"${repo_info%$LF*}\"\n \tfi\n-\tlocal ref_format=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_worktree=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal bare_repo=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_gitdir=\"${repo_info##*$'\\n'}\"\n-\tlocal g=\"${repo_info%$'\\n'*}\"\n+\tlocal ref_format=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_worktree=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal bare_repo=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_gitdir=\"${repo_info##*$LF}\"\n+\tlocal g=\"${repo_info%$LF*}\"\n \n \tif [ \"true\" = \"$inside_worktree\" ] &&\n \t   [ -n \"${GIT_PS1_HIDE_IF_PWD_IGNORED-}\" ] &&\n-- \ngitgitgadget\n\n"},{"id":"501002","messageId":"4aa75cdb5dddca0fa2a4817e856d26f724cb43eb.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 7/8] git-prompt: ta-da! document usage in other shells","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:12Z","receivedAt":"2024-08-15T13:14:23Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWith one big exception, git-prompt.sh should now be both almost posix\ncompliant, and also compatible with most (posix-ish) shells.\n\nThat exception is the use of \"local\" vars in functions, which happens\nextensively in the current code, and is not simple to replace with\nposix compliant code (but also not impossible).\n\nLuckily, almost all shells support \"local\" as used by the current\ncode, with the notable exception of ksh93[u+m], but also the Schily\nminimal posix sh (pbosh), and yash in posix mode.\n\nSee assessment below that \"local\" is likely the only blocker in those.\n\nSo except mainly ksh93, git-prompt.sh now works in most shells:\n- bash, zsh, dash since at least 0.5.8, free/net bsd sh, busybox-ash,\n  mksh, openbsd sh, pdksh(!), Schily extended Bourne sh (bosh), yash.\n\nwhich is quite nice.\n\nAs an anecdote, replacing the 1st line in __git_ps1() (local exit=$?)\nwith these 2 makes it work in all tested shells, even without \"local\":\n\n  # handles only 0/1 args for simplicity. needs +5 LOC for any $#\n  __git_e=$?; local exit=\"$__git_e\" 2>/dev/null ||\n    {(eval 'local() { export \"$@\"; }'; __git_ps1 \"$@\"); return \"$__git_e\"; }\n\nExplanation:\n\n  If the shell doesn't have the command \"local\", define our own\n  function \"local\" which instead does plain (global) assignents.\n  Then use __git_ps1 in a subshell to not clober the caller's vars.\n\n  This happens to work because currently there are no name conflicts\n  (shadow) at the code, initial value is not assumed (i.e. always\n  doing either 'local x=...'  or 'local x;...  x=...'), and assigned\n  initial values are quoted (local x=\"$y\"), preventing word split and\n  glob expansion (i.e. assignment context is not assumed).\n\n  The last two (always init, quote values) seem to be enough to use\n  \"local\" portably if supported, and otherwise shells indeed differ.\n\n  Uses \"eval\", else shells with \"local\" may reject it during parsing.\n  We don't need \"export\", but it's smaller than writing our own loop.\n\nWhile cute, this approach is not really sustainable because all the\nvars become global, which is hard to maintain without conflicts\n(but hey, it currently has no conflicts - without even trying...).\n\nHowever, regardless of being an anecdote, it provides some support to\nthe assessment that \"local\" is the only blocker in those shells.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 33 ++++++++++++++++++++++++++++++--\n 1 file changed, 31 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex c3dd38f847c..75f272daa21 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -8,8 +8,8 @@\n # To enable:\n #\n #    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).\n-#    2) Add the following line to your .bashrc/.zshrc:\n-#        source ~/.git-prompt.sh\n+#    2) Add the following line to your .bashrc/.zshrc/.profile:\n+#        . ~/.git-prompt.sh   # dot path/to/this-file\n #    3a) Change your PS1 to call __git_ps1 as\n #        command-substitution:\n #        Bash: PS1='[\\u@\\h \\W$(__git_ps1 \" (%s)\")]\\$ '\n@@ -30,6 +30,8 @@\n #        Optionally, you can supply a third argument with a printf\n #        format string to finetune the output of the branch status\n #\n+#    See notes below about compatibility with other shells.\n+#\n # The repository status will be displayed only if you are currently in a\n # git repository. The %s token is the placeholder for the shown status.\n #\n@@ -106,6 +108,33 @@\n # directory is set up to be ignored by git, then set\n # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the\n # repository level by setting bash.hideIfPwdIgnored to \"false\".\n+#\n+# Conpatibility with other shells (beyond bash/zsh):\n+#\n+#    We require posix-ish shell plus \"local\" support, which is most\n+#    shells (even pdksh), but excluding ksh93 (because no \"local\").\n+#\n+#    Prompt integration might differ between shells, but the gist is\n+#    to load it once on shell init with '. path/to/git-prompt.sh',\n+#    set GIT_PS1* vars once as needed, and either place $(__git_ps1..)\n+#    inside PS1 once (0/1 args), or, before each prompt is displayed,\n+#    call __git_ps1 (2/3 args) which sets PS1 with the status embedded.\n+#\n+#    Many shells support the 1st method of command substitution,\n+#    though some might need to first enable cmd substitution in PS1.\n+#\n+#    When using colors, each escape sequence is wrapped between byte\n+#    values 1 and 2 (control chars SOH, STX, respectively), which are\n+#    invisible at the output, but for bash/readline they mark 0-width\n+#    strings (SGR color sequences) when calculating the on-screen\n+#    prompt width, to maintain correct input editing at the prompt.\n+#\n+#    Currently there's no support for different markers, so if editing\n+#    behaves weird when using colors in __git_ps1, then the solution\n+#    is either to disable colors, or, in some shells which only care\n+#    about the width of the last prompt line (e.g. busybox-ash),\n+#    ensure the git output is not at the last line, maybe like so:\n+#      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n __git_printf_supports_v=\n-- \ngitgitgadget\n\n"},{"id":"501003","messageId":"e71ddcd2232c6f687855e2d4a0c79def1164d71c.1723727653.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v2 8/8] git-prompt: support custom 0-width PS1 markers","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-15T13:14:13Z","receivedAt":"2024-08-15T13:14:23Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWhen using colors, the shell needs to identify 0-width substrings\nin PS1 - such as color escape sequences - when calculating the\non-screen width of the prompt.\n\nUntil now, we used the form %F{<color>} in zsh - which it knows is\n0-width, or otherwise use standard SGR esc sequences wrapped between\nbyte values 1 and 2 (SOH, STX) as 0-width start/end markers, which\nbash/readline identify as such.\n\nBut now that more shells are supported, the standard SGR sequences\ntypically work, but the SOH/STX markers might not be identified.\n\nThis commit adds support for vars GIT_PS1_COLOR_{PRE,POST} which\nset custom 0-width markers or disable the markers.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 19 ++++++++++++-------\n 1 file changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 75f272daa21..5c43981aa11 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -129,11 +129,16 @@\n #    strings (SGR color sequences) when calculating the on-screen\n #    prompt width, to maintain correct input editing at the prompt.\n #\n-#    Currently there's no support for different markers, so if editing\n-#    behaves weird when using colors in __git_ps1, then the solution\n-#    is either to disable colors, or, in some shells which only care\n-#    about the width of the last prompt line (e.g. busybox-ash),\n-#    ensure the git output is not at the last line, maybe like so:\n+#    To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE\n+#    and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not\n+#    use markers. For instance, some shells support '\\[' and '\\]' as\n+#    start/end markers in PS1 - when invoking __git_ps1 with 3/4 args,\n+#    but it may or may not work in command substitution mode. YMMV.\n+#\n+#    If the shell doesn't support 0-width markers and editing behaves\n+#    incorrectly when using colors in __git_ps1, then, other than\n+#    disabling color, it might be solved using multi-line prompt,\n+#    where the git status is not at the last line, e.g.:\n #      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n@@ -309,8 +314,8 @@ __git_ps1_colorize_gitstring ()\n \t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n \t\t# which bash/readline identify while calculating the prompt\n \t\t# on-screen width - to exclude 0-screen-width esc sequences.\n-\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n-\t\tlocal c_post=\"m${__git_STX}\"\n+\t\tlocal c_pre=\"${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${GIT_PS1_COLOR_POST-$__git_STX}\"\n \n \t\tlocal c_red=\"${c_pre}31${c_post}\"\n \t\tlocal c_green=\"${c_pre}32${c_post}\"\n-- \ngitgitgadget\n"},{"id":"501019","messageId":"xmqqsev5u4yr.fsf@gitster.g","threadId":"61830","inReplyTo":"232340902a1feeafe526528eb88b8d0814d11545.1723727653.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 4/8] git-prompt: replace [[...]] with standard code","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-15T16:27:08Z","receivedAt":"2024-08-15T16:27:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avi Halachmi (:avih) via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n>\n> The existing [[...]] tests were either already valid as standard [...]\n> tests, or only required minimal retouch:\n\nFWIW, our local coding guidelines to spell these with \"test\"\n(without closing \"]\"), but this change certainly is a good first\nstep to get rid of non-portable \"[[ ... ]]\" construct.\n\nThanks.\n"},{"id":"501020","messageId":"xmqqmsldu4iu.fsf@gitster.g","threadId":"61830","inReplyTo":"4f77b7eb7f1110e47201b8c97c34a0cbcd14e24f.1723727653.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 5/8] git-prompt: add some missing quotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-15T16:36:41Z","receivedAt":"2024-08-15T16:36:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avi Halachmi (:avih) via GitGitGadget\" <gitgitgadget@gmail.com>\nwrites:\n\n> In _command-arguments_, expanded/substituted values must be quoted:\n>   Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n>   Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n>\n> Still in _agumemts_, no need to quote non-expandable values:\n\narguments.\n\n> -\tlocal bad_color=$c_red\n> -\tlocal ok_color=$c_green\n> +\tlocal bad_color=\"$c_red\"\n> +\tlocal ok_color=\"$c_green\"\n>  \tlocal flags_color=\"$c_lblue\"\n\nGood.  I think we in the past was burned by some shells that want to\nsee these assignments with \"local\" always quoted.\n\n>  \t# preserve exit status\n> -\tlocal exit=$?\n> +\tlocal exit=\"$?\"\n>  \tlocal pcmode=no\n\nWell no matter what value $? has, it by definition has a few digits\nwithout any $IFS funnies.  Does this really matter?  I'd imagine\nthat we would prefer to treat \"$?\" exactly the same way as \"no\".\n\n> @@ -379,7 +379,7 @@ __git_ps1 ()\n>  \t\t;;\n>  \t\t0|1)\tprintf_format=\"${1:-$printf_format}\"\n>  \t\t;;\n> -\t\t*)\treturn $exit\n> +\t\t*)\treturn \"$exit\"\n>  \t\t;;\n\nLikewise.\n"},{"id":"501031","messageId":"1228065843.3779090.1723743313433@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqmsldu4iu.fsf@gitster.g","subject":"Re: [PATCH v2 5/8] git-prompt: add some missing quotes","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-15T17:35:13Z","receivedAt":"2024-08-15T17:48:56Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Thursday, August 15, 2024 at 07:36:43 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n>> > Still in _agumemts_, no need to quote non-expandable values:\n>>\n> arguments.\n\nThanks. Will fix in v3 (after more comments unless asked otherwise).\n\n>> -    local bad_color=$c_red\n>> +    local bad_color=\"$c_red\"\n>\n> Good.  I think we in the past was burned by some shells that want to\n> see these assignments with \"local\" always quoted.\n\nYes. After I reached the same conclusion I noticed it was also added\nto CodingGuidelines not long ago at be34b510 (CodingGuidelines: quote\nassigned value in 'local var=$val').\n\n>>      # preserve exit status\n>> -    local exit=$?\n>> +    local exit=\"$?\"\n>\n> Well no matter what value $? has, it by definition has a few digits\n> without any $IFS funnies.  Does this really matter?  I'd imagine\n> that we would prefer to treat \"$?\" exactly the same way as \"no\".\n>\n> -        *)    return $exit\n> +        *)    return \"$exit\"\n>\n> Likewise.\n\nTwo things here:\n\n1. It can matter, because we don't control IFS. __git_ps1 is\n   a function which runs in the user's shell, so if the user did\n   IFS=0123, then unquoted $? or $exit can get IFS-split.\n   As the commit message notes, this is unlikely to fix things in\n   practice, but it will fix things with weird IFS values.\n\n2. In general, yes, $? is only needed as yes/no, and there's only\n   one place which tests $? instead of using \"&&\" or \"||\" after\n   a command in this file (rev_parse_exit_code=\"$?\"). I didn't feel\n   this needs any portability fix. It works.\n\n   But with $exit, $? is not used as yes/no, but rather to preserve\n   the exit status when __git_ps1 was entered. This is important if\n   the user wants the shell's last command $? at the prompt, e.g.:\n\n   PS1='\\w$(__git_ps1)$(e=$?; [ \"$e\" = 0 ] || echo \" E:$e\") \\$ '\n\n   If __git_ps1 didn't exit with the same $? it saw on entry, then\n   $e will be __git_ps1's exit code rather than the exit code of\n   the last command which ran in the shell, so it should be the\n   same value as before and not only yes/no.\n\n\n\n\n"},{"id":"501034","messageId":"xmqq7cchtyfc.fsf@gitster.g","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 0/8] git-prompt: support more shells v2","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-15T18:48:23Z","receivedAt":"2024-08-15T18:48:30Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avi Halachmi via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This addresses review comment on part 6/8 (git-prompt: add fallback for\n> shells without $'...') which requested to use one form for all shells\n> instead $'...' where supported and a fallback otherwise.\n\nI've read the series and they looked all sensible.  Will queue but\nI'd appreciate a second set of eyes before marking it for 'next'.\n\nThanks.\n"},{"id":"501040","messageId":"xmqqv801sil5.fsf@gitster.g","threadId":"61830","inReplyTo":"1228065843.3779090.1723743313433@mail.yahoo.com","subject":"Re: [PATCH v2 5/8] git-prompt: add some missing quotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-15T19:15:50Z","receivedAt":"2024-08-15T19:15:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n>> Well no matter what value $? has, it by definition has a few digits\n>> without any $IFS funnies.  Does this really matter?  I'd imagine\n>> that we would prefer to treat \"$?\" exactly the same way as \"no\".\n> ...\n> Two things here:\n>\n> 1. It can matter, because we don't control IFS. __git_ps1 is\n>    a function which runs in the user's shell, so if the user did\n>    IFS=0123, then unquoted $? or $exit can get IFS-split.\n\nFair enough.  My \"we would prefer to treat $? exactly the same way\nas no\" still stands.  If the user did IFS=o, \"no\" would be broken.\n\n>    As the commit message notes, this is unlikely to fix things in\n>    practice, but it will fix things with weird IFS values.\n\nYes, so I'd prefer to see us being consistent.  If we quote \"$?\" to\nprotect ourselves from crazy folks who set insane values to $IFS, we\nshould quote \"no\" the same way, no?\n\n"},{"id":"501042","messageId":"2093707499.4382922.1723751628640@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqv801sil5.fsf@gitster.g","subject":"Re: [PATCH v2 5/8] git-prompt: add some missing quotes","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-15T19:53:48Z","receivedAt":"2024-08-15T19:55:43Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Thursday, August 15, 2024 at 10:15:53 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n\n> Fair enough.  My \"we would prefer to treat $? exactly the same way\n> as no\" still stands.  If the user did IFS=o, \"no\" would be broken.\n>\n>>    As the commit message notes, this is unlikely to fix things in\n>>    practice, but it will fix things with weird IFS values.\n>\n>\n> Yes, so I'd prefer to see us being consistent.  If we quote \"$?\" to\n> protect ourselves from crazy folks who set insane values to $IFS, we\n> should quote \"no\" the same way, no?\n\nOK, I see what you mean. But IFS-split doesn't happen on literal\nshell input (i.e. script source). It only happens on parts which\nget expanded with parameter or arithmetic expansion or command\nsubstitution. To quote from POSIX (2024):\n\n  After parameter expansion (2.6.2), command substitution (2.6.3),\n  and arithmetic expansion (2.6.4), if the shell variable IFS\n  (see 2.5.3 Shell Variables ) is set and its value is not empty,\n  or if IFS is unset, the shell shall scan each field containing\n  results of expansions and substitutions that did not occur in\n  double-quotes for field splitting; zero, one or multiple fields\n  can result.\n\nSo 'IFS=n; reply=no; echo no; local x=no' work regardless of IFS,\nbecause there's no expansion, and IFS is not involved.\n\nBut 'IFS=n; reply=no; echo $reply; local x=$reply' will be affected\nwhen unquoted $reply expands as argument to \"echo\" (or \"local\"), and\nthen gets split by \"n\", so it would echo \"o\" (\" o\" because reasons).\nFixed with quotes: IFS=n; reply=no; echo \"$reply\"; local x=\"$reply\"\n\nBoth can even be adjacent: 'IFS=n reply=no; echo no $reply'\nwould echo \"no  o\" in all shells, because the literal `no' is\nunaffected, but the expanded $reply is affacted.\n\nSo $? is the same as $reply in this regards - it expands to some\nvalue, so IFS gets involved, so it needs quotes. But a literal `no'\nworks the same regardless if quoted or not.\n\nWorth noting in our context is that zsh doesn't do IFS word-split\nby default on parameter expansion like $x, but does split the output\nof command substitution $(cmd....), and code in git-prompt.sh is\nexpected to work in zsh as well (like it always did).\n"},{"id":"501105","messageId":"Zr8Sv9xZrdf6rHgg@tanuki","threadId":"61830","inReplyTo":"9ce5ddadf0bb13229461d67451094a373348771e.1723727653.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 1/8] git-prompt: use here-doc instead of here-string","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T08:50:07Z","receivedAt":"2024-08-16T08:50:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Aug 15, 2024 at 01:14:06PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n> From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n> \n> Here-documend is standard, and works in all shells.\n> \n> Both here-string and here-doc add final newline, which is important\n> in this case, because $output is without final newline, but we do\n> want \"read\" to succeed on the last line as well.\n> \n> Shells which support here-string:\n> - bash, zsh, mksh, ksh93, yash (non-posix-mode).\n> \n> shells which don't, and got fixed:\n> - ash-derivatives (dash, free/net bsd sh, busybox-ash).\n> - pdksh, openbsd sh.\n> - All Schily Bourne shell variants.\n> \n> Signed-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n> ---\n>  contrib/completion/git-prompt.sh | 4 +++-\n>  1 file changed, 3 insertions(+), 1 deletion(-)\n> \n> diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\n> index 5330e769a72..ebf2e30d684 100644\n> --- a/contrib/completion/git-prompt.sh\n> +++ b/contrib/completion/git-prompt.sh\n> @@ -137,7 +137,9 @@ __git_ps1_show_upstream ()\n>  \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n>  \t\t\t;;\n>  \t\tesac\n> -\tdone <<< \"$output\"\n> +\tdone <<-OUTPUT\n> +\t\t$output\n> +\tOUTPUT\n\nI was a bit sceptical at first whether this produces the correct output,\nbecause I wasn't sure whether the first line might be indented while the\nothers wouldn't be. And that would only happen if we indented with\nspaces, but when indenting with a tab it seems to work as expected.\n\nPatrick\n\n>  \t# parse configuration values\n>  \tlocal option\n> -- \n> gitgitgadget\n> \n> \n"},{"id":"501106","messageId":"Zr8Swsn3H2ebB7g6@tanuki","threadId":"61830","inReplyTo":"7e994eae7bc3dfa021262410c801ddb124ce24f1.1723727653.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 3/8] git-prompt: don't use shell arrays","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T08:50:10Z","receivedAt":"2024-08-16T08:50:14Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Aug 15, 2024 at 01:14:08PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n> diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\n> index 4cc2cf91bb6..75c3a813fda 100644\n> --- a/contrib/completion/git-prompt.sh\n> +++ b/contrib/completion/git-prompt.sh\n> @@ -116,10 +116,10 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n>  __git_ps1_show_upstream ()\n>  {\n>  \tlocal key value\n> -\tlocal svn_remote svn_url_pattern=\"\" count n\n> +\tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n>  \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n> +\tlocal LF=$'\\n'\n>  \n> -\tsvn_remote=()\n>  \t# get some config options from git-config\n>  \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n>  \twhile read -r key value; do\n> @@ -132,7 +132,7 @@ __git_ps1_show_upstream ()\n>  \t\t\tfi\n>  \t\t\t;;\n>  \t\tsvn-remote.*.url)\n> -\t\t\tsvn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n> +\t\t\tsvn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n\nI was wondering whether this is something we want to quote, mostly\nbecause I still have the failures of dash in mind when assigning values\nwith spaces to a `local` variable without quoting. I do not know whether\nthe same issues also apply to non-local variables though, probably not.\n\nPatrick\n"},{"id":"501107","messageId":"Zr8SxmujUZ7Run60@tanuki","threadId":"61830","inReplyTo":"4aa75cdb5dddca0fa2a4817e856d26f724cb43eb.1723727653.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v2 7/8] git-prompt: ta-da! document usage in other shells","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T08:50:14Z","receivedAt":"2024-08-16T08:50:17Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Aug 15, 2024 at 01:14:12PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n> diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\n> index c3dd38f847c..75f272daa21 100644\n> --- a/contrib/completion/git-prompt.sh\n> +++ b/contrib/completion/git-prompt.sh\n> @@ -8,8 +8,8 @@\n>  # To enable:\n>  #\n>  #    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).\n> -#    2) Add the following line to your .bashrc/.zshrc:\n> -#        source ~/.git-prompt.sh\n> +#    2) Add the following line to your .bashrc/.zshrc/.profile:\n> +#        . ~/.git-prompt.sh   # dot path/to/this-file\n>  #    3a) Change your PS1 to call __git_ps1 as\n>  #        command-substitution:\n>  #        Bash: PS1='[\\u@\\h \\W$(__git_ps1 \" (%s)\")]\\$ '\n> @@ -30,6 +30,8 @@\n>  #        Optionally, you can supply a third argument with a printf\n>  #        format string to finetune the output of the branch status\n>  #\n> +#    See notes below about compatibility with other shells.\n> +#\n>  # The repository status will be displayed only if you are currently in a\n>  # git repository. The %s token is the placeholder for the shown status.\n>  #\n> @@ -106,6 +108,33 @@\n>  # directory is set up to be ignored by git, then set\n>  # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the\n>  # repository level by setting bash.hideIfPwdIgnored to \"false\".\n> +#\n> +# Conpatibility with other shells (beyond bash/zsh):\n\ns/Conpatibility/Compatibility/\n\nPatrick\n"},{"id":"501108","messageId":"Zr8SyWSHH1lAfyuc@tanuki","threadId":"61830","inReplyTo":"xmqq7cchtyfc.fsf@gitster.g","subject":"Re: [PATCH v2 0/8] git-prompt: support more shells v2","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T08:50:17Z","receivedAt":"2024-08-16T08:50:35Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Thu, Aug 15, 2024 at 11:48:23AM -0700, Junio C Hamano wrote:\n> \"Avi Halachmi via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n> \n> > This addresses review comment on part 6/8 (git-prompt: add fallback for\n> > shells without $'...') which requested to use one form for all shells\n> > instead $'...' where supported and a fallback otherwise.\n> \n> I've read the series and they looked all sensible.  Will queue but\n> I'd appreciate a second set of eyes before marking it for 'next'.\n\nI did have a look, but honestly I wouldn't consider that to be a\nqualified review. POSIX shell tends to get borderline unreadable, so I\ndon't want to claim to understand everything I've read.\n\nIn any case, I didn't spot anything grave.\n\nPatrick\n"},{"id":"501116","messageId":"1407516636.4490130.1723801035574@mail.yahoo.com","threadId":"61830","inReplyTo":"Zr8Sv9xZrdf6rHgg@tanuki","subject":"Re: [PATCH v2 1/8] git-prompt: use here-doc instead of here-string","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-16T09:37:15Z","receivedAt":"2024-08-16T09:58:08Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Friday, August 16, 2024 at 11:50:12 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> On Thu, Aug 15, 2024 at 01:14:06PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n>> -    done <<< \"$output\"\n>> +    done <<-OUTPUT\n>> +        $output\n>> +    OUTPUT\n>\n> I was a bit sceptical at first whether this produces the correct output,\n> because I wasn't sure whether the first line might be indented while the\n> others wouldn't be. And that would only happen if we indented with\n> spaces, but when indenting with a tab it seems to work as expected.\n\nThat's what the \"-\" does in \"<<-\". It strips leading input tab chars\nat the content and the last line, and was specified as such since the\nfirst POSIX release in 1994:\n\n  If the redirection symbol is <<−, all leading tab characters will\n  be stripped from input lines and the line containing the trailing\n  delimiter.\n"},{"id":"501117","messageId":"902082087.4500648.1723802375900@mail.yahoo.com","threadId":"61830","inReplyTo":"Zr8SxmujUZ7Run60@tanuki","subject":"Re: [PATCH v2 7/8] git-prompt: ta-da! document usage in other shells","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-16T09:59:35Z","receivedAt":"2024-08-16T10:09:48Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Friday, August 16, 2024 at 11:50:17 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> On Thu, Aug 15, 2024 at 01:14:12PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n>>\n>> +# Conpatibility with other shells (beyond bash/zsh):\n>\n> s/Conpatibility/Compatibility/\n\nThanks. Will be fixed in v3.\n"},{"id":"501118","messageId":"1677713578.1741123.1723802016957@mail.yahoo.com","threadId":"61830","inReplyTo":"Zr8Swsn3H2ebB7g6@tanuki","subject":"Re: [PATCH v2 3/8] git-prompt: don't use shell arrays","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-16T09:53:36Z","receivedAt":"2024-08-16T10:24:27Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Friday, August 16, 2024 at 11:50:14 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> On Thu, Aug 15, 2024 at 01:14:08PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n>>\n>> -            svn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n>> +            svn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n>\n>\n> I was wondering whether this is something we want to quote, mostly\n> because I still have the failures of dash in mind when assigning values\n> with spaces to a `local` variable without quoting. I do not know whether\n> the same issues also apply to non-local variables though, probably not.\n\nIFS field splitting and glob expansion strictly never happen and never\nhappened at the assignment part of a \"simple command\", since the first\nversion of POSIX in 1994, so quotes are not needed to avoid that.\n\nSee my guidelines at the commit message of part 5/8 (git-prompt: add\nsome missing quotes), and this always works: a=$b$(foo bar)${x##baz}\n\nHowever, this does not answer the question of whether we want to use\nquotes in assignments.\n\nMy general take is to use quotes only when required, and if one is\nnot sure, then use quotes, or read the spec to be sure, but do keep\nin mind that some older shells are not always fully compliant with\nthe latest POSIX spec. But unquoted assignment is ubiquitous.\n\nI'd say to not quote in assignments, except to avoid tilde expansion\n(which can only happen with unquoted literal tilde at the input, but\nnot after expansion or substitution).\n\nBut if there's a strong precedence or preference to use quotes in\nassignment, then I can change it.\n\navih\n\n"},{"id":"501119","messageId":"1371885213.4494853.1723804592269@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqsev5u4yr.fsf@gitster.g","subject":"Re: [PATCH v2 4/8] git-prompt: replace [[...]] with standard code","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-16T10:36:32Z","receivedAt":"2024-08-16T10:36:38Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Thursday, August 15, 2024 at 07:27:12 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n>> From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n>>\n>> The existing [[...]] tests were either already valid as standard [...]\n>> tests, or only required minimal retouch:\n>\n> FWIW, our local coding guidelines to spell these with \"test\"\n> (without closing \"]\"), but this change certainly is a good first\n> step to get rid of non-portable \"[[ ... ]]\" construct.\n\nRight. I did see that, though only after I wrote the patch.\n\nFWIW, the common form in this file was \"[\" (46 instances),\nthen \"[[\" (13 instances), and finally \"test\" (3 instances).\n\nSo I'd still think changing \"[[\" forms into \"[\" is the better choice\nfor this file in a compatibility-focused change, as it leaves the\nfile in a mostly consistent usage of \"[\" throughout.\n\nThere can come later another change to tighten adherence to the\nguidelines.\n\nBut if you want to revise this commit and use \"test\" instead of \"[[\",\njust let me know and I'll do that. I'd be fine with that.\n\nIn such case, should we also change the existing \"[\" at the file\nto \"test\"? (in a new commit?)\n\n"},{"id":"501130","messageId":"Zr8vVQhfRqG90H4U@tanuki","threadId":"61830","inReplyTo":"1407516636.4490130.1723801035574@mail.yahoo.com","subject":"Re: [PATCH v2 1/8] git-prompt: use here-doc instead of here-string","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T10:52:05Z","receivedAt":"2024-08-16T10:52:09Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 16, 2024 at 09:37:15AM +0000, avih wrote:\n>  On Friday, August 16, 2024 at 11:50:12 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> > On Thu, Aug 15, 2024 at 01:14:06PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n> >> -    done <<< \"$output\"\n> >> +    done <<-OUTPUT\n> >> +        $output\n> >> +    OUTPUT\n> >\n> > I was a bit sceptical at first whether this produces the correct output,\n> > because I wasn't sure whether the first line might be indented while the\n> > others wouldn't be. And that would only happen if we indented with\n> > spaces, but when indenting with a tab it seems to work as expected.\n> \n> That's what the \"-\" does in \"<<-\". It strips leading input tab chars\n> at the content and the last line, and was specified as such since the\n> first POSIX release in 1994:\n> \n>   If the redirection symbol is <<−, all leading tab characters will\n>   be stripped from input lines and the line containing the trailing\n>   delimiter.\n\nOh, I know what `<<-` does. I just wasn't sure how it would behave when\n\"$output\" expands to a multi-line string, where subsequent expanded\nlines might or might not be indented.\n\nPatrick\n"},{"id":"501131","messageId":"Zr8vWCKrddYpABIr@tanuki","threadId":"61830","inReplyTo":"1677713578.1741123.1723802016957@mail.yahoo.com","subject":"Re: [PATCH v2 3/8] git-prompt: don't use shell arrays","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T10:52:08Z","receivedAt":"2024-08-16T10:52:12Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 16, 2024 at 09:53:36AM +0000, avih wrote:\n>  On Friday, August 16, 2024 at 11:50:14 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> > On Thu, Aug 15, 2024 at 01:14:08PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n> >>\n> >> -            svn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n> >> +            svn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n> >\n> >\n> > I was wondering whether this is something we want to quote, mostly\n> > because I still have the failures of dash in mind when assigning values\n> > with spaces to a `local` variable without quoting. I do not know whether\n> > the same issues also apply to non-local variables though, probably not.\n> \n> IFS field splitting and glob expansion strictly never happen and never\n> happened at the assignment part of a \"simple command\", since the first\n> version of POSIX in 1994, so quotes are not needed to avoid that.\n\nThat's the theory, yes. But as said, we did hit bugs in similar areas in\ndash where that wasn't properly honored, as Junio also pointed out on a\nlater patch. But that was in non-POSIX area anyway, as to the best of my\nknowledge it only happens with `local` assignments.\n\nPatrick\n"},{"id":"501134","messageId":"701460728.4505561.1723808133505@mail.yahoo.com","threadId":"61830","inReplyTo":"Zr8vWCKrddYpABIr@tanuki","subject":"Re: [PATCH v2 3/8] git-prompt: don't use shell arrays","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-16T11:35:33Z","receivedAt":"2024-08-16T11:57:03Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Friday, August 16, 2024 at 01:52:11 PM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n>On Fri, Aug 16, 2024 at 09:53:36AM +0000, avih wrote:\n>>  On Friday, August 16, 2024 at 11:50:14 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n>> > On Thu, Aug 15, 2024 at 01:14:08PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n>> >>\n>> >> -            svn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n>> >> +            svn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n>> >\n>> >\n>> > I was wondering whether this is something we want to quote, mostly\n>> > because I still have the failures of dash in mind when assigning values\n>> > with spaces to a `local` variable without quoting. I do not know whether\n>> > the same issues also apply to non-local variables though, probably not.\n>>\n>> IFS field splitting and glob expansion strictly never happen and never\n>> happened at the assignment part of a \"simple command\", since the first\n>> version of POSIX in 1994, so quotes are not needed to avoid that.\n>\n> That's the theory, yes. But as said, we did hit bugs in similar areas in\n> dash where that wasn't properly honored, as Junio also pointed out on a\n> later patch. But that was in non-POSIX area anyway, as to the best of my\n> knowledge it only happens with `local` assignments.\n\nYes. \"local\" is special, and not only because it's not POSIX.\n\nThe difference with \"local\" is that it takes assignment as arguments.\n\nA \"simple command\" (posix term) is composed of optional assignment[s]\nand optional command (and arguments).\n\nThe assigments part is never IFS-split or glob-expanded, while the\ncommand and arguments part is (in words which include unquoted\nexpansion or substitution) and therefore needs quotes, e.g.:\n\nfoo=$x bar=$y echo a=\"$b\" c=\"$d\"\n\nThere are other commands (beyond \"local\") which take assignment[s]\nas arguments, like \"export\", \"readonly\" and \"command\".\n\nBefore posix 2024, these commands also required quoting of the\narguments-assignments - just like \"local\" needed in dash.\n\nBut posix 2024 introduced the concept of a \"declaration utility\"\n(which takes assignments as arguments, like export, readonly, etc),\nand the concept of \"assignment context\" where IFS-split and glob\nexpansion don't happen - like the assignment part of a simple\ncommand, but now also in the assignment arguments of declaration\nutilities.\n\nAnd indeed, new versions of shells now don't need quotes in export\netc, and shells now make \"local\" a declaration utility which\ndoesn't need quotes of the assignment args, including in dash.\n\nHowever, the reason we do use quotes in local, export, etc, is\nbecause many instances of shells which don't yet (or will ever)\nsupport it still exist, so we quote for compatibility with those,\nbut still it's only needed in assignments which are arguments to\ncommands - not in the assignment part of a simple command.\n\nI've also updated the wording a bit of my guidelines in part 5/8,\nand I'll include it at the commit message of 5/8 v3.\n"},{"id":"501136","messageId":"Zr9IWBRHBkcTwPZU@tanuki","threadId":"61830","inReplyTo":"701460728.4505561.1723808133505@mail.yahoo.com","subject":"Re: [PATCH v2 3/8] git-prompt: don't use shell arrays","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2024-08-16T12:38:56Z","receivedAt":"2024-08-16T12:39:01Z","isPatch":true,"sender":{"key":"ps@pks.im","avatar":"https://avatars.githubusercontent.com/u/4056630?v=4"},"body":"On Fri, Aug 16, 2024 at 11:35:33AM +0000, avih wrote:\n>  On Friday, August 16, 2024 at 01:52:11 PM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> >On Fri, Aug 16, 2024 at 09:53:36AM +0000, avih wrote:\n> >>  On Friday, August 16, 2024 at 11:50:14 AM GMT+3, Patrick Steinhardt <ps@pks.im> wrote:\n> >> > On Thu, Aug 15, 2024 at 01:14:08PM +0000, Avi Halachmi (:avih) via GitGitGadget wrote:\n> >> >>\n> >> >> -            svn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n> >> >> +            svn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n> >> >\n> >> >\n> >> > I was wondering whether this is something we want to quote, mostly\n> >> > because I still have the failures of dash in mind when assigning values\n> >> > with spaces to a `local` variable without quoting. I do not know whether\n> >> > the same issues also apply to non-local variables though, probably not.\n> >>\n> >> IFS field splitting and glob expansion strictly never happen and never\n> >> happened at the assignment part of a \"simple command\", since the first\n> >> version of POSIX in 1994, so quotes are not needed to avoid that.\n> >\n> > That's the theory, yes. But as said, we did hit bugs in similar areas in\n> > dash where that wasn't properly honored, as Junio also pointed out on a\n> > later patch. But that was in non-POSIX area anyway, as to the best of my\n> > knowledge it only happens with `local` assignments.\n> \n> Yes. \"local\" is special, and not only because it's not POSIX.\n> \n> The difference with \"local\" is that it takes assignment as arguments.\n> \n> A \"simple command\" (posix term) is composed of optional assignment[s]\n> and optional command (and arguments).\n> \n> The assigments part is never IFS-split or glob-expanded, while the\n> command and arguments part is (in words which include unquoted\n> expansion or substitution) and therefore needs quotes, e.g.:\n> \n> foo=$x bar=$y echo a=\"$b\" c=\"$d\"\n> \n> There are other commands (beyond \"local\") which take assignment[s]\n> as arguments, like \"export\", \"readonly\" and \"command\".\n> \n> Before posix 2024, these commands also required quoting of the\n> arguments-assignments - just like \"local\" needed in dash.\n> \n> But posix 2024 introduced the concept of a \"declaration utility\"\n> (which takes assignments as arguments, like export, readonly, etc),\n> and the concept of \"assignment context\" where IFS-split and glob\n> expansion don't happen - like the assignment part of a simple\n> command, but now also in the assignment arguments of declaration\n> utilities.\n> \n> And indeed, new versions of shells now don't need quotes in export\n> etc, and shells now make \"local\" a declaration utility which\n> doesn't need quotes of the assignment args, including in dash.\n> \n> However, the reason we do use quotes in local, export, etc, is\n> because many instances of shells which don't yet (or will ever)\n> support it still exist, so we quote for compatibility with those,\n> but still it's only needed in assignments which are arguments to\n> commands - not in the assignment part of a simple command.\n> \n> I've also updated the wording a bit of my guidelines in part 5/8,\n> and I'll include it at the commit message of 5/8 v3.\n\nGreat, thanks for your thorough explanations!\n\nPatrick\n"},{"id":"501144","messageId":"xmqqttfkl8r1.fsf@gitster.g","threadId":"61830","inReplyTo":"1371885213.4494853.1723804592269@mail.yahoo.com","subject":"Re: [PATCH v2 4/8] git-prompt: replace [[...]] with standard code","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-16T16:42:26Z","receivedAt":"2024-08-16T16:42:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n> FWIW, the common form in this file was \"[\" (46 instances),\n> then \"[[\" (13 instances), and finally \"test\" (3 instances).\n\nYes, that came from the fact that this file has historically been\nconsidered bash-only and our Bourne shell coding guidelines do not\napply.  \n\n> So I'd still think changing \"[[\" forms into \"[\" is the better choice\n> for this file in a compatibility-focused change, as it leaves the\n> file in a mostly consistent usage of \"[\" throughout.\n\nAbsolutely.  We are in agreement (I said this is a good first step).\nI do think making it more consistent after the dust settles (read:\nnot before the series graduates to 'master') would be a good idea,\nthough.\n"},{"id":"501206","messageId":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v2.git.git.1723727653.gitgitgadget@gmail.com","subject":"[PATCH v3 0/8] git-prompt: support more shells v3","fromName":"Avi Halachmi via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:52Z","receivedAt":"2024-08-17T09:26:04Z","isPatch":true,"sender":{"key":"name:Avi Halachmi","avatar":null},"body":"This addresses review comments on part 5/8 v2 (git-prompt: add some missing\nquotes) to fix typo in the commit message \"aguments\" into \"arguments\", but\nwhich was used to reword it a bit so that it's more accurate.\n\nAlso addresses review comment on part 7/8 v2 (git-prompt: ta-da! document\nusage in other shells) and fix typo \"Conpatibility\".\n\nAvi Halachmi (:avih) (8):\n  git-prompt: use here-doc instead of here-string\n  git-prompt: fix uninitialized variable\n  git-prompt: don't use shell arrays\n  git-prompt: replace [[...]] with standard code\n  git-prompt: add some missing quotes\n  git-prompt: don't use shell $'...'\n  git-prompt: ta-da! document usage in other shells\n  git-prompt: support custom 0-width PS1 markers\n\n contrib/completion/git-prompt.sh | 191 ++++++++++++++++++++-----------\n 1 file changed, 126 insertions(+), 65 deletions(-)\n\n\nbase-commit: d19b6cd2dd72dc811f19df4b32c7ed223256c3ee\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1750%2Favih%2Fprompt-compat-v3\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1750/avih/prompt-compat-v3\nPull-Request: https://github.com/git/git/pull/1750\n\nRange-diff vs v2:\n\n 1:  9ce5ddadf0b = 1:  9ce5ddadf0b git-prompt: use here-doc instead of here-string\n 2:  680ecb52404 = 2:  680ecb52404 git-prompt: fix uninitialized variable\n 3:  7e994eae7bc = 3:  7e994eae7bc git-prompt: don't use shell arrays\n 4:  232340902a1 = 4:  232340902a1 git-prompt: replace [[...]] with standard code\n 5:  4f77b7eb7f1 ! 5:  3a41ad889cc git-prompt: add some missing quotes\n     @@ Commit message\n            not expanded:   t=\"~\"; a=${t}user  b=\\~foo~;  echo \"~user\" $t/dir\n      \n          But the main reason for quoting is to prevent IFS field splitting\n     -    (which also coalesces IFS chars) and glob expansion after parameter\n     -    expansion or command substitution.\n     +    (which also coalesces IFS chars) and glob expansion in parts which\n     +    contain parameter/arithmetic expansion or command substitution.\n      \n     -    In _command-arguments_, expanded/substituted values must be quoted:\n     +    \"Simple command\" (POSIX term) is assignment[s] and/or command [args].\n     +    Examples:\n     +      foo=bar         # one assignment\n     +      foo=$bar x=y    # two assignments\n     +      foo bar         # command, no assignments\n     +      x=123 foo bar   # one assignment and a command\n     +\n     +    The assignments part is not IFS-split or glob-expanded.\n     +\n     +    The command+args part does get IFS field split and glob expanded,\n     +    but only at unquoted expanded/substituted parts.\n     +\n     +    In the command+args part, expanded/substituted values must be quoted.\n     +    (the commands here are \"[\" and \"local\"):\n            Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n            Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n      \n     -    Still in _agumemts_, no need to quote non-expandable values:\n     +    The arguments to \"local\" do look like assignments, but they're not\n     +    the assignment part of a simple command. they're at the command part.\n     +\n     +    Still at the command part, no need to quote non-expandable values:\n            Good:                 local x=   y=yes;   echo OK\n            OK, but not required: local x=\"\" y=\"yes\"; echo \"OK\"\n          But completely empty (NULL) arguments must be quoted:\n     @@ Commit message\n          \"local\" does not behave with assignment context in some shells,\n          hence we require quotes when using \"local\" - for compatibility.\n      \n     -    First value in 'case...' doesn't IFS-split/glob, doesn't need quotes:\n     +    The value between 'case' and 'in' doesn't IFS-split/glob-expand:\n            Good:       case  * $foo $(cmd...)  in ... ; esac\n            identical:  case \"* $foo $(cmd...)\" in ... ; esac\n      \n 6:  363b7015763 = 6:  e735a1696a0 git-prompt: don't use shell $'...'\n 7:  4aa75cdb5dd ! 7:  e70440e669a git-prompt: ta-da! document usage in other shells\n     @@ contrib/completion/git-prompt.sh\n       # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the\n       # repository level by setting bash.hideIfPwdIgnored to \"false\".\n      +#\n     -+# Conpatibility with other shells (beyond bash/zsh):\n     ++# Compatibility with other shells (beyond bash/zsh):\n      +#\n      +#    We require posix-ish shell plus \"local\" support, which is most\n      +#    shells (even pdksh), but excluding ksh93 (because no \"local\").\n 8:  e71ddcd2232 = 8:  633e71a01d3 git-prompt: support custom 0-width PS1 markers\n\n-- \ngitgitgadget\n"},{"id":"501205","messageId":"9ce5ddadf0bb13229461d67451094a373348771e.1723886760.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 1/8] git-prompt: use here-doc instead of here-string","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:53Z","receivedAt":"2024-08-17T09:26:05Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nHere-documend is standard, and works in all shells.\n\nBoth here-string and here-doc add final newline, which is important\nin this case, because $output is without final newline, but we do\nwant \"read\" to succeed on the last line as well.\n\nShells which support here-string:\n- bash, zsh, mksh, ksh93, yash (non-posix-mode).\n\nshells which don't, and got fixed:\n- ash-derivatives (dash, free/net bsd sh, busybox-ash).\n- pdksh, openbsd sh.\n- All Schily Bourne shell variants.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5330e769a72..ebf2e30d684 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -137,7 +137,9 @@ __git_ps1_show_upstream ()\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n \t\tesac\n-\tdone <<< \"$output\"\n+\tdone <<-OUTPUT\n+\t\t$output\n+\tOUTPUT\n \n \t# parse configuration values\n \tlocal option\n-- \ngitgitgadget\n\n"},{"id":"501207","messageId":"680ecb524040c64f886c4e484a64f0d17b512e27.1723886760.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 2/8] git-prompt: fix uninitialized variable","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:54Z","receivedAt":"2024-08-17T09:26:06Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nFirst use is in the form:  local var; ...; var=$var$whatever...\n\nIf the variable was unset (as bash and others do after \"local x\"),\nthen it would error if set -u is in effect.\n\nAlso, many shells inherit the existing value after \"local var\"\nwithout init, but in this case it's unlikely to have a prior value.\n\nNow we initialize it.\n\n(local var= is enough, but local var=\"\" is the custom in this file)\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex ebf2e30d684..4cc2cf91bb6 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,7 +116,7 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern count n\n+\tlocal svn_remote svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n \n \tsvn_remote=()\n-- \ngitgitgadget\n\n"},{"id":"501208","messageId":"7e994eae7bc3dfa021262410c801ddb124ce24f1.1723886760.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 3/8] git-prompt: don't use shell arrays","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:55Z","receivedAt":"2024-08-17T09:26:07Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nArrays only existed in the svn-upstream code, used to:\n- Keep a list of svn remotes.\n- Convert commit msg to array of words, extract the 2nd-to-last word.\n\nExcept bash/zsh, nearly all shells failed load on syntax errors here.\n\nNow:\n- The svn remotes are a list of newline-terminated values.\n- The 2nd-to-last word is extracted using standard shell substrings.\n- All shells can digest the svn-upstream code.\n\nWhile using shell field splitting to extract the word is simple, and\ndoesn't even need non-standard code, e.g. set -- $(git log -1 ...),\nit would have the same issues as the old array code: it depends on IFS\nwhich we don't control, and it's subject to glob-expansion, e.g. if\nthe message happens to include * or **/* (as this commit message just\ndid), then the array could get huge. This was not great.\n\nNow it uses standard shell substrings, and we know the exact delimiter\nto expect, because it's the match from our grep just one line earlier.\n\nThe new word extraction code also fixes svn-upstream in zsh, because\npreviously it used arr[len-2], but because in zsh, unlike bash, array\nsubscripts are 1-based, it incorrectly extracted the 3rd-to-last word.\nsymptom: missing upstream status in a git-svn repo: u=, u+N-M, etc.\n\nThe breakage in zsh is surprising, because it was last touched by\n  commit d0583da838 (prompt: fix show upstream with svn and zsh),\nclaiming to fix exactly that. However, it only mentions syntax fixes.\nIt's unclear if behavior was fixed too. But it was broken, now fixed.\n\nNote LF=$'\\n' and then using $LF instead of $'\\n' few times.\nA future commit will add fallback for shells without $'...', so this\nwould be the only line to touch instead of replacing every $'\\n' .\n\nShells which could run the previous array code:\n- bash\n\nShells which have arrays but were broken anyway:\n- zsh: 1-based subscript\n- ksh93: no \"local\" (the new code can't fix this part...)\n- mksh, openbsd sh, pdksh: failed load on syntax error: \"for ((...))\".\n\nMore shells which Failed to load due to syntax error:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne shell, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 48 ++++++++++++++++++++------------\n 1 file changed, 30 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4cc2cf91bb6..75c3a813fda 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,10 +116,10 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern=\"\" count n\n+\tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n+\tlocal LF=$'\\n'\n \n-\tsvn_remote=()\n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n \twhile read -r key value; do\n@@ -132,7 +132,7 @@ __git_ps1_show_upstream ()\n \t\t\tfi\n \t\t\t;;\n \t\tsvn-remote.*.url)\n-\t\t\tsvn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n+\t\t\tsvn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n \t\t\tsvn_url_pattern=\"$svn_url_pattern\\\\|$value\"\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n@@ -156,25 +156,37 @@ __git_ps1_show_upstream ()\n \tcase \"$upstream_type\" in\n \tgit)    upstream_type=\"@{upstream}\" ;;\n \tsvn*)\n-\t\t# get the upstream from the \"git-svn-id: ...\" in a commit message\n-\t\t# (git-svn uses essentially the same procedure internally)\n-\t\tlocal -a svn_upstream\n-\t\tsvn_upstream=($(git log --first-parent -1 \\\n-\t\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null))\n-\t\tif [[ 0 -ne ${#svn_upstream[@]} ]]; then\n-\t\t\tsvn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}\n-\t\t\tsvn_upstream=${svn_upstream%@*}\n-\t\t\tlocal n_stop=\"${#svn_remote[@]}\"\n-\t\t\tfor ((n=1; n <= n_stop; n++)); do\n-\t\t\t\tsvn_upstream=${svn_upstream#${svn_remote[$n]}}\n-\t\t\tdone\n+\t\t# successful svn-upstream resolution:\n+\t\t# - get the list of configured svn-remotes ($svn_remotes set above)\n+\t\t# - get the last commit which seems from one of our svn-remotes\n+\t\t# - confirm that it is from one of the svn-remotes\n+\t\t# - use $GIT_SVN_ID if set, else \"git-svn\"\n \n-\t\t\tif [[ -z \"$svn_upstream\" ]]; then\n+\t\t# get upstream from \"git-svn-id: UPSTRM@N HASH\" in a commit message\n+\t\t# (git-svn uses essentially the same procedure internally)\n+\t\tlocal svn_upstream=\"$(\n+\t\t\tgit log --first-parent -1 \\\n+\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null\n+\t\t)\"\n+\n+\t\tif [ -n \"$svn_upstream\" ]; then\n+\t\t\t# extract the URI, assuming --grep matched the last line\n+\t\t\tsvn_upstream=${svn_upstream##*$LF}  # last line\n+\t\t\tsvn_upstream=${svn_upstream#*: }    # UPSTRM@N HASH\n+\t\t\tsvn_upstream=${svn_upstream%@*}     # UPSTRM\n+\n+\t\t\tcase ${LF}${svn_remotes} in\n+\t\t\t*\"${LF}${svn_upstream}${LF}\"*)\n+\t\t\t\t# grep indeed matched the last line - it's our remote\n \t\t\t\t# default branch name for checkouts with no layout:\n \t\t\t\tupstream_type=${GIT_SVN_ID:-git-svn}\n-\t\t\telse\n+\t\t\t\t;;\n+\t\t\t*)\n+\t\t\t\t# the commit message includes one of our remotes, but\n+\t\t\t\t# it's not at the last line. is $svn_upstream junk?\n \t\t\t\tupstream_type=${svn_upstream#/}\n-\t\t\tfi\n+\t\t\t\t;;\n+\t\t\tesac\n \t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n-- \ngitgitgadget\n\n"},{"id":"501209","messageId":"232340902a1feeafe526528eb88b8d0814d11545.1723886761.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 4/8] git-prompt: replace [[...]] with standard code","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:56Z","receivedAt":"2024-08-17T09:26:07Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe existing [[...]] tests were either already valid as standard [...]\ntests, or only required minimal retouch:\n\nNotes:\n\n- [[...]] doesn't do field splitting and glob expansion, so $var\n  or $(cmd...) don't need quoting, but [... does need quotes.\n\n- [[ X == Y ]] when Y is a string is same as [ X = Y ], but if Y is\n  a pattern, then we need:  case X in Y)... ; esac  .\n\n- [[ ... && ... ]] was replaced with [ ... ] && [ ... ] .\n\n- [[ -o <zsh-option> ]] requires [[...]], so put it in \"eval\" and only\n  eval it in zsh, so other shells would not abort on syntax error\n  (posix says [[ has unspecified results, shells allowed to reject it)\n\n- ((x++)) was changed into x=$((x+1))  (yeah, not [[...]] ...)\n\nShells which accepted the previous forms:\n- bash, zsh, ksh93, mksh, openbsd sh, pdksh.\n\nShells which didn't, and now can process it:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne sh, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 30 ++++++++++++++++--------------\n 1 file changed, 16 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 75c3a813fda..4781261f868 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -126,7 +126,7 @@ __git_ps1_show_upstream ()\n \t\tcase \"$key\" in\n \t\tbash.showupstream)\n \t\t\tGIT_PS1_SHOWUPSTREAM=\"$value\"\n-\t\t\tif [[ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]]; then\n+\t\t\tif [ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]; then\n \t\t\t\tp=\"\"\n \t\t\t\treturn\n \t\t\tfi\n@@ -187,14 +187,14 @@ __git_ps1_show_upstream ()\n \t\t\t\tupstream_type=${svn_upstream#/}\n \t\t\t\t;;\n \t\t\tesac\n-\t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n+\t\telif [ \"svn+git\" = \"$upstream_type\" ]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n \t\t;;\n \tesac\n \n \t# Find how many commits we are ahead/behind our upstream\n-\tif [[ -z \"$legacy\" ]]; then\n+\tif [ -z \"$legacy\" ]; then\n \t\tcount=\"$(git rev-list --count --left-right \\\n \t\t\t\t\"$upstream_type\"...HEAD 2>/dev/null)\"\n \telse\n@@ -206,8 +206,8 @@ __git_ps1_show_upstream ()\n \t\t\tfor commit in $commits\n \t\t\tdo\n \t\t\t\tcase \"$commit\" in\n-\t\t\t\t\"<\"*) ((behind++)) ;;\n-\t\t\t\t*)    ((ahead++))  ;;\n+\t\t\t\t\"<\"*) behind=$((behind+1)) ;;\n+\t\t\t\t*)    ahead=$((ahead+1))   ;;\n \t\t\t\tesac\n \t\t\tdone\n \t\t\tcount=\"$behind\t$ahead\"\n@@ -217,7 +217,7 @@ __git_ps1_show_upstream ()\n \tfi\n \n \t# calculate the result\n-\tif [[ -z \"$verbose\" ]]; then\n+\tif [ -z \"$verbose\" ]; then\n \t\tcase \"$count\" in\n \t\t\"\") # no upstream\n \t\t\tp=\"\" ;;\n@@ -243,7 +243,7 @@ __git_ps1_show_upstream ()\n \t\t*)\t    # diverged from upstream\n \t\t\tupstream=\"|u+${count#*\t}-${count%\t*}\" ;;\n \t\tesac\n-\t\tif [[ -n \"$count\" && -n \"$name\" ]]; then\n+\t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n \t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n@@ -265,7 +265,7 @@ __git_ps1_show_upstream ()\n # their own color.\n __git_ps1_colorize_gitstring ()\n {\n-\tif [[ -n ${ZSH_VERSION-} ]]; then\n+\tif [ -n \"${ZSH_VERSION-}\" ]; then\n \t\tlocal c_red='%F{red}'\n \t\tlocal c_green='%F{green}'\n \t\tlocal c_lblue='%F{blue}'\n@@ -417,7 +417,7 @@ __git_ps1 ()\n \t# incorrect.)\n \t#\n \tlocal ps1_expanded=yes\n-\t[ -z \"${ZSH_VERSION-}\" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no\n+\t[ -z \"${ZSH_VERSION-}\" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no\n \t[ -z \"${BASH_VERSION-}\" ] || shopt -q promptvars || ps1_expanded=no\n \n \tlocal repo_info rev_parse_exit_code\n@@ -502,11 +502,13 @@ __git_ps1 ()\n \t\t\t\t\treturn $exit\n \t\t\t\tfi\n \n-\t\t\t\tif [[ $head == \"ref: \"* ]]; then\n+\t\t\t\tcase $head in\n+\t\t\t\t\"ref: \"*)\n \t\t\t\t\thead=\"${head#ref: }\"\n-\t\t\t\telse\n+\t\t\t\t\t;;\n+\t\t\t\t*)\n \t\t\t\t\thead=\"\"\n-\t\t\t\tfi\n+\t\t\t\tesac\n \t\t\t\t;;\n \t\t\t*)\n \t\t\t\thead=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n@@ -542,8 +544,8 @@ __git_ps1 ()\n \tfi\n \n \tlocal conflict=\"\" # state indicator for unresolved conflicts\n-\tif [[ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" == \"yes\" ]] &&\n-\t   [[ $(git ls-files --unmerged 2>/dev/null) ]]; then\n+\tif [ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" = \"yes\" ] &&\n+\t   [ \"$(git ls-files --unmerged 2>/dev/null)\" ]; then\n \t\tconflict=\"|CONFLICT\"\n \tfi\n \n-- \ngitgitgadget\n\n"},{"id":"501210","messageId":"3a41ad889cc33a1fc0414b8f14af6438b49c88ee.1723886761.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 5/8] git-prompt: add some missing quotes","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:57Z","receivedAt":"2024-08-17T09:26:08Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe issues which this commit fixes are unlikely to be broken\nin real life, but the fixes improve correctness, and would prevent\nbugs in some uncommon cases, such as weird IFS values.\n\nListing some portability guideline here for future reference.\n\nI'm leaving it to someone else to decide whether to include\nit in the file itself, place is as a new file, or not.\n\n---------\n\nThe command \"local\" is non standard, but is allowed in this file:\n- Quote initialization if it can expand (local x=\"$y\"). See below.\n- Don't assume initial value after \"local x\". Either initialize it\n  (local x=..), or set before first use (local x;.. x=..; <use $x>).\n  (between shells, \"local x\" can unset x, or inherit it, or do x= )\n\nOther non-standard features beyond \"local\" are to be avoided.\n\nUse the standard \"test\" - [...] instead of non-standard [[...]] .\n\n--------\n\nQuotes (some portability things, but mainly general correctness):\n\nQuotes prevent tilde-expansion of some unquoted literal tildes (~).\nIf the expansion is undesirable, quotes would ensure that.\n  Tilds expanded: a=~user:~/ ;  echo ~user ~/dir\n  not expanded:   t=\"~\"; a=${t}user  b=\\~foo~;  echo \"~user\" $t/dir\n\nBut the main reason for quoting is to prevent IFS field splitting\n(which also coalesces IFS chars) and glob expansion in parts which\ncontain parameter/arithmetic expansion or command substitution.\n\n\"Simple command\" (POSIX term) is assignment[s] and/or command [args].\nExamples:\n  foo=bar         # one assignment\n  foo=$bar x=y    # two assignments\n  foo bar         # command, no assignments\n  x=123 foo bar   # one assignment and a command\n\nThe assignments part is not IFS-split or glob-expanded.\n\nThe command+args part does get IFS field split and glob expanded,\nbut only at unquoted expanded/substituted parts.\n\nIn the command+args part, expanded/substituted values must be quoted.\n(the commands here are \"[\" and \"local\"):\n  Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n  Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n\nThe arguments to \"local\" do look like assignments, but they're not\nthe assignment part of a simple command. they're at the command part.\n\nStill at the command part, no need to quote non-expandable values:\n  Good:                 local x=   y=yes;   echo OK\n  OK, but not required: local x=\"\" y=\"yes\"; echo \"OK\"\nBut completely empty (NULL) arguments must be quoted:\n  foo \"\"   is not the same as:   foo\n\nAssignments in simple commands - with or without an actual command,\ndon't need quoting becase there's no IFS split or glob expansion:\n  Good:   s=* a=$b c=$(cmd...)${x# foo }${y-   } [cmd ...]\n  It's also OK to use double quotes, but not required.\n\nThis behavior (no IFS/glob) is called \"assignment context\", and\n\"local\" does not behave with assignment context in some shells,\nhence we require quotes when using \"local\" - for compatibility.\n\nThe value between 'case' and 'in' doesn't IFS-split/glob-expand:\n  Good:       case  * $foo $(cmd...)  in ... ; esac\n  identical:  case \"* $foo $(cmd...)\" in ... ; esac\n\nNested quotes in command substitution are fine, often necessary:\n  Good: echo \"$(foo... \"$x\" \"$(bar ...)\")\"\n\nNested quotes in substring ops are legal, and sometimes needed\nto prevent interpretation as a pattern, but not the most readable:\n  Legal:  foo \"${x#*\"$y\" }\"\n\nNested quotes in \"maybe other value\" subst are invalid, unnecessary:\n  Good:  local x=\"${y- }\";   foo \"${z:+ $a }\"\n  Bad:   local x=\"${y-\" \"}\"; foo \"${z:+\" $a \"}\"\nOuter/inner quotes in \"maybe other value\" have different use cases:\n  \"${x-$y}\"  always one quoted arg: \"$x\" if x is set, else \"$y\".\n  ${x+\"$x\"}  one quoted arg \"$x\" if x is set, else no arg at all.\n  Unquoted $x is similar to the second case, but it would get split\n  into few arguments if it includes any of the IFS chars.\n\nAssignments don't need the outer quotes, and the braces delimit the\nvalue, so nested quotes can be avoided, for readability:\n  a=$(foo \"$x\")  a=${x#*\"$y\" }  c=${y- };  bar \"$a\" \"$b\" \"$c\"\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4781261f868..5d7f236fe48 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -246,7 +246,7 @@ __git_ps1_show_upstream ()\n \t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n-\t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\t\t\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t\t\tupstream=\"$upstream \\${__git_ps1_upstream_name}\"\n \t\t\telse\n \t\t\t\tupstream=\"$upstream ${__git_ps1_upstream_name}\"\n@@ -278,12 +278,12 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n \t\tlocal c_clear=$'\\001\\e[0m\\002'\n \tfi\n-\tlocal bad_color=$c_red\n-\tlocal ok_color=$c_green\n+\tlocal bad_color=\"$c_red\"\n+\tlocal ok_color=\"$c_green\"\n \tlocal flags_color=\"$c_lblue\"\n \n \tlocal branch_color=\"\"\n-\tif [ $detached = no ]; then\n+\tif [ \"$detached\" = no ]; then\n \t\tbranch_color=\"$ok_color\"\n \telse\n \t\tbranch_color=\"$bad_color\"\n@@ -360,7 +360,7 @@ __git_sequencer_status ()\n __git_ps1 ()\n {\n \t# preserve exit status\n-\tlocal exit=$?\n+\tlocal exit=\"$?\"\n \tlocal pcmode=no\n \tlocal detached=no\n \tlocal ps1pc_start='\\u@\\h:\\w '\n@@ -379,7 +379,7 @@ __git_ps1 ()\n \t\t;;\n \t\t0|1)\tprintf_format=\"${1:-$printf_format}\"\n \t\t;;\n-\t\t*)\treturn $exit\n+\t\t*)\treturn \"$exit\"\n \t\t;;\n \tesac\n \n@@ -427,7 +427,7 @@ __git_ps1 ()\n \trev_parse_exit_code=\"$?\"\n \n \tif [ -z \"$repo_info\" ]; then\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal short_sha=\"\"\n@@ -449,7 +449,7 @@ __git_ps1 ()\n \t   [ \"$(git config --bool bash.hideIfPwdIgnored)\" != \"false\" ] &&\n \t   git check-ignore -q .\n \tthen\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal sparse=\"\"\n@@ -499,7 +499,7 @@ __git_ps1 ()\n \t\t\tcase \"$ref_format\" in\n \t\t\tfiles)\n \t\t\t\tif ! __git_eread \"$g/HEAD\" head; then\n-\t\t\t\t\treturn $exit\n+\t\t\t\t\treturn \"$exit\"\n \t\t\t\tfi\n \n \t\t\t\tcase $head in\n@@ -597,10 +597,10 @@ __git_ps1 ()\n \t\tfi\n \tfi\n \n-\tlocal z=\"${GIT_PS1_STATESEPARATOR-\" \"}\"\n+\tlocal z=\"${GIT_PS1_STATESEPARATOR- }\"\n \n \tb=${b##refs/heads/}\n-\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t__git_ps1_branch_name=$b\n \t\tb=\"\\${__git_ps1_branch_name}\"\n \tfi\n@@ -612,7 +612,7 @@ __git_ps1 ()\n \tlocal f=\"$h$w$i$s$u$p\"\n \tlocal gitstring=\"$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}\"\n \n-\tif [ $pcmode = yes ]; then\n+\tif [ \"$pcmode\" = yes ]; then\n \t\tif [ \"${__git_printf_supports_v-}\" != yes ]; then\n \t\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n \t\telse\n@@ -623,5 +623,5 @@ __git_ps1 ()\n \t\tprintf -- \"$printf_format\" \"$gitstring\"\n \tfi\n \n-\treturn $exit\n+\treturn \"$exit\"\n }\n-- \ngitgitgadget\n\n"},{"id":"501211","messageId":"e735a1696a05eeeb24bd7eb79a55b575c59bd62b.1723886761.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 6/8] git-prompt: don't use shell $'...'","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:58Z","receivedAt":"2024-08-17T09:26:09Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\n$'...' is new in POSIX (2024), and some shells support it in recent\nversions, while others have had it for decades (bash, zsh, ksh93).\n\nHowever, there are still enough shells which don't support it, and\nit's cheap to use an alternative form which works in all shells,\nso let's do that instead of dismissing it as \"it's compliant\".\n\nIt was agreed to use one form rather than $'...' where supported and\nfallback otherwise.\n\nshells where $'...' works:\n- bash, zsh, ksh93, mksh, busybox-ash, dash master, free/net bsd sh.\n\nshells where it doesn't work, but the new fallback works:\n- all dash releases (up to 0.5.12), older versions of free/net bsd sh,\n  openbsd sh, pdksh, all Schily Bourne sh variants, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 47 ++++++++++++++++++++------------\n 1 file changed, 29 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5d7f236fe48..c3dd38f847c 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -111,6 +111,12 @@\n __git_printf_supports_v=\n printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n \n+# like __git_SOH=$'\\001' etc but works also in shells without $'...'\n+eval \"$(printf '\n+\t__git_SOH=\"\\001\" __git_STX=\"\\002\" __git_ESC=\"\\033\"\n+\t__git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n+')\"\n+\n # stores the divergence from upstream in $p\n # used by GIT_PS1_SHOWUPSTREAM\n __git_ps1_show_upstream ()\n@@ -118,7 +124,7 @@ __git_ps1_show_upstream ()\n \tlocal key value\n \tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n-\tlocal LF=$'\\n'\n+\tlocal LF=\"$__git_LF\"\n \n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n@@ -271,12 +277,16 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue='%F{blue}'\n \t\tlocal c_clear='%f'\n \telse\n-\t\t# Using \\001 and \\002 around colors is necessary to prevent\n-\t\t# issues with command line editing/browsing/completion!\n-\t\tlocal c_red=$'\\001\\e[31m\\002'\n-\t\tlocal c_green=$'\\001\\e[32m\\002'\n-\t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n-\t\tlocal c_clear=$'\\001\\e[0m\\002'\n+\t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n+\t\t# which bash/readline identify while calculating the prompt\n+\t\t# on-screen width - to exclude 0-screen-width esc sequences.\n+\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${__git_STX}\"\n+\n+\t\tlocal c_red=\"${c_pre}31${c_post}\"\n+\t\tlocal c_green=\"${c_pre}32${c_post}\"\n+\t\tlocal c_lblue=\"${c_pre}1;34${c_post}\"\n+\t\tlocal c_clear=\"${c_pre}0${c_post}\"\n \tfi\n \tlocal bad_color=\"$c_red\"\n \tlocal ok_color=\"$c_green\"\n@@ -312,7 +322,7 @@ __git_ps1_colorize_gitstring ()\n # variable, in that order.\n __git_eread ()\n {\n-\ttest -r \"$1\" && IFS=$'\\r\\n' read -r \"$2\" <\"$1\"\n+\ttest -r \"$1\" && IFS=$__git_CRLF read -r \"$2\" <\"$1\"\n }\n \n # see if a cherry-pick or revert is in progress, if the user has committed a\n@@ -430,19 +440,20 @@ __git_ps1 ()\n \t\treturn \"$exit\"\n \tfi\n \n+\tlocal LF=\"$__git_LF\"\n \tlocal short_sha=\"\"\n \tif [ \"$rev_parse_exit_code\" = \"0\" ]; then\n-\t\tshort_sha=\"${repo_info##*$'\\n'}\"\n-\t\trepo_info=\"${repo_info%$'\\n'*}\"\n+\t\tshort_sha=\"${repo_info##*$LF}\"\n+\t\trepo_info=\"${repo_info%$LF*}\"\n \tfi\n-\tlocal ref_format=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_worktree=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal bare_repo=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_gitdir=\"${repo_info##*$'\\n'}\"\n-\tlocal g=\"${repo_info%$'\\n'*}\"\n+\tlocal ref_format=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_worktree=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal bare_repo=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_gitdir=\"${repo_info##*$LF}\"\n+\tlocal g=\"${repo_info%$LF*}\"\n \n \tif [ \"true\" = \"$inside_worktree\" ] &&\n \t   [ -n \"${GIT_PS1_HIDE_IF_PWD_IGNORED-}\" ] &&\n-- \ngitgitgadget\n\n"},{"id":"501212","messageId":"e70440e669a7151cc49df2f5fa7accafb31a3f44.1723886761.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 7/8] git-prompt: ta-da! document usage in other shells","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:25:59Z","receivedAt":"2024-08-17T09:26:10Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWith one big exception, git-prompt.sh should now be both almost posix\ncompliant, and also compatible with most (posix-ish) shells.\n\nThat exception is the use of \"local\" vars in functions, which happens\nextensively in the current code, and is not simple to replace with\nposix compliant code (but also not impossible).\n\nLuckily, almost all shells support \"local\" as used by the current\ncode, with the notable exception of ksh93[u+m], but also the Schily\nminimal posix sh (pbosh), and yash in posix mode.\n\nSee assessment below that \"local\" is likely the only blocker in those.\n\nSo except mainly ksh93, git-prompt.sh now works in most shells:\n- bash, zsh, dash since at least 0.5.8, free/net bsd sh, busybox-ash,\n  mksh, openbsd sh, pdksh(!), Schily extended Bourne sh (bosh), yash.\n\nwhich is quite nice.\n\nAs an anecdote, replacing the 1st line in __git_ps1() (local exit=$?)\nwith these 2 makes it work in all tested shells, even without \"local\":\n\n  # handles only 0/1 args for simplicity. needs +5 LOC for any $#\n  __git_e=$?; local exit=\"$__git_e\" 2>/dev/null ||\n    {(eval 'local() { export \"$@\"; }'; __git_ps1 \"$@\"); return \"$__git_e\"; }\n\nExplanation:\n\n  If the shell doesn't have the command \"local\", define our own\n  function \"local\" which instead does plain (global) assignents.\n  Then use __git_ps1 in a subshell to not clober the caller's vars.\n\n  This happens to work because currently there are no name conflicts\n  (shadow) at the code, initial value is not assumed (i.e. always\n  doing either 'local x=...'  or 'local x;...  x=...'), and assigned\n  initial values are quoted (local x=\"$y\"), preventing word split and\n  glob expansion (i.e. assignment context is not assumed).\n\n  The last two (always init, quote values) seem to be enough to use\n  \"local\" portably if supported, and otherwise shells indeed differ.\n\n  Uses \"eval\", else shells with \"local\" may reject it during parsing.\n  We don't need \"export\", but it's smaller than writing our own loop.\n\nWhile cute, this approach is not really sustainable because all the\nvars become global, which is hard to maintain without conflicts\n(but hey, it currently has no conflicts - without even trying...).\n\nHowever, regardless of being an anecdote, it provides some support to\nthe assessment that \"local\" is the only blocker in those shells.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 33 ++++++++++++++++++++++++++++++--\n 1 file changed, 31 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex c3dd38f847c..6be2f1dd901 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -8,8 +8,8 @@\n # To enable:\n #\n #    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).\n-#    2) Add the following line to your .bashrc/.zshrc:\n-#        source ~/.git-prompt.sh\n+#    2) Add the following line to your .bashrc/.zshrc/.profile:\n+#        . ~/.git-prompt.sh   # dot path/to/this-file\n #    3a) Change your PS1 to call __git_ps1 as\n #        command-substitution:\n #        Bash: PS1='[\\u@\\h \\W$(__git_ps1 \" (%s)\")]\\$ '\n@@ -30,6 +30,8 @@\n #        Optionally, you can supply a third argument with a printf\n #        format string to finetune the output of the branch status\n #\n+#    See notes below about compatibility with other shells.\n+#\n # The repository status will be displayed only if you are currently in a\n # git repository. The %s token is the placeholder for the shown status.\n #\n@@ -106,6 +108,33 @@\n # directory is set up to be ignored by git, then set\n # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the\n # repository level by setting bash.hideIfPwdIgnored to \"false\".\n+#\n+# Compatibility with other shells (beyond bash/zsh):\n+#\n+#    We require posix-ish shell plus \"local\" support, which is most\n+#    shells (even pdksh), but excluding ksh93 (because no \"local\").\n+#\n+#    Prompt integration might differ between shells, but the gist is\n+#    to load it once on shell init with '. path/to/git-prompt.sh',\n+#    set GIT_PS1* vars once as needed, and either place $(__git_ps1..)\n+#    inside PS1 once (0/1 args), or, before each prompt is displayed,\n+#    call __git_ps1 (2/3 args) which sets PS1 with the status embedded.\n+#\n+#    Many shells support the 1st method of command substitution,\n+#    though some might need to first enable cmd substitution in PS1.\n+#\n+#    When using colors, each escape sequence is wrapped between byte\n+#    values 1 and 2 (control chars SOH, STX, respectively), which are\n+#    invisible at the output, but for bash/readline they mark 0-width\n+#    strings (SGR color sequences) when calculating the on-screen\n+#    prompt width, to maintain correct input editing at the prompt.\n+#\n+#    Currently there's no support for different markers, so if editing\n+#    behaves weird when using colors in __git_ps1, then the solution\n+#    is either to disable colors, or, in some shells which only care\n+#    about the width of the last prompt line (e.g. busybox-ash),\n+#    ensure the git output is not at the last line, maybe like so:\n+#      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n __git_printf_supports_v=\n-- \ngitgitgadget\n\n"},{"id":"501213","messageId":"633e71a01d3b7e3e66fdca35136a837ba4975b58.1723886761.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v3 8/8] git-prompt: support custom 0-width PS1 markers","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-17T09:26:00Z","receivedAt":"2024-08-17T09:26:11Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWhen using colors, the shell needs to identify 0-width substrings\nin PS1 - such as color escape sequences - when calculating the\non-screen width of the prompt.\n\nUntil now, we used the form %F{<color>} in zsh - which it knows is\n0-width, or otherwise use standard SGR esc sequences wrapped between\nbyte values 1 and 2 (SOH, STX) as 0-width start/end markers, which\nbash/readline identify as such.\n\nBut now that more shells are supported, the standard SGR sequences\ntypically work, but the SOH/STX markers might not be identified.\n\nThis commit adds support for vars GIT_PS1_COLOR_{PRE,POST} which\nset custom 0-width markers or disable the markers.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 19 ++++++++++++-------\n 1 file changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 6be2f1dd901..6186c474ba7 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -129,11 +129,16 @@\n #    strings (SGR color sequences) when calculating the on-screen\n #    prompt width, to maintain correct input editing at the prompt.\n #\n-#    Currently there's no support for different markers, so if editing\n-#    behaves weird when using colors in __git_ps1, then the solution\n-#    is either to disable colors, or, in some shells which only care\n-#    about the width of the last prompt line (e.g. busybox-ash),\n-#    ensure the git output is not at the last line, maybe like so:\n+#    To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE\n+#    and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not\n+#    use markers. For instance, some shells support '\\[' and '\\]' as\n+#    start/end markers in PS1 - when invoking __git_ps1 with 3/4 args,\n+#    but it may or may not work in command substitution mode. YMMV.\n+#\n+#    If the shell doesn't support 0-width markers and editing behaves\n+#    incorrectly when using colors in __git_ps1, then, other than\n+#    disabling color, it might be solved using multi-line prompt,\n+#    where the git status is not at the last line, e.g.:\n #      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n@@ -309,8 +314,8 @@ __git_ps1_colorize_gitstring ()\n \t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n \t\t# which bash/readline identify while calculating the prompt\n \t\t# on-screen width - to exclude 0-screen-width esc sequences.\n-\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n-\t\tlocal c_post=\"m${__git_STX}\"\n+\t\tlocal c_pre=\"${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${GIT_PS1_COLOR_POST-$__git_STX}\"\n \n \t\tlocal c_red=\"${c_pre}31${c_post}\"\n \t\tlocal c_green=\"${c_pre}32${c_post}\"\n-- \ngitgitgadget\n"},{"id":"501214","messageId":"CAPig+cQVHVoDFD484dxu2gOuvzVHj9-78pyTnCo2-uy6=N5P-g@mail.gmail.com","threadId":"61830","inReplyTo":"3a41ad889cc33a1fc0414b8f14af6438b49c88ee.1723886761.git.gitgitgadget@gmail.com","subject":"Re: [PATCH v3 5/8] git-prompt: add some missing quotes","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2024-08-17T09:38:10Z","receivedAt":"2024-08-17T09:38:23Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Aug 17, 2024 at 5:26 AM Avi Halachmi (:avih) via GitGitGadget\n<gitgitgadget@gmail.com> wrote:\n> The issues which this commit fixes are unlikely to be broken\n> in real life, but the fixes improve correctness, and would prevent\n> bugs in some uncommon cases, such as weird IFS values.\n>\n> Listing some portability guideline here for future reference.\n\ns/guideline/guidelines/\n\n> I'm leaving it to someone else to decide whether to include\n> it in the file itself, place is as a new file, or not.\n\nperhaps: s/is as/it as/\n\n> \"Simple command\" (POSIX term) is assignment[s] and/or command [args].\n> Examples:\n>   foo=bar         # one assignment\n>   foo=$bar x=y    # two assignments\n>   foo bar         # command, no assignments\n>   x=123 foo bar   # one assignment and a command\n>\n> The assignments part is not IFS-split or glob-expanded.\n>\n> The command+args part does get IFS field split and glob expanded,\n> but only at unquoted expanded/substituted parts.\n>\n> In the command+args part, expanded/substituted values must be quoted.\n> (the commands here are \"[\" and \"local\"):\n>   Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n>   Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n\nThis new explanation in v3 is a helpful addition.\n\n> The arguments to \"local\" do look like assignments, but they're not\n> the assignment part of a simple command. they're at the command part.\n\neither: s/they're/They're/\nor: s/. they're/; they're/\n\nI doubt that any of the above extremely minor commit message botches\nis worth a reroll.\n"},{"id":"501215","messageId":"12028161.4698975.1723889226498@mail.yahoo.com","threadId":"61830","inReplyTo":"CAPig+cQVHVoDFD484dxu2gOuvzVHj9-78pyTnCo2-uy6=N5P-g@mail.gmail.com","subject":"Re: [PATCH v3 5/8] git-prompt: add some missing quotes","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-17T10:07:06Z","receivedAt":"2024-08-17T10:07:32Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Saturday, August 17, 2024 at 12:38:23 PM GMT+3, Eric Sunshine <sunshine@sunshineco.com> wrote:\n> On Sat, Aug 17, 2024 at 5:26 AM Avi Halachmi (:avih) via GitGitGadget\n>> Listing some portability guideline here for future reference.\n>\n>> s/guideline/guidelines/\n\nRight.\n\n>> I'm leaving it to someone else to decide whether to include\n>> it in the file itself, place is as a new file, or not.\n>\n> perhaps: s/is as/it as/\n\nIndeed.\n\n>> \"Simple command\" (POSIX term) is assignment[s] and/or command [args].\n>> Examples:\n>> ...\n>\n> This new explanation in v3 is a helpful addition.\n\nThanks.\n\n>> The arguments to \"local\" do look like assignments, but they're not\n>> the assignment part of a simple command. they're at the command part.\n>\n> either: s/they're/They're/\n> or: s/. they're/; they're/\n\nIndeed. Thanks for the comments.\n\n> I doubt that any of the above extremely minor commit message botches\n> is worth a reroll.\n\nI'm not the one to judge that, but I'm OK to push as many new versions\nas deemed required/preferred. For now I'm waiting for someone to say\nwhether I should do that or not... and if yes - when.\n\nI was trying to wait few days for more comments on v2 (perhaps\nlike yours), but I noticed that v2 was already was just integrated\ninto \"seen\", so I posted v3 to address the existing comments on v2.\n\nThis is my 1st patch to \"git\", so still finding my feet with the\nprocedures.\n\navih\n\n"},{"id":"501226","messageId":"xmqqcym7i05l.fsf@gitster.g","threadId":"61830","inReplyTo":"12028161.4698975.1723889226498@mail.yahoo.com","subject":"Re: [PATCH v3 5/8] git-prompt: add some missing quotes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-17T16:28:38Z","receivedAt":"2024-08-17T16:28:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"avih <avihpit@yahoo.com> writes:\n\n> I was trying to wait few days for more comments on v2 (perhaps\n> like yours), but I noticed that v2 was already was just integrated\n> into \"seen\", so I posted v3 to address the existing comments on v2.\n\nPlease consider that it is just like being on the list and nothing\nelse to be in \"seen\".  It merely is another place some patches I've\n\"seen\" are published, to help those of you who find \"git fetch &&\ngit log -pW origin/master..origin/topic\" a more convenient way to\nreview the changes.  This is outlined in the note I send out\noccasionally.\n\n    https://lore.kernel.org/git/xmqqmslewwpo.fsf@gitster.g/\n\nIf you think that v2 needs a few more days' exposure to receive more\nfeedback from reviewers, and that v3 might be incomplete before\nwaiting for their feedback, just saying so as a response to the\n\"What's cooking\" message is a very effective way to make sure I'll\nwait for an updated iteration.  Such a comment on individual topics\nis *not* limited to the author of the topic, e.g.\n\n  https://lore.kernel.org/git/owlyil264yew.fsf@fine.c.googlers.com/\n\nis an example (but the particular example was sent a bit too\nlate---such a \"wait, don't merge, an update is coming\" needs to come\nbefore the topic is merged down to 'next'.\n\n  https://lore.kernel.org/git/13f08ce5-f036-f769-1ba9-7d47b572af28@gmail.com/\n\nis an example of a reviewer sending a \"stop, I have an improvement\nto suggest on this one I'll send soon\" on a topic by somebody else.\n\n  https://lore.kernel.org/git/Zr2_4sNu56_frqlr@tanuki/\n\nis an example of the author saying \"this topic of mine should be\ncomplete already\", which is a bit less usual and takes some finesse\nto avoid sounding too self-promoting (this particular example does\nso well).\n"},{"id":"501229","messageId":"301312741.4747142.1723917755269@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqcym7i05l.fsf@gitster.g","subject":"Re: [PATCH v3 5/8] git-prompt: add some missing quotes","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-17T18:02:35Z","receivedAt":"2024-08-17T18:13:47Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Saturday, August 17, 2024 at 07:28:44 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n> avih <avihpit@yahoo.com> writes:\n>> I was trying to wait few days for more comments on v2 (perhaps\n>> like yours), but I noticed that v2 was already was just integrated\n>> into \"seen\", so I posted v3 to address the existing comments on v2.\n>\n> Please consider that it is just like being on the list and nothing\n> else to be in \"seen\".  It merely is another place some patches I've\n> \"seen\" are published, to help those of you who find \"git fetch &&\n> git log -pW origin/master..origin/topic\" a more convenient way to\n> review the changes.  This is outlined in the note I send out\n> occasionally.\n>\n>     https://lore.kernel.org/git/xmqqmslewwpo.fsf@gitster.g/\n\nThanks for the time and info. That's a useful intro, and I now do\nsee it says this:\n\n  until a topic is merged to \"next\", updates to it is expected\n  by replacing the patch(es) in the topic with an improved version\n\n> If you think that v2 needs a few more days' exposure to receive more\n> feedback from reviewers, and that v3 might be incomplete before\n> waiting for their feedback, just saying so as a response to the\n> \"What's cooking\" message is a very effective way to make sure I'll\n> wait for an updated iteration.  Such a comment on individual topics\n> is *not* limited to the author of the topic, e.g.\n>\n>   https://lore.kernel.org/git/owlyil264yew.fsf@fine.c.googlers.com/\n>\n> is an example ...\n\nThanks. I replied few times that requested changes will be included\nin v3, so I thought it's apparent that v3 is sill to come, but in\nretrospect, when you replied to [PATCH v2 0/8]:\n\n> I've read the series and they looked all sensible.  Will queue but\n> I'd appreciate a second set of eyes before marking it for 'next'.\n\nThen I should have replied with something along those lines:\n\n  Please wait for v3 with requested non-critical changes (typos in\n  comment and commit message) before moving it to \"next\", if at all.\n\nor even sending the same message once I noticed it was merged into\n\"seen\", instead of posting v3 out of \"panic\" that it boarded the\ntrain without all the requested changes applied, yes?\n\nIf yes, then here's heads-up that there's still another non-critical\nrequested change to arrive in v4 (commit message wording), which I'll\nsend in few days, to allow for further comments to arrive.\n\nBecause resending the whole series (is that \"reroll\"?) for every\nminor typo or wording change feels noisy and inappropriate to me.\n\nThanks again for the time and info.\n\navih\n"},{"id":"501313","messageId":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v3.git.git.1723886760.gitgitgadget@gmail.com","subject":"[PATCH v4 0/8] git-prompt: support more shells v4","fromName":"Avi Halachmi via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:24Z","receivedAt":"2024-08-20T01:48:37Z","isPatch":true,"sender":{"key":"name:Avi Halachmi","avatar":null},"body":"This addresses review comments on part 5/8 v3 (git-prompt: add some missing\nquotes) to fix minor wording issues at the commit message.\n\nHopefully this is the last wording fixup.\n\nAvi Halachmi (:avih) (8):\n  git-prompt: use here-doc instead of here-string\n  git-prompt: fix uninitialized variable\n  git-prompt: don't use shell arrays\n  git-prompt: replace [[...]] with standard code\n  git-prompt: add some missing quotes\n  git-prompt: don't use shell $'...'\n  git-prompt: ta-da! document usage in other shells\n  git-prompt: support custom 0-width PS1 markers\n\n contrib/completion/git-prompt.sh | 191 ++++++++++++++++++++-----------\n 1 file changed, 126 insertions(+), 65 deletions(-)\n\n\nbase-commit: d19b6cd2dd72dc811f19df4b32c7ed223256c3ee\nPublished-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1750%2Favih%2Fprompt-compat-v4\nFetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1750/avih/prompt-compat-v4\nPull-Request: https://github.com/git/git/pull/1750\n\nRange-diff vs v3:\n\n 1:  9ce5ddadf0b = 1:  9ce5ddadf0b git-prompt: use here-doc instead of here-string\n 2:  680ecb52404 = 2:  680ecb52404 git-prompt: fix uninitialized variable\n 3:  7e994eae7bc = 3:  7e994eae7bc git-prompt: don't use shell arrays\n 4:  232340902a1 = 4:  232340902a1 git-prompt: replace [[...]] with standard code\n 5:  3a41ad889cc ! 5:  18ff70db6b3 git-prompt: add some missing quotes\n     @@ Commit message\n          in real life, but the fixes improve correctness, and would prevent\n          bugs in some uncommon cases, such as weird IFS values.\n      \n     -    Listing some portability guideline here for future reference.\n     +    Listing some portability guidelines here for future reference.\n      \n          I'm leaving it to someone else to decide whether to include\n     -    it in the file itself, place is as a new file, or not.\n     +    it in the file itself, place it as a new file, or not.\n      \n          ---------\n      \n     @@ Commit message\n            Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n      \n          The arguments to \"local\" do look like assignments, but they're not\n     -    the assignment part of a simple command. they're at the command part.\n     +    the assignment part of a simple command; they're at the command part.\n      \n          Still at the command part, no need to quote non-expandable values:\n            Good:                 local x=   y=yes;   echo OK\n 6:  e735a1696a0 = 6:  48aa31feedb git-prompt: don't use shell $'...'\n 7:  e70440e669a = 7:  cd20b830b24 git-prompt: ta-da! document usage in other shells\n 8:  633e71a01d3 = 8:  cb705d5fc8e git-prompt: support custom 0-width PS1 markers\n\n-- \ngitgitgadget\n"},{"id":"501314","messageId":"9ce5ddadf0bb13229461d67451094a373348771e.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 1/8] git-prompt: use here-doc instead of here-string","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:25Z","receivedAt":"2024-08-20T01:48:38Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nHere-documend is standard, and works in all shells.\n\nBoth here-string and here-doc add final newline, which is important\nin this case, because $output is without final newline, but we do\nwant \"read\" to succeed on the last line as well.\n\nShells which support here-string:\n- bash, zsh, mksh, ksh93, yash (non-posix-mode).\n\nshells which don't, and got fixed:\n- ash-derivatives (dash, free/net bsd sh, busybox-ash).\n- pdksh, openbsd sh.\n- All Schily Bourne shell variants.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5330e769a72..ebf2e30d684 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -137,7 +137,9 @@ __git_ps1_show_upstream ()\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n \t\tesac\n-\tdone <<< \"$output\"\n+\tdone <<-OUTPUT\n+\t\t$output\n+\tOUTPUT\n \n \t# parse configuration values\n \tlocal option\n-- \ngitgitgadget\n\n"},{"id":"501315","messageId":"680ecb524040c64f886c4e484a64f0d17b512e27.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 2/8] git-prompt: fix uninitialized variable","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:26Z","receivedAt":"2024-08-20T01:48:38Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nFirst use is in the form:  local var; ...; var=$var$whatever...\n\nIf the variable was unset (as bash and others do after \"local x\"),\nthen it would error if set -u is in effect.\n\nAlso, many shells inherit the existing value after \"local var\"\nwithout init, but in this case it's unlikely to have a prior value.\n\nNow we initialize it.\n\n(local var= is enough, but local var=\"\" is the custom in this file)\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex ebf2e30d684..4cc2cf91bb6 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,7 +116,7 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern count n\n+\tlocal svn_remote svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n \n \tsvn_remote=()\n-- \ngitgitgadget\n\n"},{"id":"501316","messageId":"7e994eae7bc3dfa021262410c801ddb124ce24f1.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 3/8] git-prompt: don't use shell arrays","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:27Z","receivedAt":"2024-08-20T01:48:39Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nArrays only existed in the svn-upstream code, used to:\n- Keep a list of svn remotes.\n- Convert commit msg to array of words, extract the 2nd-to-last word.\n\nExcept bash/zsh, nearly all shells failed load on syntax errors here.\n\nNow:\n- The svn remotes are a list of newline-terminated values.\n- The 2nd-to-last word is extracted using standard shell substrings.\n- All shells can digest the svn-upstream code.\n\nWhile using shell field splitting to extract the word is simple, and\ndoesn't even need non-standard code, e.g. set -- $(git log -1 ...),\nit would have the same issues as the old array code: it depends on IFS\nwhich we don't control, and it's subject to glob-expansion, e.g. if\nthe message happens to include * or **/* (as this commit message just\ndid), then the array could get huge. This was not great.\n\nNow it uses standard shell substrings, and we know the exact delimiter\nto expect, because it's the match from our grep just one line earlier.\n\nThe new word extraction code also fixes svn-upstream in zsh, because\npreviously it used arr[len-2], but because in zsh, unlike bash, array\nsubscripts are 1-based, it incorrectly extracted the 3rd-to-last word.\nsymptom: missing upstream status in a git-svn repo: u=, u+N-M, etc.\n\nThe breakage in zsh is surprising, because it was last touched by\n  commit d0583da838 (prompt: fix show upstream with svn and zsh),\nclaiming to fix exactly that. However, it only mentions syntax fixes.\nIt's unclear if behavior was fixed too. But it was broken, now fixed.\n\nNote LF=$'\\n' and then using $LF instead of $'\\n' few times.\nA future commit will add fallback for shells without $'...', so this\nwould be the only line to touch instead of replacing every $'\\n' .\n\nShells which could run the previous array code:\n- bash\n\nShells which have arrays but were broken anyway:\n- zsh: 1-based subscript\n- ksh93: no \"local\" (the new code can't fix this part...)\n- mksh, openbsd sh, pdksh: failed load on syntax error: \"for ((...))\".\n\nMore shells which Failed to load due to syntax error:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne shell, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 48 ++++++++++++++++++++------------\n 1 file changed, 30 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4cc2cf91bb6..75c3a813fda 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -116,10 +116,10 @@ printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n __git_ps1_show_upstream ()\n {\n \tlocal key value\n-\tlocal svn_remote svn_url_pattern=\"\" count n\n+\tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n+\tlocal LF=$'\\n'\n \n-\tsvn_remote=()\n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n \twhile read -r key value; do\n@@ -132,7 +132,7 @@ __git_ps1_show_upstream ()\n \t\t\tfi\n \t\t\t;;\n \t\tsvn-remote.*.url)\n-\t\t\tsvn_remote[$((${#svn_remote[@]} + 1))]=\"$value\"\n+\t\t\tsvn_remotes=${svn_remotes}${value}${LF}  # URI\\nURI\\n...\n \t\t\tsvn_url_pattern=\"$svn_url_pattern\\\\|$value\"\n \t\t\tupstream_type=svn+git # default upstream type is SVN if available, else git\n \t\t\t;;\n@@ -156,25 +156,37 @@ __git_ps1_show_upstream ()\n \tcase \"$upstream_type\" in\n \tgit)    upstream_type=\"@{upstream}\" ;;\n \tsvn*)\n-\t\t# get the upstream from the \"git-svn-id: ...\" in a commit message\n-\t\t# (git-svn uses essentially the same procedure internally)\n-\t\tlocal -a svn_upstream\n-\t\tsvn_upstream=($(git log --first-parent -1 \\\n-\t\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null))\n-\t\tif [[ 0 -ne ${#svn_upstream[@]} ]]; then\n-\t\t\tsvn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}\n-\t\t\tsvn_upstream=${svn_upstream%@*}\n-\t\t\tlocal n_stop=\"${#svn_remote[@]}\"\n-\t\t\tfor ((n=1; n <= n_stop; n++)); do\n-\t\t\t\tsvn_upstream=${svn_upstream#${svn_remote[$n]}}\n-\t\t\tdone\n+\t\t# successful svn-upstream resolution:\n+\t\t# - get the list of configured svn-remotes ($svn_remotes set above)\n+\t\t# - get the last commit which seems from one of our svn-remotes\n+\t\t# - confirm that it is from one of the svn-remotes\n+\t\t# - use $GIT_SVN_ID if set, else \"git-svn\"\n \n-\t\t\tif [[ -z \"$svn_upstream\" ]]; then\n+\t\t# get upstream from \"git-svn-id: UPSTRM@N HASH\" in a commit message\n+\t\t# (git-svn uses essentially the same procedure internally)\n+\t\tlocal svn_upstream=\"$(\n+\t\t\tgit log --first-parent -1 \\\n+\t\t\t\t--grep=\"^git-svn-id: \\(${svn_url_pattern#??}\\)\" 2>/dev/null\n+\t\t)\"\n+\n+\t\tif [ -n \"$svn_upstream\" ]; then\n+\t\t\t# extract the URI, assuming --grep matched the last line\n+\t\t\tsvn_upstream=${svn_upstream##*$LF}  # last line\n+\t\t\tsvn_upstream=${svn_upstream#*: }    # UPSTRM@N HASH\n+\t\t\tsvn_upstream=${svn_upstream%@*}     # UPSTRM\n+\n+\t\t\tcase ${LF}${svn_remotes} in\n+\t\t\t*\"${LF}${svn_upstream}${LF}\"*)\n+\t\t\t\t# grep indeed matched the last line - it's our remote\n \t\t\t\t# default branch name for checkouts with no layout:\n \t\t\t\tupstream_type=${GIT_SVN_ID:-git-svn}\n-\t\t\telse\n+\t\t\t\t;;\n+\t\t\t*)\n+\t\t\t\t# the commit message includes one of our remotes, but\n+\t\t\t\t# it's not at the last line. is $svn_upstream junk?\n \t\t\t\tupstream_type=${svn_upstream#/}\n-\t\t\tfi\n+\t\t\t\t;;\n+\t\t\tesac\n \t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n-- \ngitgitgadget\n\n"},{"id":"501317","messageId":"232340902a1feeafe526528eb88b8d0814d11545.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 4/8] git-prompt: replace [[...]] with standard code","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:28Z","receivedAt":"2024-08-20T01:48:40Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe existing [[...]] tests were either already valid as standard [...]\ntests, or only required minimal retouch:\n\nNotes:\n\n- [[...]] doesn't do field splitting and glob expansion, so $var\n  or $(cmd...) don't need quoting, but [... does need quotes.\n\n- [[ X == Y ]] when Y is a string is same as [ X = Y ], but if Y is\n  a pattern, then we need:  case X in Y)... ; esac  .\n\n- [[ ... && ... ]] was replaced with [ ... ] && [ ... ] .\n\n- [[ -o <zsh-option> ]] requires [[...]], so put it in \"eval\" and only\n  eval it in zsh, so other shells would not abort on syntax error\n  (posix says [[ has unspecified results, shells allowed to reject it)\n\n- ((x++)) was changed into x=$((x+1))  (yeah, not [[...]] ...)\n\nShells which accepted the previous forms:\n- bash, zsh, ksh93, mksh, openbsd sh, pdksh.\n\nShells which didn't, and now can process it:\n- dash, free/net bsd sh, busybox-ash, Schily Bourne sh, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 30 ++++++++++++++++--------------\n 1 file changed, 16 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 75c3a813fda..4781261f868 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -126,7 +126,7 @@ __git_ps1_show_upstream ()\n \t\tcase \"$key\" in\n \t\tbash.showupstream)\n \t\t\tGIT_PS1_SHOWUPSTREAM=\"$value\"\n-\t\t\tif [[ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]]; then\n+\t\t\tif [ -z \"${GIT_PS1_SHOWUPSTREAM}\" ]; then\n \t\t\t\tp=\"\"\n \t\t\t\treturn\n \t\t\tfi\n@@ -187,14 +187,14 @@ __git_ps1_show_upstream ()\n \t\t\t\tupstream_type=${svn_upstream#/}\n \t\t\t\t;;\n \t\t\tesac\n-\t\telif [[ \"svn+git\" = \"$upstream_type\" ]]; then\n+\t\telif [ \"svn+git\" = \"$upstream_type\" ]; then\n \t\t\tupstream_type=\"@{upstream}\"\n \t\tfi\n \t\t;;\n \tesac\n \n \t# Find how many commits we are ahead/behind our upstream\n-\tif [[ -z \"$legacy\" ]]; then\n+\tif [ -z \"$legacy\" ]; then\n \t\tcount=\"$(git rev-list --count --left-right \\\n \t\t\t\t\"$upstream_type\"...HEAD 2>/dev/null)\"\n \telse\n@@ -206,8 +206,8 @@ __git_ps1_show_upstream ()\n \t\t\tfor commit in $commits\n \t\t\tdo\n \t\t\t\tcase \"$commit\" in\n-\t\t\t\t\"<\"*) ((behind++)) ;;\n-\t\t\t\t*)    ((ahead++))  ;;\n+\t\t\t\t\"<\"*) behind=$((behind+1)) ;;\n+\t\t\t\t*)    ahead=$((ahead+1))   ;;\n \t\t\t\tesac\n \t\t\tdone\n \t\t\tcount=\"$behind\t$ahead\"\n@@ -217,7 +217,7 @@ __git_ps1_show_upstream ()\n \tfi\n \n \t# calculate the result\n-\tif [[ -z \"$verbose\" ]]; then\n+\tif [ -z \"$verbose\" ]; then\n \t\tcase \"$count\" in\n \t\t\"\") # no upstream\n \t\t\tp=\"\" ;;\n@@ -243,7 +243,7 @@ __git_ps1_show_upstream ()\n \t\t*)\t    # diverged from upstream\n \t\t\tupstream=\"|u+${count#*\t}-${count%\t*}\" ;;\n \t\tesac\n-\t\tif [[ -n \"$count\" && -n \"$name\" ]]; then\n+\t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n \t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n@@ -265,7 +265,7 @@ __git_ps1_show_upstream ()\n # their own color.\n __git_ps1_colorize_gitstring ()\n {\n-\tif [[ -n ${ZSH_VERSION-} ]]; then\n+\tif [ -n \"${ZSH_VERSION-}\" ]; then\n \t\tlocal c_red='%F{red}'\n \t\tlocal c_green='%F{green}'\n \t\tlocal c_lblue='%F{blue}'\n@@ -417,7 +417,7 @@ __git_ps1 ()\n \t# incorrect.)\n \t#\n \tlocal ps1_expanded=yes\n-\t[ -z \"${ZSH_VERSION-}\" ] || [[ -o PROMPT_SUBST ]] || ps1_expanded=no\n+\t[ -z \"${ZSH_VERSION-}\" ] || eval '[[ -o PROMPT_SUBST ]]' || ps1_expanded=no\n \t[ -z \"${BASH_VERSION-}\" ] || shopt -q promptvars || ps1_expanded=no\n \n \tlocal repo_info rev_parse_exit_code\n@@ -502,11 +502,13 @@ __git_ps1 ()\n \t\t\t\t\treturn $exit\n \t\t\t\tfi\n \n-\t\t\t\tif [[ $head == \"ref: \"* ]]; then\n+\t\t\t\tcase $head in\n+\t\t\t\t\"ref: \"*)\n \t\t\t\t\thead=\"${head#ref: }\"\n-\t\t\t\telse\n+\t\t\t\t\t;;\n+\t\t\t\t*)\n \t\t\t\t\thead=\"\"\n-\t\t\t\tfi\n+\t\t\t\tesac\n \t\t\t\t;;\n \t\t\t*)\n \t\t\t\thead=\"$(git symbolic-ref HEAD 2>/dev/null)\"\n@@ -542,8 +544,8 @@ __git_ps1 ()\n \tfi\n \n \tlocal conflict=\"\" # state indicator for unresolved conflicts\n-\tif [[ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" == \"yes\" ]] &&\n-\t   [[ $(git ls-files --unmerged 2>/dev/null) ]]; then\n+\tif [ \"${GIT_PS1_SHOWCONFLICTSTATE-}\" = \"yes\" ] &&\n+\t   [ \"$(git ls-files --unmerged 2>/dev/null)\" ]; then\n \t\tconflict=\"|CONFLICT\"\n \tfi\n \n-- \ngitgitgadget\n\n"},{"id":"501318","messageId":"18ff70db6b3616a9b933b44bf4d44c4405038728.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 5/8] git-prompt: add some missing quotes","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:29Z","receivedAt":"2024-08-20T01:48:41Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nThe issues which this commit fixes are unlikely to be broken\nin real life, but the fixes improve correctness, and would prevent\nbugs in some uncommon cases, such as weird IFS values.\n\nListing some portability guidelines here for future reference.\n\nI'm leaving it to someone else to decide whether to include\nit in the file itself, place it as a new file, or not.\n\n---------\n\nThe command \"local\" is non standard, but is allowed in this file:\n- Quote initialization if it can expand (local x=\"$y\"). See below.\n- Don't assume initial value after \"local x\". Either initialize it\n  (local x=..), or set before first use (local x;.. x=..; <use $x>).\n  (between shells, \"local x\" can unset x, or inherit it, or do x= )\n\nOther non-standard features beyond \"local\" are to be avoided.\n\nUse the standard \"test\" - [...] instead of non-standard [[...]] .\n\n--------\n\nQuotes (some portability things, but mainly general correctness):\n\nQuotes prevent tilde-expansion of some unquoted literal tildes (~).\nIf the expansion is undesirable, quotes would ensure that.\n  Tilds expanded: a=~user:~/ ;  echo ~user ~/dir\n  not expanded:   t=\"~\"; a=${t}user  b=\\~foo~;  echo \"~user\" $t/dir\n\nBut the main reason for quoting is to prevent IFS field splitting\n(which also coalesces IFS chars) and glob expansion in parts which\ncontain parameter/arithmetic expansion or command substitution.\n\n\"Simple command\" (POSIX term) is assignment[s] and/or command [args].\nExamples:\n  foo=bar         # one assignment\n  foo=$bar x=y    # two assignments\n  foo bar         # command, no assignments\n  x=123 foo bar   # one assignment and a command\n\nThe assignments part is not IFS-split or glob-expanded.\n\nThe command+args part does get IFS field split and glob expanded,\nbut only at unquoted expanded/substituted parts.\n\nIn the command+args part, expanded/substituted values must be quoted.\n(the commands here are \"[\" and \"local\"):\n  Good: [ \"$mode\" = yes ]; local s=\"*\" x=\"$y\" e=\"$?\" z=\"$(cmd ...)\"\n  Bad:  [ $mode = yes ];   local s=*   x=$y   e=$?   z=$(cmd...)\n\nThe arguments to \"local\" do look like assignments, but they're not\nthe assignment part of a simple command; they're at the command part.\n\nStill at the command part, no need to quote non-expandable values:\n  Good:                 local x=   y=yes;   echo OK\n  OK, but not required: local x=\"\" y=\"yes\"; echo \"OK\"\nBut completely empty (NULL) arguments must be quoted:\n  foo \"\"   is not the same as:   foo\n\nAssignments in simple commands - with or without an actual command,\ndon't need quoting becase there's no IFS split or glob expansion:\n  Good:   s=* a=$b c=$(cmd...)${x# foo }${y-   } [cmd ...]\n  It's also OK to use double quotes, but not required.\n\nThis behavior (no IFS/glob) is called \"assignment context\", and\n\"local\" does not behave with assignment context in some shells,\nhence we require quotes when using \"local\" - for compatibility.\n\nThe value between 'case' and 'in' doesn't IFS-split/glob-expand:\n  Good:       case  * $foo $(cmd...)  in ... ; esac\n  identical:  case \"* $foo $(cmd...)\" in ... ; esac\n\nNested quotes in command substitution are fine, often necessary:\n  Good: echo \"$(foo... \"$x\" \"$(bar ...)\")\"\n\nNested quotes in substring ops are legal, and sometimes needed\nto prevent interpretation as a pattern, but not the most readable:\n  Legal:  foo \"${x#*\"$y\" }\"\n\nNested quotes in \"maybe other value\" subst are invalid, unnecessary:\n  Good:  local x=\"${y- }\";   foo \"${z:+ $a }\"\n  Bad:   local x=\"${y-\" \"}\"; foo \"${z:+\" $a \"}\"\nOuter/inner quotes in \"maybe other value\" have different use cases:\n  \"${x-$y}\"  always one quoted arg: \"$x\" if x is set, else \"$y\".\n  ${x+\"$x\"}  one quoted arg \"$x\" if x is set, else no arg at all.\n  Unquoted $x is similar to the second case, but it would get split\n  into few arguments if it includes any of the IFS chars.\n\nAssignments don't need the outer quotes, and the braces delimit the\nvalue, so nested quotes can be avoided, for readability:\n  a=$(foo \"$x\")  a=${x#*\"$y\" }  c=${y- };  bar \"$a\" \"$b\" \"$c\"\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 4781261f868..5d7f236fe48 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -246,7 +246,7 @@ __git_ps1_show_upstream ()\n \t\tif [ -n \"$count\" ] && [ -n \"$name\" ]; then\n \t\t\t__git_ps1_upstream_name=$(git rev-parse \\\n \t\t\t\t--abbrev-ref \"$upstream_type\" 2>/dev/null)\n-\t\t\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\t\t\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t\t\tupstream=\"$upstream \\${__git_ps1_upstream_name}\"\n \t\t\telse\n \t\t\t\tupstream=\"$upstream ${__git_ps1_upstream_name}\"\n@@ -278,12 +278,12 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n \t\tlocal c_clear=$'\\001\\e[0m\\002'\n \tfi\n-\tlocal bad_color=$c_red\n-\tlocal ok_color=$c_green\n+\tlocal bad_color=\"$c_red\"\n+\tlocal ok_color=\"$c_green\"\n \tlocal flags_color=\"$c_lblue\"\n \n \tlocal branch_color=\"\"\n-\tif [ $detached = no ]; then\n+\tif [ \"$detached\" = no ]; then\n \t\tbranch_color=\"$ok_color\"\n \telse\n \t\tbranch_color=\"$bad_color\"\n@@ -360,7 +360,7 @@ __git_sequencer_status ()\n __git_ps1 ()\n {\n \t# preserve exit status\n-\tlocal exit=$?\n+\tlocal exit=\"$?\"\n \tlocal pcmode=no\n \tlocal detached=no\n \tlocal ps1pc_start='\\u@\\h:\\w '\n@@ -379,7 +379,7 @@ __git_ps1 ()\n \t\t;;\n \t\t0|1)\tprintf_format=\"${1:-$printf_format}\"\n \t\t;;\n-\t\t*)\treturn $exit\n+\t\t*)\treturn \"$exit\"\n \t\t;;\n \tesac\n \n@@ -427,7 +427,7 @@ __git_ps1 ()\n \trev_parse_exit_code=\"$?\"\n \n \tif [ -z \"$repo_info\" ]; then\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal short_sha=\"\"\n@@ -449,7 +449,7 @@ __git_ps1 ()\n \t   [ \"$(git config --bool bash.hideIfPwdIgnored)\" != \"false\" ] &&\n \t   git check-ignore -q .\n \tthen\n-\t\treturn $exit\n+\t\treturn \"$exit\"\n \tfi\n \n \tlocal sparse=\"\"\n@@ -499,7 +499,7 @@ __git_ps1 ()\n \t\t\tcase \"$ref_format\" in\n \t\t\tfiles)\n \t\t\t\tif ! __git_eread \"$g/HEAD\" head; then\n-\t\t\t\t\treturn $exit\n+\t\t\t\t\treturn \"$exit\"\n \t\t\t\tfi\n \n \t\t\t\tcase $head in\n@@ -597,10 +597,10 @@ __git_ps1 ()\n \t\tfi\n \tfi\n \n-\tlocal z=\"${GIT_PS1_STATESEPARATOR-\" \"}\"\n+\tlocal z=\"${GIT_PS1_STATESEPARATOR- }\"\n \n \tb=${b##refs/heads/}\n-\tif [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then\n+\tif [ \"$pcmode\" = yes ] && [ \"$ps1_expanded\" = yes ]; then\n \t\t__git_ps1_branch_name=$b\n \t\tb=\"\\${__git_ps1_branch_name}\"\n \tfi\n@@ -612,7 +612,7 @@ __git_ps1 ()\n \tlocal f=\"$h$w$i$s$u$p\"\n \tlocal gitstring=\"$c$b${f:+$z$f}${sparse}$r${upstream}${conflict}\"\n \n-\tif [ $pcmode = yes ]; then\n+\tif [ \"$pcmode\" = yes ]; then\n \t\tif [ \"${__git_printf_supports_v-}\" != yes ]; then\n \t\t\tgitstring=$(printf -- \"$printf_format\" \"$gitstring\")\n \t\telse\n@@ -623,5 +623,5 @@ __git_ps1 ()\n \t\tprintf -- \"$printf_format\" \"$gitstring\"\n \tfi\n \n-\treturn $exit\n+\treturn \"$exit\"\n }\n-- \ngitgitgadget\n\n"},{"id":"501319","messageId":"48aa31feedb117a687484651378fe682fe7c39c8.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 6/8] git-prompt: don't use shell $'...'","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:30Z","receivedAt":"2024-08-20T01:48:42Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\n$'...' is new in POSIX (2024), and some shells support it in recent\nversions, while others have had it for decades (bash, zsh, ksh93).\n\nHowever, there are still enough shells which don't support it, and\nit's cheap to use an alternative form which works in all shells,\nso let's do that instead of dismissing it as \"it's compliant\".\n\nIt was agreed to use one form rather than $'...' where supported and\nfallback otherwise.\n\nshells where $'...' works:\n- bash, zsh, ksh93, mksh, busybox-ash, dash master, free/net bsd sh.\n\nshells where it doesn't work, but the new fallback works:\n- all dash releases (up to 0.5.12), older versions of free/net bsd sh,\n  openbsd sh, pdksh, all Schily Bourne sh variants, yash.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 47 ++++++++++++++++++++------------\n 1 file changed, 29 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 5d7f236fe48..c3dd38f847c 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -111,6 +111,12 @@\n __git_printf_supports_v=\n printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1\n \n+# like __git_SOH=$'\\001' etc but works also in shells without $'...'\n+eval \"$(printf '\n+\t__git_SOH=\"\\001\" __git_STX=\"\\002\" __git_ESC=\"\\033\"\n+\t__git_LF=\"\\n\" __git_CRLF=\"\\r\\n\"\n+')\"\n+\n # stores the divergence from upstream in $p\n # used by GIT_PS1_SHOWUPSTREAM\n __git_ps1_show_upstream ()\n@@ -118,7 +124,7 @@ __git_ps1_show_upstream ()\n \tlocal key value\n \tlocal svn_remotes=\"\" svn_url_pattern=\"\" count n\n \tlocal upstream_type=git legacy=\"\" verbose=\"\" name=\"\"\n-\tlocal LF=$'\\n'\n+\tlocal LF=\"$__git_LF\"\n \n \t# get some config options from git-config\n \tlocal output=\"$(git config -z --get-regexp '^(svn-remote\\..*\\.url|bash\\.showupstream)$' 2>/dev/null | tr '\\0\\n' '\\n ')\"\n@@ -271,12 +277,16 @@ __git_ps1_colorize_gitstring ()\n \t\tlocal c_lblue='%F{blue}'\n \t\tlocal c_clear='%f'\n \telse\n-\t\t# Using \\001 and \\002 around colors is necessary to prevent\n-\t\t# issues with command line editing/browsing/completion!\n-\t\tlocal c_red=$'\\001\\e[31m\\002'\n-\t\tlocal c_green=$'\\001\\e[32m\\002'\n-\t\tlocal c_lblue=$'\\001\\e[1;34m\\002'\n-\t\tlocal c_clear=$'\\001\\e[0m\\002'\n+\t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n+\t\t# which bash/readline identify while calculating the prompt\n+\t\t# on-screen width - to exclude 0-screen-width esc sequences.\n+\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${__git_STX}\"\n+\n+\t\tlocal c_red=\"${c_pre}31${c_post}\"\n+\t\tlocal c_green=\"${c_pre}32${c_post}\"\n+\t\tlocal c_lblue=\"${c_pre}1;34${c_post}\"\n+\t\tlocal c_clear=\"${c_pre}0${c_post}\"\n \tfi\n \tlocal bad_color=\"$c_red\"\n \tlocal ok_color=\"$c_green\"\n@@ -312,7 +322,7 @@ __git_ps1_colorize_gitstring ()\n # variable, in that order.\n __git_eread ()\n {\n-\ttest -r \"$1\" && IFS=$'\\r\\n' read -r \"$2\" <\"$1\"\n+\ttest -r \"$1\" && IFS=$__git_CRLF read -r \"$2\" <\"$1\"\n }\n \n # see if a cherry-pick or revert is in progress, if the user has committed a\n@@ -430,19 +440,20 @@ __git_ps1 ()\n \t\treturn \"$exit\"\n \tfi\n \n+\tlocal LF=\"$__git_LF\"\n \tlocal short_sha=\"\"\n \tif [ \"$rev_parse_exit_code\" = \"0\" ]; then\n-\t\tshort_sha=\"${repo_info##*$'\\n'}\"\n-\t\trepo_info=\"${repo_info%$'\\n'*}\"\n+\t\tshort_sha=\"${repo_info##*$LF}\"\n+\t\trepo_info=\"${repo_info%$LF*}\"\n \tfi\n-\tlocal ref_format=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_worktree=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal bare_repo=\"${repo_info##*$'\\n'}\"\n-\trepo_info=\"${repo_info%$'\\n'*}\"\n-\tlocal inside_gitdir=\"${repo_info##*$'\\n'}\"\n-\tlocal g=\"${repo_info%$'\\n'*}\"\n+\tlocal ref_format=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_worktree=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal bare_repo=\"${repo_info##*$LF}\"\n+\trepo_info=\"${repo_info%$LF*}\"\n+\tlocal inside_gitdir=\"${repo_info##*$LF}\"\n+\tlocal g=\"${repo_info%$LF*}\"\n \n \tif [ \"true\" = \"$inside_worktree\" ] &&\n \t   [ -n \"${GIT_PS1_HIDE_IF_PWD_IGNORED-}\" ] &&\n-- \ngitgitgadget\n\n"},{"id":"501320","messageId":"cd20b830b24f236ee348ec549a7ae1e499f8c187.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 7/8] git-prompt: ta-da! document usage in other shells","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:31Z","receivedAt":"2024-08-20T01:48:43Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWith one big exception, git-prompt.sh should now be both almost posix\ncompliant, and also compatible with most (posix-ish) shells.\n\nThat exception is the use of \"local\" vars in functions, which happens\nextensively in the current code, and is not simple to replace with\nposix compliant code (but also not impossible).\n\nLuckily, almost all shells support \"local\" as used by the current\ncode, with the notable exception of ksh93[u+m], but also the Schily\nminimal posix sh (pbosh), and yash in posix mode.\n\nSee assessment below that \"local\" is likely the only blocker in those.\n\nSo except mainly ksh93, git-prompt.sh now works in most shells:\n- bash, zsh, dash since at least 0.5.8, free/net bsd sh, busybox-ash,\n  mksh, openbsd sh, pdksh(!), Schily extended Bourne sh (bosh), yash.\n\nwhich is quite nice.\n\nAs an anecdote, replacing the 1st line in __git_ps1() (local exit=$?)\nwith these 2 makes it work in all tested shells, even without \"local\":\n\n  # handles only 0/1 args for simplicity. needs +5 LOC for any $#\n  __git_e=$?; local exit=\"$__git_e\" 2>/dev/null ||\n    {(eval 'local() { export \"$@\"; }'; __git_ps1 \"$@\"); return \"$__git_e\"; }\n\nExplanation:\n\n  If the shell doesn't have the command \"local\", define our own\n  function \"local\" which instead does plain (global) assignents.\n  Then use __git_ps1 in a subshell to not clober the caller's vars.\n\n  This happens to work because currently there are no name conflicts\n  (shadow) at the code, initial value is not assumed (i.e. always\n  doing either 'local x=...'  or 'local x;...  x=...'), and assigned\n  initial values are quoted (local x=\"$y\"), preventing word split and\n  glob expansion (i.e. assignment context is not assumed).\n\n  The last two (always init, quote values) seem to be enough to use\n  \"local\" portably if supported, and otherwise shells indeed differ.\n\n  Uses \"eval\", else shells with \"local\" may reject it during parsing.\n  We don't need \"export\", but it's smaller than writing our own loop.\n\nWhile cute, this approach is not really sustainable because all the\nvars become global, which is hard to maintain without conflicts\n(but hey, it currently has no conflicts - without even trying...).\n\nHowever, regardless of being an anecdote, it provides some support to\nthe assessment that \"local\" is the only blocker in those shells.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 33 ++++++++++++++++++++++++++++++--\n 1 file changed, 31 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex c3dd38f847c..6be2f1dd901 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -8,8 +8,8 @@\n # To enable:\n #\n #    1) Copy this file to somewhere (e.g. ~/.git-prompt.sh).\n-#    2) Add the following line to your .bashrc/.zshrc:\n-#        source ~/.git-prompt.sh\n+#    2) Add the following line to your .bashrc/.zshrc/.profile:\n+#        . ~/.git-prompt.sh   # dot path/to/this-file\n #    3a) Change your PS1 to call __git_ps1 as\n #        command-substitution:\n #        Bash: PS1='[\\u@\\h \\W$(__git_ps1 \" (%s)\")]\\$ '\n@@ -30,6 +30,8 @@\n #        Optionally, you can supply a third argument with a printf\n #        format string to finetune the output of the branch status\n #\n+#    See notes below about compatibility with other shells.\n+#\n # The repository status will be displayed only if you are currently in a\n # git repository. The %s token is the placeholder for the shown status.\n #\n@@ -106,6 +108,33 @@\n # directory is set up to be ignored by git, then set\n # GIT_PS1_HIDE_IF_PWD_IGNORED to a nonempty value. Override this on the\n # repository level by setting bash.hideIfPwdIgnored to \"false\".\n+#\n+# Compatibility with other shells (beyond bash/zsh):\n+#\n+#    We require posix-ish shell plus \"local\" support, which is most\n+#    shells (even pdksh), but excluding ksh93 (because no \"local\").\n+#\n+#    Prompt integration might differ between shells, but the gist is\n+#    to load it once on shell init with '. path/to/git-prompt.sh',\n+#    set GIT_PS1* vars once as needed, and either place $(__git_ps1..)\n+#    inside PS1 once (0/1 args), or, before each prompt is displayed,\n+#    call __git_ps1 (2/3 args) which sets PS1 with the status embedded.\n+#\n+#    Many shells support the 1st method of command substitution,\n+#    though some might need to first enable cmd substitution in PS1.\n+#\n+#    When using colors, each escape sequence is wrapped between byte\n+#    values 1 and 2 (control chars SOH, STX, respectively), which are\n+#    invisible at the output, but for bash/readline they mark 0-width\n+#    strings (SGR color sequences) when calculating the on-screen\n+#    prompt width, to maintain correct input editing at the prompt.\n+#\n+#    Currently there's no support for different markers, so if editing\n+#    behaves weird when using colors in __git_ps1, then the solution\n+#    is either to disable colors, or, in some shells which only care\n+#    about the width of the last prompt line (e.g. busybox-ash),\n+#    ensure the git output is not at the last line, maybe like so:\n+#      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n __git_printf_supports_v=\n-- \ngitgitgadget\n\n"},{"id":"501321","messageId":"cb705d5fc8eedee276aa72bf1e15a36d6b4b4dd3.1724118513.git.gitgitgadget@gmail.com","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"[PATCH v4 8/8] git-prompt: support custom 0-width PS1 markers","fromName":"Avi Halachmi (:avih) via GitGitGadget","fromEmail":"gitgitgadget@gmail.com","sentAt":"2024-08-20T01:48:32Z","receivedAt":"2024-08-20T01:48:43Z","isPatch":true,"sender":{"key":"name:Avi Halachmi (:avih)","avatar":null},"body":"From: \"Avi Halachmi (:avih)\" <avihpit@yahoo.com>\n\nWhen using colors, the shell needs to identify 0-width substrings\nin PS1 - such as color escape sequences - when calculating the\non-screen width of the prompt.\n\nUntil now, we used the form %F{<color>} in zsh - which it knows is\n0-width, or otherwise use standard SGR esc sequences wrapped between\nbyte values 1 and 2 (SOH, STX) as 0-width start/end markers, which\nbash/readline identify as such.\n\nBut now that more shells are supported, the standard SGR sequences\ntypically work, but the SOH/STX markers might not be identified.\n\nThis commit adds support for vars GIT_PS1_COLOR_{PRE,POST} which\nset custom 0-width markers or disable the markers.\n\nSigned-off-by: Avi Halachmi (:avih) <avihpit@yahoo.com>\n---\n contrib/completion/git-prompt.sh | 19 ++++++++++++-------\n 1 file changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh\nindex 6be2f1dd901..6186c474ba7 100644\n--- a/contrib/completion/git-prompt.sh\n+++ b/contrib/completion/git-prompt.sh\n@@ -129,11 +129,16 @@\n #    strings (SGR color sequences) when calculating the on-screen\n #    prompt width, to maintain correct input editing at the prompt.\n #\n-#    Currently there's no support for different markers, so if editing\n-#    behaves weird when using colors in __git_ps1, then the solution\n-#    is either to disable colors, or, in some shells which only care\n-#    about the width of the last prompt line (e.g. busybox-ash),\n-#    ensure the git output is not at the last line, maybe like so:\n+#    To replace or disable the 0-width markers, set GIT_PS1_COLOR_PRE\n+#    and GIT_PS1_COLOR_POST to other markers, or empty (nul) to not\n+#    use markers. For instance, some shells support '\\[' and '\\]' as\n+#    start/end markers in PS1 - when invoking __git_ps1 with 3/4 args,\n+#    but it may or may not work in command substitution mode. YMMV.\n+#\n+#    If the shell doesn't support 0-width markers and editing behaves\n+#    incorrectly when using colors in __git_ps1, then, other than\n+#    disabling color, it might be solved using multi-line prompt,\n+#    where the git status is not at the last line, e.g.:\n #      PS1='\\n\\w \\u@\\h$(__git_ps1 \" (%s)\")\\n\\$ '\n \n # check whether printf supports -v\n@@ -309,8 +314,8 @@ __git_ps1_colorize_gitstring ()\n \t\t# \\001 (SOH) and \\002 (STX) are 0-width substring markers\n \t\t# which bash/readline identify while calculating the prompt\n \t\t# on-screen width - to exclude 0-screen-width esc sequences.\n-\t\tlocal c_pre=\"${__git_SOH}${__git_ESC}[\"\n-\t\tlocal c_post=\"m${__git_STX}\"\n+\t\tlocal c_pre=\"${GIT_PS1_COLOR_PRE-$__git_SOH}${__git_ESC}[\"\n+\t\tlocal c_post=\"m${GIT_PS1_COLOR_POST-$__git_STX}\"\n \n \t\tlocal c_red=\"${c_pre}31${c_post}\"\n \t\tlocal c_green=\"${c_pre}32${c_post}\"\n-- \ngitgitgadget\n"},{"id":"501381","messageId":"xmqqr0ajb467.fsf@gitster.g","threadId":"61830","inReplyTo":"pull.1750.v4.git.git.1724118513.gitgitgadget@gmail.com","subject":"Re: [PATCH v4 0/8] git-prompt: support more shells v4","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-20T15:32:48Z","receivedAt":"2024-08-20T15:32:54Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Avi Halachmi via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n\n> This addresses review comments on part 5/8 v3 (git-prompt: add some missing\n> quotes) to fix minor wording issues at the commit message.\n\nGood.  This exactly matches what has been queued in 'seen', as I've\nfixed these typoes locally while queueing.\n\n> Hopefully this is the last wording fixup.\n\n;-)  Let me mark the topic for 'next' in a few days, then.\n\nThanks.\n"},{"id":"501382","messageId":"1689227029.5308571.1724168839763@mail.yahoo.com","threadId":"61830","inReplyTo":"xmqqr0ajb467.fsf@gitster.g","subject":"Re: [PATCH v4 0/8] git-prompt: support more shells v4","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-20T15:47:19Z","receivedAt":"2024-08-20T15:57:36Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" On Tuesday, August 20, 2024 at 06:32:55 PM GMT+3, Junio C Hamano <gitster@pobox.com> wrote:\n\"Avi Halachmi via GitGitGadget\" <gitgitgadget@gmail.com> writes:\n>\n>> This addresses review comments on part 5/8 v3 (git-prompt: add some missing\n>> quotes) to fix minor wording issues at the commit message.\n>\n> Good.  This exactly matches what has been queued in 'seen', as I've\n> fixed these typoes locally while queueing.\n\nOuch... Indeed I didn't check whether \"seen\" includes those fixups.\nYou're testing me ;)\n\n>> Hopefully this is the last wording fixup.\n>\n> ;-)  Let me mark the topic for 'next' in a few days, then.\n\nThanks!\n\n"},{"id":"501791","messageId":"703154053.591587.1724874848280@mail.yahoo.com","threadId":"61830","inReplyTo":"1689227029.5308571.1724168839763@mail.yahoo.com","subject":"Re: [PATCH v4 0/8] git-prompt: support more shells v4","fromName":"avih","fromEmail":"avihpit@yahoo.com","sentAt":"2024-08-28T19:54:08Z","receivedAt":"2024-08-28T20:34:41Z","isPatch":true,"sender":{"key":"avihpit@yahoo.com","avatar":"https://avatars.githubusercontent.com/u/2164962?v=4"},"body":" Thanks for merging the git-prompt portability improvements into\nmaster, and for coordinating the development of git all those years!\n\nI probably won't be following the git mailing list closely, but do\nfeel free to email or CC me with any question or other comments,\neither specically about git-prompt, or anything else you think I\nmight be able to help with (I'm guessing mainly shell-related).\n\nBest regards,\n\nAvi Halachmi\n"}]}