-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | html.c | 4 | ||||
-rw-r--r-- | ui-log.c | 71 | ||||
-rw-r--r-- | vector.c | 38 | ||||
-rw-r--r-- | vector.h | 17 |
5 files changed, 118 insertions, 13 deletions
@@ -86,64 +86,65 @@ endif # %.o: %.c $(QUIET_CC)$(CC) -o $*.o -c $(CFLAGS) $< EXTLIBS = git/libgit.a git/xdiff/lib.a -lz -lpthread OBJECTS = OBJECTS += cache.o OBJECTS += cgit.o OBJECTS += cmd.o OBJECTS += configfile.o OBJECTS += html.o OBJECTS += parsing.o OBJECTS += scan-tree.o OBJECTS += shared.o OBJECTS += ui-atom.o OBJECTS += ui-blob.o OBJECTS += ui-clone.o OBJECTS += ui-commit.o OBJECTS += ui-diff.o OBJECTS += ui-log.o OBJECTS += ui-patch.o OBJECTS += ui-plain.o OBJECTS += ui-refs.o OBJECTS += ui-repolist.o OBJECTS += ui-shared.o OBJECTS += ui-snapshot.o OBJECTS += ui-ssdiff.o OBJECTS += ui-stats.o OBJECTS += ui-summary.o OBJECTS += ui-tag.o OBJECTS += ui-tree.o +OBJECTS += vector.o ifdef NEEDS_LIBICONV EXTLIBS += -liconv endif .PHONY: all libgit test install uninstall clean force-version get-git \ doc clean-doc install-doc install-man install-html install-pdf \ uninstall-doc uninstall-man uninstall-html uninstall-pdf all: cgit VERSION: force-version @./gen-version.sh "$(CGIT_VERSION)" -include VERSION CFLAGS += -g -Wall -Igit CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER)' CFLAGS += -DCGIT_VERSION='"$(CGIT_VERSION)"' CFLAGS += -DCGIT_CONFIG='"$(CGIT_CONFIG)"' CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"' CFLAGS += -DCGIT_CACHE_ROOT='"$(CACHE_ROOT)"' GIT_OPTIONS = prefix=/usr ifdef NO_ICONV CFLAGS += -DNO_ICONV endif ifdef NO_STRCASESTR CFLAGS += -DNO_STRCASESTR endif @@ -1,53 +1,53 @@ /* html.c: helper functions for html output * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <errno.h> /* Percent-encoding of each character, except: a-zA-Z0-9!$()*,./:;@- */ static const char* url_escape_table[256] = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", "%18", "%19", "%1a", "%1b", "%1c", "%1d", - "%1e", "%1f", "%20", 0, "%22", "%23", 0, "%25", "%26", "%27", 0, 0, 0, + "%1e", "%1f", "+", 0, "%22", "%23", 0, "%25", "%26", "%27", 0, 0, 0, "%2b", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%3c", "%3d", "%3e", "%3f", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%5c", 0, "%5e", 0, "%60", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "%7b", "%7c", "%7d", 0, "%7f", "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97", "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f", "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af", "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7", "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf", "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf", "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df", "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7", "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef", "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" }; int htmlfd = STDOUT_FILENO; char *fmt(const char *format, ...) { static char buf[8][1024]; static int bufidx; int len; va_list args; bufidx++; bufidx &= 7; @@ -152,65 +152,65 @@ void html_attr(const char *txt) } t++; } if (t!=txt) html(txt); } void html_url_path(const char *txt) { const char *t = txt; while(t && *t){ int c = *t; const char *e = url_escape_table[c]; if (e && c!='+' && c!='&' && c!='+') { html_raw(txt, t - txt); html_raw(e, 3); txt = t+1; } t++; } if (t!=txt) html(txt); } void html_url_arg(const char *txt) { const char *t = txt; while(t && *t){ int c = *t; const char *e = url_escape_table[c]; if (e) { html_raw(txt, t - txt); - html_raw(e, 3); + html_raw(e, strlen(e)); txt = t+1; } t++; } if (t!=txt) html(txt); } void html_hidden(const char *name, const char *value) { html("<input type='hidden' name='"); html_attr(name); html("' value='"); html_attr(value); html("'/>"); } void html_option(const char *value, const char *text, const char *selected_value) { html("<option value='"); html_attr(value); html("'"); if (selected_value && !strcmp(selected_value, value)) html(" selected='selected'"); html(">"); html_txt(text); html("</option>\n"); } void html_link_open(const char *url, const char *title, const char *class) { html("<a href='"); @@ -1,43 +1,44 @@ /* ui-log.c: functions for log output * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" #include "html.h" #include "ui-shared.h" +#include "vector.h" int files, add_lines, rem_lines; void count_lines(char *line, int size) { if (size <= 0) return; if (line[0] == '+') add_lines++; else if (line[0] == '-') rem_lines++; } void inspect_files(struct diff_filepair *pair) { unsigned long old_size = 0; unsigned long new_size = 0; int binary = 0; files++; if (ctx.repo->enable_log_linecount) cgit_diff_files(pair->one->sha1, pair->two->sha1, &old_size, &new_size, &binary, 0, ctx.qry.ignorews, count_lines); } void show_commit_decorations(struct commit *commit) { struct name_decoration *deco; static char buf[1024]; @@ -119,96 +120,144 @@ void print_commit(struct commit *commit) if (ctx.repo->enable_log_linecount) cols++; } htmlf("<tr class='nohover'><td/><td colspan='%d' class='logmsg'>", cols); html_txt(info->msg); html("</td></tr>\n"); if (notes.len != 0) { html("<tr class='nohover'>"); html("<td class='lognotes-label'>Notes:</td>"); htmlf("<td colspan='%d' class='lognotes'>", cols); html_txt(notes.buf); html("</td></tr>\n"); } strbuf_release(¬es); } cgit_free_commitinfo(info); } static const char *disambiguate_ref(const char *ref) { unsigned char sha1[20]; const char *longref; longref = fmt("refs/heads/%s", ref); if (get_sha1(longref, sha1) == 0) return longref; return ref; } +static char *next_token(char **src) +{ + char *result; + + if (!src || !*src) + return NULL; + while (isspace(**src)) + (*src)++; + if (!**src) + return NULL; + result = *src; + while (**src) { + if (isspace(**src)) { + **src = '\0'; + (*src)++; + break; + } + (*src)++; + } + return result; +} + void cgit_print_log(const char *tip, int ofs, int cnt, char *grep, char *pattern, char *path, int pager) { struct rev_info rev; struct commit *commit; - const char *argv[] = {NULL, NULL, NULL, NULL, NULL}; - int argc = 2; + struct vector vec = VECTOR_INIT(char *); int i, columns = 3; + char *arg; + + /* First argv is NULL */ + vector_push(&vec, NULL, 0); if (!tip) tip = ctx.qry.head; - - argv[1] = disambiguate_ref(tip); + tip = disambiguate_ref(tip); + vector_push(&vec, &tip, 0); if (grep && pattern && *pattern) { + pattern = xstrdup(pattern); if (!strcmp(grep, "grep") || !strcmp(grep, "author") || - !strcmp(grep, "committer")) - argv[argc++] = fmt("--%s=%s", grep, pattern); - if (!strcmp(grep, "range")) - argv[1] = pattern; + !strcmp(grep, "committer")) { + arg = fmt("--%s=%s", grep, pattern); + vector_push(&vec, &arg, 0); + } + if (!strcmp(grep, "range")) { + /* Split the pattern at whitespace and add each token + * as a revision expression. Do not accept other + * rev-list options. Also, replace the previously + * pushed tip (it's no longer relevant). + */ + vec.count--; + while ((arg = next_token(&pattern))) { + if (*arg == '-') { + fprintf(stderr, "Bad range expr: %s\n", + arg); + break; + } + vector_push(&vec, &arg, 0); + } + } } if (path) { - argv[argc++] = "--"; - argv[argc++] = path; + arg = "--"; + vector_push(&vec, &arg, 0); + vector_push(&vec, &path, 0); } + + /* Make sure the vector is NULL-terminated */ + vector_push(&vec, NULL, 0); + vec.count--; + init_revisions(&rev, NULL); rev.abbrev = DEFAULT_ABBREV; rev.commit_format = CMIT_FMT_DEFAULT; rev.verbose_header = 1; rev.show_root_diff = 0; - setup_revisions(argc, argv, &rev, NULL); + setup_revisions(vec.count, vec.data, &rev, NULL); load_ref_decorations(DECORATE_FULL_REFS); rev.show_decorations = 1; rev.grep_filter.regflags |= REG_ICASE; compile_grep_patterns(&rev.grep_filter); prepare_revision_walk(&rev); if (pager) html("<table class='list nowrap'>"); html("<tr class='nohover'><th class='left'>Age</th>" "<th class='left'>Commit message"); if (pager) { html(" ("); cgit_log_link(ctx.qry.showmsg ? "Collapse" : "Expand", NULL, NULL, ctx.qry.head, ctx.qry.sha1, ctx.qry.vpath, ctx.qry.ofs, ctx.qry.grep, ctx.qry.search, ctx.qry.showmsg ? 0 : 1); html(")"); } html("</th><th class='left'>Author</th>"); if (ctx.repo->enable_log_filecount) { html("<th class='left'>Files</th>"); columns++; if (ctx.repo->enable_log_linecount) { html("<th class='left'>Lines</th>"); columns++; } } html("</tr>\n"); if (ofs<0) ofs = 0; diff --git a/vector.c b/vector.c new file mode 100644 index 0000000..0863908 --- a/dev/null +++ b/vector.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "vector.h" + +static int grow(struct vector *vec, int gently) +{ + size_t new_alloc; + void *new_data; + + new_alloc = vec->alloc * 3 / 2; + if (!new_alloc) + new_alloc = 8; + new_data = realloc(vec->data, new_alloc * vec->size); + if (!new_data) { + if (gently) + return ENOMEM; + perror("vector.c:grow()"); + exit(1); + } + vec->data = new_data; + vec->alloc = new_alloc; + return 0; +} + +int vector_push(struct vector *vec, const void *data, int gently) +{ + int rc; + + if (vec->count == vec->alloc && (rc = grow(vec, gently))) + return rc; + if (data) + memmove(vec->data + vec->count * vec->size, data, vec->size); + else + memset(vec->data + vec->count * vec->size, 0, vec->size); + vec->count++; + return 0; +} diff --git a/vector.h b/vector.h new file mode 100644 index 0000000..c64eb1f --- a/dev/null +++ b/vector.h @@ -0,0 +1,17 @@ +#ifndef CGIT_VECTOR_H +#define CGIT_VECTOR_H + +#include <stdlib.h> + +struct vector { + size_t size; + size_t count; + size_t alloc; + void *data; +}; + +#define VECTOR_INIT(type) {sizeof(type), 0, 0, NULL} + +int vector_push(struct vector *vec, const void *data, int gently); + +#endif /* CGIT_VECTOR_H */ |