]> git.pld-linux.org Git - packages/cgit.git/blame - git.patch
- updated to 0.9.1
[packages/cgit.git] / git.patch
CommitLineData
579c7c9d
JR
1diff --git a/Makefile b/Makefile
2index bbce29d..1127961 100644
3--- a/Makefile
4+++ b/Makefile
5@@ -1,3 +1,5 @@
6+all::
7+
8 CGIT_VERSION = v0.9.1
9 CGIT_SCRIPT_NAME = cgit.cgi
10 CGIT_SCRIPT_PATH = /var/www/htdocs/cgit
11@@ -12,8 +14,8 @@ htmldir = $(docdir)
12 pdfdir = $(docdir)
13 mandir = $(prefix)/share/man
14 SHA1_HEADER = <openssl/sha.h>
15-GIT_VER = 1.7.4
16-GIT_URL = https://github.com/git/git/archive/v$(GIT_VER).tar.gz
17+GIT_VER = 1.7.12.4
18+GIT_URL = https://git-core.googlecode.com/files/git-$(GIT_VER).tar.gz
19 INSTALL = install
20 MAN5_TXT = $(wildcard *.5.txt)
21 MAN_TXT = $(MAN5_TXT)
22@@ -40,22 +42,14 @@ DOC_PDF = $(patsubst %.txt,%.pdf,$(MAN_TXT))
23 # Platform specific tweaks
24 #
25
26+VERSION: force-version
27+ @./gen-version.sh "$(CGIT_VERSION)"
28+-include VERSION
29+
30 uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
31 uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
32 uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
33
34-ifeq ($(uname_O),Cygwin)
35- NO_STRCASESTR = YesPlease
36- NEEDS_LIBICONV = YesPlease
37-endif
38-
39-ifeq ($(uname_S),$(filter $(uname_S),FreeBSD OpenBSD))
40- # Apparantly libiconv is installed in /usr/local on BSD
41- LDFLAGS ?= -L/usr/local/lib
42- CFLAGS ?= -I/usr/local/include
43- NEEDS_LIBICONV = yes
44-endif
45-
46 #
47 # Let the user override the above settings.
48 #
49@@ -76,30 +70,62 @@ endif
50
51 ifndef V
52 QUIET_CC = @echo ' ' CC $@;
53- QUIET_MM = @echo ' ' MM $@;
54+ QUIET_LINK = @echo ' ' LINK $@;
55 QUIET_SUBDIR0 = +@subdir=
56 QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
57 $(MAKE) $(PRINT_DIR) -C $$subdir
58 QUIET_TAGS = @echo ' ' TAGS $@;
59+ export V
60 endif
61
62-#
63-# Define a pattern rule for automatic dependency building
64-#
65-%.d: %.c
66- $(QUIET_MM)$(CC) $(CFLAGS) -MM -MP $< | sed -e 's/\($*\)\.o:/\1.o $@:/g' >$@
67+LDFLAGS ?=
68+CFLAGS ?= -g -Wall
69+CFLAGS += -Igit
70+CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
71+CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
72+CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
73+CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
74+CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
75
76-#
77-# Define a pattern rule for silent object building
78-#
79-%.o: %.c
80- $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $<
81+ifeq ($(uname_O),Cygwin)
82+ NO_STRCASESTR = YesPlease
83+ NEEDS_LIBICONV = YesPlease
84+endif
85
86+ifeq ($(uname_S),$(filter $(uname_S),FreeBSD OpenBSD))
87+ # Apparantly libiconv is installed in /usr/local on BSD
88+ LDFLAGS += -L/usr/local/lib
89+ CFLAGS += -I/usr/local/include
90+ NEEDS_LIBICONV = yes
91+endif
92
93-EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lpthread
94+GIT_OPTIONS = prefix=/usr NO_GETTEXT=1
95 OBJECTS =
96-OBJECTS += cache.o
97+
98+ifdef NO_ICONV
99+ CFLAGS += -DNO_ICONV
100+endif
101+ifdef NO_STRCASESTR
102+ CFLAGS += -DNO_STRCASESTR
103+endif
104+ifdef NO_C99_FORMAT
105+ CFLAGS += -DNO_C99_FORMAT
106+endif
107+ifdef NO_OPENSSL
108+ CFLAGS += -DNO_OPENSSL
109+ GIT_OPTIONS += NO_OPENSSL=1
110+else
111+ LDLIBS += -lcrypto
112+endif
113+
114+ifdef NEEDS_LIBICONV
115+ LDLIBS += -liconv
116+endif
117+
118+LDLIBS += git/libgit.a git/xdiff/lib.a -lz -lpthread
119+
120 OBJECTS += cgit.o
121+OBJECTS += cache.o
122 OBJECTS += cmd.o
123 OBJECTS += configfile.o
124 OBJECTS += html.o
125@@ -125,55 +151,30 @@ OBJECTS += ui-tag.o
126 OBJECTS += ui-tree.o
127 OBJECTS += vector.o
128
129-ifdef NEEDS_LIBICONV
130- EXTLIBS += -liconv
131-endif
132-
133-
134-.PHONY: all libgit test install uninstall clean force-version get-git \
135- doc clean-doc install-doc install-man install-html install-pdf \
136- uninstall-doc uninstall-man uninstall-html uninstall-pdf tags
137+dep_files := $(foreach f,$(OBJECTS),$(dir $f).deps/$(notdir $f).d)
138+dep_dirs := $(addsuffix .deps,$(sort $(dir $OBJECTS)))
139
140-all: cgit
141+$(dep_dirs):
142+ @mkdir -p $@
143
144-VERSION: force-version
145- @./gen-version.sh "$(CGIT_VERSION)"
146--include VERSION
147+missing_dep_dirs := $(filter-out $(wildcard $(dep_dirs)),$(dep_dirs))
148+dep_file = $(dir $@).deps/$(notdir $@).d
149+dep_args = -MF $(dep_file) -MMD -MP
150
151+.SUFFIXES:
152
153-CFLAGS += -g -Wall -Igit
154-CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)'
155-CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"'
156-CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"'
157-CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'
158-CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"'
159-
160-GIT_OPTIONS = prefix=/usr
161+$(OBJECTS): %.o: %.c $(missing_dep_dirs)
162+ $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(CFLAGS) $<
163
164-ifdef NO_ICONV
165- CFLAGS += -DNO_ICONV
166+dep_files_present := $(wildcard $(dep_files))
167+ifneq ($(dep_files_present),)
168+include $(dep_files_present)
169 endif
170-ifdef NO_STRCASESTR
171- CFLAGS += -DNO_STRCASESTR
172-endif
173-ifdef NO_C99_FORMAT
174- CFLAGS += -DNO_C99_FORMAT
175-endif
176-ifdef NO_OPENSSL
177- CFLAGS += -DNO_OPENSSL
178- GIT_OPTIONS += NO_OPENSSL=1
179-else
180- EXTLIBS += -lcrypto
181-endif
182-
183-cgit: $(OBJECTS) libgit
184- $(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o cgit $(OBJECTS) $(EXTLIBS)
185
186-cgit.o: VERSION
187+all:: cgit
188
189-ifneq "$(MAKECMDGOALS)" "clean"
190- -include $(OBJECTS:.o=.d)
191-endif
192+cgit: VERSION $(OBJECTS) libgit
193+ $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJECTS) $(LDLIBS)
194
195 libgit:
196 $(QUIET_SUBDIR0)git $(QUIET_SUBDIR1) NO_CURL=1 $(GIT_OPTIONS) libgit.a
197@@ -243,13 +244,24 @@ $(DOC_PDF): %.pdf : %.txt
198 a2x -f pdf cgitrc.5.txt
199
200 clean: clean-doc
201- rm -f cgit VERSION *.o *.d tags
202+ $(RM) cgit VERSION *.o tags
203+ $(RM) -r .deps
204+
205+cleanall: clean
206+ $(MAKE) -C git clean
207
208 clean-doc:
209- rm -f cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo
210+ $(RM) cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo
211
212 get-git:
213 curl -L $(GIT_URL) | tar -xzf - && rm -rf git && mv git-$(GIT_VER) git
214
215 tags:
216 $(QUIET_TAGS)find . -name '*.[ch]' | xargs ctags
217+
218+.PHONY: all cgit get-git libgit force-version
219+.PHONY: clean clean-doc cleanall
220+.PHONY: doc doc-html doc-man doc-pdf
221+.PHONY: install install-doc install-html install-man install-pdf
222+.PHONY: tags test
223+.PHONY: uninstall uninstall-doc uninstall-html uninstall-man uninstall-pdf
224diff --git a/cache.c b/cache.c
225index d7a8d5a..47cdcb4 100644
226--- a/cache.c
227+++ b/cache.c
228@@ -105,7 +105,7 @@ static int is_expired(struct cache_slot *slot)
229 if (slot->ttl < 0)
230 return 0;
231 else
232- return slot->cache_st.st_mtime + slot->ttl*60 < time(NULL);
233+ return slot->cache_st.st_mtime + slot->ttl * 60 < time(NULL);
234 }
235
236 /* Check if the slot has been modified since we opened it.
237@@ -141,8 +141,8 @@ static int close_lock(struct cache_slot *slot)
238 */
239 static int lock_slot(struct cache_slot *slot)
240 {
241- slot->lock_fd = open(slot->lock_name, O_RDWR|O_CREAT|O_EXCL,
242- S_IRUSR|S_IWUSR);
243+ slot->lock_fd = open(slot->lock_name, O_RDWR | O_CREAT | O_EXCL,
244+ S_IRUSR | S_IWUSR);
245 if (slot->lock_fd == -1)
246 return errno;
247 if (xwrite(slot->lock_fd, slot->key, slot->keylen + 1) < 0)
248@@ -214,7 +214,7 @@ unsigned long hash_str(const char *str)
249 if (!s)
250 return h;
251
252- while(*s) {
253+ while (*s) {
254 h *= FNV_PRIME;
255 h ^= *s++;
256 }
257@@ -342,7 +342,7 @@ int cache_process(int size, const char *path, const char *key, int ttl,
258 strcpy(filename, path);
259 if (filename[len - 1] != '/')
260 filename[len++] = '/';
261- for(i = 0; i < 8; i++) {
262+ for (i = 0; i < 8; i++) {
263 sprintf(filename + len++, "%x",
264 (unsigned char)(hash & 0xf));
265 hash >>= 4;
266@@ -407,7 +407,7 @@ int cache_ls(const char *path)
267 *name = '\0';
268 }
269 slot.cache_name = fullname;
270- while((ent = readdir(dir)) != NULL) {
271+ while ((ent = readdir(dir)) != NULL) {
272 if (strlen(ent->d_name) != 8)
273 continue;
274 strcpy(name, ent->d_name);
275diff --git a/cgit.c b/cgit.c
276index a97ed69..2ccf864 100644
277--- a/cgit.c
278+++ b/cgit.c
279@@ -172,6 +172,8 @@ void config_cb(const char *name, const char *value)
280 ctx.cfg.enable_http_clone = atoi(value);
281 else if (!strcmp(name, "enable-index-links"))
282 ctx.cfg.enable_index_links = atoi(value);
283+ else if (!strcmp(name, "enable-index-owner"))
284+ ctx.cfg.enable_index_owner = atoi(value);
285 else if (!strcmp(name, "enable-commit-graph"))
286 ctx.cfg.enable_commit_graph = atoi(value);
287 else if (!strcmp(name, "enable-log-filecount"))
288@@ -313,7 +315,7 @@ static void querystring_cb(const char *name, const char *value)
289 ctx.qry.name = xstrdup(value);
290 } else if (!strcmp(name, "mimetype")) {
291 ctx.qry.mimetype = xstrdup(value);
292- } else if (!strcmp(name, "s")){
293+ } else if (!strcmp(name, "s")) {
294 ctx.qry.sort = xstrdup(value);
295 } else if (!strcmp(name, "showmsg")) {
296 ctx.qry.showmsg = atoi(value);
297@@ -354,6 +356,7 @@ static void prepare_context(struct cgit_context *ctx)
298 ctx->cfg.logo = "/cgit.png";
299 ctx->cfg.local_time = 0;
300 ctx->cfg.enable_http_clone = 1;
301+ ctx->cfg.enable_index_owner = 1;
302 ctx->cfg.enable_tree_linenumbers = 1;
303 ctx->cfg.enable_git_config = 0;
304 ctx->cfg.max_repo_count = 50;
305@@ -442,12 +445,12 @@ char *find_default_branch(struct cgit_repo *repo)
306 return ref;
307 }
308
309-static char *guess_defbranch(const char *repo_path)
310+static char *guess_defbranch(void)
311 {
312 const char *ref;
313 unsigned char sha1[20];
314
315- ref = resolve_ref("HEAD", sha1, 0, NULL);
316+ ref = resolve_ref_unsafe("HEAD", sha1, 0, NULL);
317 if (!ref || prefixcmp(ref, "refs/heads/"))
318 return "master";
319 return xstrdup(ref + 11);
320@@ -480,7 +483,7 @@ static int prepare_repo_cmd(struct cgit_context *ctx)
321 ctx->page.title = fmt("%s - %s", ctx->repo->name, ctx->repo->desc);
322
323 if (!ctx->repo->defbranch)
324- ctx->repo->defbranch = guess_defbranch(ctx->repo->path);
325+ ctx->repo->defbranch = guess_defbranch();
326
327 if (!ctx->qry.head) {
328 ctx->qry.nohead = 1;
329@@ -650,7 +653,7 @@ void print_repolist(FILE *f, struct cgit_repolist *list, int start)
330 {
331 int i;
332
333- for(i = start; i < list->count; i++)
334+ for (i = start; i < list->count; i++)
335 print_repo(f, &list->repos[i]);
336 }
337
338@@ -738,7 +741,7 @@ static void cgit_parse_args(int argc, const char **argv)
339
340 for (i = 1; i < argc; i++) {
341 if (!strncmp(argv[i], "--cache=", 8)) {
342- ctx.cfg.cache_root = xstrdup(argv[i]+8);
343+ ctx.cfg.cache_root = xstrdup(argv[i] + 8);
344 }
345 if (!strcmp(argv[i], "--nocache")) {
346 ctx.cfg.nocache = 1;
347@@ -747,24 +750,24 @@ static void cgit_parse_args(int argc, const char **argv)
348 ctx.env.no_http = "1";
349 }
350 if (!strncmp(argv[i], "--query=", 8)) {
351- ctx.qry.raw = xstrdup(argv[i]+8);
352+ ctx.qry.raw = xstrdup(argv[i] + 8);
353 }
354 if (!strncmp(argv[i], "--repo=", 7)) {
355- ctx.qry.repo = xstrdup(argv[i]+7);
356+ ctx.qry.repo = xstrdup(argv[i] + 7);
357 }
358 if (!strncmp(argv[i], "--page=", 7)) {
359- ctx.qry.page = xstrdup(argv[i]+7);
360+ ctx.qry.page = xstrdup(argv[i] + 7);
361 }
362 if (!strncmp(argv[i], "--head=", 7)) {
363- ctx.qry.head = xstrdup(argv[i]+7);
364+ ctx.qry.head = xstrdup(argv[i] + 7);
365 ctx.qry.has_symref = 1;
366 }
367 if (!strncmp(argv[i], "--sha1=", 7)) {
368- ctx.qry.sha1 = xstrdup(argv[i]+7);
369+ ctx.qry.sha1 = xstrdup(argv[i] + 7);
370 ctx.qry.has_sha1 = 1;
371 }
372 if (!strncmp(argv[i], "--ofs=", 6)) {
373- ctx.qry.ofs = atoi(argv[i]+6);
374+ ctx.qry.ofs = atoi(argv[i] + 6);
375 }
376 if (!strncmp(argv[i], "--scan-tree=", 12) ||
377 !strncmp(argv[i], "--scan-path=", 12)) {
378@@ -831,7 +834,7 @@ int main(int argc, const char **argv)
379 ctx.cfg.virtual_root = trim_end(ctx.cfg.script_name, '/');
380 if (!ctx.cfg.virtual_root)
381 ctx.cfg.virtual_root = "";
382- }
383+ }
384
385 /* If no url parameter is specified on the querystring, lets
386 * use PATH_INFO as url. This allows cgit to work with virtual
387@@ -853,7 +856,7 @@ int main(int argc, const char **argv)
388 }
389
390 ttl = calc_ttl();
391- ctx.page.expires += ttl*60;
392+ ctx.page.expires += ttl * 60;
393 if (ctx.env.request_method && !strcmp(ctx.env.request_method, "HEAD"))
394 ctx.cfg.nocache = 1;
395 if (ctx.cfg.nocache)
396diff --git a/cgit.h b/cgit.h
397index 7a99135..c655bd8 100644
398--- a/cgit.h
399+++ b/cgit.h
400@@ -11,6 +11,7 @@
401 #include <tag.h>
402 #include <diff.h>
403 #include <diffcore.h>
404+#include <argv-array.h>
405 #include <refs.h>
406 #include <revision.h>
407 #include <log-tree.h>
408@@ -203,6 +204,7 @@ struct cgit_config {
409 int enable_filter_overrides;
410 int enable_http_clone;
411 int enable_index_links;
412+ int enable_index_owner;
413 int enable_commit_graph;
414 int enable_log_filecount;
415 int enable_log_linecount;
416@@ -273,6 +275,8 @@ struct cgit_context {
417 struct cgit_page page;
418 };
419
420+typedef int (*write_archive_fn_t)(const char *, const char *);
421+
422 struct cgit_snapshot_format {
423 const char *suffix;
424 const char *mimetype;
425diff --git a/cgitrc.5.txt b/cgitrc.5.txt
426index 95a1049..4d27d9f 100644
427--- a/cgitrc.5.txt
428+++ b/cgitrc.5.txt
429@@ -120,6 +120,10 @@ enable-index-links::
430 each repo in the repository index (specifically, to the "summary",
431 "commit" and "tree" pages). Default value: "0".
432
433+enable-index-owner::
434+ Flag which, when set to "1", will make cgit display the owner of
435+ each repo in the repository index. Default value: "1".
436+
437 enable-log-filecount::
438 Flag which, when set to "1", will make cgit print the number of
439 modified files for each commit on the repository log page. Default
440@@ -244,8 +248,8 @@ mimetype-file::
441 Specifies the file to use for automatic mimetype lookup. If specified
442 then this field is used as a fallback when no "mimetype.<ext>" match is
443 found. If unspecified then no such lookup is performed. The typical file
444- to use on a Linux system is /etc/mime.types. Default value: none. See
445- also: "mimetype.<ext>". The format of the file must comply to:
446+ to use on a Linux system is /etc/mime.types. The format of the file must
447+ comply to:
448 - a comment line is an empty line or a line starting with a hash (#),
449 optionally preceded by whitespace
450 - a non-comment line starts with the mimetype (like image/png), followed
451diff --git a/cmd.c b/cmd.c
452index 899e913..198bf2f 100644
453--- a/cmd.c
454+++ b/cmd.c
455@@ -166,7 +166,7 @@ struct cgit_cmd *cgit_get_cmd(struct cgit_context *ctx)
456 ctx->qry.page = "repolist";
457 }
458
459- for(i = 0; i < sizeof(cmds)/sizeof(*cmds); i++)
460+ for (i = 0; i < sizeof(cmds)/sizeof(*cmds); i++)
461 if (!strcmp(ctx->qry.page, cmds[i].name))
462 return &cmds[i];
463 return NULL;
464diff --git a/configfile.c b/configfile.c
465index 4908058..3fa217f 100644
466--- a/configfile.c
467+++ b/configfile.c
468@@ -13,9 +13,9 @@
469 int next_char(FILE *f)
470 {
471 int c = fgetc(f);
472- if (c=='\r') {
473+ if (c == '\r') {
474 c = fgetc(f);
475- if (c!='\n') {
476+ if (c != '\n') {
477 ungetc(c, f);
478 c = '\r';
479 }
480@@ -27,7 +27,7 @@ void skip_line(FILE *f)
481 {
482 int c;
483
484- while((c=next_char(f)) && c!='\n' && c!=EOF)
485+ while ((c = next_char(f)) && c != '\n' && c != EOF)
486 ;
487 }
488
489@@ -36,31 +36,31 @@ int read_config_line(FILE *f, char *line, const char **value, int bufsize)
490 int i = 0, isname = 0;
491
492 *value = NULL;
493- while(i<bufsize-1) {
494+ while (i < bufsize - 1) {
495 int c = next_char(f);
496- if (!isname && (c=='#' || c==';')) {
497+ if (!isname && (c == '#' || c == ';')) {
498 skip_line(f);
499 continue;
500 }
501 if (!isname && isspace(c))
502 continue;
503
504- if (c=='=' && !*value) {
505+ if (c == '=' && !*value) {
506 line[i] = 0;
507- *value = &line[i+1];
508- } else if (c=='\n' && !isname) {
509+ *value = &line[i + 1];
510+ } else if (c == '\n' && !isname) {
511 i = 0;
512 continue;
513- } else if (c=='\n' || c==EOF) {
514+ } else if (c == '\n' || c == EOF) {
515 line[i] = 0;
516 break;
517 } else {
518- line[i]=c;
519+ line[i] = c;
520 }
521 isname = 1;
522 i++;
523 }
524- line[i+1] = 0;
525+ line[i + 1] = 0;
526 return i;
527 }
528
529@@ -78,7 +78,7 @@ int parse_configfile(const char *filename, configfile_value_fn fn)
530 if (!(f = fopen(filename, "r")))
531 return -1;
532 nesting++;
533- while((len = read_config_line(f, line, &value, sizeof(line))) > 0)
534+ while ((len = read_config_line(f, line, &value, sizeof(line))) > 0)
535 fn(line, value);
536 nesting--;
537 fclose(f);
538diff --git a/html.c b/html.c
539index 8f6e4f6..90cc1c0 100644
540--- a/html.c
541+++ b/html.c
542@@ -54,7 +54,7 @@ char *fmt(const char *format, ...)
543 va_start(args, format);
544 len = vsnprintf(buf[bufidx], sizeof(buf[bufidx]), format, args);
545 va_end(args);
546- if (len>sizeof(buf[bufidx])) {
547+ if (len > sizeof(buf[bufidx])) {
548 fprintf(stderr, "[html.c] string truncated: %s\n", format);
549 exit(1);
550 }
551@@ -92,93 +92,93 @@ void html_status(int code, const char *msg, int more_headers)
552 void html_txt(const char *txt)
553 {
554 const char *t = txt;
555- while(t && *t){
556+ while (t && *t) {
557 int c = *t;
558- if (c=='<' || c=='>' || c=='&') {
559+ if (c == '<' || c == '>' || c == '&') {
560 html_raw(txt, t - txt);
561- if (c=='>')
562+ if (c == '>')
563 html("&gt;");
564- else if (c=='<')
565+ else if (c == '<')
566 html("&lt;");
567- else if (c=='&')
568+ else if (c == '&')
569 html("&amp;");
570- txt = t+1;
571+ txt = t + 1;
572 }
573 t++;
574 }
575- if (t!=txt)
576+ if (t != txt)
577 html(txt);
578 }
579
580 void html_ntxt(int len, const char *txt)
581 {
582 const char *t = txt;
583- while(t && *t && len--){
584+ while (t && *t && len--) {
585 int c = *t;
586- if (c=='<' || c=='>' || c=='&') {
587+ if (c == '<' || c == '>' || c == '&') {
588 html_raw(txt, t - txt);
589- if (c=='>')
590+ if (c == '>')
591 html("&gt;");
592- else if (c=='<')
593+ else if (c == '<')
594 html("&lt;");
595- else if (c=='&')
596+ else if (c == '&')
597 html("&amp;");
598- txt = t+1;
599+ txt = t + 1;
600 }
601 t++;
602 }
603- if (t!=txt)
604+ if (t != txt)
605 html_raw(txt, t - txt);
606- if (len<0)
607+ if (len < 0)
608 html("...");
609 }
610
611 void html_attr(const char *txt)
612 {
613 const char *t = txt;
614- while(t && *t){
615+ while (t && *t) {
616 int c = *t;
617- if (c=='<' || c=='>' || c=='\'' || c=='\"' || c=='&') {
618+ if (c == '<' || c == '>' || c == '\'' || c == '\"' || c == '&') {
619 html_raw(txt, t - txt);
620- if (c=='>')
621+ if (c == '>')
622 html("&gt;");
623- else if (c=='<')
624+ else if (c == '<')
625 html("&lt;");
626- else if (c=='\'')
627+ else if (c == '\'')
628 html("&#x27;");
629- else if (c=='"')
630+ else if (c == '"')
631 html("&quot;");
632- else if (c=='&')
633+ else if (c == '&')
634 html("&amp;");
635- txt = t+1;
636+ txt = t + 1;
637 }
638 t++;
639 }
640- if (t!=txt)
641+ if (t != txt)
642 html(txt);
643 }
644
645 void html_url_path(const char *txt)
646 {
647 const char *t = txt;
648- while(t && *t){
649+ while (t && *t) {
650 unsigned char c = *t;
651 const char *e = url_escape_table[c];
652- if (e && c!='+' && c!='&') {
653+ if (e && c != '+' && c != '&') {
654 html_raw(txt, t - txt);
655 html(e);
656- txt = t+1;
657+ txt = t + 1;
658 }
659 t++;
660 }
661- if (t!=txt)
662+ if (t != txt)
663 html(txt);
664 }
665
666 void html_url_arg(const char *txt)
667 {
668 const char *t = txt;
669- while(t && *t){
670+ while (t && *t) {
671 unsigned char c = *t;
672 const char *e = url_escape_table[c];
673 if (c == ' ')
674@@ -186,11 +186,11 @@ void html_url_arg(const char *txt)
675 if (e) {
676 html_raw(txt, t - txt);
677 html(e);
678- txt = t+1;
679+ txt = t + 1;
680 }
681 t++;
682 }
683- if (t!=txt)
684+ if (t != txt)
685 html(txt);
686 }
687
688@@ -260,7 +260,7 @@ int html_include(const char *filename)
689 filename, strerror(errno), errno);
690 return -1;
691 }
692- while((len = fread(buf, 1, 4096, f)) > 0)
693+ while ((len = fread(buf, 1, 4096, f)) > 0)
694 html_raw(buf, len);
695 fclose(f);
696 return 0;
697@@ -286,14 +286,14 @@ char *convert_query_hexchar(char *txt)
698 *txt = '\0';
699 return txt-1;
700 }
701- d1 = hextoint(*(txt+1));
702- d2 = hextoint(*(txt+2));
703- if (d1<0 || d2<0) {
704- memmove(txt, txt+3, n-2);
705+ d1 = hextoint(*(txt + 1));
706+ d2 = hextoint(*(txt + 2));
707+ if (d1 < 0 || d2 < 0) {
708+ memmove(txt, txt + 3, n - 2);
709 return txt-1;
710 } else {
711 *txt = d1 * 16 + d2;
712- memmove(txt+1, txt+3, n-2);
713+ memmove(txt + 1, txt + 3, n - 2);
714 return txt;
715 }
716 }
717@@ -310,23 +310,23 @@ int http_parse_querystring(const char *txt_, void (*fn)(const char *name, const
718 printf("Out of memory\n");
719 exit(1);
720 }
721- while((c=*t) != '\0') {
722- if (c=='=') {
723+ while ((c=*t) != '\0') {
724+ if (c == '=') {
725 *t = '\0';
726- value = t+1;
727- } else if (c=='+') {
728+ value = t + 1;
729+ } else if (c == '+') {
730 *t = ' ';
731- } else if (c=='%') {
732+ } else if (c == '%') {
733 t = convert_query_hexchar(t);
734- } else if (c=='&') {
735+ } else if (c == '&') {
736 *t = '\0';
737 (*fn)(txt, value);
738- txt = t+1;
739+ txt = t + 1;
740 value = NULL;
741 }
742 t++;
743 }
744- if (t!=txt)
745+ if (t != txt)
746 (*fn)(txt, value);
747 free(o);
748 return 0;
749diff --git a/parsing.c b/parsing.c
750index 1b2a551..9b7efb3 100644
751--- a/parsing.c
752+++ b/parsing.c
753@@ -112,7 +112,7 @@ const char *reencode(char **txt, const char *src_enc, const char *dst_enc)
754 return *txt;
755
756 /* no encoding needed if src_enc equals dst_enc */
757- if(!strcasecmp(src_enc, dst_enc))
758+ if (!strcasecmp(src_enc, dst_enc))
759 return *txt;
760
761 tmp = reencode_string(*txt, dst_enc, src_enc);
762@@ -170,7 +170,7 @@ struct commitinfo *cgit_parse_commit(struct commit *commit)
763 }
764
765 /* if no special encoding is found, assume UTF-8 */
766- if(!ret->msg_encoding)
767+ if (!ret->msg_encoding)
768 ret->msg_encoding = xstrdup("UTF-8");
769
770 // skip unknown header fields
771diff --git a/scan-tree.c b/scan-tree.c
772index 6ce8036..10d90f4 100644
773--- a/scan-tree.c
774+++ b/scan-tree.c
775@@ -106,7 +106,7 @@ static void add_repo(const char *base, const char *path, repo_config_fn fn)
776 config_fn = fn;
777 if (ctx.cfg.enable_git_config)
778 git_config_from_file(gitconfig_config, fmt("%s/config", path), NULL);
779-
780+
781 if (ctx.cfg.remove_suffix)
782 if ((p = strrchr(repo->url, '.')) && !strcmp(p, ".git"))
783 *p = '\0';
784@@ -185,7 +185,7 @@ static void scan_path(const char *base, const char *path, repo_config_fn fn)
785 add_repo(base, fmt("%s/.git", path), fn);
786 goto end;
787 }
788- while((ent = readdir(dir)) != NULL) {
789+ while ((ent = readdir(dir)) != NULL) {
790 if (ent->d_name[0] == '.') {
791 if (ent->d_name[1] == '\0')
792 continue;
793@@ -222,7 +222,7 @@ void scan_projects(const char *path, const char *projectsfile, repo_config_fn fn
794 char line[MAX_PATH * 2], *z;
795 FILE *projects;
796 int err;
797-
798+
799 projects = fopen(projectsfile, "r");
800 if (!projects) {
801 fprintf(stderr, "Error opening projectsfile %s: %s (%d)\n",
802diff --git a/shared.c b/shared.c
803index 8e5ae48..e732064 100644
804--- a/shared.c
805+++ b/shared.c
806@@ -28,8 +28,8 @@ int chk_positive(int result, char *msg)
807
808 int chk_non_negative(int result, char *msg)
809 {
810- if (result < 0)
811- die("%s: %s",msg, strerror(errno));
812+ if (result < 0)
813+ die("%s: %s", msg, strerror(errno));
814 return result;
815 }
816
817@@ -80,7 +80,7 @@ struct cgit_repo *cgit_get_repoinfo(const char *url)
818 int i;
819 struct cgit_repo *repo;
820
821- for (i=0; i<cgit_repolist.count; i++) {
822+ for (i = 0; i < cgit_repolist.count; i++) {
823 repo = &cgit_repolist.repos[i];
824 if (!strcmp(repo->url, url))
825 return repo;
826@@ -108,7 +108,7 @@ char *trim_end(const char *str, char c)
827 if (str == NULL)
828 return NULL;
829 len = strlen(str);
830- while(len > 0 && str[len - 1] == c)
831+ while (len > 0 && str[len - 1] == c)
832 len--;
833 if (len == 0)
834 return NULL;
835@@ -207,7 +207,7 @@ static int load_mmfile(mmfile_t *file, const unsigned char *sha1)
836 file->ptr = (char *)"";
837 file->size = 0;
838 } else {
839- file->ptr = read_sha1_file(sha1, &type,
840+ file->ptr = read_sha1_file(sha1, &type,
841 (unsigned long *)&file->size);
842 }
843 return 1;
844@@ -307,7 +307,7 @@ void cgit_diff_tree(const unsigned char *old_sha1,
845 filepair_fn fn, const char *prefix, int ignorews)
846 {
847 struct diff_options opt;
848- int prefixlen;
849+ struct pathspec_item item;
850
851 diff_setup(&opt);
852 opt.output_format = DIFF_FORMAT_CALLBACK;
853@@ -319,10 +319,10 @@ void cgit_diff_tree(const unsigned char *old_sha1,
854 opt.format_callback = cgit_diff_tree_cb;
855 opt.format_callback_data = fn;
856 if (prefix) {
857- opt.nr_paths = 1;
858- opt.paths = &prefix;
859- prefixlen = strlen(prefix);
860- opt.pathlens = &prefixlen;
861+ item.match = prefix;
862+ item.len = strlen(prefix);
863+ opt.pathspec.nr = 1;
864+ opt.pathspec.items = &item;
865 }
866 diff_setup_done(&opt);
867
868@@ -351,17 +351,17 @@ int cgit_parse_snapshots_mask(const char *str)
869 int tl, sl, rv = 0;
870
871 /* favor legacy setting */
872- if(atoi(str))
873+ if (atoi(str))
874 return 1;
875- for(;;) {
876- str += strspn(str,delim);
877- tl = strcspn(str,delim);
878+ for (;;) {
879+ str += strspn(str, delim);
880+ tl = strcspn(str, delim);
881 if (!tl)
882 break;
883 for (f = cgit_snapshot_formats; f->suffix; f++) {
884 sl = strlen(f->suffix);
885- if((tl == sl && !strncmp(f->suffix, str, tl)) ||
886- (tl == sl-1 && !strncmp(f->suffix+1, str, tl-1))) {
887+ if ((tl == sl && !strncmp(f->suffix, str, tl)) ||
888+ (tl == sl - 1 && !strncmp(f->suffix + 1, str, tl - 1))) {
889 rv |= f->bit;
890 break;
891 }
892diff --git a/tests/t0101-index.sh b/tests/t0101-index.sh
893index 573a351..ab63aca 100755
894--- a/tests/t0101-index.sh
895+++ b/tests/t0101-index.sh
896@@ -5,14 +5,14 @@
897 prepare_tests "Check content on index page"
898
899 run_test 'generate index page' 'cgit_url "" >trash/tmp'
900-run_test 'find foo repo' 'grep -e "foo" trash/tmp'
901-run_test 'find foo description' 'grep -e "\[no description\]" trash/tmp'
902-run_test 'find bar repo' 'grep -e "bar" trash/tmp'
903-run_test 'find bar description' 'grep -e "the bar repo" trash/tmp'
904-run_test 'find foo+bar repo' 'grep -e ">foo+bar<" trash/tmp'
905-run_test 'verify foo+bar link' 'grep -e "/foo+bar/" trash/tmp'
906-run_test 'verify "with%20space" link' 'grep -e "/with%20space/" trash/tmp'
907-run_test 'no tree-link' '! grep -e "foo/tree" trash/tmp'
908-run_test 'no log-link' '! grep -e "foo/log" trash/tmp'
909+run_test 'find foo repo' 'grep "foo" trash/tmp'
910+run_test 'find foo description' 'grep "\[no description\]" trash/tmp'
911+run_test 'find bar repo' 'grep "bar" trash/tmp'
912+run_test 'find bar description' 'grep "the bar repo" trash/tmp'
913+run_test 'find foo+bar repo' 'grep ">foo+bar<" trash/tmp'
914+run_test 'verify foo+bar link' 'grep "/foo+bar/" trash/tmp'
915+run_test 'verify "with%20space" link' 'grep "/with%20space/" trash/tmp'
916+run_test 'no tree-link' '! grep "foo/tree" trash/tmp'
917+run_test 'no log-link' '! grep "foo/log" trash/tmp'
918
919 tests_done
920diff --git a/tests/t0102-summary.sh b/tests/t0102-summary.sh
921index f299c5a..f778cb4 100755
922--- a/tests/t0102-summary.sh
923+++ b/tests/t0102-summary.sh
924@@ -5,22 +5,22 @@
925 prepare_tests "Check content on summary page"
926
927 run_test 'generate foo summary' 'cgit_url "foo" >trash/tmp'
928-run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
929-run_test 'find commit 5' 'grep -e "commit 5" trash/tmp'
930-run_test 'find branch master' 'grep -e "master" trash/tmp'
931-run_test 'no tags' '! grep -e "tags" trash/tmp'
932+run_test 'find commit 1' 'grep "commit 1" trash/tmp'
933+run_test 'find commit 5' 'grep "commit 5" trash/tmp'
934+run_test 'find branch master' 'grep "master" trash/tmp'
935+run_test 'no tags' '! grep "tags" trash/tmp'
936 run_test 'clone-url expanded correctly' '
937- grep -e "git://example.org/foo.git" trash/tmp
938+ grep "git://example.org/foo.git" trash/tmp
939 '
940
941 run_test 'generate bar summary' 'cgit_url "bar" >trash/tmp'
942-run_test 'no commit 45' '! grep -e "commit 45" trash/tmp'
943-run_test 'find commit 46' 'grep -e "commit 46" trash/tmp'
944-run_test 'find commit 50' 'grep -e "commit 50" trash/tmp'
945-run_test 'find branch master' 'grep -e "master" trash/tmp'
946-run_test 'no tags' '! grep -e "tags" trash/tmp'
947+run_test 'no commit 45' '! grep "commit 45" trash/tmp'
948+run_test 'find commit 46' 'grep "commit 46" trash/tmp'
949+run_test 'find commit 50' 'grep "commit 50" trash/tmp'
950+run_test 'find branch master' 'grep "master" trash/tmp'
951+run_test 'no tags' '! grep "tags" trash/tmp'
952 run_test 'clone-url expanded correctly' '
953- grep -e "git://example.org/bar.git" trash/tmp
954+ grep "git://example.org/bar.git" trash/tmp
955 '
956
957 tests_done
958diff --git a/tests/t0103-log.sh b/tests/t0103-log.sh
959index 7fa6754..67fcba0 100755
960--- a/tests/t0103-log.sh
961+++ b/tests/t0103-log.sh
962@@ -5,21 +5,21 @@
963 prepare_tests "Check content on log page"
964
965 run_test 'generate foo/log' 'cgit_url "foo/log" >trash/tmp'
966-run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
967-run_test 'find commit 5' 'grep -e "commit 5" trash/tmp'
968+run_test 'find commit 1' 'grep "commit 1" trash/tmp'
969+run_test 'find commit 5' 'grep "commit 5" trash/tmp'
970
971 run_test 'generate bar/log' 'cgit_url "bar/log" >trash/tmp'
972-run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
973-run_test 'find commit 50' 'grep -e "commit 50" trash/tmp'
974+run_test 'find commit 1' 'grep "commit 1" trash/tmp'
975+run_test 'find commit 50' 'grep "commit 50" trash/tmp'
976
977 run_test 'generate "with%20space/log?qt=grep&q=commit+1"' '
978 cgit_url "with+space/log&qt=grep&q=commit+1" >trash/tmp
979 '
980-run_test 'find commit 1' 'grep -e "commit 1" trash/tmp'
981-run_test 'find link with %20 in path' 'grep -e "/with%20space/log/?qt=grep" trash/tmp'
982-run_test 'find link with + in arg' 'grep -e "/log/?qt=grep&amp;q=commit+1" trash/tmp'
983-run_test 'no links with space in path' '! grep -e "href=./with space/" trash/tmp'
984-run_test 'no links with space in arg' '! grep -e "q=commit 1" trash/tmp'
985-run_test 'commit 2 is not visible' '! grep -e "commit 2" trash/tmp'
986+run_test 'find commit 1' 'grep "commit 1" trash/tmp'
987+run_test 'find link with %20 in path' 'grep "/with%20space/log/?qt=grep" trash/tmp'
988+run_test 'find link with + in arg' 'grep "/log/?qt=grep&amp;q=commit+1" trash/tmp'
989+run_test 'no links with space in path' '! grep "href=./with space/" trash/tmp'
990+run_test 'no links with space in arg' '! grep "q=commit 1" trash/tmp'
991+run_test 'commit 2 is not visible' '! grep "commit 2" trash/tmp'
992
993 tests_done
994diff --git a/tests/t0104-tree.sh b/tests/t0104-tree.sh
995index 2ce1251..7aa3b8d 100755
996--- a/tests/t0104-tree.sh
997+++ b/tests/t0104-tree.sh
998@@ -5,29 +5,29 @@
999 prepare_tests "Check content on tree page"
1000
1001 run_test 'generate bar/tree' 'cgit_url "bar/tree" >trash/tmp'
1002-run_test 'find file-1' 'grep -e "file-1" trash/tmp'
1003-run_test 'find file-50' 'grep -e "file-50" trash/tmp'
1004+run_test 'find file-1' 'grep "file-1" trash/tmp'
1005+run_test 'find file-50' 'grep "file-50" trash/tmp'
1006
1007 run_test 'generate bar/tree/file-50' 'cgit_url "bar/tree/file-50" >trash/tmp'
1008
1009 run_test 'find line 1' '
1010- grep -e "<a class=.no. id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp
1011+ grep "<a class=.no. id=.n1. name=.n1. href=.#n1.>1</a>" trash/tmp
1012 '
1013
1014 run_test 'no line 2' '
1015- ! grep -e "<a class=.no. id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp
1016+ ! grep "<a class=.no. id=.n2. name=.n2. href=.#n2.>2</a>" trash/tmp
1017 '
1018
1019 run_test 'generate foo+bar/tree' 'cgit_url "foo%2bbar/tree" >trash/tmp'
1020
1021 run_test 'verify a+b link' '
1022- grep -e "/foo+bar/tree/a+b" trash/tmp
1023+ grep "/foo+bar/tree/a+b" trash/tmp
1024 '
1025
1026 run_test 'generate foo+bar/tree?h=1+2' 'cgit_url "foo%2bbar/tree&h=1%2b2" >trash/tmp'
1027
1028 run_test 'verify a+b?h=1+2 link' '
1029- grep -e "/foo+bar/tree/a+b?h=1%2b2" trash/tmp
1030+ grep "/foo+bar/tree/a+b?h=1%2b2" trash/tmp
1031 '
1032
1033 tests_done
1034diff --git a/tests/t0105-commit.sh b/tests/t0105-commit.sh
1035index ae794c8..31b554b 100755
1036--- a/tests/t0105-commit.sh
1037+++ b/tests/t0105-commit.sh
1038@@ -5,33 +5,33 @@
1039 prepare_tests "Check content on commit page"
1040
1041 run_test 'generate foo/commit' 'cgit_url "foo/commit" >trash/tmp'
1042-run_test 'find tree link' 'grep -e "<a href=./foo/tree/.>" trash/tmp'
1043+run_test 'find tree link' 'grep "<a href=./foo/tree/.>" trash/tmp'
1044 run_test 'find parent link' 'grep -E "<a href=./foo/commit/\?id=.+>" trash/tmp'
1045
1046 run_test 'find commit subject' '
1047- grep -e "<div class=.commit-subject.>commit 5<" trash/tmp
1048+ grep "<div class=.commit-subject.>commit 5<" trash/tmp
1049 '
1050
1051-run_test 'find commit msg' 'grep -e "<div class=.commit-msg.></div>" trash/tmp'
1052-run_test 'find diffstat' 'grep -e "<table summary=.diffstat. class=.diffstat.>" trash/tmp'
1053+run_test 'find commit msg' 'grep "<div class=.commit-msg.></div>" trash/tmp'
1054+run_test 'find diffstat' 'grep "<table summary=.diffstat. class=.diffstat.>" trash/tmp'
1055
1056 run_test 'find diff summary' '
1057- grep -e "1 files changed, 1 insertions, 0 deletions" trash/tmp
1058+ grep "1 files changed, 1 insertions, 0 deletions" trash/tmp
1059 '
1060
1061 run_test 'get root commit' '
1062- root=$(cd trash/repos/foo && git rev-list --reverse HEAD | head -1) &&
1063- cgit_url "foo/commit&id=$root" >trash/tmp &&
1064- grep "</html>" trash/tmp
1065+ root=$(cd trash/repos/foo && git rev-list --reverse HEAD | head -1) &&
1066+ cgit_url "foo/commit&id=$root" >trash/tmp &&
1067+ grep "</html>" trash/tmp
1068 '
1069
1070 run_test 'root commit contains diffstat' '
1071- grep "<a href=./foo/diff/file-1.id=[0-9a-f]\{40\}.>file-1</a>" trash/tmp
1072+ grep "<a href=./foo/diff/file-1.id=[0-9a-f]\{40\}.>file-1</a>" trash/tmp
1073 '
1074
1075 run_test 'root commit contains diff' '
1076- grep ">diff --git a/file-1 b/file-1<" trash/tmp &&
1077- grep -e "<div class=.add.>+1</div>" trash/tmp
1078+ grep ">diff --git a/file-1 b/file-1<" trash/tmp &&
1079+ grep "<div class=.add.>+1</div>" trash/tmp
1080 '
1081
1082 tests_done
1083diff --git a/tests/t0106-diff.sh b/tests/t0106-diff.sh
1084index e140bcc..eee0c8c 100755
1085--- a/tests/t0106-diff.sh
1086+++ b/tests/t0106-diff.sh
1087@@ -5,16 +5,16 @@
1088 prepare_tests "Check content on diff page"
1089
1090 run_test 'generate foo/diff' 'cgit_url "foo/diff" >trash/tmp'
1091-run_test 'find diff header' 'grep -e "a/file-5 b/file-5" trash/tmp'
1092-run_test 'find blob link' 'grep -e "<a href=./foo/tree/file-5?id=" trash/tmp'
1093-run_test 'find added file' 'grep -e "new file mode 100644" trash/tmp'
1094+run_test 'find diff header' 'grep "a/file-5 b/file-5" trash/tmp'
1095+run_test 'find blob link' 'grep "<a href=./foo/tree/file-5?id=" trash/tmp'
1096+run_test 'find added file' 'grep "new file mode 100644" trash/tmp'
1097
1098 run_test 'find hunk header' '
1099- grep -e "<div class=.hunk.>@@ -0,0 +1 @@</div>" trash/tmp
1100+ grep "<div class=.hunk.>@@ -0,0 +1 @@</div>" trash/tmp
1101 '
1102
1103 run_test 'find added line' '
1104- grep -e "<div class=.add.>+5</div>" trash/tmp
1105+ grep "<div class=.add.>+5</div>" trash/tmp
1106 '
1107
1108 tests_done
1109diff --git a/tests/t0107-snapshot.sh b/tests/t0107-snapshot.sh
1110index 8ab4912..132d2e9 100755
1111--- a/tests/t0107-snapshot.sh
1112+++ b/tests/t0107-snapshot.sh
1113@@ -10,17 +10,20 @@ run_test 'get foo/snapshot/master.tar.gz' '
1114
1115 run_test 'check html headers' '
1116 head -n 1 trash/tmp |
1117- grep -e "Content-Type: application/x-gzip" &&
1118+ grep "Content-Type: application/x-gzip" &&
1119
1120 head -n 2 trash/tmp |
1121- grep -e "Content-Disposition: inline; filename=.master.tar.gz."
1122+ grep "Content-Disposition: inline; filename=.master.tar.gz."
1123 '
1124
1125 run_test 'strip off the header lines' '
1126- tail -n +6 trash/tmp > trash/master.tar.gz
1127+ tail -n +6 trash/tmp > trash/master.tar.gz
1128+'
1129+
1130+run_test 'verify gzip format' '
1131+ gunzip --test trash/master.tar.gz
1132 '
1133
1134-run_test 'verify gzip format' 'gunzip --test trash/master.tar.gz'
1135 run_test 'untar' '
1136 rm -rf trash/master &&
1137 tar -xf trash/master.tar.gz -C trash
1138@@ -32,7 +35,42 @@ run_test 'count files' '
1139 '
1140
1141 run_test 'verify untarred file-5' '
1142- grep -e "^5$" trash/master/file-5 &&
1143+ grep "^5$" trash/master/file-5 &&
1144+ test $(cat trash/master/file-5 | wc -l) = 1
1145+'
1146+
1147+run_test 'get foo/snapshot/master.zip' '
1148+ cgit_url "foo/snapshot/master.zip" >trash/tmp
1149+'
1150+
1151+run_test 'check HTML headers (zip)' '
1152+ head -n 1 trash/tmp |
1153+ grep "Content-Type: application/x-zip" &&
1154+
1155+ head -n 2 trash/tmp |
1156+ grep "Content-Disposition: inline; filename=.master.zip."
1157+'
1158+
1159+run_test 'strip off the header lines (zip)' '
1160+ tail -n +6 trash/tmp >trash/master.zip
1161+'
1162+
1163+run_test 'verify zip format' '
1164+ unzip -t trash/master.zip
1165+'
1166+
1167+run_test 'unzip' '
1168+ rm -rf trash/master &&
1169+ unzip trash/master.zip -d trash
1170+'
1171+
1172+run_test 'count files (zip)' '
1173+ c=$(ls -1 trash/master/ | wc -l) &&
1174+ test $c = 5
1175+'
1176+
1177+run_test 'verify unzipped file-5' '
1178+ grep "^5$" trash/master/file-5 &&
1179 test $(cat trash/master/file-5 | wc -l) = 1
1180 '
1181
1182diff --git a/tests/t0108-patch.sh b/tests/t0108-patch.sh
1183index 6ee70b3..f92f69c 100755
1184--- a/tests/t0108-patch.sh
1185+++ b/tests/t0108-patch.sh
1186@@ -9,19 +9,19 @@ run_test 'generate foo/patch' '
1187 '
1188
1189 run_test 'find `From:` line' '
1190- grep -e "^From: " trash/tmp
1191+ grep "^From: " trash/tmp
1192 '
1193
1194 run_test 'find `Date:` line' '
1195- grep -e "^Date: " trash/tmp
1196+ grep "^Date: " trash/tmp
1197 '
1198
1199 run_test 'find `Subject:` line' '
1200- grep -e "^Subject: commit 5" trash/tmp
1201+ grep "^Subject: commit 5" trash/tmp
1202 '
1203
1204 run_test 'find `cgit` signature' '
1205- tail -1 trash/tmp | grep -e "^cgit"
1206+ tail -1 trash/tmp | grep "^cgit"
1207 '
1208
1209 run_test 'find initial commit' '
1210@@ -33,7 +33,7 @@ run_test 'generate patch for initial commit' '
1211 '
1212
1213 run_test 'find `cgit` signature' '
1214- tail -1 trash/tmp | grep -e "^cgit"
1215+ tail -1 trash/tmp | grep "^cgit"
1216 '
1217
1218 tests_done
1219diff --git a/ui-blob.c b/ui-blob.c
1220index ec435e1..c59fbcb 100644
1221--- a/ui-blob.c
1222+++ b/ui-blob.c
1223@@ -11,17 +11,22 @@
1224 #include "html.h"
1225 #include "ui-shared.h"
1226
1227-static char *match_path;
1228-static unsigned char *matched_sha1;
1229-static int found_path;
1230+struct walk_tree_context {
1231+ char *match_path;
1232+ unsigned char *matched_sha1;
1233+ int found_path;
1234+};
1235
1236-static int walk_tree(const unsigned char *sha1, const char *base,int baselen,
1237- const char *pathname, unsigned mode, int stage, void *cbdata) {
1238- if(strncmp(base,match_path,baselen)
1239- || strcmp(match_path+baselen,pathname) )
1240+static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
1241+ const char *pathname, unsigned mode, int stage, void *cbdata)
1242+{
1243+ struct walk_tree_context *walk_tree_ctx = cbdata;
1244+
1245+ if (strncmp(base, walk_tree_ctx->match_path, baselen)
1246+ || strcmp(walk_tree_ctx->match_path + baselen, pathname))
1247 return READ_TREE_RECURSIVE;
1248- memmove(matched_sha1,sha1,20);
1249- found_path = 1;
1250+ memmove(walk_tree_ctx->matched_sha1, sha1, 20);
1251+ walk_tree_ctx->found_path = 1;
1252 return 0;
1253 }
1254
1255@@ -32,17 +37,27 @@ int cgit_print_file(char *path, const char *head)
1256 char *buf;
1257 unsigned long size;
1258 struct commit *commit;
1259- const char *paths[] = {path, NULL};
1260+ struct pathspec_item path_items = {
1261+ .match = path,
1262+ .len = strlen(path)
1263+ };
1264+ struct pathspec paths = {
1265+ .nr = 1,
1266+ .items = &path_items
1267+ };
1268+ struct walk_tree_context walk_tree_ctx = {
1269+ .match_path = path,
1270+ .matched_sha1 = sha1,
1271+ .found_path = 0
1272+ };
1273+
1274 if (get_sha1(head, sha1))
1275 return -1;
1276 type = sha1_object_info(sha1, &size);
1277- if(type == OBJ_COMMIT && path) {
1278+ if (type == OBJ_COMMIT && path) {
1279 commit = lookup_commit_reference(sha1);
1280- match_path = path;
1281- matched_sha1 = sha1;
1282- found_path = 0;
1283- read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
1284- if (!found_path)
1285+ read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
1286+ if (!walk_tree_ctx.found_path)
1287 return -1;
1288 type = sha1_object_info(sha1, &size);
1289 }
1290@@ -63,15 +78,26 @@ void cgit_print_blob(const char *hex, char *path, const char *head)
1291 char *buf;
1292 unsigned long size;
1293 struct commit *commit;
1294- const char *paths[] = {path, NULL};
1295+ struct pathspec_item path_items = {
1296+ .match = path,
1297+ .len = strlen(path)
1298+ };
1299+ struct pathspec paths = {
1300+ .nr = 1,
1301+ .items = &path_items
1302+ };
1303+ struct walk_tree_context walk_tree_ctx = {
1304+ .match_path = path,
1305+ .matched_sha1 = sha1,
1306+ };
1307
1308 if (hex) {
1309- if (get_sha1_hex(hex, sha1)){
1310+ if (get_sha1_hex(hex, sha1)) {
1311 cgit_print_error(fmt("Bad hex value: %s", hex));
1312 return;
1313 }
1314 } else {
1315- if (get_sha1(head,sha1)) {
1316+ if (get_sha1(head, sha1)) {
1317 cgit_print_error(fmt("Bad ref: %s", head));
1318 return;
1319 }
1320@@ -79,11 +105,9 @@ void cgit_print_blob(const char *hex, char *path, const char *head)
1321
1322 type = sha1_object_info(sha1, &size);
1323
1324- if((!hex) && type == OBJ_COMMIT && path) {
1325+ if ((!hex) && type == OBJ_COMMIT && path) {
1326 commit = lookup_commit_reference(sha1);
1327- match_path = path;
1328- matched_sha1 = sha1;
1329- read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
1330+ read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
1331 type = sha1_object_info(sha1,&size);
1332 }
1333
1334diff --git a/ui-clone.c b/ui-clone.c
1335index 81e7a4e..fdea24f 100644
1336--- a/ui-clone.c
1337+++ b/ui-clone.c
1338@@ -19,12 +19,10 @@ static int print_ref_info(const char *refname, const unsigned char *sha1,
1339 if (!(obj = parse_object(sha1)))
1340 return 0;
1341
1342- if (!strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/"))
1343- htmlf("%s\t%s\n", sha1_to_hex(sha1), refname);
1344- else if (!prefixcmp(refname, "refs/tags") && obj->type == OBJ_TAG) {
1345+ htmlf("%s\t%s\n", sha1_to_hex(sha1), refname);
1346+ if (obj->type == OBJ_TAG) {
1347 if (!(obj = deref_tag(obj, refname, 0)))
1348 return 0;
1349- htmlf("%s\t%s\n", sha1_to_hex(sha1), refname);
1350 htmlf("%s\t%s^{}\n", sha1_to_hex(obj->sha1), refname);
1351 }
1352 return 0;
1353diff --git a/ui-commit.c b/ui-commit.c
1354index 536a8e8..74f37c8 100644
1355--- a/ui-commit.c
1356+++ b/ui-commit.c
1357@@ -39,7 +39,7 @@ void cgit_print_commit(char *hex, const char *prefix)
1358 format_note(NULL, sha1, &notes, PAGE_ENCODING, 0);
1359
1360 load_ref_decorations(DECORATE_FULL_REFS);
1361-
1362+
1363 cgit_print_diff_ctrls();
1364 html("<table summary='commit info' class='commit-info'>\n");
1365 html("<tr><th>author</th><td>");
1366@@ -75,7 +75,7 @@ void cgit_print_commit(char *hex, const char *prefix)
1367 cgit_tree_link(prefix, NULL, NULL, ctx.qry.head, tmp, prefix);
1368 }
1369 html("</td></tr>\n");
1370- for (p = commit->parents; p ; p = p->next) {
1371+ for (p = commit->parents; p; p = p->next) {
1372 parent = lookup_commit_reference(p->item->object.sha1);
1373 if (!parent) {
1374 html("<tr><td colspan='3'>");
1375diff --git a/ui-diff.c b/ui-diff.c
1376index 3d46da2..49e5b46 100644
1377--- a/ui-diff.c
1378+++ b/ui-diff.c
1379@@ -184,7 +184,7 @@ void cgit_print_diffstat(const unsigned char *old_sha1,
1380 max_changes = 0;
1381 cgit_diff_tree(old_sha1, new_sha1, inspect_filepair, prefix,
1382 ctx.qry.ignorews);
1383- for(i = 0; i<files; i++)
1384+ for (i = 0; i<files; i++)
1385 print_fileinfo(&items[i]);
1386 html("</table>");
1387 html("<div class='diffstat-summary'>");
1388diff --git a/ui-plain.c b/ui-plain.c
1389index 85877d7..8ef4ec6 100644
1390--- a/ui-plain.c
1391+++ b/ui-plain.c
1392@@ -11,8 +11,10 @@
1393 #include "html.h"
1394 #include "ui-shared.h"
1395
1396-int match_baselen;
1397-int match;
1398+struct walk_tree_context {
1399+ int match_baselen;
1400+ int match;
1401+};
1402
1403 static char *get_mimetype_from_file(const char *filename, const char *ext)
1404 {
1405@@ -54,7 +56,7 @@ static char *get_mimetype_from_file(const char *filename, const char *ext)
1406 return result;
1407 }
1408
1409-static void print_object(const unsigned char *sha1, const char *path)
1410+static int print_object(const unsigned char *sha1, const char *path)
1411 {
1412 enum object_type type;
1413 char *buf, *ext;
1414@@ -65,13 +67,13 @@ static void print_object(const unsigned char *sha1, const char *path)
1415 type = sha1_object_info(sha1, &size);
1416 if (type == OBJ_BAD) {
1417 html_status(404, "Not found", 0);
1418- return;
1419+ return 0;
1420 }
1421
1422 buf = read_sha1_file(sha1, &type, &size);
1423 if (!buf) {
1424 html_status(404, "Not found", 0);
1425- return;
1426+ return 0;
1427 }
1428 ctx.page.mimetype = NULL;
1429 ext = strrchr(path, '.');
1430@@ -97,9 +99,9 @@ static void print_object(const unsigned char *sha1, const char *path)
1431 ctx.page.etag = sha1_to_hex(sha1);
1432 cgit_print_http_headers(&ctx);
1433 html_raw(buf, size);
1434- match = 1;
1435 if (freemime)
1436 free(ctx.page.mimetype);
1437+ return 1;
1438 }
1439
1440 static char *buildpath(const char *base, int baselen, const char *path)
1441@@ -138,7 +140,6 @@ static void print_dir(const unsigned char *sha1, const char *base,
1442 fullpath);
1443 html("</li>\n");
1444 }
1445- match = 2;
1446 }
1447
1448 static void print_dir_entry(const unsigned char *sha1, const char *base,
1449@@ -156,7 +157,6 @@ static void print_dir_entry(const unsigned char *sha1, const char *base,
1450 cgit_plain_link(path, NULL, NULL, ctx.qry.head, ctx.qry.sha1,
1451 fullpath);
1452 html("</li>\n");
1453- match = 2;
1454 }
1455
1456 static void print_dir_tail(void)
1457@@ -168,18 +168,23 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
1458 const char *pathname, unsigned mode, int stage,
1459 void *cbdata)
1460 {
1461- if (baselen == match_baselen) {
1462- if (S_ISREG(mode))
1463- print_object(sha1, pathname);
1464- else if (S_ISDIR(mode)) {
1465+ struct walk_tree_context *walk_tree_ctx = cbdata;
1466+
1467+ if (baselen == walk_tree_ctx->match_baselen) {
1468+ if (S_ISREG(mode)) {
1469+ if (print_object(sha1, pathname))
1470+ walk_tree_ctx->match = 1;
1471+ } else if (S_ISDIR(mode)) {
1472 print_dir(sha1, base, baselen, pathname);
1473+ walk_tree_ctx->match = 2;
1474 return READ_TREE_RECURSIVE;
1475 }
1476- }
1477- else if (baselen > match_baselen)
1478+ } else if (baselen > walk_tree_ctx->match_baselen) {
1479 print_dir_entry(sha1, base, baselen, pathname, mode);
1480- else if (S_ISDIR(mode))
1481+ walk_tree_ctx->match = 2;
1482+ } else if (S_ISDIR(mode)) {
1483 return READ_TREE_RECURSIVE;
1484+ }
1485
1486 return 0;
1487 }
1488@@ -197,7 +202,17 @@ void cgit_print_plain(struct cgit_context *ctx)
1489 const char *rev = ctx->qry.sha1;
1490 unsigned char sha1[20];
1491 struct commit *commit;
1492- const char *paths[] = {ctx->qry.path, NULL};
1493+ struct pathspec_item path_items = {
1494+ .match = ctx->qry.path,
1495+ .len = ctx->qry.path ? strlen(ctx->qry.path) : 0
1496+ };
1497+ struct pathspec paths = {
1498+ .nr = 1,
1499+ .items = &path_items
1500+ };
1501+ struct walk_tree_context walk_tree_ctx = {
1502+ .match = 0
1503+ };
1504
1505 if (!rev)
1506 rev = ctx->qry.head;
1507@@ -211,16 +226,17 @@ void cgit_print_plain(struct cgit_context *ctx)
1508 html_status(404, "Not found", 0);
1509 return;
1510 }
1511- if (!paths[0]) {
1512- paths[0] = "";
1513- match_baselen = -1;
1514+ if (!path_items.match) {
1515+ path_items.match = "";
1516+ walk_tree_ctx.match_baselen = -1;
1517 print_dir(commit->tree->object.sha1, "", 0, "");
1518+ walk_tree_ctx.match = 2;
1519 }
1520 else
1521- match_baselen = basedir_len(paths[0]);
1522- read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
1523- if (!match)
1524+ walk_tree_ctx.match_baselen = basedir_len(path_items.match);
1525+ read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
1526+ if (!walk_tree_ctx.match)
1527 html_status(404, "Not found", 0);
1528- else if (match == 2)
1529+ else if (walk_tree_ctx.match == 2)
1530 print_dir_tail();
1531 }
1532diff --git a/ui-refs.c b/ui-refs.c
1533index caddfbc..ce06b08 100644
1534--- a/ui-refs.c
1535+++ b/ui-refs.c
1536@@ -200,7 +200,7 @@ void cgit_print_branches(int maxcount)
1537 qsort(list.refs, maxcount, sizeof(*list.refs), cmp_ref_name);
1538 }
1539
1540- for(i=0; i<maxcount; i++)
1541+ for (i = 0; i < maxcount; i++)
1542 print_branch(list.refs[i]);
1543
1544 if (maxcount < list.count)
1545@@ -224,7 +224,7 @@ void cgit_print_tags(int maxcount)
1546 else if (maxcount > list.count)
1547 maxcount = list.count;
1548 print_tag_header();
1549- for(i=0; i<maxcount; i++)
1550+ for (i = 0; i < maxcount; i++)
1551 print_tag(list.refs[i]);
1552
1553 if (maxcount < list.count)
1554diff --git a/ui-repolist.c b/ui-repolist.c
1555index dead1bf..1ae22aa 100644
1556--- a/ui-repolist.c
1557+++ b/ui-repolist.c
1558@@ -110,12 +110,13 @@ void print_sort_header(const char *title, const char *sort)
1559 htmlf("'>%s</a></th>", title);
1560 }
1561
1562-void print_header(int columns)
1563+void print_header()
1564 {
1565 html("<tr class='nohover'>");
1566 print_sort_header("Name", "name");
1567 print_sort_header("Description", "desc");
1568- print_sort_header("Owner", "owner");
1569+ if (ctx.cfg.enable_index_owner)
1570+ print_sort_header("Owner", "owner");
1571 print_sort_header("Idle", "idle");
1572 if (ctx.cfg.enable_index_links)
1573 html("<th class='left'>Links</th>");
1574@@ -128,10 +129,10 @@ void print_pager(int items, int pagelen, char *search, char *sort)
1575 int i, ofs;
1576 char *class = NULL;
1577 html("<div class='pager'>");
1578- for(i = 0, ofs = 0; ofs < items; i++, ofs = i * pagelen) {
1579+ for (i = 0, ofs = 0; ofs < items; i++, ofs = i * pagelen) {
1580 class = (ctx.qry.ofs == ofs) ? "current" : NULL;
1581- cgit_index_link(fmt("[%d]", i+1), fmt("Page %d", i+1), class,
1582- search, sort, ofs);
1583+ cgit_index_link(fmt("[%d]", i + 1), fmt("Page %d", i + 1),
1584+ class, search, sort, ofs);
1585 }
1586 html("</div>");
1587 }
1588@@ -239,13 +240,15 @@ int sort_repolist(char *field)
1589
1590 void cgit_print_repolist()
1591 {
1592- int i, columns = 4, hits = 0, header = 0;
1593+ int i, columns = 3, hits = 0, header = 0;
1594 char *last_section = NULL;
1595 char *section;
1596 int sorted = 0;
1597
1598 if (ctx.cfg.enable_index_links)
1599- columns++;
1600+ ++columns;
1601+ if (ctx.cfg.enable_index_owner)
1602+ ++columns;
1603
1604 ctx.page.title = ctx.cfg.root_title;
1605 cgit_print_http_headers(&ctx);
1606@@ -255,13 +258,13 @@ void cgit_print_repolist()
1607 if (ctx.cfg.index_header)
1608 html_include(ctx.cfg.index_header);
1609
1610- if(ctx.qry.sort)
1611+ if (ctx.qry.sort)
1612 sorted = sort_repolist(ctx.qry.sort);
1613 else if (ctx.cfg.section_sort)
1614 sort_repolist("section");
1615
1616 html("<table summary='repository list' class='list nowrap'>");
1617- for (i=0; i<cgit_repolist.count; i++) {
1618+ for (i = 0; i < cgit_repolist.count; i++) {
1619 ctx.repo = &cgit_repolist.repos[i];
1620 if (!(is_match(ctx.repo) && is_in_url(ctx.repo)))
1621 continue;
1622@@ -271,7 +274,7 @@ void cgit_print_repolist()
1623 if (hits > ctx.qry.ofs + ctx.cfg.max_repo_count)
1624 continue;
1625 if (!header++)
1626- print_header(columns);
1627+ print_header();
1628 section = ctx.repo->section;
1629 if (section && !strcmp(section, ""))
1630 section = NULL;
1631@@ -294,8 +297,10 @@ void cgit_print_repolist()
1632 html_ntxt(ctx.cfg.max_repodesc_len, ctx.repo->desc);
1633 html_link_close();
1634 html("</td><td>");
1635- html_txt(ctx.repo->owner);
1636- html("</td><td>");
1637+ if (ctx.cfg.enable_index_owner) {
1638+ html_txt(ctx.repo->owner);
1639+ html("</td><td>");
1640+ }
1641 print_modtime(ctx.repo);
1642 html("</td>");
1643 if (ctx.cfg.enable_index_links) {
1644diff --git a/ui-shared.c b/ui-shared.c
1645index 75b97a1..af5310b 100644
1646--- a/ui-shared.c
1647+++ b/ui-shared.c
1648@@ -23,7 +23,7 @@ static char *http_date(time_t t)
1649 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
1650 struct tm *tm = gmtime(&t);
1651 return fmt("%s, %02d %s %04d %02d:%02d:%02d GMT", day[tm->tm_wday],
1652- tm->tm_mday, month[tm->tm_mon], 1900+tm->tm_year,
1653+ tm->tm_mday, month[tm->tm_mon], 1900 + tm->tm_year,
1654 tm->tm_hour, tm->tm_min, tm->tm_sec);
1655 }
1656
1657@@ -93,7 +93,7 @@ char *cgit_fileurl(const char *reponame, const char *pagename,
1658 char *cgit_pageurl(const char *reponame, const char *pagename,
1659 const char *query)
1660 {
1661- return cgit_fileurl(reponame,pagename,0,query);
1662+ return cgit_fileurl(reponame, pagename, 0, query);
1663 }
1664
1665 const char *cgit_repobasename(const char *reponame)
1666@@ -102,21 +102,21 @@ const char *cgit_repobasename(const char *reponame)
1667 static char rvbuf[1024];
1668 int p;
1669 const char *rv;
1670- strncpy(rvbuf,reponame,sizeof(rvbuf));
1671- if(rvbuf[sizeof(rvbuf)-1])
1672+ strncpy(rvbuf, reponame, sizeof(rvbuf));
1673+ if (rvbuf[sizeof(rvbuf)-1])
1674 die("cgit_repobasename: truncated repository name '%s'", reponame);
1675 p = strlen(rvbuf)-1;
1676 /* strip trailing slashes */
1677- while(p && rvbuf[p]=='/') rvbuf[p--]=0;
1678+ while (p && rvbuf[p] == '/') rvbuf[p--] = 0;
1679 /* strip trailing .git */
1680- if(p>=3 && !strncmp(&rvbuf[p-3],".git",4)) {
1681+ if (p >= 3 && !strncmp(&rvbuf[p-3], ".git", 4)) {
1682 p -= 3; rvbuf[p--] = 0;
1683 }
1684 /* strip more trailing slashes if any */
1685- while( p && rvbuf[p]=='/') rvbuf[p--]=0;
1686+ while ( p && rvbuf[p] == '/') rvbuf[p--] = 0;
1687 /* find last slash in the remaining string */
1688 rv = strrchr(rvbuf,'/');
1689- if(rv)
1690+ if (rv)
1691 return ++rv;
1692 return rvbuf;
1693 }
1694@@ -499,7 +499,7 @@ void cgit_object_link(struct object *obj)
1695 shortrev = xstrdup(fullrev);
1696 shortrev[10] = '\0';
1697 if (obj->type == OBJ_COMMIT) {
1698- cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL,
1699+ cgit_commit_link(fmt("commit %s...", shortrev), NULL, NULL,
1700 ctx.qry.head, fullrev, NULL, 0);
1701 return;
1702 } else if (obj->type == OBJ_TREE)
1703@@ -564,6 +564,7 @@ void cgit_submodule_link(const char *class, char *path, const char *rev)
1704 html("'>");
1705 html_txt(path);
1706 html("</a>");
1707+ html_txt(fmt(" @ %.7s", rev));
1708 if (item && tail)
1709 path[len - 1] = tail;
1710 }
1711@@ -575,7 +576,7 @@ void cgit_print_date(time_t secs, const char *format, int local_time)
1712
1713 if (!secs)
1714 return;
1715- if(local_time)
1716+ if (local_time)
1717 time = localtime(&secs);
1718 else
1719 time = gmtime(&secs);
1720@@ -735,7 +736,7 @@ int print_archive_ref(const char *refname, const unsigned char *sha1,
1721
1722 if (prefixcmp(refname, "refs/archives"))
1723 return 0;
1724- strncpy(buf, refname+14, sizeof(buf));
1725+ strncpy(buf, refname + 14, sizeof(buf));
1726 obj = parse_object(sha1);
1727 if (!obj)
1728 return 1;
1729@@ -967,7 +968,7 @@ void cgit_print_snapshot_links(const char *repo, const char *head,
1730 {
1731 const struct cgit_snapshot_format* f;
1732 char *prefix;
1733- char *filename;
1734+ char *filename;
1735 unsigned char sha1[20];
1736
1737 if (get_sha1(fmt("refs/tags/%s", hex), sha1) == 0 &&
1738diff --git a/ui-snapshot.c b/ui-snapshot.c
1739index 47432bd..54e659c 100644
1740--- a/ui-snapshot.c
1741+++ b/ui-snapshot.c
1742@@ -11,7 +11,32 @@
1743 #include "html.h"
1744 #include "ui-shared.h"
1745
1746-static int write_compressed_tar_archive(struct archiver_args *args, char *filter_argv[])
1747+static int write_archive_type(const char *format, const char *hex, const char *prefix)
1748+{
1749+ struct argv_array argv = ARGV_ARRAY_INIT;
1750+ argv_array_push(&argv, "snapshot");
1751+ argv_array_push(&argv, format);
1752+ if (prefix) {
1753+ argv_array_push(&argv, "--prefix");
1754+ argv_array_push(&argv, fmt("%s/", prefix));
1755+ }
1756+ argv_array_push(&argv, hex);
1757+ return write_archive(argv.argc, argv.argv, NULL, 1, NULL, 0);
1758+}
1759+
1760+static int write_tar_archive(const char *hex, const char *prefix)
1761+{
1762+ return write_archive_type("--format=tar", hex, prefix);
1763+}
1764+
1765+static int write_zip_archive(const char *hex, const char *prefix)
1766+{
1767+ return write_archive_type("--format=zip", hex, prefix);
1768+}
1769+
1770+static int write_compressed_tar_archive(const char *hex,
1771+ const char *prefix,
1772+ char *filter_argv[])
1773 {
1774 int rv;
1775 struct cgit_filter f;
1776@@ -19,27 +44,27 @@ static int write_compressed_tar_archive(struct archiver_args *args, char *filter
1777 f.cmd = filter_argv[0];
1778 f.argv = filter_argv;
1779 cgit_open_filter(&f);
1780- rv = write_tar_archive(args);
1781+ rv = write_tar_archive(hex, prefix);
1782 cgit_close_filter(&f);
1783 return rv;
1784 }
1785
1786-static int write_tar_gzip_archive(struct archiver_args *args)
1787+static int write_tar_gzip_archive(const char *hex, const char *prefix)
1788 {
1789 char *argv[] = { "gzip", "-n", NULL };
1790- return write_compressed_tar_archive(args, argv);
1791+ return write_compressed_tar_archive(hex, prefix, argv);
1792 }
1793
1794-static int write_tar_bzip2_archive(struct archiver_args *args)
1795+static int write_tar_bzip2_archive(const char *hex, const char *prefix)
1796 {
1797 char *argv[] = { "bzip2", NULL };
1798- return write_compressed_tar_archive(args, argv);
1799+ return write_compressed_tar_archive(hex, prefix, argv);
1800 }
1801
1802-static int write_tar_xz_archive(struct archiver_args *args)
1803+static int write_tar_xz_archive(const char *hex, const char *prefix)
1804 {
1805 char *argv[] = { "xz", NULL };
1806- return write_compressed_tar_archive(args, argv);
1807+ return write_compressed_tar_archive(hex, prefix, argv);
1808 }
1809
1810 const struct cgit_snapshot_format cgit_snapshot_formats[] = {
1811@@ -48,7 +73,7 @@ const struct cgit_snapshot_format cgit_snapshot_formats[] = {
1812 { ".tar.bz2", "application/x-bzip2", write_tar_bzip2_archive, 0x04 },
1813 { ".tar", "application/x-tar", write_tar_archive, 0x08 },
1814 { ".tar.xz", "application/x-xz", write_tar_xz_archive, 0x10 },
1815- {}
1816+ { NULL }
1817 };
1818
1819 static const struct cgit_snapshot_format *get_format(const char *filename)
1820@@ -57,7 +82,7 @@ static const struct cgit_snapshot_format *get_format(const char *filename)
1821 int fl, sl;
1822
1823 fl = strlen(filename);
1824- for(fmt = cgit_snapshot_formats; fmt->suffix; fmt++) {
1825+ for (fmt = cgit_snapshot_formats; fmt->suffix; fmt++) {
1826 sl = strlen(fmt->suffix);
1827 if (sl >= fl)
1828 continue;
1829@@ -71,34 +96,20 @@ static int make_snapshot(const struct cgit_snapshot_format *format,
1830 const char *hex, const char *prefix,
1831 const char *filename)
1832 {
1833- struct archiver_args args;
1834- struct commit *commit;
1835 unsigned char sha1[20];
1836
1837- if(get_sha1(hex, sha1)) {
1838+ if (get_sha1(hex, sha1)) {
1839 cgit_print_error(fmt("Bad object id: %s", hex));
1840 return 1;
1841 }
1842- commit = lookup_commit_reference(sha1);
1843- if(!commit) {
1844+ if (!lookup_commit_reference(sha1)) {
1845 cgit_print_error(fmt("Not a commit reference: %s", hex));
1846 return 1;
1847 }
1848- memset(&args, 0, sizeof(args));
1849- if (prefix) {
1850- args.base = fmt("%s/", prefix);
1851- args.baselen = strlen(prefix) + 1;
1852- } else {
1853- args.base = "";
1854- args.baselen = 0;
1855- }
1856- args.tree = commit->tree;
1857- args.time = commit->date;
1858- args.compression_level = Z_DEFAULT_COMPRESSION;
1859 ctx.page.mimetype = xstrdup(format->mimetype);
1860 ctx.page.filename = xstrdup(filename);
1861 cgit_print_http_headers(&ctx);
1862- format->write_func(&args);
1863+ format->write_func(hex, prefix);
1864 return 0;
1865 }
1866
1867diff --git a/ui-ssdiff.c b/ui-ssdiff.c
1868index 7108779..3d3dad6 100644
1869--- a/ui-ssdiff.c
1870+++ b/ui-ssdiff.c
1871@@ -138,9 +138,8 @@ static char *replace_tabs(char *line)
1872 strcat(result, prev_buf);
1873 break;
1874 } else {
1875- strcat(result, " ");
1876- strncat(result, spaces, 8 - (strlen(result) % 8));
1877 strncat(result, prev_buf, cur_buf - prev_buf);
1878+ strncat(result, spaces, 8 - (strlen(result) % 8));
1879 }
1880 prev_buf = cur_buf + 1;
1881 }
1882diff --git a/ui-stats.c b/ui-stats.c
1883index 59f4c1e..9cf1dbd 100644
1884--- a/ui-stats.c
1885+++ b/ui-stats.c
1886@@ -23,21 +23,21 @@ static void trunc_week(struct tm *tm)
1887 {
1888 time_t t = timegm(tm);
1889 t -= ((tm->tm_wday + 6) % 7) * DAY_SECS;
1890- gmtime_r(&t, tm);
1891+ gmtime_r(&t, tm);
1892 }
1893
1894 static void dec_week(struct tm *tm)
1895 {
1896 time_t t = timegm(tm);
1897 t -= WEEK_SECS;
1898- gmtime_r(&t, tm);
1899+ gmtime_r(&t, tm);
1900 }
1901
1902 static void inc_week(struct tm *tm)
1903 {
1904 time_t t = timegm(tm);
1905 t += WEEK_SECS;
1906- gmtime_r(&t, tm);
1907+ gmtime_r(&t, tm);
1908 }
1909
1910 static char *pretty_week(struct tm *tm)
1911@@ -83,7 +83,7 @@ static char *pretty_month(struct tm *tm)
1912 static void trunc_quarter(struct tm *tm)
1913 {
1914 trunc_month(tm);
1915- while(tm->tm_mon % 3 != 0)
1916+ while (tm->tm_mon % 3 != 0)
1917 dec_month(tm);
1918 }
1919
1920@@ -153,7 +153,7 @@ int cgit_find_stats_period(const char *expr, struct cgit_period **period)
1921 if (periods[i].code == code || !strcmp(periods[i].name, expr)) {
1922 if (period)
1923 *period = &periods[i];
1924- return i+1;
1925+ return i + 1;
1926 }
1927 return 0;
1928 }
1929@@ -239,7 +239,7 @@ struct string_list collect_stats(struct cgit_context *ctx,
1930 init_revisions(&rev, NULL);
1931 rev.abbrev = DEFAULT_ABBREV;
1932 rev.commit_format = CMIT_FMT_DEFAULT;
1933- rev.no_merges = 1;
1934+ rev.max_parents = 1;
1935 rev.verbose_header = 1;
1936 rev.show_root_diff = 0;
1937 setup_revisions(argc, argv, &rev, NULL);
1938diff --git a/ui-tag.c b/ui-tag.c
1939index 39e4cb8..cab96b1 100644
1940--- a/ui-tag.c
1941+++ b/ui-tag.c
1942@@ -99,6 +99,6 @@ void cgit_print_tag(char *revname)
1943 if (ctx.repo->snapshots)
1944 print_download_links(revname);
1945 html("</table>\n");
1946- }
1947+ }
1948 return;
1949 }
1950diff --git a/ui-tree.c b/ui-tree.c
1951index b1adcc7..561f9e7 100644
1952--- a/ui-tree.c
1953+++ b/ui-tree.c
1954@@ -11,9 +11,11 @@
1955 #include "html.h"
1956 #include "ui-shared.h"
1957
1958-char *curr_rev;
1959-char *match_path;
1960-int header = 0;
1961+struct walk_tree_context {
1962+ char *curr_rev;
1963+ char *match_path;
1964+ int state;
1965+};
1966
1967 static void print_text_buffer(const char *name, char *buf, unsigned long size)
1968 {
1969@@ -27,10 +29,10 @@ static void print_text_buffer(const char *name, char *buf, unsigned long size)
1970 html("<tr><td class='linenumbers'><pre>");
1971 idx = 0;
1972 lineno = 0;
1973-
1974+
1975 if (size) {
1976 htmlf(numberfmt, ++lineno);
1977- while(idx < size - 1) { // skip absolute last newline
1978+ while (idx < size - 1) { // skip absolute last newline
1979 if (buf[idx] == '\n')
1980 htmlf(numberfmt, ++lineno);
1981 idx++;
1982@@ -84,7 +86,7 @@ static void print_binary_buffer(char *buf, unsigned long size)
1983 html("</table>\n");
1984 }
1985
1986-static void print_object(const unsigned char *sha1, char *path, const char *basename)
1987+static void print_object(const unsigned char *sha1, char *path, const char *basename, const char *rev)
1988 {
1989 enum object_type type;
1990 char *buf;
1991@@ -106,7 +108,7 @@ static void print_object(const unsigned char *sha1, char *path, const char *base
1992
1993 htmlf("blob: %s (", sha1_to_hex(sha1));
1994 cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
1995- curr_rev, path);
1996+ rev, path);
1997 html(")\n");
1998
1999 if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
2000@@ -126,6 +128,7 @@ static int ls_item(const unsigned char *sha1, const char *base, int baselen,
2001 const char *pathname, unsigned int mode, int stage,
2002 void *cbdata)
2003 {
2004+ struct walk_tree_context *walk_tree_ctx = cbdata;
2005 char *name;
2006 char *fullpath;
2007 char *class;
2008@@ -153,7 +156,7 @@ static int ls_item(const unsigned char *sha1, const char *base, int baselen,
2009 cgit_submodule_link("ls-mod", fullpath, sha1_to_hex(sha1));
2010 } else if (S_ISDIR(mode)) {
2011 cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head,
2012- curr_rev, fullpath);
2013+ walk_tree_ctx->curr_rev, fullpath);
2014 } else {
2015 class = strrchr(name, '.');
2016 if (class != NULL) {
2017@@ -161,19 +164,20 @@ static int ls_item(const unsigned char *sha1, const char *base, int baselen,
2018 } else
2019 class = "ls-blob";
2020 cgit_tree_link(name, NULL, class, ctx.qry.head,
2021- curr_rev, fullpath);
2022+ walk_tree_ctx->curr_rev, fullpath);
2023 }
2024 htmlf("</td><td class='ls-size'>%li</td>", size);
2025
2026 html("<td>");
2027- cgit_log_link("log", NULL, "button", ctx.qry.head, curr_rev,
2028- fullpath, 0, NULL, NULL, ctx.qry.showmsg);
2029+ cgit_log_link("log", NULL, "button", ctx.qry.head,
2030+ walk_tree_ctx->curr_rev, fullpath, 0, NULL, NULL,
2031+ ctx.qry.showmsg);
2032 if (ctx.repo->max_stats)
2033 cgit_stats_link("stats", NULL, "button", ctx.qry.head,
2034 fullpath);
2035 if (!S_ISGITLINK(mode))
2036- cgit_plain_link("plain", NULL, "button", ctx.qry.head, curr_rev,
2037- fullpath);
2038+ cgit_plain_link("plain", NULL, "button", ctx.qry.head,
2039+ walk_tree_ctx->curr_rev, fullpath);
2040 html("</td></tr>\n");
2041 free(name);
2042 return 0;
2043@@ -188,20 +192,19 @@ static void ls_head()
2044 html("<th class='right'>Size</th>");
2045 html("<th/>");
2046 html("</tr>\n");
2047- header = 1;
2048 }
2049
2050 static void ls_tail()
2051 {
2052- if (!header)
2053- return;
2054 html("</table>\n");
2055- header = 0;
2056 }
2057
2058-static void ls_tree(const unsigned char *sha1, char *path)
2059+static void ls_tree(const unsigned char *sha1, char *path, struct walk_tree_context *walk_tree_ctx)
2060 {
2061 struct tree *tree;
2062+ struct pathspec paths = {
2063+ .nr = 0
2064+ };
2065
2066 tree = parse_tree_indirect(sha1);
2067 if (!tree) {
2068@@ -211,7 +214,7 @@ static void ls_tree(const unsigned char *sha1, char *path)
2069 }
2070
2071 ls_head();
2072- read_tree_recursive(tree, "", 0, 1, NULL, ls_item, NULL);
2073+ read_tree_recursive(tree, "", 0, 1, &paths, ls_item, walk_tree_ctx);
2074 ls_tail();
2075 }
2076
2077@@ -220,25 +223,25 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
2078 const char *pathname, unsigned mode, int stage,
2079 void *cbdata)
2080 {
2081- static int state;
2082+ struct walk_tree_context *walk_tree_ctx = cbdata;
2083 static char buffer[PATH_MAX];
2084
2085- if (state == 0) {
2086+ if (walk_tree_ctx->state == 0) {
2087 memcpy(buffer, base, baselen);
2088- strcpy(buffer+baselen, pathname);
2089- if (strcmp(match_path, buffer))
2090+ strcpy(buffer + baselen, pathname);
2091+ if (strcmp(walk_tree_ctx->match_path, buffer))
2092 return READ_TREE_RECURSIVE;
2093
2094 if (S_ISDIR(mode)) {
2095- state = 1;
2096+ walk_tree_ctx->state = 1;
2097 ls_head();
2098 return READ_TREE_RECURSIVE;
2099 } else {
2100- print_object(sha1, buffer, pathname);
2101+ print_object(sha1, buffer, pathname, walk_tree_ctx->curr_rev);
2102 return 0;
2103 }
2104 }
2105- ls_item(sha1, base, baselen, pathname, mode, stage, NULL);
2106+ ls_item(sha1, base, baselen, pathname, mode, stage, walk_tree_ctx);
2107 return 0;
2108 }
2109
2110@@ -252,12 +255,23 @@ void cgit_print_tree(const char *rev, char *path)
2111 {
2112 unsigned char sha1[20];
2113 struct commit *commit;
2114- const char *paths[] = {path, NULL};
2115+ struct pathspec_item path_items = {
2116+ .match = path,
2117+ .len = path ? strlen(path) : 0
2118+ };
2119+ struct pathspec paths = {
2120+ .nr = path ? 1 : 0,
2121+ .items = &path_items
2122+ };
2123+ struct walk_tree_context walk_tree_ctx = {
2124+ .match_path = path,
2125+ .state = 0
2126+ };
2127
2128 if (!rev)
2129 rev = ctx.qry.head;
2130
2131- curr_rev = xstrdup(rev);
2132+ walk_tree_ctx.curr_rev = xstrdup(rev);
2133 if (get_sha1(rev, sha1)) {
2134 cgit_print_error(fmt("Invalid revision name: %s", rev));
2135 return;
2136@@ -269,11 +283,11 @@ void cgit_print_tree(const char *rev, char *path)
2137 }
2138
2139 if (path == NULL) {
2140- ls_tree(commit->tree->object.sha1, NULL);
2141+ ls_tree(commit->tree->object.sha1, NULL, &walk_tree_ctx);
2142 return;
2143 }
2144
2145- match_path = path;
2146- read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
2147- ls_tail();
2148+ read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
2149+ if (walk_tree_ctx.state == 1)
2150+ ls_tail();
2151 }
This page took 0.595887 seconds and 4 git commands to generate.