All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benno Evers <benno@bmevers.de>
To: git@vger.kernel.org
Cc: spearce@spearce.org, Benno Evers <benno@bmevers.de>
Subject: [PATCH] describe: dont abort too early when searching tags
Date: Sun, 23 Feb 2020 13:51:02 +0100	[thread overview]
Message-ID: <20200223125102.6697-1-benno@bmevers.de> (raw)

When searching the commit graph for tag candidates, `git-describe`
will stop as soon as there is only one active branch left and
it already found an annotated tag as a candidate.

This works well as long as all branches eventually connect back
to a common root, but if the tags are found across branches
with no common ancestor

                  B
                  o----.
                        \
          o-----o---o----x
          A

it can happen that the search on one branch terminates prematurely
because a tag was found on another, independent branch. This scenario
isn't quite as obscure as it sounds, since cloning with a limited
depth often introduces many independent "dead ends" into the commit
graph.

The help text of `git-describe` states pretty clearly that when
describing a commit D, the number appended to the emitted tag X should
correspond to the number of commits found by `git log X..D`.

Thus, this commit modifies the stopping condition to only abort
the search when only one branch is left to search *and* all current
best candidates are descendants from that branch.

Signed-off-by: Benno Evers <benno@bmevers.de>
---
We originally found this issue in one of our internal CI jobs,
which relied on `git-describe` to assign filenames to the generated
artifacts.
---
 builtin/describe.c  | 22 +++++++++++++++----
 t/t6120-describe.sh | 53 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/builtin/describe.c b/builtin/describe.c
index b6df81d8d0..420f4c6401 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -376,11 +376,25 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
 			if (!(c->object.flags & t->flag_within))
 				t->depth++;
 		}
+		/* Stop if last remaining path already covered by best candidate(s) */
 		if (annotated_cnt && !list) {
-			if (debug)
-				fprintf(stderr, _("finished search at %s\n"),
-					oid_to_hex(&c->object.oid));
-			break;
+			int best_depth = INT_MAX;
+			unsigned best_within = 0;
+			for (cur_match = 0; cur_match < match_cnt; cur_match++) {
+				struct possible_tag *t = &all_matches[cur_match];
+				if (t->depth < best_depth) {
+					best_depth = t->depth;
+					best_within = t->flag_within;
+				} else if (t->depth == best_depth) {
+					best_within |= t->flag_within;
+				}
+			}
+			if ((c->object.flags & best_within) == best_within) {
+				if (debug)
+					fprintf(stderr, _("finished search at %s\n"),
+						oid_to_hex(&c->object.oid));
+				break;
+			}
 		}
 		while (parents) {
 			struct commit *p = parents->item;
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 09c50f3f04..d8cc08258e 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -479,4 +479,55 @@ test_expect_success 'name-rev covers all conditions while looking at parents' '
 	)
 '
 
-test_done
+#               B
+#               o
+#                \
+#  o-----o---o----x
+#        A
+#
+test_expect_success 'describe commits with disjoint bases' '
+	git init disjoint1 &&
+	(
+		cd disjoint1 &&
+
+		echo o >> file && git add file && git commit -m o &&
+		echo A >> file && git add file && git commit -m A &&
+		git tag A -a -m A &&
+		echo o >> file && git add file && git commit -m o &&
+
+		git checkout --orphan branch && rm file &&
+		echo B > file2 && git add file2 && git commit -m B &&
+		git tag B -a -m B &&
+		git merge --no-ff --allow-unrelated-histories master -m x &&
+
+		check_describe "A-3-*" HEAD
+	)
+'
+
+#           B
+#   o---o---o------------.
+#                         \
+#                  o---o---x
+#                  A
+#
+test_expect_success 'describe commits with disjoint bases 2' '
+	git init disjoint2 &&
+	(
+		cd disjoint2 &&
+
+		echo A >> file && git add file && GIT_COMMITTER_DATE="2020-01-01 18:00" git commit -m A &&
+		git tag A -a -m A &&
+		echo o >> file && git add file && GIT_COMMITTER_DATE="2020-01-01 18:01" git commit -m o &&
+
+		git checkout --orphan branch &&
+		echo o >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:00" git commit -m o &&
+		echo o >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:01" git commit -m o &&
+		echo B >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:02" git commit -m B &&
+		git tag B -a -m B &&
+		git merge --no-ff --allow-unrelated-histories master -m x &&
+
+		check_describe "B-3-*" HEAD
+	)
+'
+
+test_done
\ No newline at end of file
-- 
2.20.1


             reply	other threads:[~2020-02-23 12:58 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-23 12:51 Benno Evers [this message]
2020-02-24 20:52 ` [PATCH] describe: dont abort too early when searching tags Junio C Hamano
2020-02-25 19:07   ` benno
2020-02-25 20:10     ` Junio C Hamano
2021-02-28 19:54 ` [PATCH 00/10] describe tests: refactor & fix recent broken tests Ævar Arnfjörð Bjarmason
2021-03-09  0:47   ` Junio C Hamano
2021-03-12 23:59   ` Junio C Hamano
2021-04-12 11:21   ` [PATCH v2 0/5] describe test fixes Ævar Arnfjörð Bjarmason
2021-04-12 11:21     ` [PATCH v2 1/5] describe tests: improve test for --work-tree & --dirty Ævar Arnfjörð Bjarmason
2021-04-12 11:21     ` [PATCH v2 2/5] describe tests: refactor away from glob matching Ævar Arnfjörð Bjarmason
2021-04-12 11:21     ` [PATCH v2 3/5] describe tests: don't rely on err.actual from "check_describe" Ævar Arnfjörð Bjarmason
2021-04-12 11:21     ` [PATCH v2 4/5] describe tests: fix nested "test_expect_success" call Ævar Arnfjörð Bjarmason
2021-04-12 11:21     ` [PATCH v2 5/5] describe tests: support -C in "check_describe" Ævar Arnfjörð Bjarmason
2021-04-12 11:33   ` [PATCH v2 0/2] svn tests: trivial "set -e" in main body of test fixes Ævar Arnfjörð Bjarmason
2021-04-12 11:33     ` [PATCH v2 1/2] svn tests: remove legacy re-setup from init-clone test Ævar Arnfjörð Bjarmason
2021-04-12 11:33     ` [PATCH v2 2/2] svn tests: refactor away a "set -e" in test body Ævar Arnfjörð Bjarmason
2021-02-28 19:54 ` [PATCH 01/10] describe tests: improve test for --work-tree & --dirty Ævar Arnfjörð Bjarmason
2021-02-28 19:54 ` [PATCH 02/10] describe tests: refactor away from glob matching Ævar Arnfjörð Bjarmason
2021-03-01 21:26   ` Junio C Hamano
2021-02-28 19:54 ` [PATCH 03/10] describe tests: always assert empty stderr from "describe" Ævar Arnfjörð Bjarmason
2021-03-01 21:32   ` Junio C Hamano
2021-02-28 19:54 ` [PATCH 04/10] test-lib functions: add an --annotated-tag option to "test_commit" Ævar Arnfjörð Bjarmason
2021-03-01 21:41   ` Junio C Hamano
2021-03-02  9:34     ` Ævar Arnfjörð Bjarmason
2021-03-03  6:35       ` Junio C Hamano
2021-02-28 19:54 ` [PATCH 05/10] describe tests: convert setup to use test_commit Ævar Arnfjörð Bjarmason
2021-03-01 21:42   ` Junio C Hamano
2021-02-28 19:54 ` [PATCH 06/10] describe tests: fix nested "test_expect_success" call Ævar Arnfjörð Bjarmason
2021-02-28 19:54 ` [PATCH 07/10] describe tests: support -C in "check_describe" Ævar Arnfjörð Bjarmason
2021-02-28 19:54 ` [PATCH 08/10] svn tests: remove legacy re-setup from init-clone test Ævar Arnfjörð Bjarmason
2021-02-28 19:54 ` [PATCH 09/10] svn tests: refactor away a "set -e" in test body Ævar Arnfjörð Bjarmason
2021-02-28 21:14   ` Eric Wong
2021-02-28 19:54 ` [PATCH 10/10] test-lib: return 1 from test_expect_{success,failure} Ævar Arnfjörð Bjarmason
2021-03-01 21:43   ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200223125102.6697-1-benno@bmevers.de \
    --to=benno@bmevers.de \
    --cc=git@vger.kernel.org \
    --cc=spearce@spearce.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.