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 <[email protected]>
---
 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

_______________________________________________
CGit mailing list
[email protected]
http://lists.zx2c4.com/mailman/listinfo/cgit

Reply via email to