{"thread":{"id":"10807","subject":"[PATCH 4/6] add ref_abbrev_matches_full_with_rules()","startedAt":"2007-11-11T14:01:42Z","lastAt":"2007-11-12T20:51:16Z","messageCount":18,"participants":["Steffen Prohaska","Andreas Ericsson","Jakub Narebski","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"59322","messageId":"1194789708646-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":null,"subject":"[REPLACEMENT PATCH 0/6] improve refspec handling in push, refactor matching in fetch","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:42Z","receivedAt":"2007-11-11T14:01:42Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"This is a replacement for sp/push-refspec. It is rebased to the current master.\n\n Documentation/git-push.txt      |    4 ++--\n Documentation/git-send-pack.txt |    4 +++-\n builtin-push.c                  |   11 +++++++++++\n cache.h                         |    4 ++++\n refs.c                          |   31 +++++++++++++++++++++++++++++++\n remote.c                        |   28 +++-------------------------\n sha1_name.c                     |   14 ++------------\n t/t5510-fetch.sh                |   25 +++++++++++++++++++++++++\n t/t5516-fetch-push.sh           |   29 ++++++++++++++++++++++++++++-\n transport.c                     |    8 ++++++--\n transport.h                     |    1 +\n 11 files changed, 116 insertions(+), 43 deletions(-)\n\n [PATCH 1/6] push: mention --verbose option in documentation\n    Push uses parseopts, which supports '--verbose'.\n\n [PATCH 2/6] push: teach push to pass --verbose option to transport layer\n    Adapted to paresopts changes.\n\n [PATCH 3/6] push: support pushing HEAD to real branch name\n    Same as before.\n\n [PATCH 4/6] add ref_abbrev_matches_full_with_rules()\n [PATCH 5/6] push: use same rules as git-rev-parse to resolve refspecs\n [PATCH 6/6] refactor fetch's ref matching to use ref_abbrev_matches_full_with_rules()\n    Start unification of refspec matching rules.\n"},{"id":"59326","messageId":"11947897083381-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"1194789708646-git-send-email-prohaska@zib.de","subject":"[PATCH 1/6] push: mention --verbose option in documentation","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:43Z","receivedAt":"2007-11-11T14:01:43Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"From: Steffen Prohaska <gitster@pobox.com>\n\nBefore this commit, only '-v' was documented.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n Documentation/git-push.txt |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-push.txt b/Documentation/git-push.txt\nindex e5dd4c1..4a68aab 100644\n--- a/Documentation/git-push.txt\n+++ b/Documentation/git-push.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n --------\n [verse]\n 'git-push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]\n-           [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]\n+           [--repo=all] [-f | --force] [-v | --verbose] [<repository> <refspec>...]\n \n DESCRIPTION\n -----------\n@@ -95,7 +95,7 @@ the remote repository.\n \ttransfer spends extra cycles to minimize the number of\n \tobjects to be sent and meant to be used on slower connection.\n \n--v::\n+-v, \\--verbose::\n \tRun verbosely.\n \n include::urls-remotes.txt[]\n-- \n1.5.3.5.578.g886d\n"},{"id":"59320","messageId":"11947897081278-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"11947897083381-git-send-email-prohaska@zib.de","subject":"[PATCH 2/6] push: teach push to pass --verbose option to transport layer","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:44Z","receivedAt":"2007-11-11T14:01:44Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"From: Steffen Prohaska <gitster@pobox.com>\n\nA --verbose option to push should also be passed to the\ntransport layer, i.e. git-send-pack, git-http-push.\n\ngit push is modified to do so.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-push.c |    2 ++\n transport.c    |    8 ++++++--\n transport.h    |    1 +\n 3 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 2c56195..6d1da07 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -115,6 +115,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)\n \t\tflags |= TRANSPORT_PUSH_FORCE;\n \tif (dry_run)\n \t\tflags |= TRANSPORT_PUSH_DRY_RUN;\n+\tif (verbose)\n+\t\tflags |= TRANSPORT_PUSH_VERBOSE;\n \tif (tags)\n \t\tadd_refspec(\"refs/tags/*\");\n \tif (all)\ndiff --git a/transport.c b/transport.c\nindex fa5cfbb..e8a2608 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -386,7 +386,7 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \tint argc;\n \tint err;\n \n-\targv = xmalloc((refspec_nr + 11) * sizeof(char *));\n+\targv = xmalloc((refspec_nr + 12) * sizeof(char *));\n \targv[0] = \"http-push\";\n \targc = 1;\n \tif (flags & TRANSPORT_PUSH_ALL)\n@@ -395,6 +395,8 @@ static int curl_transport_push(struct transport *transport, int refspec_nr, cons\n \t\targv[argc++] = \"--force\";\n \tif (flags & TRANSPORT_PUSH_DRY_RUN)\n \t\targv[argc++] = \"--dry-run\";\n+\tif (flags & TRANSPORT_PUSH_VERBOSE)\n+\t\targv[argc++] = \"--verbose\";\n \targv[argc++] = transport->url;\n \twhile (refspec_nr--)\n \t\targv[argc++] = *refspec++;\n@@ -655,7 +657,7 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n \tint argc;\n \tint err;\n \n-\targv = xmalloc((refspec_nr + 11) * sizeof(char *));\n+\targv = xmalloc((refspec_nr + 12) * sizeof(char *));\n \targv[0] = \"send-pack\";\n \targc = 1;\n \tif (flags & TRANSPORT_PUSH_ALL)\n@@ -664,6 +666,8 @@ static int git_transport_push(struct transport *transport, int refspec_nr, const\n \t\targv[argc++] = \"--force\";\n \tif (flags & TRANSPORT_PUSH_DRY_RUN)\n \t\targv[argc++] = \"--dry-run\";\n+\tif (flags & TRANSPORT_PUSH_VERBOSE)\n+\t\targv[argc++] = \"--verbose\";\n \tif (data->receivepack) {\n \t\tchar *rp = xmalloc(strlen(data->receivepack) + 16);\n \t\tsprintf(rp, \"--receive-pack=%s\", data->receivepack);\ndiff --git a/transport.h b/transport.h\nindex df12ea7..2f80ab4 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -30,6 +30,7 @@ struct transport {\n #define TRANSPORT_PUSH_ALL 1\n #define TRANSPORT_PUSH_FORCE 2\n #define TRANSPORT_PUSH_DRY_RUN 4\n+#define TRANSPORT_PUSH_VERBOSE 8\n \n /* Returns a transport suitable for the url */\n struct transport *transport_get(struct remote *, const char *);\n-- \n1.5.3.5.578.g886d\n"},{"id":"59323","messageId":"11947897083159-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"11947897081278-git-send-email-prohaska@zib.de","subject":"[PATCH 3/6] push: support pushing HEAD to real branch name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:45Z","receivedAt":"2007-11-11T14:01:45Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"From: Steffen Prohaska <gitster@pobox.com>\n\nThis teaches \"push <remote> HEAD\" to resolve HEAD on the local\nside to its real branch name, e.g. master, and then act as if\nthe real branch name was specified. So we have a shorthand for\npushing the current branch. Besides HEAD, no other symbolic ref\nis resolved.\n\nThanks to Daniel Barkalow <barkalow@iabervon.org> for suggesting\nthis implementation, which is much simpler than the\nimplementation proposed before.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin-push.c        |    9 +++++++++\n t/t5516-fetch-push.sh |   17 +++++++++++++++++\n 2 files changed, 26 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 6d1da07..a99ba0c 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -44,6 +44,15 @@ static void set_refspecs(const char **refs, int nr)\n \t\t\tstrcat(tag, refs[i]);\n \t\t\tref = tag;\n \t\t}\n+\t\tif (!strcmp(\"HEAD\", ref)) {\n+\t\t\tunsigned char sha1_dummy[20];\n+\t\t\tref = resolve_ref(ref, sha1_dummy, 1, NULL);\n+\t\t\tif (!ref)\n+\t\t\t\tdie(\"HEAD cannot be resolved.\");\n+\t\t\tif (strncmp(ref, \"refs/heads/\", 11))\n+\t\t\t\tdie(\"HEAD cannot be resolved to branch.\");\n+\t\t\tref = xstrdup(ref + 11);\n+\t\t}\n \t\tadd_refspec(ref);\n \t}\n }\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 86f9b53..b0ff488 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -244,6 +244,23 @@ test_expect_success 'push with colon-less refspec (4)' '\n \n '\n \n+test_expect_success 'push with HEAD' '\n+\n+\tmk_test heads/master &&\n+\tgit checkout master &&\n+\tgit push testrepo HEAD &&\n+\tcheck_push_result $the_commit heads/master\n+\n+'\n+\n+test_expect_success 'push with HEAD nonexisting at remote' '\n+\n+\tmk_test heads/master &&\n+\tgit checkout -b local master &&\n+\tgit push testrepo HEAD &&\n+\tcheck_push_result $the_commit heads/local\n+'\n+\n test_expect_success 'push with dry-run' '\n \n \tmk_test heads/master &&\n-- \n1.5.3.5.578.g886d\n"},{"id":"59319","messageId":"11947897083265-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"11947897083159-git-send-email-prohaska@zib.de","subject":"[PATCH 4/6] add ref_abbrev_matches_full_with_rules()","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:46Z","receivedAt":"2007-11-11T14:01:46Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"We use at least two rulesets for matching abbreviated refnames with\nfull refnames (starting with 'refs/').  git-rev-parse and git-fetch\nuse slightly different rules.\n\nThis commit introduces a new function\nref_abbrev_matches_full_with_rules(\n    const char *abbrev_name, const char *full_name, const char **rules).\nabbrev_name is expanded using the rules and matched against full_name.\nIf a match is found the function returns true.  rules is a NULL-terminate\nlist of format patterns with \"%.*s\", for example\n\n    const char *ref_rev_parse_rules[] = {\n               \"%.*s\",\n               \"refs/%.*s\",\n               \"refs/tags/%.*s\",\n               \"refs/heads/%.*s\",\n               \"refs/remotes/%.*s\",\n               \"refs/remotes/%.*s/HEAD\",\n               NULL\n    };\n\nAsterisks are included in the format strings because this is the form\nrequired in sha1_name.c.  Sharing the list with the functions there is\na good idea to avoid duplicating the rules.  Hopefully this\nfacilitates unified matching rules in the future.\n\nThis commit makes the rules used by rev-parse for resolving refs to\nsha1s available for string comparison.  Before this change, the rules\nwere buried in get_sha1*() and dwim_ref().\n\nA follow-up commit will refactor the rules used by fetch.\n\nref_abbrev_matches_full_with_rules() will be used for matching\nrefspecs in git-send-pack.\n\nThanks to Daniel Barkalow <barkalow@iabervon.org> for pointing\nout that ref_matches_abbrev in remote.c solves a similar problem\nand care should be taken to avoid confusion.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n cache.h     |    3 +++\n refs.c      |   24 ++++++++++++++++++++++++\n sha1_name.c |   14 ++------------\n 3 files changed, 29 insertions(+), 12 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex f0a25c7..d36b91d 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -409,6 +409,9 @@ 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 \n+extern int ref_abbrev_matches_full_with_rules(const char *abbrev_name, const char *full_name, const char **rules);\n+extern const char *ref_rev_parse_rules[];\n+\n extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg);\n extern int validate_headref(const char *ref);\n \ndiff --git a/refs.c b/refs.c\nindex aff02cd..4bb16e5 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -655,6 +655,30 @@ int check_ref_format(const char *ref)\n \t}\n }\n \n+const char *ref_rev_parse_rules[] = {\n+\t\"%.*s\",\n+\t\"refs/%.*s\",\n+\t\"refs/tags/%.*s\",\n+\t\"refs/heads/%.*s\",\n+\t\"refs/remotes/%.*s\",\n+\t\"refs/remotes/%.*s/HEAD\",\n+\tNULL\n+};\n+\n+int ref_abbrev_matches_full_with_rules(const char *abbrev_name, const char *full_name, const char **rules)\n+{\n+\tconst char **p;\n+\tconst int abbrev_name_len = strlen(abbrev_name);\n+\n+\tfor (p = rules; *p; p++) {\n+\t\tif (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {\n+\t\t\treturn 1;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n static struct ref_lock *verify_lock(struct ref_lock *lock,\n \tconst unsigned char *old_sha1, int mustexist)\n {\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 2d727d5..d364244 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -239,23 +239,13 @@ static int ambiguous_path(const char *path, int len)\n \treturn slash;\n }\n \n-static const char *ref_fmt[] = {\n-\t\"%.*s\",\n-\t\"refs/%.*s\",\n-\t\"refs/tags/%.*s\",\n-\t\"refs/heads/%.*s\",\n-\t\"refs/remotes/%.*s\",\n-\t\"refs/remotes/%.*s/HEAD\",\n-\tNULL\n-};\n-\n int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)\n {\n \tconst char **p, *r;\n \tint refs_found = 0;\n \n \t*ref = NULL;\n-\tfor (p = ref_fmt; *p; p++) {\n+\tfor (p = ref_rev_parse_rules; *p; p++) {\n \t\tunsigned char sha1_from_ref[20];\n \t\tunsigned char *this_result;\n \n@@ -277,7 +267,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)\n \tint logs_found = 0;\n \n \t*log = NULL;\n-\tfor (p = ref_fmt; *p; p++) {\n+\tfor (p = ref_rev_parse_rules; *p; p++) {\n \t\tstruct stat st;\n \t\tunsigned char hash[20];\n \t\tchar path[PATH_MAX];\n-- \n1.5.3.5.578.g886d\n"},{"id":"59324","messageId":"1194789709671-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"11947897083265-git-send-email-prohaska@zib.de","subject":"[PATCH 5/6] push: use same rules as git-rev-parse to resolve refspecs","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:47Z","receivedAt":"2007-11-11T14:01:47Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"This commit changes the rules for resolving refspecs to match the\nrules for resolving refs in rev-parse. git-rev-parse uses clear rules\nto resolve a short ref to its full name, which are well documented.\nThe rules for resolving refspecs documented in git-send-pack were\nless strict and harder to understand. This commit replaces them by\nthe rules of git-rev-parse.\n\nThe unified rules are easier to understand and better resolve ambiguous\ncases. You can now push from a repository containing several branches\nending on the same short name.\n\nNote, this may break existing setups. For example \"master\" will no longer\nresolve to \"origin/master\".\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n Documentation/git-send-pack.txt |    4 +++-\n remote.c                        |    5 +----\n t/t5516-fetch-push.sh           |   12 +++++++++++-\n 3 files changed, 15 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt\nindex 2fa01d4..a2d9cb6 100644\n--- a/Documentation/git-send-pack.txt\n+++ b/Documentation/git-send-pack.txt\n@@ -85,7 +85,9 @@ Each pattern pair consists of the source side (before the colon)\n and the destination side (after the colon).  The ref to be\n pushed is determined by finding a match that matches the source\n side, and where it is pushed is determined by using the\n-destination side.\n+destination side. The rules used to match a ref are the same\n+rules used by gitlink:git-rev-parse[1] to resolve a symbolic ref\n+name.\n \n  - It is an error if <src> does not match exactly one of the\n    local refs.\ndiff --git a/remote.c b/remote.c\nindex bec2ba1..28d8eb7 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -519,10 +519,7 @@ static int count_refspec_match(const char *pattern,\n \t\tchar *name = refs->name;\n \t\tint namelen = strlen(name);\n \n-\t\tif (namelen < patlen ||\n-\t\t    memcmp(name + namelen - patlen, pattern, patlen))\n-\t\t\tcontinue;\n-\t\tif (namelen != patlen && name[namelen - patlen - 1] != '/')\n+\t\tif (!ref_abbrev_matches_full_with_rules(pattern, name, ref_rev_parse_rules))\n \t\t\tcontinue;\n \n \t\t/* A match is \"weak\" if it is with refs outside\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex b0ff488..fd5f284 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -145,11 +145,21 @@ test_expect_success 'push with no ambiguity (1)' '\n test_expect_success 'push with no ambiguity (2)' '\n \n \tmk_test remotes/origin/master &&\n-\tgit push testrepo master:master &&\n+\tgit push testrepo master:origin/master &&\n \tcheck_push_result $the_commit remotes/origin/master\n \n '\n \n+test_expect_success 'push with colon-less refspec, no ambiguity' '\n+\n+\tmk_test heads/master heads/t/master &&\n+\tgit branch -f t/master master &&\n+\tgit push testrepo master &&\n+\tcheck_push_result $the_commit heads/master &&\n+\tcheck_push_result $the_first_commit heads/t/master\n+\n+'\n+\n test_expect_success 'push with weak ambiguity (1)' '\n \n \tmk_test heads/master remotes/origin/master &&\n-- \n1.5.3.5.578.g886d\n"},{"id":"59321","messageId":"11947897092576-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"1194789709671-git-send-email-prohaska@zib.de","subject":"[PATCH 6/6] refactor fetch's ref matching to use ref_abbrev_matches_full_with_rules()","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:01:48Z","receivedAt":"2007-11-11T14:01:48Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"The old rules used by fetch were coded as a series of ifs.  The old\nrules are:\n1) match full refname if it starts with \"refs/\" or matches \"HEAD\"\n2) verify that full refname starts with \"refs/\"\n3) match abbreviated name in \"refs/\" if it starts with \"heads/\",\n    \"tags/\", or \"remotes/\".\n4) match abbreviated name in \"refs/heads/\"\n\nThis is replaced by the new rules\na) match full refname\nb) match abbreviated name prefixed with \"refs/\"\nc) match abbreviated name prefixed with \"refs/heads/\"\n\nThe details of the new rules are different from the old rules.  We no\nlonger verify that the full refname starts with \"refs/\".  The new rule\n(a) matches any full string.  The old rules (1) and (2) were stricter.\nNow, the caller is responsible for using sensible full refnames.  This\nshould be the case for the current code.  The new rule (b) is less\nstrict than old rule (3).  The new rule accepts abbreviated names that\nstart with a non-standard prefix below \"refs/\".\n\nDespite this modifications the new rules should handle all cases as\nexpected.  Two tests are added to verify that fetch does not resolve\nshort tags or HEAD in remotes.\n\nWe may even think about loosening the rules a bit more and unify them\nwith the rev-parse rules.  This would be done by replacing\nref_ref_fetch_rules with ref_ref_parse_rules.  Note, the two new test\nwould break.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n cache.h          |    1 +\n refs.c           |    7 +++++++\n remote.c         |   23 ++---------------------\n t/t5510-fetch.sh |   25 +++++++++++++++++++++++++\n 4 files changed, 35 insertions(+), 21 deletions(-)\n\ndiff --git a/cache.h b/cache.h\nindex d36b91d..1313378 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -411,6 +411,7 @@ extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);\n \n extern int ref_abbrev_matches_full_with_rules(const char *abbrev_name, const char *full_name, const char **rules);\n extern const char *ref_rev_parse_rules[];\n+extern const char *ref_fetch_rules[];\n \n extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg);\n extern int validate_headref(const char *ref);\ndiff --git a/refs.c b/refs.c\nindex 4bb16e5..7db2146 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -665,6 +665,13 @@ const char *ref_rev_parse_rules[] = {\n \tNULL\n };\n \n+const char *ref_fetch_rules[] = {\n+\t\"%.*s\",\n+\t\"refs/%.*s\",\n+\t\"refs/heads/%.*s\",\n+\tNULL\n+};\n+\n int ref_abbrev_matches_full_with_rules(const char *abbrev_name, const char *full_name, const char **rules)\n {\n \tconst char **p;\ndiff --git a/remote.c b/remote.c\nindex 28d8eb7..2dfce70 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -417,25 +417,6 @@ int remote_has_url(struct remote *remote, const char *url)\n \treturn 0;\n }\n \n-/*\n- * Returns true if, under the matching rules for fetching, name is the\n- * same as the given full name.\n- */\n-static int ref_matches_abbrev(const char *name, const char *full)\n-{\n-\tif (!prefixcmp(name, \"refs/\") || !strcmp(name, \"HEAD\"))\n-\t\treturn !strcmp(name, full);\n-\tif (prefixcmp(full, \"refs/\"))\n-\t\treturn 0;\n-\tif (!prefixcmp(name, \"heads/\") ||\n-\t    !prefixcmp(name, \"tags/\") ||\n-\t    !prefixcmp(name, \"remotes/\"))\n-\t\treturn !strcmp(name, full + 5);\n-\tif (prefixcmp(full + 5, \"heads/\"))\n-\t\treturn 0;\n-\treturn !strcmp(full + 11, name);\n-}\n-\n int remote_find_tracking(struct remote *remote, struct refspec *refspec)\n {\n \tint find_src = refspec->src == NULL;\n@@ -804,7 +785,7 @@ int branch_merge_matches(struct branch *branch,\n {\n \tif (!branch || i < 0 || i >= branch->merge_nr)\n \t\treturn 0;\n-\treturn ref_matches_abbrev(branch->merge[i]->src, refname);\n+\treturn ref_abbrev_matches_full_with_rules(branch->merge[i]->src, refname, ref_fetch_rules);\n }\n \n static struct ref *get_expanded_map(struct ref *remote_refs,\n@@ -843,7 +824,7 @@ static struct ref *find_ref_by_name_abbrev(struct ref *refs, const char *name)\n {\n \tstruct ref *ref;\n \tfor (ref = refs; ref; ref = ref->next) {\n-\t\tif (ref_matches_abbrev(name, ref->name))\n+\t\tif (ref_abbrev_matches_full_with_rules(name, ref->name, ref_fetch_rules))\n \t\t\treturn ref;\n \t}\n \treturn NULL;\ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex aad863d..2025742 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -95,6 +95,31 @@ test_expect_success 'fetch following tags' '\n \n '\n \n+test_expect_failure 'fetch must not resolve short tag name' '\n+\n+\tcd \"$D\" &&\n+\n+\tmkdir five &&\n+\tcd five &&\n+\tgit init &&\n+\n+\tgit fetch .. anno:five\n+\n+'\n+\n+test_expect_failure 'fetch must not resolve short remote name' '\n+\n+\tcd \"$D\" &&\n+\tgit-update-ref refs/remotes/six/HEAD HEAD\n+\n+\tmkdir six &&\n+\tcd six &&\n+\tgit init &&\n+\n+\tgit fetch .. six:six\n+\n+'\n+\n test_expect_success 'create bundle 1' '\n \tcd \"$D\" &&\n \techo >file updated again by origin &&\n-- \n1.5.3.5.578.g886d\n"},{"id":"59327","messageId":"51B9B630-85F7-42BA-BCFF-4374A2527733@zib.de","threadId":"10807","inReplyTo":"11947897083381-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 1/6] push: mention --verbose option in documentation","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:10:48Z","receivedAt":"2007-11-11T14:10:48Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Nov 11, 2007, at 3:01 PM, Steffen Prohaska wrote:\n\n> From: Steffen Prohaska <gitster@pobox.com>\n\nThis is obviously wrong. I have no clear idea how this happend.\nI remember I took the topic branch sp/push-refspec from pu and\nstarted to refactor. I used 'rebase' and 'rebase -i' a couple\nof times and now I have my name with Junios email address.\n\nI'll investigate how this could happen.\n\n\tSteffen\n"},{"id":"59328","messageId":"FAB11CE3-B834-45A9-9D29-A37C302A9E1D@zib.de","threadId":"10807","inReplyTo":"51B9B630-85F7-42BA-BCFF-4374A2527733@zib.de","subject":"Re: [PATCH 1/6] push: mention --verbose option in documentation","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:14:42Z","receivedAt":"2007-11-11T14:14:42Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Nov 11, 2007, at 3:10 PM, Steffen Prohaska wrote:\n\n>\n> On Nov 11, 2007, at 3:01 PM, Steffen Prohaska wrote:\n>\n>> From: Steffen Prohaska <gitster@pobox.com>\n>\n> This is obviously wrong. I have no clear idea how this happend.\n> I remember I took the topic branch sp/push-refspec from pu and\n> started to refactor. I used 'rebase' and 'rebase -i' a couple\n> of times and now I have my name with Junios email address.\n>\n> I'll investigate how this could happen.\n\nThe Author line was already wrong in Junio's pu branch, commit\nf31447f5f06200305393ca16e2eb9485e65dcccc,  and I carried this\nover without noticing.\n\n\tSteffen\n"},{"id":"59329","messageId":"47370EDF.3090907@op5.se","threadId":"10807","inReplyTo":"11947897083159-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 3/6] push: support pushing HEAD to real branch name","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2007-11-11T14:17:03Z","receivedAt":"2007-11-11T14:17:03Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Steffen Prohaska wrote:\n> diff --git a/builtin-push.c b/builtin-push.c\n> index 6d1da07..a99ba0c 100644\n> --- a/builtin-push.c\n> +++ b/builtin-push.c\n> @@ -44,6 +44,15 @@ static void set_refspecs(const char **refs, int nr)\n>  \t\t\tstrcat(tag, refs[i]);\n>  \t\t\tref = tag;\n>  \t\t}\n> +\t\tif (!strcmp(\"HEAD\", ref)) {\n> +\t\t\tunsigned char sha1_dummy[20];\n> +\t\t\tref = resolve_ref(ref, sha1_dummy, 1, NULL);\n> +\t\t\tif (!ref)\n> +\t\t\t\tdie(\"HEAD cannot be resolved.\");\n> +\t\t\tif (strncmp(ref, \"refs/heads/\", 11))\n\nWhy not prefixcmp(ref, \"refs/heads/\")?\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"59331","messageId":"1194791707467-git-send-email-prohaska@zib.de","threadId":"10807","inReplyTo":"47370EDF.3090907@op5.se","subject":"[REPLACEMENT PATCH 3/6] push: support pushing HEAD to real branch name","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T14:35:07Z","receivedAt":"2007-11-11T14:35:07Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"This teaches \"push <remote> HEAD\" to resolve HEAD on the local\nside to its real branch name, e.g. master, and then act as if\nthe real branch name was specified. So we have a shorthand for\npushing the current branch. Besides HEAD, no other symbolic ref\nis resolved.\n\nThanks to Daniel Barkalow <barkalow@iabervon.org> for suggesting\nthis implementation, which is much simpler than the\nimplementation proposed before.\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n builtin-push.c        |    9 +++++++++\n t/t5516-fetch-push.sh |   17 +++++++++++++++++\n 2 files changed, 26 insertions(+), 0 deletions(-)\n\nprefixcmp() is simpler.\n\n    Steffen\n\ndiff --git a/builtin-push.c b/builtin-push.c\nindex 6d1da07..54fba0e 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -44,6 +44,15 @@ static void set_refspecs(const char **refs, int nr)\n \t\t\tstrcat(tag, refs[i]);\n \t\t\tref = tag;\n \t\t}\n+\t\tif (!strcmp(\"HEAD\", ref)) {\n+\t\t\tunsigned char sha1_dummy[20];\n+\t\t\tref = resolve_ref(ref, sha1_dummy, 1, NULL);\n+\t\t\tif (!ref)\n+\t\t\t\tdie(\"HEAD cannot be resolved.\");\n+\t\t\tif (prefixcmp(ref, \"refs/heads/\"))\n+\t\t\t\tdie(\"HEAD cannot be resolved to branch.\");\n+\t\t\tref = xstrdup(ref + 11);\n+\t\t}\n \t\tadd_refspec(ref);\n \t}\n }\ndiff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh\nindex 86f9b53..b0ff488 100755\n--- a/t/t5516-fetch-push.sh\n+++ b/t/t5516-fetch-push.sh\n@@ -244,6 +244,23 @@ test_expect_success 'push with colon-less refspec (4)' '\n \n '\n \n+test_expect_success 'push with HEAD' '\n+\n+\tmk_test heads/master &&\n+\tgit checkout master &&\n+\tgit push testrepo HEAD &&\n+\tcheck_push_result $the_commit heads/master\n+\n+'\n+\n+test_expect_success 'push with HEAD nonexisting at remote' '\n+\n+\tmk_test heads/master &&\n+\tgit checkout -b local master &&\n+\tgit push testrepo HEAD &&\n+\tcheck_push_result $the_commit heads/local\n+'\n+\n test_expect_success 'push with dry-run' '\n \n \tmk_test heads/master &&\n-- \n1.5.3.5.643.g20245\n"},{"id":"59332","messageId":"fh7548$15u$1@ger.gmane.org","threadId":"10807","inReplyTo":"11947897092576-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 6/6] refactor fetch's ref matching to use ref_abbrev_matches_full_with_rules()","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-11-11T14:55:05Z","receivedAt":"2007-11-11T14:55:05Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Steffen Prohaska wrote:\n\n> The old rules used by fetch were coded as a series of ifs.  The old\n> rules are:\n> 1) match full refname if it starts with \"refs/\" or matches \"HEAD\"\n> 2) verify that full refname starts with \"refs/\"\n> 3) match abbreviated name in \"refs/\" if it starts with \"heads/\",\n>     \"tags/\", or \"remotes/\".\n> 4) match abbreviated name in \"refs/heads/\"\n> \n> This is replaced by the new rules\n> a) match full refname\n> b) match abbreviated name prefixed with \"refs/\"\n> c) match abbreviated name prefixed with \"refs/heads/\"\n> \n> The details of the new rules are different from the old rules.  We no\n> longer verify that the full refname starts with \"refs/\".  The new rule\n> (a) matches any full string.  The old rules (1) and (2) were stricter.\n> Now, the caller is responsible for using sensible full refnames.  This\n> should be the case for the current code.  The new rule (b) is less\n> strict than old rule (3).  The new rule accepts abbreviated names that\n> start with a non-standard prefix below \"refs/\".\n> \n> Despite this modifications the new rules should handle all cases as\n> expected.  Two tests are added to verify that fetch does not resolve\n> short tags or HEAD in remotes.\n> \n> We may even think about loosening the rules a bit more and unify them\n> with the rev-parse rules.  This would be done by replacing\n> ref_ref_fetch_rules with ref_ref_parse_rules.  Note, the two new test\n> would break.\n\nDoes still \"origin\" matches \"origin/HEAD\" if we have emote \"origin\"?\n\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n"},{"id":"59341","messageId":"BC8C5856-E629-44F2-8B77-510E2B5C3194@zib.de","threadId":"10807","inReplyTo":"fh7548$15u$1@ger.gmane.org","subject":"Re: [PATCH 6/6] refactor fetch's ref matching to use ref_abbrev_matches_full_with_rules()","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-11T17:31:32Z","receivedAt":"2007-11-11T17:31:32Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Nov 11, 2007, at 3:55 PM, Jakub Narebski wrote:\n\n> Steffen Prohaska wrote:\n>\n>> The old rules used by fetch were coded as a series of ifs.  The old\n>> rules are:\n>> 1) match full refname if it starts with \"refs/\" or matches \"HEAD\"\n>> 2) verify that full refname starts with \"refs/\"\n>> 3) match abbreviated name in \"refs/\" if it starts with \"heads/\",\n>>     \"tags/\", or \"remotes/\".\n>> 4) match abbreviated name in \"refs/heads/\"\n>>\n>> This is replaced by the new rules\n>> a) match full refname\n>> b) match abbreviated name prefixed with \"refs/\"\n>> c) match abbreviated name prefixed with \"refs/heads/\"\n>>\n>> The details of the new rules are different from the old rules.  We no\n>> longer verify that the full refname starts with \"refs/\".  The new  \n>> rule\n>> (a) matches any full string.  The old rules (1) and (2) were  \n>> stricter.\n>> Now, the caller is responsible for using sensible full refnames.   \n>> This\n>> should be the case for the current code.  The new rule (b) is less\n>> strict than old rule (3).  The new rule accepts abbreviated names  \n>> that\n>> start with a non-standard prefix below \"refs/\".\n>>\n>> Despite this modifications the new rules should handle all cases as\n>> expected.  Two tests are added to verify that fetch does not resolve\n>> short tags or HEAD in remotes.\n>>\n>> We may even think about loosening the rules a bit more and unify them\n>> with the rev-parse rules.  This would be done by replacing\n>> ref_ref_fetch_rules with ref_ref_parse_rules.  Note, the two new test\n>> would break.\n>\n> Does still \"origin\" matches \"origin/HEAD\" if we have emote \"origin\"?\n\nNo, and it did not before. fetch does _not_ match origin as\nrefs/remotes/origin/HEAD. I added a test to confirm the old\nbehaviour. Only the git-rev-parse rules match origin as\nrefs/remotes/origin/HEAD.\n\n\tSteffen\n"},{"id":"59361","messageId":"7v8x54efml.fsf@gitster.siamese.dyndns.org","threadId":"10807","inReplyTo":"FAB11CE3-B834-45A9-9D29-A37C302A9E1D@zib.de","subject":"Re: [PATCH 1/6] push: mention --verbose option in documentation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-11T19:39:14Z","receivedAt":"2007-11-11T19:39:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> The Author line was already wrong in Junio's pu branch, commit\n> f31447f5f06200305393ca16e2eb9485e65dcccc,  and I carried this\n> over without noticing.\n\nYes, I know I pushed out a faulty one on 'pu' in the past.  I am\nsuspecting that it probably was a misuse of \"git commit --author\"\nafter _not_ applying a WS mangled patch and instead of typing,\nor something like that.\n"},{"id":"59556","messageId":"7v1wav44z8.fsf@gitster.siamese.dyndns.org","threadId":"10807","inReplyTo":"1194789709671-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 5/6] push: use same rules as git-rev-parse to resolve refspecs","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-12T19:51:39Z","receivedAt":"2007-11-12T19:51:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> diff --git a/remote.c b/remote.c\n> index bec2ba1..28d8eb7 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -519,10 +519,7 @@ static int count_refspec_match(const char *pattern,\n>  \t\tchar *name = refs->name;\n>  \t\tint namelen = strlen(name);\n>  \n> -\t\tif (namelen < patlen ||\n> -\t\t    memcmp(name + namelen - patlen, pattern, patlen))\n> -\t\t\tcontinue;\n> -\t\tif (namelen != patlen && name[namelen - patlen - 1] != '/')\n> +\t\tif (!ref_abbrev_matches_full_with_rules(pattern, name, ref_rev_parse_rules))\n>  \t\t\tcontinue;\n\nI vaguely recall that in the old round this check used to be\nwithout negation '!' in the front.  I think this version is\ncorrect.\n"},{"id":"59558","messageId":"7vve872qen.fsf@gitster.siamese.dyndns.org","threadId":"10807","inReplyTo":"11947897083265-git-send-email-prohaska@zib.de","subject":"Re: [PATCH 4/6] add ref_abbrev_matches_full_with_rules()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-12T19:51:44Z","receivedAt":"2007-11-12T19:51:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> +int ref_abbrev_matches_full_with_rules(const char *abbrev_name, const char *full_name, const char **rules)\n> +{\n> +\tconst char **p;\n> +\tconst int abbrev_name_len = strlen(abbrev_name);\n> +\n> +\tfor (p = rules; *p; p++) {\n> +\t\tif (!strcmp(full_name, mkpath(*p, abbrev_name_len, abbrev_name))) {\n> +\t\t\treturn 1;\n> +\t\t}\n> +\t}\n> +\n> +\treturn 0;\n> +}\n> +\n\nHow about calling this simply \"ref_abbrev_matches()\" or\n\"refname_match()\" which is even shorter?\n"},{"id":"59568","messageId":"DEDBC16B-0BDD-4671-8446-EFD0B32969BF@zib.de","threadId":"10807","inReplyTo":"7v1wav44z8.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/6] push: use same rules as git-rev-parse to resolve refspecs","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-12T20:48:49Z","receivedAt":"2007-11-12T20:48:49Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Nov 12, 2007, at 8:51 PM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> diff --git a/remote.c b/remote.c\n>> index bec2ba1..28d8eb7 100644\n>> --- a/remote.c\n>> +++ b/remote.c\n>> @@ -519,10 +519,7 @@ static int count_refspec_match(const char  \n>> *pattern,\n>>  \t\tchar *name = refs->name;\n>>  \t\tint namelen = strlen(name);\n>>\n>> -\t\tif (namelen < patlen ||\n>> -\t\t    memcmp(name + namelen - patlen, pattern, patlen))\n>> -\t\t\tcontinue;\n>> -\t\tif (namelen != patlen && name[namelen - patlen - 1] != '/')\n>> +\t\tif (!ref_abbrev_matches_full_with_rules(pattern, name,  \n>> ref_rev_parse_rules))\n>>  \t\t\tcontinue;\n>\n> I vaguely recall that in the old round this check used to be\n> without negation '!' in the front.  I think this version is\n> correct.\n\nYes. I started with a syntax inspired by strcmp. But later\nthe function got match in its name. I think returning a\nmatch with 'true' is more natural; and reserving '-1, 0, 1'\nfor compare (as in strcmp). Therefore I changed the return\nvalue.\n\nWith '!' is correct now. Without '!' was correct before.\n\n\tSteffen\n"},{"id":"59570","messageId":"03A9B0D0-5B70-47BB-B528-B86CE3FAAD8C@zib.de","threadId":"10807","inReplyTo":"7vve872qen.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 4/6] add ref_abbrev_matches_full_with_rules()","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2007-11-12T20:51:16Z","receivedAt":"2007-11-12T20:51:16Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Nov 12, 2007, at 8:51 PM, Junio C Hamano wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n>\n>> +int ref_abbrev_matches_full_with_rules(const char *abbrev_name,  \n>> const char *full_name, const char **rules)\n>> +{\n>> +\tconst char **p;\n>> +\tconst int abbrev_name_len = strlen(abbrev_name);\n>> +\n>> +\tfor (p = rules; *p; p++) {\n>> +\t\tif (!strcmp(full_name, mkpath(*p, abbrev_name_len,  \n>> abbrev_name))) {\n>> +\t\t\treturn 1;\n>> +\t\t}\n>> +\t}\n>> +\n>> +\treturn 0;\n>> +}\n>> +\n>\n> How about calling this simply \"ref_abbrev_matches()\" or\n> \"refname_match()\" which is even shorter?\n\nYes. As you already did on pu. Thanks for cleaning up.\n\n\tSteffen\n"}]}