author | Lars Hjemli <hjemli@gmail.com> | 2007-05-18 01:00:54 (UTC) |
---|---|---|
committer | Lars Hjemli <hjemli@gmail.com> | 2007-05-18 20:51:01 (UTC) |
commit | 30ccdcaa74ebc0aab2b7843b0db8251d0ddf56de (patch) (side-by-side diff) | |
tree | efb3eddd091117281d5592c9eab44bc63121edf6 /parsing.c | |
parent | 43d40f2b704151d145a1383b2b964210915ecae4 (diff) | |
download | cgit-30ccdcaa74ebc0aab2b7843b0db8251d0ddf56de.zip cgit-30ccdcaa74ebc0aab2b7843b0db8251d0ddf56de.tar.gz cgit-30ccdcaa74ebc0aab2b7843b0db8251d0ddf56de.tar.bz2 |
Enable url=value querystring parameter
This makes is possible to use repo-urls like '/pub/scm/git/git.git' and
even add path specifications, like '/pub/scm/git/git.git/log/documentation'.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r-- | parsing.c | 43 |
1 files changed, 43 insertions, 0 deletions
@@ -1,249 +1,292 @@ /* config.c: parsing of config files * * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" int next_char(FILE *f) { int c = fgetc(f); if (c=='\r') { c = fgetc(f); if (c!='\n') { ungetc(c, f); c = '\r'; } } return c; } void skip_line(FILE *f) { int c; while((c=next_char(f)) && c!='\n' && c!=EOF) ; } int read_config_line(FILE *f, char *line, const char **value, int bufsize) { int i = 0, isname = 0; *value = NULL; while(i<bufsize-1) { int c = next_char(f); if (!isname && (c=='#' || c==';')) { skip_line(f); continue; } if (!isname && isspace(c)) continue; if (c=='=' && !*value) { line[i] = 0; *value = &line[i+1]; } else if (c=='\n' && !isname) { i = 0; continue; } else if (c=='\n' || c==EOF) { line[i] = 0; break; } else { line[i]=c; } isname = 1; i++; } line[i+1] = 0; return i; } int cgit_read_config(const char *filename, configfn fn) { static int nesting; int len; char line[256]; const char *value; FILE *f; /* cancel deeply nested include-commands */ if (nesting > 8) return -1; if (!(f = fopen(filename, "r"))) return -1; nesting++; while((len = read_config_line(f, line, &value, sizeof(line))) > 0) (*fn)(line, value); nesting--; fclose(f); return 0; } char *convert_query_hexchar(char *txt) { int d1, d2; if (strlen(txt) < 3) { *txt = '\0'; return txt-1; } d1 = hextoint(*(txt+1)); d2 = hextoint(*(txt+2)); if (d1<0 || d2<0) { strcpy(txt, txt+3); return txt-1; } else { *txt = d1 * 16 + d2; strcpy(txt+1, txt+3); return txt; } } int cgit_parse_query(char *txt, configfn fn) { char *t, *value = NULL, c; if (!txt) return 0; t = txt = xstrdup(txt); while((c=*t) != '\0') { if (c=='=') { *t = '\0'; value = t+1; } else if (c=='+') { *t = ' '; } else if (c=='%') { t = convert_query_hexchar(t); } else if (c=='&') { *t = '\0'; (*fn)(txt, value); txt = t+1; value = NULL; } t++; } if (t!=txt) (*fn)(txt, value); return 0; } +/* + * url syntax: [repo ['/' cmd [ '/' path]]] + * repo: any valid repo url, may contain '/' + * cmd: log | commit | diff | tree | view | blob | snapshot + * path: any valid path, may contain '/' + * + */ +void cgit_parse_url(const char *url) +{ + char *cmd, *p; + + cgit_repo = NULL; + if (!url || url[0] == '\0') + return; + + cgit_repo = cgit_get_repoinfo(url); + if (cgit_repo) { + cgit_query_repo = cgit_repo->url; + return; + } + + cmd = strchr(url, '/'); + while (!cgit_repo && cmd) { + cmd[0] = '\0'; + cgit_repo = cgit_get_repoinfo(url); + if (cgit_repo == NULL) { + cmd[0] = '/'; + cmd = strchr(cmd + 1, '/'); + continue; + } + + cgit_query_repo = cgit_repo->url; + p = strchr(cmd + 1, '/'); + if (p) { + p[0] = '\0'; + cgit_query_path = xstrdup(p + 1); + } + cgit_cmd = cgit_get_cmd_index(cmd + 1); + cgit_query_page = xstrdup(cmd + 1); + return; + } +} + char *substr(const char *head, const char *tail) { char *buf; buf = xmalloc(tail - head + 1); strncpy(buf, head, tail - head); buf[tail - head] = '\0'; return buf; } struct commitinfo *cgit_parse_commit(struct commit *commit) { struct commitinfo *ret; char *p = commit->buffer, *t = commit->buffer; ret = xmalloc(sizeof(*ret)); ret->commit = commit; ret->author = NULL; ret->author_email = NULL; ret->committer = NULL; ret->committer_email = NULL; ret->subject = NULL; ret->msg = NULL; if (strncmp(p, "tree ", 5)) die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); else p += 46; // "tree " + hex[40] + "\n" while (!strncmp(p, "parent ", 7)) p += 48; // "parent " + hex[40] + "\n" if (!strncmp(p, "author ", 7)) { p += 7; t = strchr(p, '<') - 1; ret->author = substr(p, t); p = t; t = strchr(t, '>') + 1; ret->author_email = substr(p, t); ret->author_date = atol(++t); p = strchr(t, '\n') + 1; } if (!strncmp(p, "committer ", 9)) { p += 9; t = strchr(p, '<') - 1; ret->committer = substr(p, t); p = t; t = strchr(t, '>') + 1; ret->committer_email = substr(p, t); ret->committer_date = atol(++t); p = strchr(t, '\n') + 1; } while (*p == '\n') p = strchr(p, '\n') + 1; t = strchr(p, '\n'); if (t && *t) { ret->subject = substr(p, t); p = t + 1; while (*p == '\n') p = strchr(p, '\n') + 1; ret->msg = p; } return ret; } struct taginfo *cgit_parse_tag(struct tag *tag) { void *data; enum object_type type; unsigned long size; char *p, *t; struct taginfo *ret; data = read_sha1_file(tag->object.sha1, &type, &size); if (!data || type != OBJ_TAG) { free(data); return 0; } ret = xmalloc(sizeof(*ret)); ret->tagger = NULL; ret->tagger_email = NULL; ret->tagger_date = 0; ret->msg = NULL; p = data; while (p && *p) { if (*p == '\n') break; if (!strncmp(p, "tagger ", 7)) { p += 7; t = strchr(p, '<') - 1; ret->tagger = substr(p, t); p = t; t = strchr(t, '>') + 1; ret->tagger_email = substr(p, t); ret->tagger_date = atol(++t); } p = strchr(p, '\n') + 1; } while (p && (*p == '\n')) p = strchr(p, '\n') + 1; if (p && *p) ret->msg = xstrdup(p); free(data); return ret; } |