{"thread":{"id":"18452","subject":"[PATCH 0/7] Clean up interpret_nth_last_branch feature","startedAt":"2009-03-21T22:13:32Z","lastAt":"2009-03-22T23:19:21Z","messageCount":14,"participants":["Junio C Hamano","Bert Wesarg","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":7},"messages":[{"id":"108832","messageId":"1237673619-12608-1-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":null,"subject":"[PATCH 0/7] Clean up interpret_nth_last_branch feature","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:32Z","receivedAt":"2009-03-21T22:13:32Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Dscho and Pasky seem to want to introduce %name and there were a few\ndiscussions around this area, mostly on the syntax.\n\nI am not personally interested in the implementation of this new feature\nitself, but I would want to solidify the codepath that they will be\nbuilding on before accepting any patch for it, because I have a stake at\nthe overall health of the resulting code we need to maintain.\n\nThe first one is what I already sent.  The last one is a bit iffy.\n\nJunio C Hamano (7):\n  check_ref_format(): tighten refname rules\n  Rename interpret/substitute nth_last_branch functions\n  check-ref-format --branch: give Porcelain a way to grok branch\n    shorthand\n  strbuf_branchname(): a wrapper for branch name shorthands\n  Fix branch -m @{-1} newname\n  strbuf_check_branch_ref(): a helper to check a refname for a branch\n  checkout -: make \"-\" to mean \"previous branch\" everywhere\n\n branch.c                   |   10 +---------\n builtin-branch.c           |   20 ++++++--------------\n builtin-check-ref-format.c |    9 +++++++++\n builtin-checkout.c         |   26 +++++++++++---------------\n builtin-merge.c            |    5 ++---\n cache.h                    |    2 +-\n refs.c                     |   12 ++++++++----\n sha1_name.c                |   33 +++++++++++++++++++--------------\n strbuf.c                   |   17 +++++++++++++++++\n strbuf.h                   |    3 +++\n 10 files changed, 77 insertions(+), 60 deletions(-)\n"},{"id":"108833","messageId":"1237673619-12608-2-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/7] check_ref_format(): tighten refname rules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:33Z","receivedAt":"2009-03-21T22:13:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yes, I know that tightening rules retroactively is bad, but this changes\nthe rules for refnames to forbid:\n\n (1) a refname that ends with a dot.\n\n     We already reject a path component that begins with a dot, primarily\n     to avoid ambiguous range interpretation.  If we allowed \".B\" as a\n     valid ref, it is unclear if \"A...B\" means \"in dot-B but not in A\" or\n     \"either in A or B but not in both\".\n\n     But for this to be complete, we need also to forbid \"A.\" to avoid \"in\n     B but not in A-dot\".  This was not a problem in the original range\n     notation, but we should have added this restriction when three-dot\n     notation was introduced.\n\n     Unlike \"no dot at the beginning of any path component\" rule, this\n     rule does not have to be \"no dot at the end of any path component\",\n     because you cannot abbreviate the tail end away, similar to you can\n     say \"dot-B\" to mean \"refs/heads/dot-B\".\n\n (2) a refname that contains \"@{\" in it.\n\n     Some people and foreign SCM converter may have named their branches\n     as frotz@243 and we still want to keep supporting it, but \"git branch\n     @{1}\" is a disaster.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n refs.c |   12 ++++++++----\n 1 files changed, 8 insertions(+), 4 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex 8d3c502..abd5623 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -693,7 +693,7 @@ static inline int bad_ref_char(int ch)\n \n int check_ref_format(const char *ref)\n {\n-\tint ch, level, bad_type;\n+\tint ch, level, bad_type, last;\n \tint ret = CHECK_REF_FORMAT_OK;\n \tconst char *cp = ref;\n \n@@ -717,19 +717,23 @@ int check_ref_format(const char *ref)\n \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t}\n \n+\t\tlast = ch;\n \t\t/* scan the rest of the path component */\n \t\twhile ((ch = *cp++) != 0) {\n \t\t\tbad_type = bad_ref_char(ch);\n-\t\t\tif (bad_type) {\n+\t\t\tif (bad_type)\n \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n-\t\t\t}\n \t\t\tif (ch == '/')\n \t\t\t\tbreak;\n-\t\t\tif (ch == '.' && *cp == '.')\n+\t\t\tif (last == '.' && ch == '.')\n+\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n+\t\t\tif (last == '@' && ch == '{')\n \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t}\n \t\tlevel++;\n \t\tif (!ch) {\n+\t\t\tif (ref <= cp - 2 && cp[-2] == '.')\n+\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t\tif (level < 2)\n \t\t\t\treturn CHECK_REF_FORMAT_ONELEVEL;\n \t\t\treturn ret;\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108834","messageId":"1237673619-12608-3-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-2-git-send-email-gitster@pobox.com","subject":"[PATCH 2/7] Rename interpret/substitute nth_last_branch functions","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:34Z","receivedAt":"2009-03-21T22:13:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"These allow you to say \"git checkout @{-2}\" to switch to the branch two\n\"branch switching\" ago by pretending as if you typed the name of that\nbranch.  As it is likely that we will be introducing more short-hands to\nwrite the name of a branch without writing it explicitly, rename the\nfunctions from \"nth_last_branch\" to more generic \"branch_name\", to prepare\nfor different semantics.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n branch.c           |    2 +-\n builtin-branch.c   |    2 +-\n builtin-checkout.c |    2 +-\n builtin-merge.c    |    2 +-\n cache.h            |    2 +-\n sha1_name.c        |   12 ++++++------\n 6 files changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex 5f889fe..313bcf1 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -137,7 +137,7 @@ void create_branch(const char *head,\n \tint len;\n \n \tlen = strlen(name);\n-\tif (interpret_nth_last_branch(name, &ref) != len) {\n+\tif (interpret_branch_name(name, &ref) != len) {\n \t\tstrbuf_reset(&ref);\n \t\tstrbuf_add(&ref, name, len);\n \t}\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 14d4b91..cacd7da 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -123,7 +123,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \tfor (i = 0; i < argc; i++, strbuf_release(&bname)) {\n \t\tint len = strlen(argv[i]);\n \n-\t\tif (interpret_nth_last_branch(argv[i], &bname) != len)\n+\t\tif (interpret_branch_name(argv[i], &bname) != len)\n \t\t\tstrbuf_add(&bname, argv[i], len);\n \n \t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 9fdfc58..a8d9d97 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -355,7 +355,7 @@ static void setup_branch_path(struct branch_info *branch)\n \tstruct strbuf buf = STRBUF_INIT;\n \tint ret;\n \n-\tif ((ret = interpret_nth_last_branch(branch->name, &buf))\n+\tif ((ret = interpret_branch_name(branch->name, &buf))\n \t    && ret == strlen(branch->name)) {\n \t\tbranch->name = xstrdup(buf.buf);\n \t\tstrbuf_splice(&buf, 0, 0, \"refs/heads/\", 11);\ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex 4c11935..e94ea7c 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -361,7 +361,7 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \tint len, early;\n \n \tlen = strlen(remote);\n-\tif (interpret_nth_last_branch(remote, &bname) == len)\n+\tif (interpret_branch_name(remote, &bname) == len)\n \t\tremote = bname.buf;\n \n \tmemset(branch_head, 0, sizeof(branch_head));\ndiff --git a/cache.h b/cache.h\nindex 39789ee..d28fd74 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -671,7 +671,7 @@ extern int read_ref(const char *filename, unsigned char *sha1);\n extern const char *resolve_ref(const char *path, unsigned char *sha1, int, int *);\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_nth_last_branch(const char *str, struct strbuf *);\n+extern int interpret_branch_name(const char *str, struct strbuf *);\n \n extern int refname_match(const char *abbrev_name, const char *full_name, const char **rules);\n extern const char *ref_rev_parse_rules[];\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 2f75179..904bcd9 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -242,10 +242,10 @@ static int ambiguous_path(const char *path, int len)\n  * *string and *len will only be substituted, and *string returned (for\n  * later free()ing) if the string passed in is of the form @{-<n>}.\n  */\n-static char *substitute_nth_last_branch(const char **string, int *len)\n+static char *substitute_branch_name(const char **string, int *len)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n-\tint ret = interpret_nth_last_branch(*string, &buf);\n+\tint ret = interpret_branch_name(*string, &buf);\n \n \tif (ret == *len) {\n \t\tsize_t size;\n@@ -259,7 +259,7 @@ static char *substitute_nth_last_branch(const char **string, int *len)\n \n int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)\n {\n-\tchar *last_branch = substitute_nth_last_branch(&str, &len);\n+\tchar *last_branch = substitute_branch_name(&str, &len);\n \tconst char **p, *r;\n \tint refs_found = 0;\n \n@@ -288,7 +288,7 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)\n \n int dwim_log(const char *str, int len, unsigned char *sha1, char **log)\n {\n-\tchar *last_branch = substitute_nth_last_branch(&str, &len);\n+\tchar *last_branch = substitute_branch_name(&str, &len);\n \tconst char **p;\n \tint logs_found = 0;\n \n@@ -355,7 +355,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)\n \t\tstruct strbuf buf = STRBUF_INIT;\n \t\tint ret;\n \t\t/* try the @{-N} syntax for n-th checkout */\n-\t\tret = interpret_nth_last_branch(str+at, &buf);\n+\t\tret = interpret_branch_name(str+at, &buf);\n \t\tif (ret > 0) {\n \t\t\t/* substitute this branch name and restart */\n \t\t\treturn get_sha1_1(buf.buf, buf.len, sha1);\n@@ -750,7 +750,7 @@ static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,\n  * If the input was ok but there are not N branch switches in the\n  * reflog, it returns 0.\n  */\n-int interpret_nth_last_branch(const char *name, struct strbuf *buf)\n+int interpret_branch_name(const char *name, struct strbuf *buf)\n {\n \tlong nth;\n \tint i, retval;\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108836","messageId":"1237673619-12608-4-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-3-git-send-email-gitster@pobox.com","subject":"[PATCH 3/7] check-ref-format --branch: give Porcelain a way to grok branch shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:35Z","receivedAt":"2009-03-21T22:13:35Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The command may not be the best place to add this new feature, but\n\n    $ git check-ref-format --branch \"@{-1}\"\n\nallows Porcelains to figure out what branch you were on before the last\nbranch switching.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-check-ref-format.c |   10 ++++++++++\n 1 files changed, 10 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-check-ref-format.c b/builtin-check-ref-format.c\nindex 701de43..39db6cb 100644\n--- a/builtin-check-ref-format.c\n+++ b/builtin-check-ref-format.c\n@@ -5,9 +5,19 @@\n #include \"cache.h\"\n #include \"refs.h\"\n #include \"builtin.h\"\n+#include \"strbuf.h\"\n \n int cmd_check_ref_format(int argc, const char **argv, const char *prefix)\n {\n+\tif (argc == 3 && !strcmp(argv[1], \"--branch\")) {\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tstrbuf_branchname(&sb, argv[2]);\n+\t\tstrbuf_splice(&sb, 0, 0, \"refs/heads/\", 11);\n+\t\tif (check_ref_format(sb.buf))\n+\t\t\tdie(\"'%s' is not a valid branch name\", argv[2]);\n+\t\tprintf(\"%s\\n\", sb.buf + 11);\n+\t\texit(0);\n+\t}\n \tif (argc != 2)\n \t\tusage(\"git check-ref-format refname\");\n \treturn !!check_ref_format(argv[1]);\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108837","messageId":"1237673619-12608-5-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-4-git-send-email-gitster@pobox.com","subject":"[PATCH 4/7] strbuf_branchname(): a wrapper for branch name shorthands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:36Z","receivedAt":"2009-03-21T22:13:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The function takes a user-supplied string that is supposed to be a branch\nname, and puts it in a strbuf after expanding possible shorthand notation.\nThis removes repeated lines to do so in existing code.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n branch.c           |    7 +------\n builtin-branch.c   |    6 +-----\n builtin-checkout.c |   11 +++--------\n builtin-merge.c    |    5 ++---\n strbuf.c           |    9 +++++++++\n strbuf.h           |    2 ++\n 6 files changed, 18 insertions(+), 22 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex 313bcf1..558f092 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -134,13 +134,8 @@ void create_branch(const char *head,\n \tchar *real_ref, msg[PATH_MAX + 20];\n \tstruct strbuf ref = STRBUF_INIT;\n \tint forcing = 0;\n-\tint len;\n \n-\tlen = strlen(name);\n-\tif (interpret_branch_name(name, &ref) != len) {\n-\t\tstrbuf_reset(&ref);\n-\t\tstrbuf_add(&ref, name, len);\n-\t}\n+\tstrbuf_branchname(&ref, name);\n \tstrbuf_splice(&ref, 0, 0, \"refs/heads/\", 11);\n \n \tif (check_ref_format(ref.buf))\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex cacd7da..7452db1 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -121,11 +121,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)\n \t\t\tdie(\"Couldn't look up commit object for HEAD\");\n \t}\n \tfor (i = 0; i < argc; i++, strbuf_release(&bname)) {\n-\t\tint len = strlen(argv[i]);\n-\n-\t\tif (interpret_branch_name(argv[i], &bname) != len)\n-\t\t\tstrbuf_add(&bname, argv[i], len);\n-\n+\t\tstrbuf_branchname(&bname, argv[i]);\n \t\tif (kinds == REF_LOCAL_BRANCH && !strcmp(head, bname.buf)) {\n \t\t\terror(\"Cannot delete the branch '%s' \"\n \t\t\t      \"which you are currently on.\", bname.buf);\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex a8d9d97..b268046 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -353,16 +353,11 @@ struct branch_info {\n static void setup_branch_path(struct branch_info *branch)\n {\n \tstruct strbuf buf = STRBUF_INIT;\n-\tint ret;\n \n-\tif ((ret = interpret_branch_name(branch->name, &buf))\n-\t    && ret == strlen(branch->name)) {\n+\tstrbuf_branchname(&buf, branch->name);\n+\tif (strcmp(buf.buf, branch->name))\n \t\tbranch->name = xstrdup(buf.buf);\n-\t\tstrbuf_splice(&buf, 0, 0, \"refs/heads/\", 11);\n-\t} else {\n-\t\tstrbuf_addstr(&buf, \"refs/heads/\");\n-\t\tstrbuf_addstr(&buf, branch->name);\n-\t}\n+\tstrbuf_splice(&buf, 0, 0, \"refs/heads/\", 11);\n \tbranch->path = strbuf_detach(&buf, NULL);\n }\n \ndiff --git a/builtin-merge.c b/builtin-merge.c\nindex e94ea7c..6a51823 100644\n--- a/builtin-merge.c\n+++ b/builtin-merge.c\n@@ -360,9 +360,8 @@ static void merge_name(const char *remote, struct strbuf *msg)\n \tconst char *ptr;\n \tint len, early;\n \n-\tlen = strlen(remote);\n-\tif (interpret_branch_name(remote, &bname) == len)\n-\t\tremote = bname.buf;\n+\tstrbuf_branchname(&bname, remote);\n+\tremote = bname.buf;\n \n \tmemset(branch_head, 0, sizeof(branch_head));\n \tremote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT);\ndiff --git a/strbuf.c b/strbuf.c\nindex bfbd816..a60b0ad 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -357,3 +357,12 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)\n \n \treturn len;\n }\n+\n+int strbuf_branchname(struct strbuf *sb, const char *name)\n+{\n+\tint len = strlen(name);\n+\tif (interpret_branch_name(name, sb) == len)\n+\t\treturn 0;\n+\tstrbuf_add(sb, name, len);\n+\treturn len;\n+}\ndiff --git a/strbuf.h b/strbuf.h\nindex 89bd36e..68923e1 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -131,4 +131,6 @@ extern int strbuf_getline(struct strbuf *, FILE *, int);\n extern void stripspace(struct strbuf *buf, int skip_comments);\n extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);\n \n+extern int strbuf_branchname(struct strbuf *sb, const char *name);\n+\n #endif /* STRBUF_H */\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108838","messageId":"1237673619-12608-6-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-5-git-send-email-gitster@pobox.com","subject":"[PATCH 5/7] Fix \"branch -m @{-1} newname\"","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:37Z","receivedAt":"2009-03-21T22:13:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"The command is supposed to rename the branch we were on before switched\nfrom to a new name, but the codepath involved in it was not aware of the\nshort-hand notation we added recently.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-branch.c |   14 +++++++-------\n 1 files changed, 7 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex 7452db1..e15440f 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -468,18 +468,18 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tif (!oldname)\n \t\tdie(\"cannot rename the current branch while not on any.\");\n \n-\tstrbuf_addf(&oldref, \"refs/heads/%s\", oldname);\n-\n+\tstrbuf_branchname(&oldref, oldname);\n+\tstrbuf_splice(&oldref, 0, 0, \"refs/heads/\", 11);\n \tif (check_ref_format(oldref.buf))\n-\t\tdie(\"Invalid branch name: %s\", oldref.buf);\n-\n-\tstrbuf_addf(&newref, \"refs/heads/%s\", newname);\n+\t\tdie(\"Invalid branch name: '%s'\", oldname);\n \n+\tstrbuf_branchname(&newref, newname);\n+\tstrbuf_splice(&newref, 0, 0, \"refs/heads/\", 11);\n \tif (check_ref_format(newref.buf))\n-\t\tdie(\"Invalid branch name: %s\", newref.buf);\n+\t\tdie(\"Invalid branch name: '%s'\", newname);\n \n \tif (resolve_ref(newref.buf, sha1, 1, NULL) && !force)\n-\t\tdie(\"A branch named '%s' already exists.\", newname);\n+\t\tdie(\"A branch named '%s' already exists.\", newref.buf+11);\n \n \tstrbuf_addf(&logmsg, \"Branch: renamed %s to %s\",\n \t\t oldref.buf, newref.buf);\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108835","messageId":"1237673619-12608-7-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-6-git-send-email-gitster@pobox.com","subject":"[PATCH 6/7] strbuf_check_branch_ref(): a helper to check a refname for a branch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:38Z","receivedAt":"2009-03-21T22:13:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This allows a common calling sequence\n\n\tstrbuf_branchname(&ref, name);\n\tstrbuf_splice(&ref, 0, 0, \"refs/heads/\", 11);\n\tif (check_ref_format(ref.buf))\n\t\tdie(...);\n\nto be refactored into\n\n\tif (strbuf_check_branch_ref(&ref, name))\n\t\tdie(...);\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n branch.c                   |    5 +----\n builtin-branch.c           |    8 ++------\n builtin-check-ref-format.c |    5 ++---\n builtin-checkout.c         |    7 +++----\n strbuf.c                   |    8 ++++++++\n strbuf.h                   |    1 +\n 6 files changed, 17 insertions(+), 17 deletions(-)\n\ndiff --git a/branch.c b/branch.c\nindex 558f092..62030af 100644\n--- a/branch.c\n+++ b/branch.c\n@@ -135,10 +135,7 @@ void create_branch(const char *head,\n \tstruct strbuf ref = STRBUF_INIT;\n \tint forcing = 0;\n \n-\tstrbuf_branchname(&ref, name);\n-\tstrbuf_splice(&ref, 0, 0, \"refs/heads/\", 11);\n-\n-\tif (check_ref_format(ref.buf))\n+\tif (strbuf_check_branch_ref(&ref, name))\n \t\tdie(\"'%s' is not a valid branch name.\", name);\n \n \tif (resolve_ref(ref.buf, sha1, 1, NULL)) {\ndiff --git a/builtin-branch.c b/builtin-branch.c\nindex e15440f..cd8f42d 100644\n--- a/builtin-branch.c\n+++ b/builtin-branch.c\n@@ -468,14 +468,10 @@ static void rename_branch(const char *oldname, const char *newname, int force)\n \tif (!oldname)\n \t\tdie(\"cannot rename the current branch while not on any.\");\n \n-\tstrbuf_branchname(&oldref, oldname);\n-\tstrbuf_splice(&oldref, 0, 0, \"refs/heads/\", 11);\n-\tif (check_ref_format(oldref.buf))\n+\tif (strbuf_check_branch_ref(&oldref, oldname))\n \t\tdie(\"Invalid branch name: '%s'\", oldname);\n \n-\tstrbuf_branchname(&newref, newname);\n-\tstrbuf_splice(&newref, 0, 0, \"refs/heads/\", 11);\n-\tif (check_ref_format(newref.buf))\n+\tif (strbuf_check_branch_ref(&newref, newname))\n \t\tdie(\"Invalid branch name: '%s'\", newname);\n \n \tif (resolve_ref(newref.buf, sha1, 1, NULL) && !force)\ndiff --git a/builtin-check-ref-format.c b/builtin-check-ref-format.c\nindex 39db6cb..f9381e0 100644\n--- a/builtin-check-ref-format.c\n+++ b/builtin-check-ref-format.c\n@@ -11,9 +11,8 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)\n {\n \tif (argc == 3 && !strcmp(argv[1], \"--branch\")) {\n \t\tstruct strbuf sb = STRBUF_INIT;\n-\t\tstrbuf_branchname(&sb, argv[2]);\n-\t\tstrbuf_splice(&sb, 0, 0, \"refs/heads/\", 11);\n-\t\tif (check_ref_format(sb.buf))\n+\n+\t\tif (strbuf_check_branch_ref(&sb, argv[2]))\n \t\t\tdie(\"'%s' is not a valid branch name\", argv[2]);\n \t\tprintf(\"%s\\n\", sb.buf + 11);\n \t\texit(0);\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex b268046..66df0c0 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -733,12 +733,11 @@ no_reference:\n \n \tif (opts.new_branch) {\n \t\tstruct strbuf buf = STRBUF_INIT;\n-\t\tstrbuf_addstr(&buf, \"refs/heads/\");\n-\t\tstrbuf_addstr(&buf, opts.new_branch);\n+\t\tif (strbuf_check_branch_ref(&buf, opts.new_branch))\n+\t\t\tdie(\"git checkout: we do not like '%s' as a branch name.\",\n+\t\t\t    opts.new_branch);\n \t\tif (!get_sha1(buf.buf, rev))\n \t\t\tdie(\"git checkout: branch %s already exists\", opts.new_branch);\n-\t\tif (check_ref_format(buf.buf))\n-\t\t\tdie(\"git checkout: we do not like '%s' as a branch name.\", opts.new_branch);\n \t\tstrbuf_release(&buf);\n \t}\n \ndiff --git a/strbuf.c b/strbuf.c\nindex a60b0ad..a884960 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -1,4 +1,5 @@\n #include \"cache.h\"\n+#include \"refs.h\"\n \n int prefixcmp(const char *str, const char *prefix)\n {\n@@ -366,3 +367,10 @@ int strbuf_branchname(struct strbuf *sb, const char *name)\n \tstrbuf_add(sb, name, len);\n \treturn len;\n }\n+\n+int strbuf_check_branch_ref(struct strbuf *sb, const char *name)\n+{\n+\tstrbuf_branchname(sb, name);\n+\tstrbuf_splice(sb, 0, 0, \"refs/heads/\", 11);\n+\treturn check_ref_format(sb->buf);\n+}\ndiff --git a/strbuf.h b/strbuf.h\nindex 68923e1..9ee908a 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -132,5 +132,6 @@ extern void stripspace(struct strbuf *buf, int skip_comments);\n extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);\n \n extern int strbuf_branchname(struct strbuf *sb, const char *name);\n+extern int strbuf_check_branch_ref(struct strbuf *sb, const char *name);\n \n #endif /* STRBUF_H */\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108839","messageId":"1237673619-12608-8-git-send-email-gitster@pobox.com","threadId":"18452","inReplyTo":"1237673619-12608-7-git-send-email-gitster@pobox.com","subject":"[PATCH 7/7] checkout -: make \"-\" to mean \"previous branch\" everywhere","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T22:13:39Z","receivedAt":"2009-03-21T22:13:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is iffy, in that it teaches the very low level machinery to interpret\nit as \"the tip of the previous branch\" when \"-\" is fed to it, and may have\na high risk of unintended side effects.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-checkout.c |    8 +++++---\n sha1_name.c        |   21 +++++++++++++--------\n 2 files changed, 18 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 66df0c0..6b3b450 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -666,9 +666,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\targ = argv[0];\n \t\thas_dash_dash = (argc > 1) && !strcmp(argv[1], \"--\");\n \n-\t\tif (!strcmp(arg, \"-\"))\n-\t\t\targ = \"@{-1}\";\n-\n+\t\t{\n+\t\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\t\tstrbuf_branchname(&sb, arg);\n+\t\t\targ = strbuf_detach(&sb, NULL);\n+\t\t}\n \t\tif (get_sha1(arg, rev)) {\n \t\t\tif (has_dash_dash)          /* case (1) */\n \t\t\t\tdie(\"invalid reference: %s\", arg);\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 904bcd9..3972f4c 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -758,14 +758,19 @@ int interpret_branch_name(const char *name, struct strbuf *buf)\n \tconst char *brace;\n \tchar *num_end;\n \n-\tif (name[0] != '@' || name[1] != '{' || name[2] != '-')\n-\t\treturn -1;\n-\tbrace = strchr(name, '}');\n-\tif (!brace)\n-\t\treturn -1;\n-\tnth = strtol(name+3, &num_end, 10);\n-\tif (num_end != brace)\n-\t\treturn -1;\n+\tif (name[0] == '-' && !name[1]) {\n+\t\tnth = 1;\n+\t\tbrace = name; /* \"end of branch name expression\" */\n+\t} else {\n+\t\tif (name[0] != '@' || name[1] != '{' || name[2] != '-')\n+\t\t\treturn -1;\n+\t\tbrace = strchr(name, '}');\n+\t\tif (!brace)\n+\t\t\treturn -1;\n+\t\tnth = strtol(name+3, &num_end, 10);\n+\t\tif (num_end != brace)\n+\t\t\treturn -1;\n+\t}\n \tif (nth <= 0)\n \t\treturn -1;\n \tcb.alloc = nth;\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108848","messageId":"7vwsaibh8f.fsf@gitster.siamese.dyndns.org","threadId":"18452","inReplyTo":"1237673619-12608-2-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 1/7] check_ref_format(): tighten refname rules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-21T23:15:12Z","receivedAt":"2009-03-21T23:15: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> diff --git a/refs.c b/refs.c\n> index 8d3c502..abd5623 100644\n> --- a/refs.c\n> +++ b/refs.c\n> @@ -717,19 +717,23 @@ int check_ref_format(const char *ref)\n>  \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n>  \t\t}\n>  \n> +\t\tlast = ch;\n>  \t\t/* scan the rest of the path component */\n>  \t\twhile ((ch = *cp++) != 0) {\n>  \t\t\tbad_type = bad_ref_char(ch);\n> -\t\t\tif (bad_type) {\n> +\t\t\tif (bad_type)\n>  \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n> -\t\t\t}\n>  \t\t\tif (ch == '/')\n>  \t\t\t\tbreak;\n> -\t\t\tif (ch == '.' && *cp == '.')\n> +\t\t\tif (last == '.' && ch == '.')\n> +\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n> +\t\t\tif (last == '@' && ch == '{')\n>  \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n\nOops; here I need:\n\n+\t\t\tlast = ch;\n\nhere.\n\n>  \t\t}\n"},{"id":"108863","messageId":"7vskl69xw3.fsf_-_@gitster.siamese.dyndns.org","threadId":"18452","inReplyTo":"1237673619-12608-8-git-send-email-gitster@pobox.com","subject":"[PATCH 7/7 (v2)] checkout -: make \"-\" to mean \"previous branch\" everywhere","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T00:58:20Z","receivedAt":"2009-03-22T00:58:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is iffy, in that it teaches the very low level machinery to interpret\nit as \"the tip of the previous branch\" when \"-\" is fed to it, and has a\nhigh risk of unintended side effects.\n\nThis makes \"git log ..-\" to work as expected, which is marginally useful\nbecause the revision parameter parser misinterprets the other direction\n\"git log -..\".  It also makes \"git check-ref-format --branch -\" to work,\nwhich is not very useful because Porcelains can always ask for @{-1}.\n\nIt also makes a refname whose last component is \"-\" forbidden.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-checkout.c |    8 +++++---\n refs.c             |    3 +++\n sha1_name.c        |   21 +++++++++++++--------\n 3 files changed, 21 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin-checkout.c b/builtin-checkout.c\nindex 66df0c0..6b3b450 100644\n--- a/builtin-checkout.c\n+++ b/builtin-checkout.c\n@@ -666,9 +666,11 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)\n \t\targ = argv[0];\n \t\thas_dash_dash = (argc > 1) && !strcmp(argv[1], \"--\");\n \n-\t\tif (!strcmp(arg, \"-\"))\n-\t\t\targ = \"@{-1}\";\n-\n+\t\t{\n+\t\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\t\tstrbuf_branchname(&sb, arg);\n+\t\t\targ = strbuf_detach(&sb, NULL);\n+\t\t}\n \t\tif (get_sha1(arg, rev)) {\n \t\t\tif (has_dash_dash)          /* case (1) */\n \t\t\t\tdie(\"invalid reference: %s\", arg);\ndiff --git a/refs.c b/refs.c\nindex e355489..7e27537 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -735,6 +735,9 @@ int check_ref_format(const char *ref)\n \t\tif (!ch) {\n \t\t\tif (ref <= cp - 2 && cp[-2] == '.')\n \t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n+\t\t\tif (ref <= cp - 2 && cp[-2] == '-' &&\n+\t\t\t    (cp - 3 < ref || cp[-3] == '/'))\n+\t\t\t\treturn CHECK_REF_FORMAT_ERROR;\n \t\t\tif (level < 2)\n \t\t\t\treturn CHECK_REF_FORMAT_ONELEVEL;\n \t\t\treturn ret;\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 904bcd9..3972f4c 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -758,14 +758,19 @@ int interpret_branch_name(const char *name, struct strbuf *buf)\n \tconst char *brace;\n \tchar *num_end;\n \n-\tif (name[0] != '@' || name[1] != '{' || name[2] != '-')\n-\t\treturn -1;\n-\tbrace = strchr(name, '}');\n-\tif (!brace)\n-\t\treturn -1;\n-\tnth = strtol(name+3, &num_end, 10);\n-\tif (num_end != brace)\n-\t\treturn -1;\n+\tif (name[0] == '-' && !name[1]) {\n+\t\tnth = 1;\n+\t\tbrace = name; /* \"end of branch name expression\" */\n+\t} else {\n+\t\tif (name[0] != '@' || name[1] != '{' || name[2] != '-')\n+\t\t\treturn -1;\n+\t\tbrace = strchr(name, '}');\n+\t\tif (!brace)\n+\t\t\treturn -1;\n+\t\tnth = strtol(name+3, &num_end, 10);\n+\t\tif (num_end != brace)\n+\t\t\treturn -1;\n+\t}\n \tif (nth <= 0)\n \t\treturn -1;\n \tcb.alloc = nth;\n-- \n1.6.2.1.299.gda643a\n"},{"id":"108890","messageId":"36ca99e90903220318g2cfb192fi9d4ef0da95e1a65b@mail.gmail.com","threadId":"18452","inReplyTo":"1237673619-12608-4-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 3/7] check-ref-format --branch: give Porcelain a way to grok branch shorthand","fromName":"Bert Wesarg","fromEmail":"bert.wesarg@googlemail.com","sentAt":"2009-03-22T10:18:29Z","receivedAt":"2009-03-22T10:18:29Z","isPatch":true,"sender":{"key":"bert.wesarg@googlemail.com","avatar":"https://avatars.githubusercontent.com/u/111934?v=4"},"body":"On Sat, Mar 21, 2009 at 23:13, Junio C Hamano <gitster@pobox.com> wrote:\n> The command may not be the best place to add this new feature, but\n>\n>    $ git check-ref-format --branch \"@{-1}\"\n>\n> allows Porcelains to figure out what branch you were on before the last\n> branch switching.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n>  builtin-check-ref-format.c |   10 ++++++++++\n>  1 files changed, 10 insertions(+), 0 deletions(-)\n>\n> diff --git a/builtin-check-ref-format.c b/builtin-check-ref-format.c\n> index 701de43..39db6cb 100644\n> --- a/builtin-check-ref-format.c\n> +++ b/builtin-check-ref-format.c\n> @@ -5,9 +5,19 @@\n>  #include \"cache.h\"\n>  #include \"refs.h\"\n>  #include \"builtin.h\"\n> +#include \"strbuf.h\"\n>\n>  int cmd_check_ref_format(int argc, const char **argv, const char *prefix)\n>  {\n> +       if (argc == 3 && !strcmp(argv[1], \"--branch\")) {\n> +               struct strbuf sb = STRBUF_INIT;\n> +               strbuf_branchname(&sb, argv[2]);\nstrbuf_branchname() will be introduced in the next patch!\n\nBert\n> +               strbuf_splice(&sb, 0, 0, \"refs/heads/\", 11);\n> +               if (check_ref_format(sb.buf))\n> +                       die(\"'%s' is not a valid branch name\", argv[2]);\n> +               printf(\"%s\\n\", sb.buf + 11);\n> +               exit(0);\n> +       }\n>        if (argc != 2)\n>                usage(\"git check-ref-format refname\");\n>        return !!check_ref_format(argv[1]);\n> --\n> 1.6.2.1.299.gda643a\n>\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n>\n"},{"id":"108898","messageId":"alpine.DEB.1.00.0903221539060.10279@pacific.mpi-cbg.de","threadId":"18452","inReplyTo":"1237673619-12608-2-git-send-email-gitster@pobox.com","subject":"Re: [PATCH 1/7] check_ref_format(): tighten refname rules","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-03-22T14:41:11Z","receivedAt":"2009-03-22T14:41:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 21 Mar 2009, Junio C Hamano wrote:\n\n> Yes, I know that tightening rules retroactively is bad, but this changes \n> the rules for refnames to forbid:\n\nTightening rules retroactively is not only bad (if sometimes necessary), \nbut tightening rules without giving the user a chance to recover is really \nbad.\n\n'git branch -m' uses check_ref_format() to check the old name.\n\nOTOH, a _warning_ should be plenty enough in most cases, and _not_ share \nthe shortcomings with tightening.\n\nCiao,\nDscho\n"},{"id":"108934","messageId":"7v8wmxdxt9.fsf@gitster.siamese.dyndns.org","threadId":"18452","inReplyTo":"36ca99e90903220318g2cfb192fi9d4ef0da95e1a65b@mail.gmail.com","subject":"Re: [PATCH 3/7] check-ref-format --branch: give Porcelain a way to grok branch shorthand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T21:58:42Z","receivedAt":"2009-03-22T21:58:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Bert Wesarg <bert.wesarg@googlemail.com> writes:\n\n>>  int cmd_check_ref_format(int argc, const char **argv, const char *prefix)\n>>  {\n>> +       if (argc == 3 && !strcmp(argv[1], \"--branch\")) {\n>> +               struct strbuf sb = STRBUF_INIT;\n>> +               strbuf_branchname(&sb, argv[2]);\n>\n> strbuf_branchname() will be introduced in the next patch!\n\nGood eyes; thanks.\n"},{"id":"108957","messageId":"7vocvtb0xy.fsf@gitster.siamese.dyndns.org","threadId":"18452","inReplyTo":"alpine.DEB.1.00.0903221539060.10279@pacific.mpi-cbg.de","subject":"Re: [PATCH 1/7] check_ref_format(): tighten refname rules","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-03-22T23:19:21Z","receivedAt":"2009-03-22T23:19:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Sat, 21 Mar 2009, Junio C Hamano wrote:\n>\n>> Yes, I know that tightening rules retroactively is bad, but this changes \n>> the rules for refnames to forbid:\n>\n> Tightening rules retroactively is not only bad (if sometimes necessary), \n> but tightening rules without giving the user a chance to recover is really \n> bad.\n>\n> 'git branch -m' uses check_ref_format() to check the old name.\n\nBecause \"git branch -d\" still allows a malformed funny branch to be\nremoved with this patch, I would say it is Ok as long as release notes\nclearly says what we are tightening the rule for.\n\nIt is very probable that some people may have \"master@{24}\" in their\nrepositories, but such a branch cannot be accessed with or without this\npatch anyway, and it is unlikely they created it because they wanted to.\n\n\"git branch wtf-dot wtf.\" followed by \"git branch -d wtf.\" also works; for\nthis one, it might make sense to allow \"git branch -m\" to rename it, but\nI do not think it is worth it.\n"}]}