From 314d9ea5a3bc60ec518e314bb0bf8072123dc08f Mon Sep 17 00:00:00 2001
From: Natanael Copa
Date: Sat, 29 Nov 2008 21:49:07 -0800
Subject: Set prefix in snapshots when using dwimmery

This patch sets the directory prefix in archives to be the filename,
excluding the suffix (.tar.gz, .tar.bz2 etc).

The patch also removes the prefix parameter in cgit_print_snapshot()
as the prefix might differ.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 cmd.c         |  3 +--
 ui-snapshot.c | 14 ++++++++++++--
 ui-snapshot.h |  3 +--
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/cmd.c b/cmd.c
index 5b3c14c..8914fa5 100644
--- a/cmd.c
+++ b/cmd.c
@@ -104,8 +104,7 @@ static void refs_fn(struct cgit_context *ctx)
 
 static void snapshot_fn(struct cgit_context *ctx)
 {
-	cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1,
-			    cgit_repobasename(ctx->repo->url), ctx->qry.path,
+	cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, ctx->qry.path,
 			    ctx->repo->snapshots, ctx->qry.nohead);
 }
 
diff --git a/ui-snapshot.c b/ui-snapshot.c
index 9c4d086..76457d6 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -162,10 +162,11 @@ static const char *get_ref_from_filename(const char *url, const char *filename,
 	return dwim_refname;
 }
 
-void cgit_print_snapshot(const char *head, const char *hex, const char *prefix,
+void cgit_print_snapshot(const char *head, const char *hex,
 			 const char *filename, int snapshots, int dwim)
 {
 	const struct cgit_snapshot_format* f;
+	char *prefix = NULL;
 
 	f = get_format(filename);
 	if (!f) {
@@ -178,11 +179,20 @@ void cgit_print_snapshot(const char *head, const char *hex, const char *prefix,
 		return;
 	}
 
-	if (!hex && dwim)
+	if (!hex && dwim) {
 		hex = get_ref_from_filename(ctx.repo->url, filename, f);
+		if (hex != NULL) {
+			prefix = xstrdup(filename);
+			prefix[strlen(filename) - strlen(f->suffix)] = '\0';
+		}
+	}
 
 	if (!hex)
 		hex = head;
 
+	if (!prefix)
+		prefix = xstrdup(cgit_repobasename(ctx.repo->url));
+
 	make_snapshot(f, hex, prefix, filename);
+	free(prefix);
 }
diff --git a/ui-snapshot.h b/ui-snapshot.h
index 3540303..b6ede52 100644
--- a/ui-snapshot.h
+++ b/ui-snapshot.h
@@ -2,7 +2,6 @@
 #define UI_SNAPSHOT_H
 
 extern void cgit_print_snapshot(const char *head, const char *hex,
-				const char *prefix, const char *filename,
-				int snapshot, int dwim);
+				const char *filename, int snapshot, int dwim);
 
 #endif /* UI_SNAPSHOT_H */
-- 
cgit 1.4.1-21-gabe81


From 4b4f8d1256669bf9838e17f83a070de0ec09a699 Mon Sep 17 00:00:00 2001
From: Lars Hjemli
Date: Mon, 1 Dec 2008 19:13:44 +0100
Subject: ui-snapshot: improve extraction of revision from snapshot name

The modified get_ref_from_filename() supports the following snapshot
formats:
* $REV.$EXT
* $REPO[-_]*v?$REV.$EXT

This implies that the following urls will retrieve the expected revision:
* http://hjemli.net/git/cgit/snapshot/v0.8.1.tar.gz
* http://hjemli.net/git/cgit/snapshot/0.8.1.tar.gz
* http://hjemli.net/git/cgit/snapshot/cgit-0.8.1.tar.gz
* http://hjemli.net/git/cgit/snapshot/cgit-140012d7a8.tar.gz

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-snapshot.c | 80 +++++++++++++++++++++++++++--------------------------------
 1 file changed, 37 insertions(+), 43 deletions(-)

diff --git a/ui-snapshot.c b/ui-snapshot.c
index 76457d6..6f09151 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -114,52 +114,46 @@ static int make_snapshot(const struct cgit_snapshot_format *format,
 	return 0;
 }
 
-char *dwim_filename = NULL;
-const char *dwim_refname = NULL;
-
-static int ref_cb(const char *refname, const unsigned char *sha1, int flags,
-		  void *cb_data)
-{
-	const char *r = refname;
-	while (r && *r) {
-		fprintf(stderr, "  cmp %s with %s:", dwim_filename, r);
-		if (!strcmp(dwim_filename, r)) {
-			fprintf(stderr, "MATCH!\n");
-			dwim_refname = refname;
-			return 1;
-		}
-		fprintf(stderr, "no match\n");
-		if (isdigit(*r))
-			break;
-		r++;
-	}
-	return 0;
-}
-
-/* Try to guess the requested revision by combining repo name and tag name
- * and comparing this to the requested snapshot name. E.g. the requested
- * snapshot is "cgit-0.7.2.tar.gz" while repo name is "cgit" and tag name
- * is "v0.7.2". First, the reponame is stripped off, leaving "-0.7.2.tar.gz".
- * Next, any '-' and '_' characters are stripped, leaving "0.7.2.tar.gz".
- * Finally, the requested format suffix is removed and we end up with "0.7.2".
- * Then we test each tag against this dwimmed filename, and for each tag
- * we even try to remove any leading characters which are non-digits. I.e.
- * we first compare with "v0.7.2", then with "0.7.2" and we've got a match.
+/* Try to guess the requested revision from the requested snapshot name.
+ * First the format extension is stripped, e.g. "cgit-0.7.2.tar.gz" become
+ * "cgit-0.7.2". If this is a valid commit object name we've got a winner.
+ * Otherwise, if the snapshot name has a prefix matching the result from
+ * repo_basename(), we strip the basename and any following '-' and '_'
+ * characters ("cgit-0.7.2" -> "0.7.2") and check the resulting name once
+ * more. If this still isn't a valid commit object name, we check if pre-
+ * pending a 'v' to the remaining snapshot name ("0.7.2" -> "v0.7.2") gives
+ * us something valid.
  */
 static const char *get_ref_from_filename(const char *url, const char *filename,
-					 const struct cgit_snapshot_format *fmt)
+					 const struct cgit_snapshot_format *format)
 {
-	const char *reponame = cgit_repobasename(url);
-	fprintf(stderr, "reponame=%s, filename=%s\n", reponame, filename);
-	if (prefixcmp(filename, reponame))
-		return NULL;
-	filename += strlen(reponame);
-	while (filename && (*filename == '-' || *filename == '_'))
-		filename++;
-	dwim_filename = xstrdup(filename);
-	dwim_filename[strlen(filename) - strlen(fmt->suffix)] = '\0';
-	for_each_tag_ref(ref_cb, NULL);
-	return dwim_refname;
+	const char *reponame;
+	unsigned char sha1[20];
+	char *snapshot;
+
+	snapshot = xstrdup(filename);
+	snapshot[strlen(snapshot) - strlen(format->suffix)] = '\0';
+	fprintf(stderr, "snapshot=%s\n", snapshot);
+
+	if (get_sha1(snapshot, sha1) == 0)
+		return snapshot;
+
+	reponame = cgit_repobasename(url);
+	fprintf(stderr, "reponame=%s\n", reponame);
+	if (prefixcmp(snapshot, reponame) == 0) {
+		snapshot += strlen(reponame);
+		while (snapshot && (*snapshot == '-' || *snapshot == '_'))
+			snapshot++;
+	}
+
+	if (get_sha1(snapshot, sha1) == 0)
+		return snapshot;
+
+	snapshot = fmt("v%s", snapshot);
+	if (get_sha1(snapshot, sha1) == 0)
+		return snapshot;
+
+	return NULL;
 }
 
 void cgit_print_snapshot(const char *head, const char *hex,
-- 
cgit 1.4.1-21-gabe81


From b9053a4ff04fef90d1b9ab3f813ae3fcee63a8c3 Mon Sep 17 00:00:00 2001
From: Lars Hjemli
Date: Mon, 1 Dec 2008 21:50:19 +0100
Subject: ui-shared: exploit snapshot dwimmery in cgit_print_snapshot_links

Since we know that ui-snapshot.c is able to extract the revision from the
filename, there's no longer necessary to specify the revision with a 'id'
querystring argument.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/ui-shared.c b/ui-shared.c
index 224e5f3..c4a506e 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -707,8 +707,7 @@ void cgit_print_snapshot_links(const char *repo, const char *head,
 			continue;
 		filename = fmt("%s-%s%s", cgit_repobasename(repo), hex,
 			       f->suffix);
-		cgit_snapshot_link(filename, NULL, NULL, (char *)head,
-				   (char *)hex, filename);
+		cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename);
 		html("<br/>");
 	}
 }
-- 
cgit 1.4.1-21-gabe81


From 6596268576a4f5fe2f5c8a3238856b0fb205ff76 Mon Sep 17 00:00:00 2001
From: Lars Hjemli
Date: Mon, 1 Dec 2008 21:56:07 +0100
Subject: ui-refs.c: show download links for all tags referring to commit
 objects

The snapshot function has only been linked to from the commit page while
users often would want to download a certain release. With this patch,
direct download links will now be printed for each tagged release on the
repo summary page.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-refs.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/ui-refs.c b/ui-refs.c
index 32e0429..0805fc8 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -78,12 +78,37 @@ static int print_branch(struct refinfo *ref)
 static void print_tag_header()
 {
 	html("<tr class='nohover'><th class='left'>Tag</th>"
-	     "<th class='left'>Reference</th>"
+	     "<th class='left'>Download</th>"
 	     "<th class='left'>Author</th>"
 	     "<th class='left' colspan='2'>Age</th></tr>\n");
 	header = 1;
 }
 
+static void print_tag_downloads(const struct cgit_repo *repo, const char *ref)
+{
+	const struct cgit_snapshot_format* f;
+    	char *filename;
+	const char *basename;
+
+	if (!ref || strlen(ref) < 2)
+		return;
+
+	basename = cgit_repobasename(repo->url);
+	if (prefixcmp(ref, basename) != 0) {
+		if ((ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]))
+			ref++;
+		if (isdigit(ref[0]))
+			ref = xstrdup(fmt("%s-%s", basename, ref));
+	}
+
+	for (f = cgit_snapshot_formats; f->suffix; f++) {
+		if (!(repo->snapshots & f->bit))
+			continue;
+		filename = fmt("%s%s", ref, f->suffix);
+		cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename);
+		html("&nbsp;&nbsp;");
+	}
+}
 static int print_tag(struct refinfo *ref)
 {
 	struct tag *tag;
@@ -98,7 +123,10 @@ static int print_tag(struct refinfo *ref)
 		html("<tr><td>");
 		cgit_tag_link(name, NULL, NULL, ctx.qry.head, name);
 		html("</td><td>");
-		cgit_object_link(tag->tagged);
+		if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT))
+			print_tag_downloads(ctx.repo, name);
+		else
+			cgit_object_link(tag->tagged);
 		html("</td><td>");
 		if (info->tagger)
 			html(info->tagger);
@@ -112,7 +140,10 @@ static int print_tag(struct refinfo *ref)
 		html("<tr><td>");
 		html_txt(name);
 		html("</td><td>");
-		cgit_object_link(ref->object);
+		if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT))
+			print_tag_downloads(ctx.repo, name);
+		else
+			cgit_object_link(ref->object);
 		html("</td></tr>\n");
 	}
 	return 0;
-- 
cgit 1.4.1-21-gabe81


From c57aceb1d2f1a7d9fd3218fc8c6e9ea01b2952d2 Mon Sep 17 00:00:00 2001
From: Lars Hjemli
Date: Mon, 1 Dec 2008 21:58:59 +0100
Subject: ui-shared: shorten the sha1 printed by cgit_object_link

Such links was printed as the object type followed by the objects complete
sha1. We still use the complete sha1 in the link but we no longer show it
in all its glory; only the first 10 hex chars are printed.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
 ui-shared.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/ui-shared.c b/ui-shared.c
index c4a506e..9319881 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -365,11 +365,14 @@ void cgit_patch_link(char *name, char *title, char *class, char *head,
 
 void cgit_object_link(struct object *obj)
 {
-	char *page, *rev, *name;
+	char *page, *shortrev, *fullrev, *name;
 
+	fullrev = sha1_to_hex(obj->sha1);
+	shortrev = xstrdup(fullrev);
+	shortrev[10] = '\0';
 	if (obj->type == OBJ_COMMIT) {
-                cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL,
-				 ctx.qry.head, sha1_to_hex(obj->sha1));
+                cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL,
+				 ctx.qry.head, fullrev);
 		return;
 	} else if (obj->type == OBJ_TREE)
 		page = "tree";
@@ -377,9 +380,8 @@ void cgit_object_link(struct object *obj)
 		page = "tag";
 	else
 		page = "blob";
-	rev = sha1_to_hex(obj->sha1);
-	name = fmt("%s %s", typename(obj->type), rev);
-	reporevlink(page, name, NULL, NULL, ctx.qry.head, rev, NULL);
+	name = fmt("%s %s...", typename(obj->type), shortrev);
+	reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL);
 }
 
 void cgit_print_date(time_t secs, char *format, int local_time)
-- 
cgit 1.4.1-21-gabe81