{"thread":{"id":"34481","subject":"[PATCH 2/2] describe: fix --contains when a tag is given as input","startedAt":"2013-07-18T22:16:06Z","lastAt":"2013-07-18T22:16:08Z","messageCount":3,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"223715","messageId":"1374185768-7537-1-git-send-email-gitster@pobox.com","threadId":"34481","inReplyTo":null,"subject":"[PATCH 0/2] Finishing touches to \"name-rev\" fix","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-07-18T22:16:06Z","receivedAt":"2013-07-18T22:16:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This is an update to finish the jc/name-rev-exact-ref topic, which\nfixed the command to convert an object name that points at a tag to\na refname of the tag (earlier, it did not show anything).  The\ncodepath to handle its command line arguments, however, fed the\ncommit that the tag points at to the underlying naming machinery.\n\nThe first patch in this follow-up series corrects it for the command\nline codepath.\n\nThe second patch is a related fix for \"git describe\".  The command\nis about naming the given commit in relation to a tag in its\nneighbourhood, and while it does allow the input to be a commit-ish\n(e.g. a tag that points at a commit), it did not unwrap it down to\ncommit, which is a bug (it is like \"git commit-tree -p $tag\" that\nwould mistakenly record a tag object as one of the parents of the\nresulting commit).\n\nJunio C Hamano (2):\n  name-rev: differentiate between tags and commits they point at\n  describe: fix --contains when a tag is given as input\n\n builtin/describe.c  |  3 ++-\n builtin/name-rev.c  | 41 ++++++++++++++++++++++++++++++++---------\n t/t6120-describe.sh | 24 ++++++++++++++++++++++++\n 3 files changed, 58 insertions(+), 10 deletions(-)\n\n-- \n1.8.3.3-992-gf0e5e44\n"},{"id":"223714","messageId":"1374185768-7537-2-git-send-email-gitster@pobox.com","threadId":"34481","inReplyTo":"1374185768-7537-1-git-send-email-gitster@pobox.com","subject":"[PATCH 1/2] name-rev: differentiate between tags and commits they point at","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-07-18T22:16:07Z","receivedAt":"2013-07-18T22:16:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git name-rev --stdin\" has been fixed to convert an object name that\npoints at a tag to a refname of the tag.  The codepath to handle its\ncommand line arguments, however, fed the commit that the tag points\nat to the underlying naming machinery.\n\nWith this fix, you will get this:\n\n    $ git name-rev --refs=tags/\\* --name-only $(git rev-parse v1.8.3 v1.8.3^0)\n    v1.8.3\n    v1.8.3^0\n\nwhich is the same as what you would get from the fixed \"--stdin\" variant:\n\n    $ git rev-parse v1.8.3 v1.8.3^0 | git name-rev --refs=tags/\\* --name-only\n    v1.8.3\n    v1.8.3^0\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/name-rev.c  | 24 ++++++++++++++++--------\n t/t6120-describe.sh | 12 ++++++++++++\n 2 files changed, 28 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex 29a6f56..4c7cc62 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -334,7 +334,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)\n \n \tfor (; argc; argc--, argv++) {\n \t\tunsigned char sha1[20];\n-\t\tstruct object *o;\n+\t\tstruct object *object;\n \t\tstruct commit *commit;\n \n \t\tif (get_sha1(*argv, sha1)) {\n@@ -343,17 +343,25 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)\n \t\t\tcontinue;\n \t\t}\n \n-\t\to = deref_tag(parse_object(sha1), *argv, 0);\n-\t\tif (!o || o->type != OBJ_COMMIT) {\n-\t\t\tfprintf(stderr, \"Could not get commit for %s. Skipping.\\n\",\n+\t\tcommit = NULL;\n+\t\tobject = parse_object(sha1);\n+\t\tif (object) {\n+\t\t\tstruct object *peeled = deref_tag(object, *argv, 0);\n+\t\t\tif (peeled && peeled->type == OBJ_COMMIT)\n+\t\t\t\tcommit = (struct commit *)peeled;\n+\t\t}\n+\n+\t\tif (!object) {\n+\t\t\tfprintf(stderr, \"Could not get object for %s. Skipping.\\n\",\n \t\t\t\t\t*argv);\n \t\t\tcontinue;\n \t\t}\n \n-\t\tcommit = (struct commit *)o;\n-\t\tif (cutoff > commit->date)\n-\t\t\tcutoff = commit->date;\n-\t\tadd_object_array((struct object *)commit, *argv, &revs);\n+\t\tif (commit) {\n+\t\t\tif (cutoff > commit->date)\n+\t\t\t\tcutoff = commit->date;\n+\t\t}\n+\t\tadd_object_array(object, *argv, &revs);\n \t}\n \n \tif (cutoff)\ndiff --git a/t/t6120-describe.sh b/t/t6120-describe.sh\nindex a25729f..1d20854 100755\n--- a/t/t6120-describe.sh\n+++ b/t/t6120-describe.sh\n@@ -174,4 +174,16 @@ check_describe \"test2-lightweight-*\" --tags --match=\"test2-*\"\n \n check_describe \"test2-lightweight-*\" --long --tags --match=\"test2-*\" HEAD^\n \n+test_expect_success 'name-rev with exact tags' '\n+\techo A >expect &&\n+\ttag_object=$(git rev-parse refs/tags/A) &&\n+\tgit name-rev --tags --name-only $tag_object >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo \"A^0\" >expect &&\n+\ttagged_commit=$(git rev-parse \"refs/tags/A^0\") &&\n+\tgit name-rev --tags --name-only $tagged_commit >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.8.3.3-992-gf0e5e44\n"},{"id":"223713","messageId":"1374185768-7537-3-git-send-email-gitster@pobox.com","threadId":"34481","inReplyTo":"1374185768-7537-1-git-send-email-gitster@pobox.com","subject":"[PATCH 2/2] describe: fix --contains when a tag is given as input","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-07-18T22:16:08Z","receivedAt":"2013-07-18T22:16:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"git describe\" takes a commit and gives it a name based on tags in\nits neighbourhood.  The command does take a commit-ish but when\ngiven a tag that points at a commit, it should dereference the tag\nbefore computing the name for the commit.\n\nAs the whole processing is internally delegated to name-rev, if we\nunwrap tags down to the underlying commit when invoking name-rev, it\nwill make the name-rev issue an error message based on the unwrapped\nobject name (i.e. either 40-hex object name, or \"$tag^0\") that is\ndifferent from what the end-user gave to the command when the commit\ncannot be described.  Introduce an internal option --peel-tag to the\nname-rev to tell it to unwrap a tag in its input from the command\nline.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/describe.c  |  3 ++-\n builtin/name-rev.c  | 17 ++++++++++++++++-\n t/t6120-describe.sh | 12 ++++++++++++\n 3 files changed, 30 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex db41cd7..7d73722 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -446,7 +446,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)\n \t\tstruct argv_array args;\n \n \t\targv_array_init(&args);\n-\t\targv_array_pushl(&args, \"name-rev\", \"--name-only\", \"--no-undefined\",\n+\t\targv_array_pushl(&args, \"name-rev\",\n+\t\t\t\t \"--peel-tag\", \"--name-only\", \"--no-undefined\",\n \t\t\t\t NULL);\n \t\tif (always)\n \t\t\targv_array_push(&args, \"--always\");\ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex 4c7cc62..0aaa19e 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -307,7 +307,7 @@ static void name_rev_line(char *p, struct name_ref_data *data)\n int cmd_name_rev(int argc, const char **argv, const char *prefix)\n {\n \tstruct object_array revs = OBJECT_ARRAY_INIT;\n-\tint all = 0, transform_stdin = 0, allow_undefined = 1, always = 0;\n+\tint all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;\n \tstruct name_ref_data data = { 0, 0, NULL };\n \tstruct option opts[] = {\n \t\tOPT_BOOLEAN(0, \"name-only\", &data.name_only, N_(\"print only names (no SHA-1)\")),\n@@ -320,6 +320,12 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)\n \t\tOPT_BOOLEAN(0, \"undefined\", &allow_undefined, N_(\"allow to print `undefined` names\")),\n \t\tOPT_BOOLEAN(0, \"always\",     &always,\n \t\t\t   N_(\"show abbreviated commit object as fallback\")),\n+\t\t{\n+\t\t\t/* A Hidden OPT_BOOL */\n+\t\t\tOPTION_SET_INT, 0, \"peel-tag\", &peel_tag, NULL,\n+\t\t\tN_(\"dereference tags in the input (internal use)\"),\n+\t\t\tPARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1,\n+\t\t},\n \t\tOPT_END(),\n \t};\n \n@@ -361,6 +367,15 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)\n \t\t\tif (cutoff > commit->date)\n \t\t\t\tcutoff = commit->date;\n \t\t}\n+\n+\t\tif (peel_tag) {\n+\t\t\tif (!commit) {\n+\t\t\t\tfprintf(stderr, \"Could not get commit for %s. Skipping.\\n\",\n+\t\t\t\t\t*argv);\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tobject = (struct object *)commit;\n+\t\t}\n \t\tadd_object_array(object, *argv, &revs);\n \t}\n \ndiff --git a/t/t6120-describe.sh b/t/t6120-describe.sh\nindex 1d20854..c0e5b2a 100755\n--- a/t/t6120-describe.sh\n+++ b/t/t6120-describe.sh\n@@ -186,4 +186,16 @@ test_expect_success 'name-rev with exact tags' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'describe --contains with the exact tags' '\n+\techo \"A^0\" >expect &&\n+\ttag_object=$(git rev-parse refs/tags/A) &&\n+\tgit describe --contains $tag_object >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo \"A^0\" >expect &&\n+\ttagged_commit=$(git rev-parse \"refs/tags/A^0\") &&\n+\tgit describe --contains $tagged_commit >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n1.8.3.3-992-gf0e5e44\n"}]}