Diffstat (limited to 'shared.c')
| -rw-r--r-- | shared.c | 643 |
1 files changed, 250 insertions, 393 deletions
@@ -1,53 +1,102 @@ /* shared.c: global vars + some callback functions * - * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com> - * Copyright (C) 2026 Saya Andy <saya.andy@posteo.com> - * - * Modified 2026 by Saya Andy: - * Add cgit_have_repository() - * Add ci filter configuration + * Copyright (C) 2006 Lars Hjemli * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ -#define USE_THE_REPOSITORY_VARIABLE - #include "cgit.h" -struct cgit_repolist cgit_repolist; -struct cgit_context ctx; +struct repolist cgit_repolist; +struct repoinfo *cgit_repo; +int cgit_cmd; + +const char *cgit_version = CGIT_VERSION; + +char *cgit_root_title = "Git repository browser"; +char *cgit_css = "/cgit.css"; +char *cgit_logo = "/git-logo.png"; +char *cgit_index_header = NULL; +char *cgit_logo_link = "http://www.kernel.org/pub/software/scm/git/docs/"; +char *cgit_module_link = "./?repo=%s&page=commit&id=%s"; +char *cgit_agefile = "info/web/last-modified"; +char *cgit_virtual_root = NULL; +char *cgit_script_name = CGIT_SCRIPT_NAME; +char *cgit_cache_root = CGIT_CACHE_ROOT; +char *cgit_repo_group = NULL; + +int cgit_nocache = 0; +int cgit_snapshots = 0; +int cgit_enable_index_links = 0; +int cgit_enable_log_filecount = 0; +int cgit_enable_log_linecount = 0; +int cgit_max_lock_attempts = 5; +int cgit_cache_root_ttl = 5; +int cgit_cache_repo_ttl = 5; +int cgit_cache_dynamic_ttl = 5; +int cgit_cache_static_ttl = -1; +int cgit_cache_max_create_time = 5; +int cgit_summary_log = 0; +int cgit_renamelimit = -1; + +int cgit_max_msg_len = 60; +int cgit_max_repodesc_len = 60; +int cgit_max_commit_count = 50; + +int cgit_query_has_symref = 0; +int cgit_query_has_sha1 = 0; + +char *cgit_querystring = NULL; +char *cgit_query_repo = NULL; +char *cgit_query_page = NULL; +char *cgit_query_head = NULL; +char *cgit_query_search = NULL; +char *cgit_query_sha1 = NULL; +char *cgit_query_sha2 = NULL; +char *cgit_query_path = NULL; +char *cgit_query_name = NULL; +int cgit_query_ofs = 0; -int cgit_have_repository(void) +int htmlfd = 0; + + +int cgit_get_cmd_index(const char *cmd) { - return startup_info->have_repository; + static char *cmds[] = {"log", "commit", "diff", "tree", "blob", + "snapshot", "tag", NULL}; + int i; + + for(i = 0; cmds[i]; i++) + if (!strcmp(cmd, cmds[i])) + return i + 1; + return 0; } int chk_zero(int result, char *msg) { if (result != 0) - die_errno("%s", msg); + die("%s: %s", msg, strerror(errno)); return result; } int chk_positive(int result, char *msg) { if (result <= 0) - die_errno("%s", msg); + die("%s: %s", msg, strerror(errno)); return result; } int chk_non_negative(int result, char *msg) { - if (result < 0) - die_errno("%s", msg); + if (result < 0) + die("%s: %s",msg, strerror(errno)); return result; } -char *cgit_default_repo_desc = "[no description]"; -struct cgit_repo *cgit_add_repo(const char *url) +struct repoinfo *add_repo(const char *url) { - struct cgit_repo *ret; + struct repoinfo *ret; if (++cgit_repolist.count > cgit_repolist.length) { if (cgit_repolist.length == 0) @@ -56,110 +105,190 @@ struct cgit_repo *cgit_add_repo(const char *url) cgit_repolist.length *= 2; cgit_repolist.repos = xrealloc(cgit_repolist.repos, cgit_repolist.length * - sizeof(struct cgit_repo)); + sizeof(struct repoinfo)); } ret = &cgit_repolist.repos[cgit_repolist.count-1]; - memset(ret, 0, sizeof(struct cgit_repo)); ret->url = trim_end(url, '/'); - *strchrnul(ret->url, '\n') = '\0'; ret->name = ret->url; ret->path = NULL; - ret->desc = cgit_default_repo_desc; - ret->extra_head_content = NULL; + ret->desc = NULL; ret->owner = NULL; - ret->homepage = NULL; - ret->ci_url = ctx.cfg.ci_url; - ret->ci_branch_url = ctx.cfg.ci_branch_url; - ret->ci_tag_url = ctx.cfg.ci_tag_url; - ret->section = ctx.cfg.section; - ret->snapshots = ctx.cfg.snapshots; - ret->enable_blame = ctx.cfg.enable_blame; - ret->enable_commit_graph = ctx.cfg.enable_commit_graph; - ret->enable_follow_links = ctx.cfg.enable_follow_links; - 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->enable_html_serving = ctx.cfg.enable_html_serving; - ret->max_stats = ctx.cfg.max_stats; - ret->branch_sort = ctx.cfg.branch_sort; - ret->commit_sort = ctx.cfg.commit_sort; - ret->module_link = ctx.cfg.module_link; - ret->readme = ctx.cfg.readme; - ret->mtime = -1; - ret->about_filter = ctx.cfg.about_filter; - ret->commit_filter = ctx.cfg.commit_filter; - ret->source_filter = ctx.cfg.source_filter; - ret->email_filter = ctx.cfg.email_filter; - ret->owner_filter = ctx.cfg.owner_filter; - ret->ci_filter = ctx.cfg.ci_filter; - ret->clone_url = ctx.cfg.clone_url; - ret->submodules.strdup_strings = 1; - ret->hide = ret->ignore = 0; + ret->group = cgit_repo_group; + ret->defbranch = "master"; + ret->snapshots = cgit_snapshots; + ret->enable_log_filecount = cgit_enable_log_filecount; + ret->enable_log_linecount = cgit_enable_log_linecount; + ret->module_link = cgit_module_link; + ret->readme = NULL; return ret; } -struct cgit_repo *cgit_get_repoinfo(const char *url) +struct repoinfo *cgit_get_repoinfo(const char *url) { int i; - struct cgit_repo *repo; + struct repoinfo *repo; - for (i = 0; i < cgit_repolist.count; i++) { + for (i=0; i<cgit_repolist.count; i++) { repo = &cgit_repolist.repos[i]; - if (repo->ignore) - continue; if (!strcmp(repo->url, url)) return repo; } return NULL; } -void cgit_free_commitinfo(struct commitinfo *info) +void cgit_global_config_cb(const char *name, const char *value) +{ + if (!strcmp(name, "root-title")) + cgit_root_title = xstrdup(value); + else if (!strcmp(name, "css")) + cgit_css = xstrdup(value); + else if (!strcmp(name, "logo")) + cgit_logo = xstrdup(value); + else if (!strcmp(name, "index-header")) + cgit_index_header = xstrdup(value); + else if (!strcmp(name, "logo-link")) + cgit_logo_link = xstrdup(value); + else if (!strcmp(name, "module-link")) + cgit_module_link = xstrdup(value); + else if (!strcmp(name, "virtual-root")) + cgit_virtual_root = trim_end(value, '/'); + else if (!strcmp(name, "nocache")) + cgit_nocache = atoi(value); + else if (!strcmp(name, "snapshots")) + cgit_snapshots = cgit_parse_snapshots_mask(value); + else if (!strcmp(name, "enable-index-links")) + cgit_enable_index_links = atoi(value); + else if (!strcmp(name, "enable-log-filecount")) + cgit_enable_log_filecount = atoi(value); + else if (!strcmp(name, "enable-log-linecount")) + cgit_enable_log_linecount = atoi(value); + else if (!strcmp(name, "cache-root")) + cgit_cache_root = xstrdup(value); + else if (!strcmp(name, "cache-root-ttl")) + cgit_cache_root_ttl = atoi(value); + else if (!strcmp(name, "cache-repo-ttl")) + cgit_cache_repo_ttl = atoi(value); + else if (!strcmp(name, "cache-static-ttl")) + cgit_cache_static_ttl = atoi(value); + else if (!strcmp(name, "cache-dynamic-ttl")) + cgit_cache_dynamic_ttl = atoi(value); + else if (!strcmp(name, "max-message-length")) + cgit_max_msg_len = atoi(value); + else if (!strcmp(name, "max-repodesc-length")) + cgit_max_repodesc_len = atoi(value); + else if (!strcmp(name, "max-commit-count")) + cgit_max_commit_count = atoi(value); + else if (!strcmp(name, "summary-log")) + cgit_summary_log = atoi(value); + else if (!strcmp(name, "agefile")) + cgit_agefile = xstrdup(value); + else if (!strcmp(name, "renamelimit")) + cgit_renamelimit = atoi(value); + else if (!strcmp(name, "repo.group")) + cgit_repo_group = xstrdup(value); + else if (!strcmp(name, "repo.url")) + cgit_repo = add_repo(value); + else if (!strcmp(name, "repo.name")) + cgit_repo->name = xstrdup(value); + else if (cgit_repo && !strcmp(name, "repo.path")) + cgit_repo->path = trim_end(value, '/'); + else if (cgit_repo && !strcmp(name, "repo.desc")) + cgit_repo->desc = xstrdup(value); + else if (cgit_repo && !strcmp(name, "repo.owner")) + cgit_repo->owner = xstrdup(value); + else if (cgit_repo && !strcmp(name, "repo.defbranch")) + cgit_repo->defbranch = xstrdup(value); + else if (cgit_repo && !strcmp(name, "repo.snapshots")) + cgit_repo->snapshots = cgit_snapshots & cgit_parse_snapshots_mask(value); /* XXX: &? */ + else if (cgit_repo && !strcmp(name, "repo.enable-log-filecount")) + cgit_repo->enable_log_filecount = cgit_enable_log_filecount * atoi(value); + else if (cgit_repo && !strcmp(name, "repo.enable-log-linecount")) + cgit_repo->enable_log_linecount = cgit_enable_log_linecount * atoi(value); + else if (cgit_repo && !strcmp(name, "repo.module-link")) + cgit_repo->module_link= xstrdup(value); + else if (cgit_repo && !strcmp(name, "repo.readme") && value != NULL) { + if (*value == '/') + cgit_repo->readme = xstrdup(value); + else + cgit_repo->readme = xstrdup(fmt("%s/%s", cgit_repo->path, value)); + } else if (!strcmp(name, "include")) + cgit_read_config(value, cgit_global_config_cb); +} + +void cgit_querystring_cb(const char *name, const char *value) +{ + if (!strcmp(name,"r")) { + cgit_query_repo = xstrdup(value); + cgit_repo = cgit_get_repoinfo(value); + } else if (!strcmp(name, "p")) { + cgit_query_page = xstrdup(value); + cgit_cmd = cgit_get_cmd_index(value); + } else if (!strcmp(name, "url")) { + cgit_parse_url(value); + } else if (!strcmp(name, "q")) { + cgit_query_search = xstrdup(value); + } else if (!strcmp(name, "h")) { + cgit_query_head = xstrdup(value); + cgit_query_has_symref = 1; + } else if (!strcmp(name, "id")) { + cgit_query_sha1 = xstrdup(value); + cgit_query_has_sha1 = 1; + } else if (!strcmp(name, "id2")) { + cgit_query_sha2 = xstrdup(value); + cgit_query_has_sha1 = 1; + } else if (!strcmp(name, "ofs")) { + cgit_query_ofs = atoi(value); + } else if (!strcmp(name, "path")) { + cgit_query_path = trim_end(value, '/'); + } else if (!strcmp(name, "name")) { + cgit_query_name = xstrdup(value); + } +} + +void *cgit_free_commitinfo(struct commitinfo *info) { free(info->author); free(info->author_email); free(info->committer); free(info->committer_email); free(info->subject); - free(info->msg); - free(info->msg_encoding); free(info); + return NULL; +} + +int hextoint(char c) +{ + if (c >= 'a' && c <= 'f') + return 10 + c - 'a'; + else if (c >= 'A' && c <= 'F') + return 10 + c - 'A'; + else if (c >= '0' && c <= '9') + return c - '0'; + else + return -1; } char *trim_end(const char *str, char c) { int len; + char *s, *t; if (str == NULL) return NULL; - len = strlen(str); - while (len > 0 && str[len - 1] == c) + t = (char *)str; + len = strlen(t); + while(len > 0 && t[len - 1] == c) len--; + if (len == 0) return NULL; - return xstrndup(str, len); -} - -char *ensure_end(const char *str, char c) -{ - size_t len = strlen(str); - char *result; - if (len && str[len - 1] == c) - return xstrndup(str, len); - - result = xmalloc(len + 2); - memcpy(result, str, len); - result[len] = '/'; - result[len + 1] = '\0'; - return result; -} - -void strbuf_ensure_end(struct strbuf *sb, char c) -{ - if (!sb->len || sb->buf[sb->len - 1] != c) - strbuf_addch(sb, c); + c = t[len]; + t[len] = '\0'; + s = xstrdup(t); + t[len] = c; + return s; } void cgit_add_ref(struct reflist *list, struct refinfo *ref) @@ -174,13 +303,13 @@ void cgit_add_ref(struct reflist *list, struct refinfo *ref) list->refs[list->count++] = ref; } -static struct refinfo *cgit_mk_refinfo(const char *refname, const struct object_id *oid) +struct refinfo *cgit_mk_refinfo(const char *refname, const unsigned char *sha1) { struct refinfo *ref; ref = xmalloc(sizeof (struct refinfo)); ref->refname = xstrdup(refname); - ref->object = parse_object(the_repository, oid); + ref->object = parse_object(sha1); switch (ref->object->type) { case OBJ_TAG: ref->tag = cgit_parse_tag((struct tag *)ref->object); @@ -192,46 +321,11 @@ static struct refinfo *cgit_mk_refinfo(const char *refname, const struct object_ return ref; } -void cgit_free_taginfo(struct taginfo *tag) -{ - if (tag->tagger) - free(tag->tagger); - if (tag->tagger_email) - free(tag->tagger_email); - if (tag->msg) - free(tag->msg); - free(tag); -} - -static void cgit_free_refinfo(struct refinfo *ref) -{ - if (ref->refname) - free((char *)ref->refname); - switch (ref->object->type) { - case OBJ_TAG: - cgit_free_taginfo(ref->tag); - break; - case OBJ_COMMIT: - cgit_free_commitinfo(ref->commit); - break; - } - free(ref); -} - -void cgit_free_reflist_inner(struct reflist *list) -{ - int i; - - for (i = 0; i < list->count; i++) { - cgit_free_refinfo(list->refs[i]); - } - free(list->refs); -} - -int cgit_refs_cb(const struct reference *ref, void *cb_data) +int cgit_refs_cb(const char *refname, const unsigned char *sha1, int flags, + void *cb_data) { struct reflist *list = (struct reflist *)cb_data; - struct refinfo *info = cgit_mk_refinfo(ref->name, ref->oid); + struct refinfo *info = cgit_mk_refinfo(refname, sha1); if (info) cgit_add_ref(list, info); @@ -250,15 +344,15 @@ void cgit_diff_tree_cb(struct diff_queue_struct *q, } } -static int load_mmfile(mmfile_t *file, const struct object_id *oid) +static int load_mmfile(mmfile_t *file, const unsigned char *sha1) { enum object_type type; - if (is_null_oid(oid)) { + if (is_null_sha1(sha1)) { file->ptr = (char *)""; file->size = 0; } else { - file->ptr = odb_read_object(the_repository->objects, oid, &type, + file->ptr = read_sha1_file(sha1, &type, (unsigned long *)&file->size); } return 1; @@ -272,10 +366,10 @@ static int load_mmfile(mmfile_t *file, const struct object_id *oid) * ripped from git and modified to use globals instead of * a special callback-struct. */ -static char *diffbuf = NULL; -static int buflen = 0; +char *diffbuf = NULL; +int buflen = 0; -static int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) +int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) { int i; @@ -309,301 +403,64 @@ static int filediff_cb(void *priv, mmbuffer_t *mb, int nbuf) return 0; } -int cgit_diff_files(const struct object_id *old_oid, - const struct object_id *new_oid, unsigned long *old_size, - unsigned long *new_size, int *binary, int context, - int ignorews, linediff_fn fn) +int cgit_diff_files(const unsigned char *old_sha1, + const unsigned char *new_sha1, + linediff_fn fn) { mmfile_t file1, file2; xpparam_t diff_params; xdemitconf_t emit_params; xdemitcb_t emit_cb; - if (!load_mmfile(&file1, old_oid) || !load_mmfile(&file2, new_oid)) + if (!load_mmfile(&file1, old_sha1) || !load_mmfile(&file2, new_sha1)) return 1; - *old_size = file1.size; - *new_size = file2.size; - - 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; - } - - memset(&diff_params, 0, sizeof(diff_params)); - 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.ctxlen = 3; emit_params.flags = XDL_EMIT_FUNCNAMES; - emit_cb.out_line = filediff_cb; + emit_params.find_func = NULL; + 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 struct object_id *old_oid, - const struct object_id *new_oid, - filepair_fn fn, const char *prefix, int ignorews) +void cgit_diff_tree(const unsigned char *old_sha1, + const unsigned char *new_sha1, + filepair_fn fn, const char *prefix) { struct diff_options opt; - struct pathspec_item *item; + int ret; + int prefixlen; - repo_diff_setup(the_repository, &opt); + diff_setup(&opt); opt.output_format = DIFF_FORMAT_CALLBACK; opt.detect_rename = 1; - opt.rename_limit = ctx.cfg.renamelimit; - opt.flags.recursive = 1; - if (ignorews) - DIFF_XDL_SET(&opt, IGNORE_WHITESPACE); + opt.rename_limit = cgit_renamelimit; + opt.recursive = 1; opt.format_callback = cgit_diff_tree_cb; opt.format_callback_data = fn; if (prefix) { - item = xcalloc(1, sizeof(*item)); - item->match = xstrdup(prefix); - item->len = strlen(prefix); - opt.pathspec.nr = 1; - opt.pathspec.items = item; + opt.nr_paths = 1; + opt.paths = &prefix; + prefixlen = strlen(prefix); + opt.pathlens = &prefixlen; } diff_setup_done(&opt); - if (old_oid && !is_null_oid(old_oid)) - diff_tree_oid(old_oid, new_oid, "", &opt); + if (old_sha1 && !is_null_sha1(old_sha1)) + ret = diff_tree_sha1(old_sha1, new_sha1, "", &opt); else - diff_root_tree_oid(new_oid, "", &opt); + ret = diff_root_tree_sha1(new_sha1, "", &opt); diffcore_std(&opt); diff_flush(&opt); } -void cgit_diff_commit(struct commit *commit, filepair_fn fn, const char *prefix) +void cgit_diff_commit(struct commit *commit, filepair_fn fn) { - const struct object_id *old_oid = NULL; + unsigned char *old_sha1 = NULL; if (commit->parents) - old_oid = &commit->parents->item->object.oid; - cgit_diff_tree(old_oid, &commit->object.oid, fn, prefix, - ctx.qry.ignorews); -} - -int cgit_parse_snapshots_mask(const char *str) -{ - struct string_list tokens = STRING_LIST_INIT_DUP; - struct string_list_item *item; - const struct cgit_snapshot_format *f; - int rv = 0; - - /* favor legacy setting */ - if (atoi(str)) - return 1; - - if (strcmp(str, "all") == 0) - return INT_MAX; - - string_list_split(&tokens, str, " ", -1); - string_list_remove_empty_items(&tokens, 0); - - for_each_string_list_item(item, &tokens) { - for (f = cgit_snapshot_formats; f->suffix; f++) { - if (!strcmp(item->string, f->suffix) || - !strcmp(item->string, f->suffix + 1)) { - rv |= cgit_snapshot_format_bit(f); - break; - } - } - } - - string_list_clear(&tokens, 0); - return rv; -} - -typedef struct { - char * name; - char * value; -} cgit_env_var; - -void cgit_prepare_repo_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 (p->value && setenv(p->name, p->value, 1)) - fprintf(stderr, warn, p->name, p->value); -} - -/* Read the content of the specified file into a newly allocated buffer, - * zeroterminate the buffer, truncate at a new line, and return 0 on success, - * errno otherwise. - */ -int read_first_line(const char *path, char **buf, size_t *size) -{ - int fd, e; - struct stat st; - - fd = open(path, O_RDONLY); - if (fd == -1) - return errno; - if (fstat(fd, &st)) { - e = errno; - close(fd); - return e; - } - if (!S_ISREG(st.st_mode)) { - close(fd); - return EISDIR; - } - *buf = xmalloc(st.st_size + 1); - *size = read_in_full(fd, *buf, st.st_size); - e = errno; - (*buf)[*size] = '\0'; - *strchrnul(*buf, '\n') = '\0'; - close(fd); - return (*size == st.st_size ? 0 : e); -} - -char *strdup_first_line(const char *txt) -{ - char *t = xstrdup(txt); - *strchrnul(t, '\n') = '\0'; - return t; -} - -static int is_token_char(char c) -{ - return isalnum(c) || c == '_'; -} - -/* Replace name with getenv(name), return pointer to zero-terminating char - */ -static char *expand_macro(char *name, int maxlength) -{ - char *value; - size_t len; - - len = 0; - value = getenv(name); - if (value) { - len = strlen(value) + 1; - if (len > maxlength) - len = maxlength; - strlcpy(name, value, len); - --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; -} - -char *get_mimetype_for_filename(const char *filename) -{ - const char *ext; - char *mimetype, line[1024]; - struct string_list list = STRING_LIST_INIT_NODUP; - int i; - FILE *file; - struct string_list_item *mime; - - if (!filename) - return NULL; - - ext = strrchr(filename, '.'); - if (!ext) - return NULL; - ++ext; - if (!ext[0]) - return NULL; - mime = string_list_lookup(&ctx.cfg.mimetypes, ext); - if (mime) - return xstrdup(mime->util); - - if (!ctx.cfg.mimetype_file) - return NULL; - file = fopen(ctx.cfg.mimetype_file, "r"); - if (!file) - return NULL; - while (fgets(line, sizeof(line), file)) { - if (!line[0] || line[0] == '#') - continue; - string_list_split_in_place(&list, line, " \t\r\n", -1); - string_list_remove_empty_items(&list, 0); - mimetype = list.items[0].string; - for (i = 1; i < list.nr; i++) { - if (!strcasecmp(ext, list.items[i].string)) { - fclose(file); - return xstrdup(mimetype); - } - } - string_list_clear(&list, 0); - } - fclose(file); - return NULL; + old_sha1 = commit->parents->item->object.sha1; + cgit_diff_tree(old_sha1, commit->object.sha1, fn, NULL); } |