aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile23
-rw-r--r--cgit.h6
-rw-r--r--cmd.c3
-rw-r--r--parsing.c4
-rw-r--r--ui-log.c17
-rw-r--r--ui-refs.c37
-rw-r--r--ui-repolist.c4
-rw-r--r--ui-shared.c17
-rw-r--r--ui-snapshot.c94
-rw-r--r--ui-snapshot.h3
10 files changed, 140 insertions, 68 deletions
diff --git a/Makefile b/Makefile
index 2107610..2e51c31 100644
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,26 @@ SHA1_HEADER = <openssl/sha.h>
7GIT_VER = 1.6.0.3 7GIT_VER = 1.6.0.3
8GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2 8GIT_URL = http://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.bz2
9 9
10# Define NO_STRCASESTR if you don't have strcasestr.
11#
12# Define NEEDS_LIBICONV if linking with libc is not enough (eg. Darwin).
13#
14
15#-include config.mak
16
17#
18# Platform specific tweaks
19#
20
21uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
22uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
23uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
24
25ifeq ($(uname_O),Cygwin)
26 NO_STRCASESTR = YesPlease
27 NEEDS_LIBICONV = YesPlease
28endif
29
10# 30#
11# Let the user override the above settings. 31# Let the user override the above settings.
12# 32#
@@ -96,6 +116,9 @@ CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
96ifdef NO_ICONV 116ifdef NO_ICONV
97 CFLAGS += -DNO_ICONV 117 CFLAGS += -DNO_ICONV
98endif 118endif
119ifdef NO_STRCASESTR
120 CFLAGS += -DNO_STRCASESTR
121endif
99 122
100cgit: $(OBJECTS) libgit 123cgit: $(OBJECTS) libgit
101 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS) 124 $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS)
diff --git a/cgit.h b/cgit.h
index c99d337..f1fbeca 100644
--- a/cgit.h
+++ b/cgit.h
@@ -235,11 +235,5 @@ extern const char *cgit_repobasename(const char *reponame);
235 235
236extern int cgit_parse_snapshots_mask(const char *str); 236extern int cgit_parse_snapshots_mask(const char *str);
237 237
238/* libgit.a either links against or compiles its own implementation of
239 * strcasestr(), and we'd like to reuse it. Simply re-declaring it
240 * seems to do the trick.
241 */
242extern char *strcasestr(const char *haystack, const char *needle);
243
244 238
245#endif /* CGIT_H */ 239#endif /* CGIT_H */
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)
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
diff --git a/parsing.c b/parsing.c
index c8f3048..f3f3b15 100644
--- a/parsing.c
+++ b/parsing.c
@@ -96,6 +96,9 @@ char *parse_user(char *t, char **name, char **email, unsigned long *date)
96 return p; 96 return p;
97} 97}
98 98
99#ifdef NO_ICONV
100#define reencode(a, b, c)
101#else
99const char *reencode(char **txt, const char *src_enc, const char *dst_enc) 102const char *reencode(char **txt, const char *src_enc, const char *dst_enc)
100{ 103{
101 char *tmp; 104 char *tmp;
@@ -110,6 +113,7 @@ const char *reencode(char **txt, const char *src_enc, const char *dst_enc)
110 } 113 }
111 return *txt; 114 return *txt;
112} 115}
116#endif
113 117
114struct commitinfo *cgit_parse_commit(struct commit *commit) 118struct commitinfo *cgit_parse_commit(struct commit *commit)
115{ 119{
diff --git a/ui-log.c b/ui-log.c
index 8dd8b89..d212984 100644
--- a/ui-log.c
+++ b/ui-log.c
@@ -64,18 +64,31 @@ void print_commit(struct commit *commit)
64 cgit_free_commitinfo(info); 64 cgit_free_commitinfo(info);
65} 65}
66 66
67static const char *disambiguate_ref(const char *ref)
68{
69 unsigned char sha1[20];
70 const char *longref;
71
72 longref = fmt("refs/heads/%s", ref);
73 if (get_sha1(longref, sha1) == 0)
74 return longref;
75
76 return ref;
77}
67 78
68void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, 79void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern,
69 char *path, int pager) 80 char *path, int pager)
70{ 81{
71 struct rev_info rev; 82 struct rev_info rev;
72 struct commit *commit; 83 struct commit *commit;
73 const char *argv[] = {NULL, tip, NULL, NULL, NULL}; 84 const char *argv[] = {NULL, NULL, NULL, NULL, NULL};
74 int argc = 2; 85 int argc = 2;
75 int i, columns = 3; 86 int i, columns = 3;
76 87
77 if (!tip) 88 if (!tip)
78 argv[1] = ctx.qry.head; 89 tip = ctx.qry.head;
90
91 argv[1] = disambiguate_ref(tip);
79 92
80 if (grep && pattern && (!strcmp(grep, "grep") || 93 if (grep && pattern && (!strcmp(grep, "grep") ||
81 !strcmp(grep, "author") || 94 !strcmp(grep, "author") ||
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)
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;
@@ -98,7 +123,10 @@ static int print_tag(struct refinfo *ref)
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);
@@ -112,7 +140,10 @@ static int print_tag(struct refinfo *ref)
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;
diff --git a/ui-repolist.c b/ui-repolist.c
index aa743bf..87196f0 100644
--- a/ui-repolist.c
+++ b/ui-repolist.c
@@ -6,6 +6,10 @@
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9/* This is needed for strcasestr to be defined by <string.h> */
10#define _GNU_SOURCE 1
11#include <string.h>
12
9#include <time.h> 13#include <time.h>
10 14
11#include "cgit.h" 15#include "cgit.h"
diff --git a/ui-shared.c b/ui-shared.c
index 224e5f3..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,
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";
@@ -377,9 +380,8 @@ void cgit_object_link(struct object *obj)
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)
@@ -707,8 +709,7 @@ void cgit_print_snapshot_links(const char *repo, const char *head,
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
@@ -114,58 +114,53 @@ static int make_snapshot(const struct cgit_snapshot_format *format,
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) {
@@ -178,11 +173,20 @@ void cgit_print_snapshot(const char *head, const char *hex, const char *prefix,
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
@@ -2,7 +2,6 @@
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 */