[PATCH] Handle tags outside of refs/tags gracefully.

John Keeping john at keeping.me.uk
Tue Jan 5 13:09:47 UTC 2021


On Tue, Jan 05, 2021 at 11:53:03AM +0000, Gianni Ceccarelli wrote:
> I have found an annoying case…
> 
> In the repository created as per my previous message, I did::
> 
>   $ git tag -a foo
>   $ git rev-parse refs/tags/foo > .git/refs/weird/annotated
>   $ git push origin refs/weird/*:refs/weird/*
> 
> This creates an "annotated tag", which is an object in the store, not
> just a reference.
> 
> Now CGit shows the ``refs/weird/annotated`` as a tag in
> https://www.thenautilus.net/cgit/example/ and several other views, but
> following that link goes to
> https://www.thenautilus.net/cgit/example/tag/?h=refs/weird/annotated
> which says "bad tag reference"
> 
> I hope you'll concur this is not the best behaviour.
> 
> I see several ways to "fix" this:
> 
> * in all the various views, don't show links to annotated tags whose
>   ref is outside of ``refs/tags/``
> * in ``/tag``, try ``refs/tags/$h`` first, and if that doesn't work,
>   try ``$h``, and show that only if it's an annotated tag (not just a
>   reference)
> * create another endpoint (``/atag``?) to show tag objects, and link
>   to that one for annotated tags whose ref is outside of
>   ``refs/tags/``

I think something like option 2 is the right answer here, since that
brings us closer to Git's behaviour.  Does the patch below help?

-- >8 --
Subject: [PATCH] ui-tag: accept tags not under refs/tags/

In log views, we decorate commits with tags under any ref hierarchy,
which generates links to ui-tag with, for example, refs/weird/tag.  By
forcing a refs/tags/ prefix onto this, a 404 not found error is
guaranteed.

Taking inspiration from Git's ref_rev_parse_rules, let's try to resolve
the given tag name raw and relative to refs/ before trying refs/tags/.

Reported-by: Gianni Ceccarelli <dakkar at thenautilus.net>
Signed-off-by: John Keeping <john at metanate.com>
---
 ui-tag.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/ui-tag.c b/ui-tag.c
index 846d5b1..c1f81d1 100644
--- a/ui-tag.c
+++ b/ui-tag.c
@@ -38,17 +38,32 @@ static void print_download_links(char *revname)
 	html("</td></tr>");
 }
 
+static const char *tag_patterns[] = {
+	"%s",
+	"refs/%s",
+	"refs/tags/%s",
+	NULL
+};
+
 void cgit_print_tag(char *revname)
 {
 	struct strbuf fullref = STRBUF_INIT;
 	struct object_id oid;
 	struct object *obj;
+	const char **pattern;
 
 	if (!revname)
 		revname = ctx.qry.head;
 
-	strbuf_addf(&fullref, "refs/tags/%s", revname);
-	if (get_oid(fullref.buf, &oid)) {
+	for (pattern = tag_patterns; *pattern; pattern++) {
+		strbuf_reset(&fullref);
+		strbuf_addf(&fullref, *pattern, revname);
+
+		if (!get_oid(fullref.buf, &oid))
+			break;
+	}
+
+	if (!*pattern) {
 		cgit_print_error_page(404, "Not found",
 			"Bad tag reference: %s", revname);
 		goto cleanup;
-- 
2.30.0



More information about the CGit mailing list