summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--cmd.c3
-rw-r--r--ui-refs.c37
-rw-r--r--ui-shared.c17
-rw-r--r--ui-snapshot.c94
-rw-r--r--ui-snapshot.h3
5 files changed, 94 insertions, 60 deletions
diff --git a/cmd.c b/cmd.c
index 5b3c14c..8914fa5 100644
--- a/cmd.c
+++ b/cmd.c
@@ -101,14 +101,13 @@ static void refs_fn(struct cgit_context *ctx)
101{ 101{
102 cgit_print_refs(); 102 cgit_print_refs();
103} 103}
104 104
105static void snapshot_fn(struct cgit_context *ctx) 105static void snapshot_fn(struct cgit_context *ctx)
106{ 106{
107 cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, 107 cgit_print_snapshot(ctx->qry.head, ctx->qry.sha1, ctx->qry.path,
108 cgit_repobasename(ctx->repo->url), ctx->qry.path,
109 ctx->repo->snapshots, ctx->qry.nohead); 108 ctx->repo->snapshots, ctx->qry.nohead);
110} 109}
111 110
112static void summary_fn(struct cgit_context *ctx) 111static void summary_fn(struct cgit_context *ctx)
113{ 112{
114 cgit_print_summary(); 113 cgit_print_summary();
diff --git a/ui-refs.c b/ui-refs.c
index 32e0429..0805fc8 100644
--- a/ui-refs.c
+++ b/ui-refs.c
@@ -75,18 +75,43 @@ static int print_branch(struct refinfo *ref)
75 return 0; 75 return 0;
76} 76}
77 77
78static void print_tag_header() 78static void print_tag_header()
79{ 79{
80 html("<tr class='nohover'><th class='left'>Tag</th>" 80 html("<tr class='nohover'><th class='left'>Tag</th>"
81 "<th class='left'>Reference</th>" 81 "<th class='left'>Download</th>"
82 "<th class='left'>Author</th>" 82 "<th class='left'>Author</th>"
83 "<th class='left' colspan='2'>Age</th></tr>\n"); 83 "<th class='left' colspan='2'>Age</th></tr>\n");
84 header = 1; 84 header = 1;
85} 85}
86 86
87static void print_tag_downloads(const struct cgit_repo *repo, const char *ref)
88{
89 const struct cgit_snapshot_format* f;
90 char *filename;
91 const char *basename;
92
93 if (!ref || strlen(ref) < 2)
94 return;
95
96 basename = cgit_repobasename(repo->url);
97 if (prefixcmp(ref, basename) != 0) {
98 if ((ref[0] == 'v' || ref[0] == 'V') && isdigit(ref[1]))
99 ref++;
100 if (isdigit(ref[0]))
101 ref = xstrdup(fmt("%s-%s", basename, ref));
102 }
103
104 for (f = cgit_snapshot_formats; f->suffix; f++) {
105 if (!(repo->snapshots & f->bit))
106 continue;
107 filename = fmt("%s%s", ref, f->suffix);
108 cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename);
109 html("&nbsp;&nbsp;");
110 }
111}
87static int print_tag(struct refinfo *ref) 112static int print_tag(struct refinfo *ref)
88{ 113{
89 struct tag *tag; 114 struct tag *tag;
90 struct taginfo *info; 115 struct taginfo *info;
91 char *name = (char *)ref->refname; 116 char *name = (char *)ref->refname;
92 117
@@ -95,13 +120,16 @@ static int print_tag(struct refinfo *ref)
95 info = ref->tag; 120 info = ref->tag;
96 if (!tag || !info) 121 if (!tag || !info)
97 return 1; 122 return 1;
98 html("<tr><td>"); 123 html("<tr><td>");
99 cgit_tag_link(name, NULL, NULL, ctx.qry.head, name); 124 cgit_tag_link(name, NULL, NULL, ctx.qry.head, name);
100 html("</td><td>"); 125 html("</td><td>");
101 cgit_object_link(tag->tagged); 126 if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT))
127 print_tag_downloads(ctx.repo, name);
128 else
129 cgit_object_link(tag->tagged);
102 html("</td><td>"); 130 html("</td><td>");
103 if (info->tagger) 131 if (info->tagger)
104 html(info->tagger); 132 html(info->tagger);
105 html("</td><td colspan='2'>"); 133 html("</td><td colspan='2'>");
106 if (info->tagger_date > 0) 134 if (info->tagger_date > 0)
107 cgit_print_age(info->tagger_date, -1, NULL); 135 cgit_print_age(info->tagger_date, -1, NULL);
@@ -109,13 +137,16 @@ static int print_tag(struct refinfo *ref)
109 } else { 137 } else {
110 if (!header) 138 if (!header)
111 print_tag_header(); 139 print_tag_header();
112 html("<tr><td>"); 140 html("<tr><td>");
113 html_txt(name); 141 html_txt(name);
114 html("</td><td>"); 142 html("</td><td>");
115 cgit_object_link(ref->object); 143 if (ctx.repo->snapshots && (tag->tagged->type == OBJ_COMMIT))
144 print_tag_downloads(ctx.repo, name);
145 else
146 cgit_object_link(ref->object);
116 html("</td></tr>\n"); 147 html("</td></tr>\n");
117 } 148 }
118 return 0; 149 return 0;
119} 150}
120 151
121static void print_refs_link(char *path) 152static void print_refs_link(char *path)
diff --git a/ui-shared.c b/ui-shared.c
index 224e5f3..9319881 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -362,27 +362,29 @@ void cgit_patch_link(char *name, char *title, char *class, char *head,
362{ 362{
363 reporevlink("patch", name, title, class, head, rev, NULL); 363 reporevlink("patch", name, title, class, head, rev, NULL);
364} 364}
365 365
366void cgit_object_link(struct object *obj) 366void cgit_object_link(struct object *obj)
367{ 367{
368 char *page, *rev, *name; 368 char *page, *shortrev, *fullrev, *name;
369 369
370 fullrev = sha1_to_hex(obj->sha1);
371 shortrev = xstrdup(fullrev);
372 shortrev[10] = '\0';
370 if (obj->type == OBJ_COMMIT) { 373 if (obj->type == OBJ_COMMIT) {
371 cgit_commit_link(fmt("commit %s", sha1_to_hex(obj->sha1)), NULL, NULL, 374 cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL,
372 ctx.qry.head, sha1_to_hex(obj->sha1)); 375 ctx.qry.head, fullrev);
373 return; 376 return;
374 } else if (obj->type == OBJ_TREE) 377 } else if (obj->type == OBJ_TREE)
375 page = "tree"; 378 page = "tree";
376 else if (obj->type == OBJ_TAG) 379 else if (obj->type == OBJ_TAG)
377 page = "tag"; 380 page = "tag";
378 else 381 else
379 page = "blob"; 382 page = "blob";
380 rev = sha1_to_hex(obj->sha1); 383 name = fmt("%s %s...", typename(obj->type), shortrev);
381 name = fmt("%s %s", typename(obj->type), rev); 384 reporevlink(page, name, NULL, NULL, ctx.qry.head, fullrev, NULL);
382 reporevlink(page, name, NULL, NULL, ctx.qry.head, rev, NULL);
383} 385}
384 386
385void cgit_print_date(time_t secs, char *format, int local_time) 387void cgit_print_date(time_t secs, char *format, int local_time)
386{ 388{
387 char buf[64]; 389 char buf[64];
388 struct tm *time; 390 struct tm *time;
@@ -704,11 +706,10 @@ void cgit_print_snapshot_links(const char *repo, const char *head,
704 706
705 for (f = cgit_snapshot_formats; f->suffix; f++) { 707 for (f = cgit_snapshot_formats; f->suffix; f++) {
706 if (!(snapshots & f->bit)) 708 if (!(snapshots & f->bit))
707 continue; 709 continue;
708 filename = fmt("%s-%s%s", cgit_repobasename(repo), hex, 710 filename = fmt("%s-%s%s", cgit_repobasename(repo), hex,
709 f->suffix); 711 f->suffix);
710 cgit_snapshot_link(filename, NULL, NULL, (char *)head, 712 cgit_snapshot_link(filename, NULL, NULL, NULL, NULL, filename);
711 (char *)hex, filename);
712 html("<br/>"); 713 html("<br/>");
713 } 714 }
714} 715}
diff --git a/ui-snapshot.c b/ui-snapshot.c
index 9c4d086..6f09151 100644
--- a/ui-snapshot.c
+++ b/ui-snapshot.c
@@ -111,78 +111,82 @@ static int make_snapshot(const struct cgit_snapshot_format *format,
111 ctx.page.filename = xstrdup(filename); 111 ctx.page.filename = xstrdup(filename);
112 cgit_print_http_headers(&ctx); 112 cgit_print_http_headers(&ctx);
113 format->write_func(&args); 113 format->write_func(&args);
114 return 0; 114 return 0;
115} 115}
116 116
117char *dwim_filename = NULL; 117/* Try to guess the requested revision from the requested snapshot name.
118const char *dwim_refname = NULL; 118 * First the format extension is stripped, e.g. "cgit-0.7.2.tar.gz" become
119 119 * "cgit-0.7.2". If this is a valid commit object name we've got a winner.
120static int ref_cb(const char *refname, const unsigned char *sha1, int flags, 120 * Otherwise, if the snapshot name has a prefix matching the result from
121 void *cb_data) 121 * repo_basename(), we strip the basename and any following '-' and '_'
122{ 122 * characters ("cgit-0.7.2" -> "0.7.2") and check the resulting name once
123 const char *r = refname; 123 * more. If this still isn't a valid commit object name, we check if pre-
124 while (r && *r) { 124 * pending a 'v' to the remaining snapshot name ("0.7.2" -> "v0.7.2") gives
125 fprintf(stderr, " cmp %s with %s:", dwim_filename, r); 125 * us something valid.
126 if (!strcmp(dwim_filename, r)) {
127 fprintf(stderr, "MATCH!\n");
128 dwim_refname = refname;
129 return 1;
130 }
131 fprintf(stderr, "no match\n");
132 if (isdigit(*r))
133 break;
134 r++;
135 }
136 return 0;
137}
138
139/* Try to guess the requested revision by combining repo name and tag name
140 * and comparing this to the requested snapshot name. E.g. the requested
141 * snapshot is "cgit-0.7.2.tar.gz" while repo name is "cgit" and tag name
142 * is "v0.7.2". First, the reponame is stripped off, leaving "-0.7.2.tar.gz".
143 * Next, any '-' and '_' characters are stripped, leaving "0.7.2.tar.gz".
144 * Finally, the requested format suffix is removed and we end up with "0.7.2".
145 * Then we test each tag against this dwimmed filename, and for each tag
146 * we even try to remove any leading characters which are non-digits. I.e.
147 * we first compare with "v0.7.2", then with "0.7.2" and we've got a match.
148 */ 126 */
149static const char *get_ref_from_filename(const char *url, const char *filename, 127static const char *get_ref_from_filename(const char *url, const char *filename,
150 const struct cgit_snapshot_format *fmt) 128 const struct cgit_snapshot_format *format)
151{ 129{
152 const char *reponame = cgit_repobasename(url); 130 const char *reponame;
153 fprintf(stderr, "reponame=%s, filename=%s\n", reponame, filename); 131 unsigned char sha1[20];
154 if (prefixcmp(filename, reponame)) 132 char *snapshot;
155 return NULL; 133
156 filename += strlen(reponame); 134 snapshot = xstrdup(filename);
157 while (filename && (*filename == '-' || *filename == '_')) 135 snapshot[strlen(snapshot) - strlen(format->suffix)] = '\0';
158 filename++; 136 fprintf(stderr, "snapshot=%s\n", snapshot);
159 dwim_filename = xstrdup(filename); 137
160 dwim_filename[strlen(filename) - strlen(fmt->suffix)] = '\0'; 138 if (get_sha1(snapshot, sha1) == 0)
161 for_each_tag_ref(ref_cb, NULL); 139 return snapshot;
162 return dwim_refname; 140
141 reponame = cgit_repobasename(url);
142 fprintf(stderr, "reponame=%s\n", reponame);
143 if (prefixcmp(snapshot, reponame) == 0) {
144 snapshot += strlen(reponame);
145 while (snapshot && (*snapshot == '-' || *snapshot == '_'))
146 snapshot++;
147 }
148
149 if (get_sha1(snapshot, sha1) == 0)
150 return snapshot;
151
152 snapshot = fmt("v%s", snapshot);
153 if (get_sha1(snapshot, sha1) == 0)
154 return snapshot;
155
156 return NULL;
163} 157}
164 158
165void cgit_print_snapshot(const char *head, const char *hex, const char *prefix, 159void cgit_print_snapshot(const char *head, const char *hex,
166 const char *filename, int snapshots, int dwim) 160 const char *filename, int snapshots, int dwim)
167{ 161{
168 const struct cgit_snapshot_format* f; 162 const struct cgit_snapshot_format* f;
163 char *prefix = NULL;
169 164
170 f = get_format(filename); 165 f = get_format(filename);
171 if (!f) { 166 if (!f) {
172 ctx.page.mimetype = "text/html"; 167 ctx.page.mimetype = "text/html";
173 cgit_print_http_headers(&ctx); 168 cgit_print_http_headers(&ctx);
174 cgit_print_docstart(&ctx); 169 cgit_print_docstart(&ctx);
175 cgit_print_pageheader(&ctx); 170 cgit_print_pageheader(&ctx);
176 cgit_print_error(fmt("Unsupported snapshot format: %s", filename)); 171 cgit_print_error(fmt("Unsupported snapshot format: %s", filename));
177 cgit_print_docend(); 172 cgit_print_docend();
178 return; 173 return;
179 } 174 }
180 175
181 if (!hex && dwim) 176 if (!hex && dwim) {
182 hex = get_ref_from_filename(ctx.repo->url, filename, f); 177 hex = get_ref_from_filename(ctx.repo->url, filename, f);
178 if (hex != NULL) {
179 prefix = xstrdup(filename);
180 prefix[strlen(filename) - strlen(f->suffix)] = '\0';
181 }
182 }
183 183
184 if (!hex) 184 if (!hex)
185 hex = head; 185 hex = head;
186 186
187 if (!prefix)
188 prefix = xstrdup(cgit_repobasename(ctx.repo->url));
189
187 make_snapshot(f, hex, prefix, filename); 190 make_snapshot(f, hex, prefix, filename);
191 free(prefix);
188} 192}
diff --git a/ui-snapshot.h b/ui-snapshot.h
index 3540303..b6ede52 100644
--- a/ui-snapshot.h
+++ b/ui-snapshot.h
@@ -1,8 +1,7 @@
1#ifndef UI_SNAPSHOT_H 1#ifndef UI_SNAPSHOT_H
2#define UI_SNAPSHOT_H 2#define UI_SNAPSHOT_H
3 3
4extern void cgit_print_snapshot(const char *head, const char *hex, 4extern void cgit_print_snapshot(const char *head, const char *hex,
5 const char *prefix, const char *filename, 5 const char *filename, int snapshot, int dwim);
6 int snapshot, int dwim);
7 6
8#endif /* UI_SNAPSHOT_H */ 7#endif /* UI_SNAPSHOT_H */