{"thread":{"id":"34830","subject":"[PATCH v5 0/2] Add @ shortcut, again","startedAt":"2013-09-02T06:34:28Z","lastAt":"2013-09-10T22:08:12Z","messageCount":8,"participants":["Felipe Contreras","Junio C Hamano"],"isPatch":true,"patchVersion":5,"patchTotal":2},"messages":[{"id":"226511","messageId":"1378103670-3394-1-git-send-email-felipe.contreras@gmail.com","threadId":"34830","inReplyTo":null,"subject":"[PATCH v5 0/2] Add @ shortcut, again","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T06:34:28Z","receivedAt":"2013-09-02T06:34:28Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Felipe Contreras (2):\n  sha1-name: pass len argument to interpret_branch_name()\n  Add new @ shortcut for HEAD\n\n Documentation/git-check-ref-format.txt |  2 ++\n Documentation/revisions.txt            |  3 +++\n cache.h                                |  2 +-\n refs.c                                 |  6 +++++-\n revision.c                             |  2 +-\n sha1_name.c                            | 36 ++++++++++++++++++++++++++++++----\n t/t1508-at-combinations.sh             |  4 ++++\n 7 files changed, 48 insertions(+), 7 deletions(-)\n\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226513","messageId":"1378103670-3394-2-git-send-email-felipe.contreras@gmail.com","threadId":"34830","inReplyTo":"1378103670-3394-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name()","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T06:34:29Z","receivedAt":"2013-09-02T06:34:29Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"This is useful to make sure we don't step outside the boundaries of what\nwe are interpreting at the moment. For example while interpreting\nfoobar@{u}~1, the job of interpret_branch_name() ends right before ~1,\nbut there's no way to figure that out inside the function, unless the\nlen argument is passed.\n\nSo let's do that.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n---\n cache.h     |  2 +-\n refs.c      |  2 +-\n revision.c  |  2 +-\n sha1_name.c | 10 ++++++----\n 4 files changed, 9 insertions(+), 7 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex 85b544f..9fbc5fa 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -893,7 +893,7 @@ extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, i\n \n extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);\n extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);\n-extern int interpret_branch_name(const char *str, struct strbuf *);\n+extern int interpret_branch_name(const char *str, int len, struct strbuf *);\n extern int get_sha1_mb(const char *str, unsigned char *sha1);\n \n extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);\ndiff --git a/refs.c b/refs.c\nindex 7922261..8fd5faf 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -1951,7 +1951,7 @@ static int remove_empty_directories(const char *file)\n static char *substitute_branch_name(const char **string, int *len)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n-\tint ret = interpret_branch_name(*string, &buf);\n+\tint ret = interpret_branch_name(*string, *len, &buf);\n \n \tif (ret == *len) {\n \t\tsize_t size;\ndiff --git a/revision.c b/revision.c\nindex 84ccc05..3ef1384 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -200,7 +200,7 @@ static void add_pending_object_with_mode(struct rev_info *revs,\n \t\trevs->no_walk = 0;\n \tif (revs->reflog_info && obj->type == OBJ_COMMIT) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tint len = interpret_branch_name(name, &buf);\n+\t\tint len = interpret_branch_name(name, 0, &buf);\n \t\tint st;\n \n \t\tif (0 < len && name[len] && buf.len)\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 65ad066..93197b9 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1012,7 +1012,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu\n \tint ret;\n \n \tstrbuf_add(buf, name + len, namelen - len);\n-\tret = interpret_branch_name(buf->buf, &tmp);\n+\tret = interpret_branch_name(buf->buf, buf->len, &tmp);\n \t/* that data was not interpreted, remove our cruft */\n \tif (ret < 0) {\n \t\tstrbuf_setlen(buf, used);\n@@ -1046,14 +1046,16 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu\n  * If the input was ok but there are not N branch switches in the\n  * reflog, it returns 0.\n  */\n-int interpret_branch_name(const char *name, struct strbuf *buf)\n+int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n {\n \tchar *cp;\n \tstruct branch *upstream;\n-\tint namelen = strlen(name);\n \tint len = interpret_nth_prior_checkout(name, buf);\n \tint tmp_len;\n \n+\tif (!namelen)\n+\t\tnamelen = strlen(name);\n+\n \tif (!len) {\n \t\treturn len; /* syntax Ok, not enough switches */\n \t} else if (len > 0) {\n@@ -1100,7 +1102,7 @@ int interpret_branch_name(const char *name, struct strbuf *buf)\n int strbuf_branchname(struct strbuf *sb, const char *name)\n {\n \tint len = strlen(name);\n-\tint used = interpret_branch_name(name, sb);\n+\tint used = interpret_branch_name(name, len, sb);\n \n \tif (used == len)\n \t\treturn 0;\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226512","messageId":"1378103670-3394-3-git-send-email-felipe.contreras@gmail.com","threadId":"34830","inReplyTo":"1378103670-3394-1-git-send-email-felipe.contreras@gmail.com","subject":"[PATCH v5 2/2] Add new @ shortcut for HEAD","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-02T06:34:30Z","receivedAt":"2013-09-02T06:34:30Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Typing 'HEAD' is tedious, especially when we can use '@' instead.\n\nThe reason for choosing '@' is that it follows naturally from the\nref@op syntax (e.g. HEAD@{u}), except we have no ref, and no\noperation, and when we don't have those, it makes sens to assume\n'HEAD'.\n\nSo now we can use 'git show @~1', and all that goody goodness.\n\nUntil now '@' was a valid name, but it conflicts with this idea, so\nlet's make it invalid. Probably very few people, if any, used this name.\n\nSigned-off-by: Felipe Contreras <felipe.contreras@gmail.com>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n Documentation/git-check-ref-format.txt |  2 ++\n Documentation/revisions.txt            |  3 +++\n refs.c                                 |  4 ++++\n sha1_name.c                            | 26 ++++++++++++++++++++++++++\n t/t1508-at-combinations.sh             |  4 ++++\n 5 files changed, 39 insertions(+)\n\ndiff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt\nindex a49be1b..fc02959 100644\n--- a/Documentation/git-check-ref-format.txt\n+++ b/Documentation/git-check-ref-format.txt\n@@ -54,6 +54,8 @@ Git imposes the following rules on how references are named:\n \n . They cannot contain a sequence `@{`.\n \n+. They cannot be the single character `@`.\n+\n . They cannot contain a `\\`.\n \n These rules make it easy for shell script based tools to parse\ndiff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\nindex d477b3f..09896a3 100644\n--- a/Documentation/revisions.txt\n+++ b/Documentation/revisions.txt\n@@ -58,6 +58,9 @@ the '$GIT_DIR/refs' directory or from the '$GIT_DIR/packed-refs' file.\n While the ref name encoding is unspecified, UTF-8 is preferred as\n some output processing may assume ref names in UTF-8.\n \n+'@'::\n+  '@' alone is a shortcut for 'HEAD'.\n+\n '<refname>@\\{<date>\\}', e.g. 'master@\\{yesterday\\}', 'HEAD@\\{5 minutes ago\\}'::\n   A ref followed by the suffix '@' with a date specification\n   enclosed in a brace\ndiff --git a/refs.c b/refs.c\nindex 8fd5faf..bfe10e2 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -72,6 +72,10 @@ int check_refname_format(const char *refname, int flags)\n {\n \tint component_len, component_count = 0;\n \n+\tif (!strcmp(refname, \"@\"))\n+\t\t/* Refname is a single character '@'. */\n+\t\treturn -1;\n+\n \twhile (1) {\n \t\t/* We are at the start of a path component. */\n \t\tcomponent_len = check_refname_component(refname, flags);\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 93197b9..b8ece6e 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1004,6 +1004,26 @@ int get_sha1_mb(const char *name, unsigned char *sha1)\n \treturn st;\n }\n \n+/* parse @something syntax, when 'something' is not {.*} */\n+static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)\n+{\n+\tconst char *next;\n+\n+\tif (len || name[1] == '{')\n+\t\treturn -1;\n+\n+\t/* make sure it's a single @, or @@{.*}, not @foo */\n+\tnext = strchr(name + len + 1, '@');\n+\tif (!next)\n+\t\tnext = name + namelen;\n+\tif (next != name + 1)\n+\t\treturn -1;\n+\n+\tstrbuf_reset(buf);\n+\tstrbuf_add(buf, \"HEAD\", 4);\n+\treturn 1;\n+}\n+\n static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf)\n {\n \t/* we have extra data, which might need further processing */\n@@ -1068,9 +1088,15 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n \tcp = strchr(name, '@');\n \tif (!cp)\n \t\treturn -1;\n+\n+\tlen = interpret_empty_at(name, namelen, cp - name, buf);\n+\tif (len > 0)\n+\t\treturn reinterpret(name, namelen, len, buf);\n+\n \ttmp_len = upstream_mark(cp, namelen - (cp - name));\n \tif (!tmp_len)\n \t\treturn -1;\n+\n \tlen = cp + tmp_len - name;\n \tcp = xstrndup(name, cp - name);\n \tupstream = branch_get(*cp ? cp : NULL);\ndiff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh\nindex e5aea3b..3a52375 100755\n--- a/t/t1508-at-combinations.sh\n+++ b/t/t1508-at-combinations.sh\n@@ -32,6 +32,7 @@ test_expect_success 'setup' '\n \tgit checkout -b upstream-branch &&\n \ttest_commit upstream-one &&\n \ttest_commit upstream-two &&\n+\tgit checkout -b @at-test &&\n \tgit checkout -b old-branch &&\n \ttest_commit old-one &&\n \ttest_commit old-two &&\n@@ -55,6 +56,9 @@ check \"HEAD@{u}\" ref refs/heads/upstream-branch\n check \"@{u}@{1}\" commit upstream-one\n check \"@{-1}@{u}\" ref refs/heads/master\n check \"@{-1}@{u}@{1}\" commit master-one\n+check \"@\" commit new-two\n+check \"@@{u}\" ref refs/heads/upstream-branch\n+check \"@at-test\" ref refs/heads/@at-test\n nonsense \"@{u}@{-1}\"\n nonsense \"@{0}@{0}\"\n nonsense \"@{1}@{u}\"\n-- \n1.8.4-338-gefd7fa6\n"},{"id":"226652","messageId":"xmqqioyhsq8q.fsf@gitster.dls.corp.google.com","threadId":"34830","inReplyTo":"1378103670-3394-2-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH v5 1/2] sha1-name: pass len argument to interpret_branch_name()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-03T18:40:37Z","receivedAt":"2013-09-03T18:40:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> This is useful to make sure we don't step outside the boundaries of what\n> we are interpreting at the moment. For example while interpreting\n> foobar@{u}~1, the job of interpret_branch_name() ends right before ~1,\n> but there's no way to figure that out inside the function, unless the\n> len argument is passed.\n>\n> So let's do that.\n>\n> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>\n\nMakes sense to me.  Thanks.\n\n> ---\n>  cache.h     |  2 +-\n>  refs.c      |  2 +-\n>  revision.c  |  2 +-\n>  sha1_name.c | 10 ++++++----\n>  4 files changed, 9 insertions(+), 7 deletions(-)\n>\n> diff --git a/cache.h b/cache.h\n> index 85b544f..9fbc5fa 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -893,7 +893,7 @@ extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, i\n>  \n>  extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);\n>  extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);\n> -extern int interpret_branch_name(const char *str, struct strbuf *);\n> +extern int interpret_branch_name(const char *str, int len, struct strbuf *);\n>  extern int get_sha1_mb(const char *str, unsigned char *sha1);\n>  \n>  extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);\n> diff --git a/refs.c b/refs.c\n> index 7922261..8fd5faf 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -1951,7 +1951,7 @@ static int remove_empty_directories(const char *file)\n>  static char *substitute_branch_name(const char **string, int *len)\n>  {\n>  \tstruct strbuf buf = STRBUF_INIT;\n> -\tint ret = interpret_branch_name(*string, &buf);\n> +\tint ret = interpret_branch_name(*string, *len, &buf);\n>  \n>  \tif (ret == *len) {\n>  \t\tsize_t size;\n> diff --git a/revision.c b/revision.c\n> index 84ccc05..3ef1384 100644\n> --- a/revision.c\n> +++ b/revision.c\n> @@ -200,7 +200,7 @@ static void add_pending_object_with_mode(struct rev_info *revs,\n>  \t\trevs->no_walk = 0;\n>  \tif (revs->reflog_info && obj->type == OBJ_COMMIT) {\n>  \t\tstruct strbuf buf = STRBUF_INIT;\n> -\t\tint len = interpret_branch_name(name, &buf);\n> +\t\tint len = interpret_branch_name(name, 0, &buf);\n>  \t\tint st;\n>  \n>  \t\tif (0 < len && name[len] && buf.len)\n> diff --git a/sha1_name.c b/sha1_name.c\n> index 65ad066..93197b9 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -1012,7 +1012,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu\n>  \tint ret;\n>  \n>  \tstrbuf_add(buf, name + len, namelen - len);\n> -\tret = interpret_branch_name(buf->buf, &tmp);\n> +\tret = interpret_branch_name(buf->buf, buf->len, &tmp);\n>  \t/* that data was not interpreted, remove our cruft */\n>  \tif (ret < 0) {\n>  \t\tstrbuf_setlen(buf, used);\n> @@ -1046,14 +1046,16 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu\n>   * If the input was ok but there are not N branch switches in the\n>   * reflog, it returns 0.\n>   */\n> -int interpret_branch_name(const char *name, struct strbuf *buf)\n> +int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)\n>  {\n>  \tchar *cp;\n>  \tstruct branch *upstream;\n> -\tint namelen = strlen(name);\n>  \tint len = interpret_nth_prior_checkout(name, buf);\n>  \tint tmp_len;\n>  \n> +\tif (!namelen)\n> +\t\tnamelen = strlen(name);\n> +\n>  \tif (!len) {\n>  \t\treturn len; /* syntax Ok, not enough switches */\n>  \t} else if (len > 0) {\n> @@ -1100,7 +1102,7 @@ int interpret_branch_name(const char *name, struct strbuf *buf)\n>  int strbuf_branchname(struct strbuf *sb, const char *name)\n>  {\n>  \tint len = strlen(name);\n> -\tint used = interpret_branch_name(name, sb);\n> +\tint used = interpret_branch_name(name, len, sb);\n>  \n>  \tif (used == len)\n>  \t\treturn 0;\n"},{"id":"226653","messageId":"xmqqd2opsprq.fsf@gitster.dls.corp.google.com","threadId":"34830","inReplyTo":"1378103670-3394-3-git-send-email-felipe.contreras@gmail.com","subject":"Re: [PATCH v5 2/2] Add new @ shortcut for HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-03T18:50:49Z","receivedAt":"2013-09-03T18:50:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n> diff --git a/sha1_name.c b/sha1_name.c\n> index 93197b9..b8ece6e 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -1004,6 +1004,26 @@ int get_sha1_mb(const char *name, unsigned char *sha1)\n>  \treturn st;\n>  }\n>  \n> +/* parse @something syntax, when 'something' is not {.*} */\n> +static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)\n> +{\n> +\tconst char *next;\n> +\n> +\tif (len || name[1] == '{')\n> +\t\treturn -1;\n> +\n> +\t/* make sure it's a single @, or @@{.*}, not @foo */\n> +\tnext = strchr(name + len + 1, '@');\n> +\tif (!next)\n> +\t\tnext = name + namelen;\n> +\tif (next != name + 1)\n> +\t\treturn -1;\n> +\n> +\tstrbuf_reset(buf);\n> +\tstrbuf_add(buf, \"HEAD\", 4);\n> +\treturn 1;\n> +}\n\nHmph, is the above sufficient?  I added a case that mimics Stefano's\noriginal regression report (which is handled) and another that uses\ndoubled \"@\" for the same purpose of introducing a \"funny\" hierarchy,\nand it appears that \"checkout -b\" chokes on it.\n\n t/t1508-at-combinations.sh | 4 ++++\n 1 file changed, 4 insertions(+)\n\ndiff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh\nindex 3a52375..ceb8449 100755\n--- a/t/t1508-at-combinations.sh\n+++ b/t/t1508-at-combinations.sh\n@@ -32,6 +32,8 @@ test_expect_success 'setup' '\n \tgit checkout -b upstream-branch &&\n \ttest_commit upstream-one &&\n \ttest_commit upstream-two &&\n+\tgit checkout -b @/at-test &&\n+\tgit checkout -b @@/at-test &&\n \tgit checkout -b @at-test &&\n \tgit checkout -b old-branch &&\n \ttest_commit old-one &&\n@@ -58,6 +60,8 @@ check \"@{-1}@{u}\" ref refs/heads/master\n check \"@{-1}@{u}@{1}\" commit master-one\n check \"@\" commit new-two\n check \"@@{u}\" ref refs/heads/upstream-branch\n+check \"@@/at-test\" ref refs/heads/@@/at-test\n+check \"@/at-test\" ref refs/heads/@/at-test\n check \"@at-test\" ref refs/heads/@at-test\n nonsense \"@{u}@{-1}\"\n nonsense \"@{0}@{0}\"\n"},{"id":"227190","messageId":"CAMP44s1-+i30CuTH5uRpu4Qi_hWhHmygc2-quYkTrrBV+4hZXQ@mail.gmail.com","threadId":"34830","inReplyTo":"xmqqd2opsprq.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v5 2/2] Add new @ shortcut for HEAD","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2013-09-09T02:09:49Z","receivedAt":"2013-09-09T02:09:49Z","isPatch":true,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Tue, Sep 3, 2013 at 1:50 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>> diff --git a/sha1_name.c b/sha1_name.c\n>> index 93197b9..b8ece6e 100644\n>> --- a/sha1_name.c\n>> +++ b/sha1_name.c\n>> @@ -1004,6 +1004,26 @@ int get_sha1_mb(const char *name, unsigned char *sha1)\n>>       return st;\n>>  }\n>>\n>> +/* parse @something syntax, when 'something' is not {.*} */\n>> +static int interpret_empty_at(const char *name, int namelen, int len, struct strbuf *buf)\n>> +{\n>> +     const char *next;\n>> +\n>> +     if (len || name[1] == '{')\n>> +             return -1;\n>> +\n>> +     /* make sure it's a single @, or @@{.*}, not @foo */\n>> +     next = strchr(name + len + 1, '@');\n>> +     if (!next)\n>> +             next = name + namelen;\n>> +     if (next != name + 1)\n>> +             return -1;\n>> +\n>> +     strbuf_reset(buf);\n>> +     strbuf_add(buf, \"HEAD\", 4);\n>> +     return 1;\n>> +}\n>\n> Hmph, is the above sufficient?  I added a case that mimics Stefano's\n> original regression report (which is handled) and another that uses\n> doubled \"@\" for the same purpose of introducing a \"funny\" hierarchy,\n> and it appears that \"checkout -b\" chokes on it.\n\nThis fixes it:\n\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -1014,6 +1014,8 @@ static int interpret_empty_at(const char *name,\nint namelen, int len, struct str\n\n        /* make sure it's a single @, or @@{.*}, not @foo */\n        next = strchr(name + len + 1, '@');\n+       if (next && next[1] != '{')\n+               return -1;\n        if (!next)\n                next = name + namelen;\n        if (next != name + 1)\n\n-- \nFelipe Contreras\n"},{"id":"227276","messageId":"xmqq38pd38t4.fsf@gitster.dls.corp.google.com","threadId":"34830","inReplyTo":"CAMP44s1-+i30CuTH5uRpu4Qi_hWhHmygc2-quYkTrrBV+4hZXQ@mail.gmail.com","subject":"Re: [PATCH v5 2/2] Add new @ shortcut for HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-09T22:54:31Z","receivedAt":"2013-09-09T22:54:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Felipe Contreras <felipe.contreras@gmail.com> writes:\n\n>> Hmph, is the above sufficient?  I added a case that mimics Stefano's\n>> original regression report (which is handled) and another that uses\n>> doubled \"@\" for the same purpose of introducing a \"funny\" hierarchy,\n>> and it appears that \"checkout -b\" chokes on it.\n>\n> This fixes it:\n>\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -1014,6 +1014,8 @@ static int interpret_empty_at(const char *name,\n> int namelen, int len, struct str\n>\n>         /* make sure it's a single @, or @@{.*}, not @foo */\n>         next = strchr(name + len + 1, '@');\n> +       if (next && next[1] != '{')\n> +               return -1;\n>         if (!next)\n>                 next = name + namelen;\n>         if (next != name + 1)\n\nI think this should be sufficient for all cases, as the sequence\n\"@{\" cannot be a part of valid reference names.\n\nThanks.\n\nI see v6 was posted yesterday after this message, but it does not\nseem to have this fix, nor the additional test case I gave you in\nthe message upthread.  Sent a wrong version of patch by mistake?\n"},{"id":"227375","messageId":"xmqq7geowcs3.fsf@gitster.dls.corp.google.com","threadId":"34830","inReplyTo":"xmqq38pd38t4.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v5 2/2] Add new @ shortcut for HEAD","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-09-10T22:08:12Z","receivedAt":"2013-09-10T22:08:12Z","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> Felipe Contreras <felipe.contreras@gmail.com> writes:\n>\n>>> Hmph, is the above sufficient?  I added a case that mimics Stefano's\n>>> original regression report (which is handled) and another that uses\n>>> doubled \"@\" for the same purpose of introducing a \"funny\" hierarchy,\n>>> and it appears that \"checkout -b\" chokes on it.\n>>\n>> This fixes it:\n>>\n>> --- a/sha1_name.c\n>> +++ b/sha1_name.c\n>> @@ -1014,6 +1014,8 @@ static int interpret_empty_at(const char *name,\n>> int namelen, int len, struct str\n>>\n>>         /* make sure it's a single @, or @@{.*}, not @foo */\n>>         next = strchr(name + len + 1, '@');\n>> +       if (next && next[1] != '{')\n>> +               return -1;\n>>         if (!next)\n>>                 next = name + namelen;\n>>         if (next != name + 1)\n>\n> I think this should be sufficient for all cases, as the sequence\n> \"@{\" cannot be a part of valid reference names.\n>\n> Thanks.\n>\n> I see v6 was posted yesterday after this message, but it does not\n> seem to have this fix, nor the additional test case I gave you in\n> the message upthread.  Sent a wrong version of patch by mistake?\n\nPing?\n\nI could squash the fixup at the tip of on fc/at-head in if you want\nme to, but v6 seems to be a mistake to me.\n"}]}