about summary refs log tree commit
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2020-03-26 17:11:21 -0700
committerJunio C Hamano <gitster@pobox.com>2020-03-26 17:11:21 -0700
commit0f0625a630081d532d528d87ba236a6385bbbac1 (patch)
treee6c3e6c57219732b8165105970590a7d09cec91d
parentfb4175b0e4bec59b97dae84a0073d8a5334508d6 (diff)
parentff165f00c1065d94c0bcab8708364e6dc5655f5d (diff)
downloadgit-0f0625a630081d532d528d87ba236a6385bbbac1.tar.gz
When "git describe C" finds an annotated tag with tagname A to be
the best name to explain commit C, and the tag is stored in a
"wrong" place in the refs/tags hierarchy, e.g. refs/tags/B, the
command gave a warning message but used A (not B) to describe C.
If C is exactly at the tag, the describe output would be "A", but
"git rev-parse A^0" would not be equal as "git rev-parse C^0".  The
behavior of the command has been changed to use the "long" form
i.e. A-0-gOBJECTNAME, which is correctly interpreted by rev-parse.

* jc/describe-misnamed-annotated-tag:
  describe: force long format for a name based on a mislocated tag
-rw-r--r--builtin/describe.c15
-rwxr-xr-xt/t6120-describe.sh20
2 files changed, 28 insertions, 7 deletions
diff --git a/builtin/describe.c b/builtin/describe.c
index 420f4c6401..21d2cb9e57 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -54,6 +54,7 @@ struct commit_name {
         struct tag *tag;
         unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
         unsigned name_checked:1;
+        unsigned misnamed:1;
         struct object_id oid;
         char *path;
 };
@@ -132,6 +133,7 @@ static void add_to_known_names(const char *path,
                 e->tag = tag;
                 e->prio = prio;
                 e->name_checked = 0;
+                e->misnamed = 0;
                 oidcpy(&e->oid, oid);
                 free(e->path);
                 e->path = xstrdup(path);
@@ -275,10 +277,11 @@ static void append_name(struct commit_name *n, struct strbuf *dst)
                         die(_("annotated tag %s not available"), n->path);
         }
         if (n->tag && !n->name_checked) {
-                if (!n->tag->tag)
-                        die(_("annotated tag %s has no embedded name"), n->path);
-                if (strcmp(n->tag->tag, all ? n->path + 5 : n->path))
-                        warning(_("tag '%s' is really '%s' here"), n->tag->tag, n->path);
+                if (strcmp(n->tag->tag, all ? n->path + 5 : n->path)) {
+                        warning(_("tag '%s' is externally known as '%s'"),
+                                n->path, n->tag->tag);
+                        n->misnamed = 1;
+                }
                 n->name_checked = 1;
         }
 
@@ -314,7 +317,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
                  * Exact match to an existing ref.
                  */
                 append_name(n, dst);
-                if (longformat)
+                if (n->misnamed || longformat)
                         append_suffix(0, n->tag ? get_tagged_oid(n->tag) : oid, dst);
                 if (suffix)
                         strbuf_addstr(dst, suffix);
@@ -463,7 +466,7 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
         }
 
         append_name(all_matches[0].name, dst);
-        if (abbrev)
+        if (all_matches[0].name->misnamed || abbrev)
                 append_suffix(all_matches[0].depth, &cmit->object.oid, dst);
         if (suffix)
                 strbuf_addstr(dst, suffix);
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 34502e3a50..f822d5d328 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -129,12 +129,30 @@ test_expect_success 'rename tag A to Q locally' '
         mv .git/refs/tags/A .git/refs/tags/Q
 '
 cat - >err.expect <<EOF
-warning: tag 'A' is really 'Q' here
+warning: tag 'Q' is externally known as 'A'
 EOF
 check_describe A-* HEAD
 test_expect_success 'warning was displayed for Q' '
         test_i18ncmp err.expect err.actual
 '
+test_expect_success 'misnamed annotated tag forces long output' '
+        description=$(git describe --no-long Q^0) &&
+        expr "$description" : "A-0-g[0-9a-f]*$" &&
+        git rev-parse --verify "$description" >actual &&
+        git rev-parse --verify Q^0 >expect &&
+        test_cmp expect actual
+'
+
+test_expect_success 'abbrev=0 will not break misplaced tag (1)' '
+        description=$(git describe --abbrev=0 Q^0) &&
+        expr "$description" : "A-0-g[0-9a-f]*$"
+'
+
+test_expect_success 'abbrev=0 will not break misplaced tag (2)' '
+        description=$(git describe --abbrev=0 c^0) &&
+        expr "$description" : "A-1-g[0-9a-f]*$"
+'
+
 test_expect_success 'rename tag Q back to A' '
         mv .git/refs/tags/Q .git/refs/tags/A
 '