{"thread":{"id":"19186","subject":"Two problems on alias of git","startedAt":"2009-05-05T12:42:04Z","lastAt":"2009-05-08T09:06:15Z","messageCount":7,"participants":["Kana Natsuno","Jakub Narebski","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"113034","messageId":"op.utgiv92f6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","threadId":"19186","inReplyTo":null,"subject":"Two problems on alias of git","fromName":"Kana Natsuno","fromEmail":"kana@whileimautomaton.net","sentAt":"2009-05-05T12:42:04Z","receivedAt":"2009-05-05T12:42:04Z","isPatch":false,"sender":{"key":"kana@whileimautomaton.net","avatar":"https://gravatar.com/avatar/ba41d8bdcb5c0e519ad72afff742ac2ee0c6ec2bbdce4a86f746d37c650f53b9?d=mp&s=160"},"body":"Hello.  I found 2 problems on alias of git.\n\n\nThe first one is that git crashes with the following situation.\nWithout GIT_TRACE, everthing works well.  But with GIT_TRACE=1,\ngit crashes every time.\n\n---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ----\n$ git remote show origin\n* remote origin\n  URL: git://repo.or.cz/git.git\n  Remote branch merged with 'git pull' while on branch master\n    master\n  Tracked remote branches\n    html\n    maint\n    man\n    master\n    next\n    pu\n    todo\n\n$ git --version\ngit version 1.6.2.rc0.90.g0753\n\n$ git show HEAD | grep commit\ncommit 3536ae331014c68a25c80b3fb530a19c8dee0f11\n\n$ uname -a                   \nDarwin foobarbaz 9.6.1 Darwin Kernel Version 9.6.1: Sun Dec 21 19:45:33 PST 2008; root:xnu-1228.9.75~4/RELEASE_I386 i386 i386 MacBook5,2 Darwin\n\n$ git config --get alias.l1\nlog --pretty=oneline\n\n$ GIT_TRACE=1 git l1         \ntrace: exec: 'git-l1'\ntrace: run_command: 'git-l1'\ntrace: exec 'git-l1' failed: No such file or directory\n[1]    41772 segmentation fault  GIT_TRACE=1 git l1\n---- >8 ---- >8 ---- >8 ---- >8 ---- >8 ----\n\n\nThe second one is that git doesn't expand a kind of aliases\nproperly, especially with double quotation marks (\").  I used the\nfollowing alias recently to list the last 10 commits on HEAD:\n\n[alias]\n        lr = !git l1 | head | tac\n\nThen I want to extend this alias to list the last N commits on\na branch with \"git lr 20\", \"git lr master\", \"git lr master 20\",\netc.  So that I wrote the following definition (note that the\nactual definition is written in a single line, though the quoted\ndefinition is folded in multiple lines for readability):\n\n[alias]\n        lr = !$SHELL -c '\n                n=10;\n                1=\"${1:-$n}\";\n                if ! [ \"${1##[0-9]*}\" = \"\" ]; then\n                  t=\"$1\";\n                  1=\"${2:-$n}\";\n                  2=\"$t\";\n                fi;\n                git --no-pager l1 --reverse -\"$1\" \"${2:-HEAD}\"\n              ' __dummy__\n\nBut it doesn't work because git expands as follows:\n\n$ git config --get alias.lr\n!$SHELL -c '1=${1:-10}\n\nDouble quotation marks (\") are removed and the aliased string is\ncut at a random position.  I expect that the aliased string is\npassed to system() as-is, but git doesn't so.  Why does git behave\nso?  Is it a bug or an intentional behavior?\n\n\n-- \nTo Vim, or not to Vim.\nhttp://whileimautomaton.net/\n"},{"id":"113039","messageId":"m3bpq7oddw.fsf@localhost.localdomain","threadId":"19186","inReplyTo":"op.utgiv92f6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","subject":"Re: Two problems on alias of git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-05-05T14:03:49Z","receivedAt":"2009-05-05T14:03:49Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"\"Kana Natsuno\" <kana@whileimautomaton.net> writes:\n\n> Hello.  I found 2 problems on alias of git.\n\n[...]\n> The second one is that git doesn't expand a kind of aliases\n> properly, especially with double quotation marks (\").  I used the\n> following alias recently to list the last 10 commits on HEAD:\n> \n> [alias]\n>         lr = !git l1 | head | tac\n> \n> Then I want to extend this alias to list the last N commits on\n> a branch with \"git lr 20\", \"git lr master\", \"git lr master 20\",\n> etc.  So that I wrote the following definition (note that the\n> actual definition is written in a single line, though the quoted\n> definition is folded in multiple lines for readability):\n> \n> [alias]\n>         lr = !$SHELL -c '\n>                 n=10;\n>                 1=\"${1:-$n}\";\n>                 if ! [ \"${1##[0-9]*}\" = \"\" ]; then\n>                   t=\"$1\";\n>                   1=\"${2:-$n}\";\n>                   2=\"$t\";\n>                 fi;\n>                 git --no-pager l1 --reverse -\"$1\" \"${2:-HEAD}\"\n>               ' __dummy__\n> \n> But it doesn't work because git expands as follows:\n> \n> $ git config --get alias.lr\n> !$SHELL -c '1=${1:-10}\n> \n> Double quotation marks (\") are removed and the aliased string is\n> cut at a random position.  I expect that the aliased string is\n> passed to system() as-is, but git doesn't so.  Why does git behave\n> so?  Is it a bug or an intentional behavior?\n\nI don't know if it is a bug or a feature, but git-config supports\nquoted strings (required if you want to have value which has trailing\nor leading whitespace, or which contains '#' which is beginning of\ncomment character).  Inside quoted string you need to escape '\"':\n\n   [string]\n        quotes = \"quoted \\\" string ' with # character\"\n\nexpands as intended.  Perhaps stripping of double quotes\ninside string are artifact of that feature.  Try escaping or\ndouble escaping quotes: \\\" or \\\\\\\".\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"113041","messageId":"op.utgptirm6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","threadId":"19186","inReplyTo":"m3bpq7oddw.fsf@localhost.localdomain","subject":"Re: Two problems on alias of git","fromName":"Kana Natsuno","fromEmail":"kana@whileimautomaton.net","sentAt":"2009-05-05T15:11:32Z","receivedAt":"2009-05-05T15:11:32Z","isPatch":false,"sender":{"key":"kana@whileimautomaton.net","avatar":"https://gravatar.com/avatar/ba41d8bdcb5c0e519ad72afff742ac2ee0c6ec2bbdce4a86f746d37c650f53b9?d=mp&s=160"},"body":"On Tue, 05 May 2009 23:03:49 +0900, Jakub Narebski <jnareb@gmail.com> wrote:\n> I don't know if it is a bug or a feature, but git-config supports\n> quoted strings (required if you want to have value which has trailing\n> or leading whitespace, or which contains '#' which is beginning of\n> comment character).  Inside quoted string you need to escape '\"':\n>\n>    [string]\n>         quotes = \"quoted \\\" string ' with # character\"\n>\n> expands as intended.  Perhaps stripping of double quotes\n> inside string are artifact of that feature.  Try escaping or\n> double escaping quotes: \\\" or \\\\\\\".\n\nThank you for the information.  I've read the source code of git\nand I confirmed that this stripping is caused by parse_value() in\nconfig.c.\n\n\nAnd as I changed the old definition\n\n        lr = !$SHELL -c 'n=10; 1=\"${1:-$n}\"; ...' __dummy__\n\nby enclosing all text in double quotes and substituting '\"' with\n'\\\"' as follows,\n\n\tlr = \"!$SHELL -c 'n=10; 1=\\\"${1:-$n}\\\"; ...' __dummy__\"\n\nit works well now.\n\n\t$ git config --get alias.lr\n\t!$SHELL -c 'n=10; 1=\"${1:-$n}\"; if ! [ \"${1##[0-9]*}\" ...\n\n\n-- \nTo Vim, or not to Vim.\nhttp://whileimautomaton.net/\n"},{"id":"113044","messageId":"200905051742.51163.jnareb@gmail.com","threadId":"19186","inReplyTo":"op.utgptirm6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","subject":"Re: Two problems on alias of git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-05-05T15:42:49Z","receivedAt":"2009-05-05T15:42:49Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Tue, 5 May 2009, Kana Natsuno wrote:\n> On Tue, 05 May 2009 23:03:49 +0900, Jakub Narebski <jnareb@gmail.com> wrote:\n\n> > I don't know if it is a bug or a feature, but git-config supports\n> > quoted strings (required if you want to have value which has trailing\n> > or leading whitespace, or which contains '#' which is beginning of\n> > comment character).  Inside quoted string you need to escape '\"':\n\nErrr... what I meant here is that I don't know whether stripping\nquotes inside value which is not quoted (does not begin and end in '\"')\nis intended or unintended consequence of git-config behaviour.\n\n> >\n> >    [string]\n> >         quotes = \"quoted \\\" string ' with # character\"\n> >\n> > expands as intended.  Perhaps stripping of double quotes\n> > inside string are artifact of that feature.  Try escaping or\n> > double escaping quotes: \\\" or \\\\\\\".\n> \n> Thank you for the information.  I've read the source code of git\n> and I confirmed that this stripping is caused by parse_value() in\n> config.c.\n> \n> \n> And as I changed the old definition\n> \n>         lr = !$SHELL -c 'n=10; 1=\"${1:-$n}\"; ...' __dummy__\n> \n> by enclosing all text in double quotes and substituting '\"' with\n> '\\\"' as follows,\n> \n> \tlr = \"!$SHELL -c 'n=10; 1=\\\"${1:-$n}\\\"; ...' __dummy__\"\n> \n> it works well now.\n> \n> \t$ git config --get alias.lr\n> \t!$SHELL -c 'n=10; 1=\"${1:-$n}\"; if ! [ \"${1##[0-9]*}\" ...\n\nBy the way, you can use continuation-of-line character (end line\nwith '\\') and/or can embed newlines using C escape sequence, i.e. \"\\n\".\n\nSo your code can look like this (although I am not sure it is worth it):\n\n  [alias]\n        lr = \"!$SHELL -c '                               \\n\\\n                n=10;                                    \\n\\\n                1=\\\"${1:-$n}\\\";                          \\n\\\n                if ! [ \\\"${1##[0-9]*}\\\" = \\\"\\\" ]; then   \\n\\\n                  t=\\\"$1\\\";                              \\n\\\n                  1=\\\"${2:-$n}\\\";                        \\n\\\n                  2=\\\"$t\\\";                              \\n\\\n                fi;                                      \\n\\\n                git --no-pager l1 --reverse -\\\"$1\\\" \\\"${2:-HEAD}\\\" \\n\\\n              ' __dummy__\"\n\nBTW. you need to quote value because it contains comment character '#'\nin 4th line of script.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"113046","messageId":"op.utgs86ta6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","threadId":"19186","inReplyTo":"200905051742.51163.jnareb@gmail.com","subject":"Re: Two problems on alias of git","fromName":"Kana Natsuno","fromEmail":"kana@whileimautomaton.net","sentAt":"2009-05-05T16:25:50Z","receivedAt":"2009-05-05T16:25:50Z","isPatch":false,"sender":{"key":"kana@whileimautomaton.net","avatar":"https://gravatar.com/avatar/ba41d8bdcb5c0e519ad72afff742ac2ee0c6ec2bbdce4a86f746d37c650f53b9?d=mp&s=160"},"body":"On Wed, 06 May 2009 00:42:49 +0900, Jakub Narebski <jnareb@gmail.com> wrote:\n> By the way, you can use continuation-of-line character (end line\n> with '\\') and/or can embed newlines using C escape sequence, i.e. \"\\n\".\n>\n> So your code can look like this (although I am not sure it is worth it):\n>\n>   [alias]\n>         lr = \"!$SHELL -c '                               \\n\\\n>                 n=10;                                    \\n\\\n>                 1=\\\"${1:-$n}\\\";                          \\n\\\n>                 if ! [ \\\"${1##[0-9]*}\\\" = \\\"\\\" ]; then   \\n\\\n>                   t=\\\"$1\\\";                              \\n\\\n>                   1=\\\"${2:-$n}\\\";                        \\n\\\n>                   2=\\\"$t\\\";                              \\n\\\n>                 fi;                                      \\n\\\n>                 git --no-pager l1 --reverse -\\\"$1\\\" \\\"${2:-HEAD}\\\" \\n\\\n>               ' __dummy__\"\n\nThank you again, I didn't know that.  It is better than what I wrote.\n\n\n> BTW. you need to quote value because it contains comment character '#'\n> in 4th line of script.\n\nReally?  As far as I read the code of git, especially parse_value() in config.c,\nit is not necessary to escape '#'s because they are inside of the outermost\ndoublequotes and they should not be escaped, because \\# is an unknown escape\nsequence and git rejects them.  If #s are escaped, it causes an error as follows:\n\n$ git config --get alias.lr\nfatal: bad config file line 29 in /Users/kana/.gitconfig\n\n\n-- \nTo Vim, or not to Vim.\nhttp://whileimautomaton.net/\n"},{"id":"113047","messageId":"200905051901.38151.jnareb@gmail.com","threadId":"19186","inReplyTo":"op.utgs86ta6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","subject":"Re: Two problems on alias of git","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-05-05T17:01:36Z","receivedAt":"2009-05-05T17:01:36Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Wed, 5 May 2009 (yes, different timezones), Kana Natsuno wrote:\n> On Wed, 06 May 2009 00:42:49 +0900, Jakub Narebski <jnareb@gmail.com> wrote:\n\n> > By the way, you can use continuation-of-line character (end line\n> > with '\\') and/or can embed newlines using C escape sequence, i.e. \"\\n\".\n> >\n> > So your code can look like this (although I am not sure it is worth it):\n> >\n> >   [alias]\n> >         lr = \"!$SHELL -c '                               \\n\\\n> >                 n=10;                                    \\n\\\n> >                 1=\\\"${1:-$n}\\\";                          \\n\\\n> >                 if ! [ \\\"${1##[0-9]*}\\\" = \\\"\\\" ]; then   \\n\\\n> >                   t=\\\"$1\\\";                              \\n\\\n> >                   1=\\\"${2:-$n}\\\";                        \\n\\\n> >                   2=\\\"$t\\\";                              \\n\\\n> >                 fi;                                      \\n\\\n> >                 git --no-pager l1 --reverse -\\\"$1\\\" \\\"${2:-HEAD}\\\" \\n\\\n> >               ' __dummy__\"\n> \n> Thank you again, I didn't know that.  It is better than what I wrote.\n\nBy the way, \"\\n\" is there only for nice looking output of git-config\nfor this variable.  For config file you need only to escape end of line. \n \n> > BTW. you need to quote value because it contains comment character '#'\n> > in 4th line of script.\n> \n> Really?  As far as I read the code of git, especially parse_value() in config.c,\n> it is not necessary to escape '#'s because they are inside of the outermost\n> doublequotes and they should not be escaped, because \\# is an unknown escape\n> sequence and git rejects them.  If #s are escaped, it causes an error as follows:\n> \n> $ git config --get alias.lr\n> fatal: bad config file line 29 in /Users/kana/.gitconfig\n\nErrrr... what I meant is that you have to _quote_ value if it contains\ncomment character, compare\n\n  [string]\n  \tunquoted =  a # b\n  \tquoted   = \"a # b\"\n\nnot that you have to escape comment character '#'. But I forgot about\nthe fact that ## in your example is inside quotes anyway.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"113334","messageId":"20090508090614.GB29737@coredump.intra.peff.net","threadId":"19186","inReplyTo":"op.utgiv92f6f2obg@i220-99-253-139.s27.a098.ap.plala.or.jp","subject":"Re: Two problems on alias of git","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-05-08T09:06:15Z","receivedAt":"2009-05-08T09:06:15Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, May 05, 2009 at 09:42:04PM +0900, Kana Natsuno wrote:\n\n> The first one is that git crashes with the following situation.\n> Without GIT_TRACE, everthing works well.  But with GIT_TRACE=1,\n> git crashes every time.\n\nI wasn't able to reproduce on Linux, but valgrind found it. The patch\nbelow should fix it.\n\n-- >8 --\nSubject: [PATCH] fix GIT_TRACE segfault with shell-quoted aliases\n\nThe alias argv comes from the split_cmdline function, which\nsplits the config text for the alias into an array of\nstrings. It returns the number of elements in the array, but\ndoes not actually put a NULL at the end of the array.\nLater, the trace function tries to print this argv and\nassumes that it has the trailing NULL.\n\nThe split_cmdline function is probably at fault, since argv\nlists almost always end with a NULL signal. This patch adds\none, in addition to the returned count; this doesn't hurt\nthe other callers at all, since they were presumably using\nthe count already (and will never look at the NULL).\n\nWhile we're there and using ALLOC_GROW, let's clean up the\nother manual grow.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n alias.c |    8 ++++----\n 1 files changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/alias.c b/alias.c\nindex e687fe5..372b7d8 100644\n--- a/alias.c\n+++ b/alias.c\n@@ -38,10 +38,7 @@ int split_cmdline(char *cmdline, const char ***argv)\n \t\t\twhile (cmdline[++src]\n \t\t\t\t\t&& isspace(cmdline[src]))\n \t\t\t\t; /* skip */\n-\t\t\tif (count >= size) {\n-\t\t\t\tsize += 16;\n-\t\t\t\t*argv = xrealloc(*argv, sizeof(char *) * size);\n-\t\t\t}\n+\t\t\tALLOC_GROW(*argv, count+1, size);\n \t\t\t(*argv)[count++] = cmdline + dst;\n \t\t} else if (!quoted && (c == '\\'' || c == '\"')) {\n \t\t\tquoted = c;\n@@ -72,6 +69,9 @@ int split_cmdline(char *cmdline, const char ***argv)\n \t\treturn error(\"unclosed quote\");\n \t}\n \n+\tALLOC_GROW(*argv, count+1, size);\n+\t(*argv)[count] = NULL;\n+\n \treturn count;\n }\n \n-- \n1.6.3.203.g7c7de.dirty\n"}]}