[PATCH v3 08/21] Add cgit_namespaced_dwim_ref for resolving short refs

Richard Maw richard.maw at gmail.com
Mon Aug 1 23:35:40 CEST 2016


CGit generates links to branches in a natural form,
with the refs/heads stripped off
provided it is unambigously identifiable.

Since humans are likely to change the URLs to point to branches
by their short name anyway, we need to support this.

It is not yet fesible to add namespaced ref resolving to libgit,
so this implements a subset of the ref parsing logic,
which we'll need to parse branches in links.

Signed-off-by: Richard Maw <richard.maw at gmail.com>
---
 cgit.h   |  2 ++
 shared.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/cgit.h b/cgit.h
index 9129fd9..f4c444e 100644
--- a/cgit.h
+++ b/cgit.h
@@ -394,6 +394,8 @@ extern char *get_mimetype_for_filename(const char *filename);
 
 extern char *cgit_namespaced_resolve_ref(const char *name, int resolve_flags, unsigned char *sha1, int *flags);
 
+extern int cgit_namespaced_dwim_ref(const char *name, unsigned char *sha1, char **ref);
+
 extern int cgit_get_sha1(const char *name, unsigned char *sha1);
 
 #endif /* CGIT_H */
diff --git a/shared.c b/shared.c
index 789fb5e..77cb120 100644
--- a/shared.c
+++ b/shared.c
@@ -622,6 +622,51 @@ char *cgit_namespaced_resolve_ref(const char *refname, int resolve_flags, unsign
 	return ret;
 }
 
+int cgit_namespaced_dwim_ref(const char *name, unsigned char *sha1, char **ref)
+{
+	/* TODO: If libgit gets a version of dwim_ref that is namespace aware
+	         then rework this function to use it instead */
+	/* The standard git name disambiguation order is:
+	     $name
+	     refs/$name
+	     refs/tags/$name
+	     refs/heads/$name
+	     refs/remotes/$name
+	     refs/remotes/$name/HEAD
+	   we don't care about remotes, so we can skip those,
+	   and we can't specify a prefix for dwim_ref,
+	   so we have to use something that puts the namespace prefix on. */
+	static const char *namespaced_ref_patterns[] = {
+		"%s",
+		"refs/%s",
+		"refs/tags/%s",
+		"refs/heads/%s",
+		NULL,
+	};
+	int ret = 0;
+	struct strbuf fullref = STRBUF_INIT;
+
+	for (const char **p = namespaced_ref_patterns; *p; p++) {
+		char *r;
+		strbuf_reset(&fullref);
+		strbuf_addf(&fullref, *p, name);
+
+		r = cgit_namespaced_resolve_ref(fullref.buf, RESOLVE_REF_READING, sha1, NULL);
+		if (r) {
+			if (ref)
+				*ref = r;
+			else
+				free(r);
+
+			ret = 1;
+			break;
+		}
+	}
+
+	strbuf_release(&fullref);
+	return ret;
+}
+
 int cgit_get_sha1(const char *name, unsigned char *sha1)
 {
 	return get_sha1(name, sha1);
-- 
2.9.0



More information about the CGit mailing list