X-Git-Url: https://gitweb.ps.run/ps-cgit/blobdiff_plain/6180e6169d6e87a3bea7e4da835dca17f93e5cfd..c2b58ed8539fcfa4f05cc9da316bbc782f4b8f10:/shared.c diff --git a/shared.c b/shared.c index 7cf1e59..986f965 100644 --- a/shared.c +++ b/shared.c @@ -7,6 +7,8 @@ */ #include "cgit.h" +#include +#include struct cgit_repolist cgit_repolist; struct cgit_context ctx; @@ -56,12 +58,14 @@ struct cgit_repo *cgit_add_repo(const char *url) ret->section = ctx.cfg.section; ret->defbranch = "master"; ret->snapshots = ctx.cfg.snapshots; + ret->enable_commit_graph = ctx.cfg.enable_commit_graph; ret->enable_log_filecount = ctx.cfg.enable_log_filecount; ret->enable_log_linecount = ctx.cfg.enable_log_linecount; ret->enable_remote_branches = ctx.cfg.enable_remote_branches; + ret->enable_subject_links = ctx.cfg.enable_subject_links; ret->max_stats = ctx.cfg.max_stats; ret->module_link = ctx.cfg.module_link; - ret->readme = NULL; + ret->readme = ctx.cfg.readme; ret->mtime = -1; ret->about_filter = ctx.cfg.about_filter; ret->commit_filter = ctx.cfg.commit_filter; @@ -263,7 +267,7 @@ int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) int cgit_diff_files(const unsigned char *old_sha1, const unsigned char *new_sha1, unsigned long *old_size, unsigned long *new_size, int *binary, int context, - linediff_fn fn) + int ignorews, linediff_fn fn) { mmfile_t file1, file2; xpparam_t diff_params; @@ -279,6 +283,10 @@ int cgit_diff_files(const unsigned char *old_sha1, if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) || (file2.ptr && buffer_is_binary(file2.ptr, file2.size))) { *binary = 1; + if (file1.size) + free(file1.ptr); + if (file2.size) + free(file2.ptr); return 0; } @@ -286,17 +294,23 @@ int cgit_diff_files(const unsigned char *old_sha1, memset(&emit_params, 0, sizeof(emit_params)); memset(&emit_cb, 0, sizeof(emit_cb)); diff_params.flags = XDF_NEED_MINIMAL; + if (ignorews) + diff_params.flags |= XDF_IGNORE_WHITESPACE; emit_params.ctxlen = context > 0 ? context : 3; emit_params.flags = XDL_EMIT_FUNCNAMES; emit_cb.outf = filediff_cb; emit_cb.priv = fn; xdl_diff(&file1, &file2, &diff_params, &emit_params, &emit_cb); + if (file1.size) + free(file1.ptr); + if (file2.size) + free(file2.ptr); return 0; } void cgit_diff_tree(const unsigned char *old_sha1, const unsigned char *new_sha1, - filepair_fn fn, const char *prefix) + filepair_fn fn, const char *prefix, int ignorews) { struct diff_options opt; int ret; @@ -307,6 +321,8 @@ void cgit_diff_tree(const unsigned char *old_sha1, opt.detect_rename = 1; opt.rename_limit = ctx.cfg.renamelimit; DIFF_OPT_SET(&opt, RECURSIVE); + if (ignorews) + DIFF_XDL_SET(&opt, IGNORE_WHITESPACE); opt.format_callback = cgit_diff_tree_cb; opt.format_callback_data = fn; if (prefix) { @@ -325,13 +341,14 @@ void cgit_diff_tree(const unsigned char *old_sha1, diff_flush(&opt); } -void cgit_diff_commit(struct commit *commit, filepair_fn fn) +void cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix) { unsigned char *old_sha1 = NULL; if (commit->parents) old_sha1 = commit->parents->item->object.sha1; - cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); + cgit_diff_tree(old_sha1, commit->object.sha1, fn, prefix, + ctx.qry.ignorews); } int cgit_parse_snapshots_mask(const char *str) @@ -361,7 +378,33 @@ int cgit_parse_snapshots_mask(const char *str) return rv; } -int cgit_open_filter(struct cgit_filter *filter) +typedef struct { + char * name; + char * value; +} cgit_env_var; + +static void prepare_env(struct cgit_repo * repo) { + cgit_env_var env_vars[] = { + { .name = "CGIT_REPO_URL", .value = repo->url }, + { .name = "CGIT_REPO_NAME", .value = repo->name }, + { .name = "CGIT_REPO_PATH", .value = repo->path }, + { .name = "CGIT_REPO_OWNER", .value = repo->owner }, + { .name = "CGIT_REPO_DEFBRANCH", .value = repo->defbranch }, + { .name = "CGIT_REPO_SECTION", .value = repo->section }, + { .name = "CGIT_REPO_CLONE_URL", .value = repo->clone_url } + }; + int env_var_count = ARRAY_SIZE(env_vars); + cgit_env_var *p, *q; + static char *warn = "cgit warning: failed to set env: %s=%s\n"; + + p = env_vars; + q = p + env_var_count; + for (; p < q; p++) + if (setenv(p->name, p->value, 1)) + fprintf(stderr, warn, p->name, p->value); +} + +int cgit_open_filter(struct cgit_filter *filter, struct cgit_repo * repo) { filter->old_stdout = chk_positive(dup(STDOUT_FILENO), @@ -372,6 +415,8 @@ int cgit_open_filter(struct cgit_filter *filter) close(filter->pipe_fh[1]); chk_non_negative(dup2(filter->pipe_fh[0], STDIN_FILENO), "Unable to use pipe as STDIN"); + if (repo) + prepare_env(repo); execvp(filter->cmd, filter->argv); die("Unable to exec subprocess %s: %s (%d)", filter->cmd, strerror(errno), errno); @@ -423,3 +468,74 @@ int readfile(const char *path, char **buf, size_t *size) close(fd); return (*size == st.st_size ? 0 : e); } + +int is_token_char(char c) +{ + return isalnum(c) || c == '_'; +} + +/* Replace name with getenv(name), return pointer to zero-terminating char + */ +char *expand_macro(char *name, int maxlength) +{ + char *value; + int len; + + len = 0; + value = getenv(name); + if (value) { + len = strlen(value); + if (len > maxlength) + len = maxlength; + strncpy(name, value, len); + } + return name + len; +} + +#define EXPBUFSIZE (1024 * 8) + +/* Replace all tokens prefixed by '$' in the specified text with the + * value of the named environment variable. + * NB: the return value is a static buffer, i.e. it must be strdup'd + * by the caller. + */ +char *expand_macros(const char *txt) +{ + static char result[EXPBUFSIZE]; + char *p, *start; + int len; + + p = result; + start = NULL; + while (p < result + EXPBUFSIZE - 1 && txt && *txt) { + *p = *txt; + if (start) { + if (!is_token_char(*txt)) { + if (p - start > 0) { + *p = '\0'; + len = result + EXPBUFSIZE - start - 1; + p = expand_macro(start, len) - 1; + } + start = NULL; + txt--; + } + p++; + txt++; + continue; + } + if (*txt == '$') { + start = p; + txt++; + continue; + } + p++; + txt++; + } + *p = '\0'; + if (start && p - start > 0) { + len = result + EXPBUFSIZE - start - 1; + p = expand_macro(start, len); + *p = '\0'; + } + return result; +}