git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Luke Shumaker <lukeshu@lukeshu.com>
To: git@vger.kernel.org
Cc: "Elijah Newren" <newren@gmail.com>,
	"Junio C Hamano" <gitster@pobox.com>, "Jeff King" <peff@peff.net>,
	"brian m . carlson " <sandals@crustytoothpaste.net>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"Luke Shumaker" <lukeshu@datawire.io>
Subject: [PATCH 2/3] fast-export: fix bug with nested tags
Date: Wed, 21 Apr 2021 19:06:58 -0600	[thread overview]
Message-ID: <20210422010659.2498280-3-lukeshu@lukeshu.com> (raw)
In-Reply-To: <20210422010659.2498280-1-lukeshu@lukeshu.com>

From: Luke Shumaker <lukeshu@datawire.io>

The t9350-fast-export.sh 'handling nested tags' test takes an annotated
tag named 'muss' and creates a second annotated tag named 'nested' that
points to 'muss'.  As the test observes, fast-export indeed does spit out
a stream that creates a tag named 'nested' that points to another tag.

However, the test doesn't do a very thorough job of inspecting the
resulting tag.  It doesn't notice that the output 'nested' isn't quite the
same as the input 'nested'.

The 'nested' tags are different because the 'muss' tags that they point to
are different; fast-export accidentally creates the 'muss' tag object as
saying "tag nested" instead of "tag muss".

This is because of a quirk in how the fast-export walk sets the refname
for objects that aren't directly pointed to by an exported ref.  So, fix
the bug by getting the tagname from the tag object itself, rather than
from the refname.

Signed-off-by: Luke Shumaker <lukeshu@datawire.io>
---
 builtin/fast-export.c  | 28 +++++++++++++++++++++++++---
 t/t9350-fast-export.sh |  9 ++++++++-
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index e697f87172..2bf83fe52e 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -550,6 +550,21 @@ static const char *anonymize_refname(const char *refname)
 	return anon.buf;
 }
 
+static const char *anonymize_tagname(size_t tagname_len, const char *tagname)
+{
+	/*
+	 * Use anonymize_refname internally, so that the anonymization
+	 * is consistent between a tag's refname and its internal
+	 * tagname (if they were consistent to begin with, anyway).
+	 */
+	static struct strbuf as_refname = STRBUF_INIT;
+
+	strbuf_reset(&as_refname);
+	strbuf_addf(&as_refname, "refs/tags/%.*s", (int)tagname_len, tagname);
+
+	return anonymize_refname(as_refname.buf) + strlen("refs/tags/");
+}
+
 /*
  * We do not even bother to cache commit messages, as they are unlikely
  * to be repeated verbatim, and it is not that interesting when they are.
@@ -775,6 +790,7 @@ static void handle_tag(const char *refname, struct tag *tag)
 	const char *message;
 	size_t message_size = 0;
 	const char *tagname;
+	size_t tagname_len;
 	const char *tagger, *tagger_end;
 	struct object *tagged;
 	int tagged_mark;
@@ -804,6 +820,12 @@ static void handle_tag(const char *refname, struct tag *tag)
 		message_size = strlen(message);
 	}
 
+	tagname = memmem(buf, message ? message - buf : size, "\ntag ", 5);
+	if (!tagname)
+		die("malformed tag %s", oid_to_hex(&tag->object.oid));
+	tagname += 5;
+	tagname_len = (size_t)(strchrnul(tagname, '\n') - tagname);
+
 	tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
 	if (!tagger) {
 		if (fake_missing_tagger)
@@ -821,6 +843,8 @@ static void handle_tag(const char *refname, struct tag *tag)
 
 	if (anonymize) {
 		refname = anonymize_refname(refname);
+		tagname = anonymize_tagname(tagname_len, tagname);
+		tagname_len = strlen(tagname);
 		if (message) {
 			static struct hashmap tags;
 			message = anonymize_str(&tags, anonymize_tag,
@@ -890,9 +914,7 @@ static void handle_tag(const char *refname, struct tag *tag)
 		printf("reset %s\nfrom %s\n\n",
 		       refname, oid_to_hex(&null_oid));
 	}
-	tagname = refname;
-	skip_prefix(tagname, "refs/tags/", &tagname);
-	printf("tag %s\n", tagname);
+	printf("tag %.*s\n", (int)tagname_len, tagname);
 	if (mark_tags) {
 		mark_next_object(&tag->object);
 		printf("mark :%"PRIu32"\n", last_idnum);
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 409b48e244..0bcc1bd54e 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -572,10 +572,17 @@ test_expect_success 'handling tags of blobs' '
 
 test_expect_success 'handling nested tags' '
 	git tag -a -m "This is a nested tag" nested muss &&
+	NESTED=$(git rev-parse --verify nested) &&
 	git fast-export --mark-tags nested >output &&
 	grep "^from $ZERO_OID$" output &&
 	grep "^tag nested$" output >tag_lines &&
-	test_line_count = 2 tag_lines
+	test_line_count = 1 tag_lines &&
+	rm -rf new &&
+	mkdir new &&
+	git --git-dir=new/.git init &&
+	(cd new &&
+	 git fast-import &&
+	 test $NESTED = $(git rev-parse --verify refs/tags/nested)) <output
 '
 
 test_expect_success 'directory becomes symlink'        '
-- 
2.31.1


  parent reply	other threads:[~2021-04-22  1:07 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-22  1:06 [PATCH 0/3] fast-export, fast-import: let tags specify a different refname Luke Shumaker
2021-04-22  1:06 ` [PATCH 1/3] fast-export, fast-import: make stylistic changes Luke Shumaker
2021-04-22  1:06 ` Luke Shumaker [this message]
2021-04-22  1:06 ` [PATCH 3/3] fast-export, fast-import: let tags specify a different refname Luke Shumaker

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=20210422010659.2498280-3-lukeshu@lukeshu.com \
    --to=lukeshu@lukeshu.com \
    --cc=avarab@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=lukeshu@datawire.io \
    --cc=newren@gmail.com \
    --cc=peff@peff.net \
    --cc=sandals@crustytoothpaste.net \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).