Diff options
Diffstat (limited to '')
| -rw-r--r-- | source/shared.c | 264 | |
| -rw-r--r-- | source/shared.h | 27 |
2 files changed, 144 insertions, 147 deletions
diff --git a/source/shared.c b/source/shared.c index 7538c85..1e1bb26 100644 --- a/source/shared.c +++ b/source/shared.c @@ -1,15 +1,13 @@ /* - * The helpers that no single page owns, along with the process wide state - * every page reads. Repositories are registered here as cgitrc is parsed, the - * reference and commit records that the renderers list are built and freed - * here, and git's diff machinery is wrapped so a caller is handed whole - * filepairs or whole lines instead of xdiff buffers. + * The helpers that no single page owns, along with the process-wide state + * every page reads. Repositories are registered here as cgitrc is parsed, and + * git's diff machinery is wrapped so a caller is handed whole filepairs or + * whole lines instead of xdiff buffers. */ #define USE_THE_REPOSITORY_VARIABLE #include "cgit.h" -#include "parsing.h" #include "shared.h" #define MACRO_EXPANSION_BUFSIZE (1024 * 8) @@ -20,103 +18,6 @@ struct cgit_repolist cgit_repolist; struct cgit_context ctx; char cgit_default_repo_desc[] = "[no description]"; -/* - * Git's wider syntax is refused, since :/pattern and rev^{/pattern} walk the - * whole history for a match, and a leading dash reads as an option further - * down. - */ -int cgit_valid_rev(const char *rev) -{ - const char *p = rev; - - if (!rev || !*rev || *rev == '-') - return 0; - while (isxdigit((unsigned char)*p)) - p++; - if (!*p) - return 1; - return !check_refname_format(rev, REFNAME_ALLOW_ONELEVEL); -} - -static int load_mmfile(mmfile_t *file, const struct object_id *oid) -{ - enum object_type type; - size_t size; - - // A null oid is the absent side of an add or a delete, and diffs as an - // empty file rather than as a failure. - if (is_null_oid(oid)) { - file->ptr = (char *)""; - file->size = 0; - return 1; - } - - file->ptr = odb_read_object(the_repository->objects, oid, &type, &size); - if (!file->ptr) - return 0; - file->size = size; - return 1; -} - -/* - * The test is on the oid rather than the size, because load_mmfile uses a - * literal only for a null oid, while a real but empty blob owns its buffer. - */ -static void release_mmfile(mmfile_t *file, const struct object_id *oid) -{ - if (!is_null_oid(oid)) - free(file->ptr); -} - -/* - * Xdiff hands over one line per call, in pieces that are the prefix, the - * record and, for a record with no newline, the marker saying so. They are - * joined here before the line reaches fn. - */ -static int emit_line(void *priv, mmbuffer_t *mb, int nbuf) -{ - linediff_fn emit = *(linediff_fn *)priv; - struct strbuf line = STRBUF_INIT; - int i; - - for (i = 0; i < nbuf; i++) - strbuf_add(&line, mb[i].ptr, mb[i].size); - emit(line.buf, line.len); - strbuf_release(&line); - return 0; -} - -/* - * Takes an unsigned char because a byte over 0x7f is negative where char is - * signed, which the ctype tests are not defined for. - */ -static int is_token_char(unsigned char c) -{ - return isalnum(c) || c == '_'; -} - -/* - * Replace the variable name held at name with its value from the environment, - * writing at most room bytes including the terminator, and return where the - * text now ends. - */ -static char *expand_macro(char *name, size_t room) -{ - char *value; - size_t len; - - len = 0; - value = getenv(name); - if (value) { - len = strlen(value) + 1; - if (len > room) - len = room; - strlcpy(name, value, len); - --len; - } - return name + len; -} - struct cgit_repo *cgit_add_repo(const char *url) { struct cgit_repo *repo; @@ -179,20 +80,6 @@ struct cgit_repo *cgit_get_repoinfo(const char *url) return NULL; } -char *cgit_trim_end(const char *str, char c) -{ - size_t len; - - if (!str) - return NULL; - len = strlen(str); - while (len > 0 && str[len - 1] == c) - len--; - if (len == 0) - return NULL; - return xstrndup(str, len); -} - void cgit_diff_tree_cb(struct diff_queue_struct *q, struct diff_options *options UNUSED, void *data) { filepair_fn fn = *(filepair_fn *)data; @@ -206,6 +93,54 @@ void cgit_diff_tree_cb(struct diff_queue_struct *q, struct diff_options *options } } +static int load_mmfile(mmfile_t *file, const struct object_id *oid) +{ + enum object_type type; + size_t size; + + // A null oid is the absent side of an add or a delete, and diffs as an + // empty file rather than as a failure. + if (is_null_oid(oid)) { + file->ptr = (char *)""; + file->size = 0; + return 1; + } + + file->ptr = odb_read_object(the_repository->objects, oid, &type, &size); + if (!file->ptr) + return 0; + file->size = size; + return 1; +} + +/* + * The test is on the oid rather than the size, because load_mmfile uses a + * literal only for a null oid, while a real but empty blob owns its buffer. + */ +static void release_mmfile(mmfile_t *file, const struct object_id *oid) +{ + if (!is_null_oid(oid)) + free(file->ptr); +} + +/* + * Xdiff hands over one line per call, in pieces that are the prefix, the + * record and, for a record with no newline, the marker saying so. They are + * joined here before the line reaches fn. + */ +static int emit_line(void *priv, mmbuffer_t *mb, int nbuf) +{ + linediff_fn emit = *(linediff_fn *)priv; + struct strbuf line = STRBUF_INIT; + int i; + + for (i = 0; i < nbuf; i++) + strbuf_add(&line, mb[i].ptr, mb[i].size); + emit(line.buf, line.len); + strbuf_release(&line); + return 0; +} + int cgit_diff_files(const struct object_id *old_oid, const struct object_id *new_oid, size_t *old_size, size_t *new_size, int *binary, int context, int ignorews, linediff_fn fn) @@ -273,22 +208,6 @@ int cgit_diff_files(const struct object_id *old_oid, const struct object_id *new return 0; } -int cgit_blob_too_large(size_t size) -{ - return ctx.cfg.max_blob_size && size / 1024 > (size_t)ctx.cfg.max_blob_size; -} - -void cgit_literal_pathspec(struct pathspec *ps, struct pathspec_item *item, const char *path) -{ - int len = path ? strlen(path) : 0; - - // nowildcard_len matching len makes git treat the path as literal - // rather than as a glob. - *item = (struct pathspec_item){ .match = path, .len = len, .nowildcard_len = len }; - ps->nr = path ? 1 : 0; - ps->items = item; -} - void cgit_diff_limit_path(struct diff_options *opt, const char *prefix) { cgit_literal_pathspec(&opt->pathspec, xmalloc(sizeof(struct pathspec_item)), xstrdup(prefix)); @@ -329,6 +248,36 @@ void cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix) cgit_diff_tree(old_oid, &commit->object.oid, fn, prefix, ctx.qry.ignorews); } +int cgit_blob_too_large(size_t size) +{ + return ctx.cfg.max_blob_size && size / 1024 > (size_t)ctx.cfg.max_blob_size; +} + +void cgit_literal_pathspec(struct pathspec *ps, struct pathspec_item *item, const char *path) +{ + int len = path ? strlen(path) : 0; + + // nowildcard_len matching len makes git treat the path as literal + // rather than as a glob. + *item = (struct pathspec_item){ .match = path, .len = len, .nowildcard_len = len }; + ps->nr = path ? 1 : 0; + ps->items = item; +} + +char *cgit_trim_end(const char *str, char c) +{ + size_t len; + + if (!str) + return NULL; + len = strlen(str); + while (len > 0 && str[len - 1] == c) + len--; + if (len == 0) + return NULL; + return xstrndup(str, len); +} + int cgit_read_first_line(const char *path, char **buf) { int fd, err; @@ -423,6 +372,37 @@ void cgit_utf8_sanitize(char *text) } } +/* + * Takes an unsigned char because a byte over 0x7f is negative where char is + * signed, which the ctype tests are not defined for. + */ +static int is_token_char(unsigned char c) +{ + return isalnum(c) || c == '_'; +} + +/* + * Replace the variable name held at name with its value from the environment, + * writing at most room bytes including the terminator, and return where the + * text now ends. + */ +static char *expand_macro(char *name, size_t room) +{ + char *value; + size_t len; + + len = 0; + value = getenv(name); + if (value) { + len = strlen(value) + 1; + if (len > room) + len = room; + strlcpy(name, value, len); + --len; + } + return name + len; +} + char *cgit_expand_macros(const char *text) { static char result[MACRO_EXPANSION_BUFSIZE]; @@ -473,6 +453,24 @@ int cgit_readme_is_tracked(const char *readme) return colon && colon[1]; } +/* + * Git's wider syntax is refused, since :/pattern and rev^{/pattern} walk the + * whole history for a match, and a leading dash reads as an option further + * down. + */ +int cgit_valid_rev(const char *rev) +{ + const char *p = rev; + + if (!rev || !*rev || *rev == '-') + return 0; + while (isxdigit((unsigned char)*p)) + p++; + if (!*p) + return 1; + return !check_refname_format(rev, REFNAME_ALLOW_ONELEVEL); +} + int cgit_notes_ref_usable(const char *notes_ref) { struct object_id oid; diff --git a/source/shared.h b/source/shared.h index 4359bef..302b752 100644 --- a/source/shared.h +++ b/source/shared.h @@ -1,9 +1,8 @@ /* - * The helpers that belong to no single page. Repository registration, the - * lifetimes of the reference and commit records the renderers build, thin - * wrappers over git's diff machinery, and a handful of string, date and - * mimetype utilities all live here because several renderers need them. The - * two process-wide globals, ctx and cgit_repolist, are defined here as well. + * The helpers that more than one file needs. Repository registration and thin + * wrappers over git's diff machinery make up most of it, beside a few string + * and request checks. The two process-wide globals, ctx and cgit_repolist, + * are defined here as well. */ #ifndef CGIT_SHARED_H @@ -42,6 +41,15 @@ extern int cgit_diff_files(const struct object_id *old_oid, const struct object_ linediff_fn fn); /* + * Limit a diff to the paths below prefix, which is taken literally. + */ +extern void cgit_diff_limit_path(struct diff_options *opt, const char *prefix); + +extern void cgit_diff_tree(const struct object_id *old_oid, const struct object_id *new_oid, + filepair_fn fn, const char *prefix, int ignorews); +extern void cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix); + +/* * Whether a blob of size bytes is past max-blob-size. Callers ask before * reading the object, so a huge blob stays out of memory rather than being * noticed once it is already there. @@ -55,15 +63,6 @@ extern int cgit_blob_too_large(size_t size); extern void cgit_literal_pathspec(struct pathspec *ps, struct pathspec_item *item, const char *path); /* - * Limit a diff to the paths below prefix, which is taken literally. - */ -extern void cgit_diff_limit_path(struct diff_options *opt, const char *prefix); - -extern void cgit_diff_tree(const struct object_id *old_oid, const struct object_id *new_oid, - filepair_fn fn, const char *prefix, int ignorews); -extern void cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix); - -/* * Copy str without its trailing runs of c, returning NULL if nothing is left. */ extern char *cgit_trim_end(const char *str, char c); |
