diff options
-rw-r--r-- | cgit.c | 59 | ||||
-rw-r--r-- | cgit.h | 3 | ||||
-rw-r--r-- | cgitrc.5.txt | 24 | ||||
-rw-r--r-- | cmd.c | 27 | ||||
-rw-r--r-- | shared.c | 1 | ||||
-rw-r--r-- | ui-shared.c | 4 | ||||
-rw-r--r-- | ui-summary.c | 17 | ||||
-rw-r--r-- | ui-summary.h | 4 |
8 files changed, 107 insertions, 32 deletions
@@ -99,6 +99,10 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va if (repo->readme.items == ctx.cfg.readme.items) memset(&repo->readme, 0, sizeof(repo->readme)); string_list_append(&repo->readme, xstrdup(value)); + } else if (!strcmp(name, "license") && value != NULL) { + if (repo->license.items == ctx.cfg.license.items) + memset(&repo->license, 0, sizeof(repo->license)); + string_list_append(&repo->license, xstrdup(value)); } else if (!strcmp(name, "logo") && value != NULL) repo->logo = xstrdup(value); else if (!strcmp(name, "logo-link") && value != NULL) @@ -135,6 +139,8 @@ static void config_cb(const char *name, const char *value) repo_config(ctx.repo, arg, value); else if (!strcmp(name, "readme")) string_list_append(&ctx.cfg.readme, xstrdup(value)); + else if (!strcmp(name, "license")) + string_list_append(&ctx.cfg.license, xstrdup(value)); else if (!strcmp(name, "root-title")) ctx.cfg.root_title = xstrdup(value); else if (!strcmp(name, "root-desc")) @@ -213,6 +219,8 @@ static void config_cb(const char *name, const char *value) ctx.cfg.cache_dynamic_ttl = atoi(value); else if (!strcmp(name, "cache-about-ttl")) ctx.cfg.cache_about_ttl = atoi(value); + else if (!strcmp(name, "cache-license-ttl")) + ctx.cfg.cache_license_ttl = atoi(value); else if (!strcmp(name, "cache-snapshot-ttl")) ctx.cfg.cache_snapshot_ttl = atoi(value); else if (!strcmp(name, "case-sensitive-sort")) @@ -367,6 +375,7 @@ static void prepare_context(void) ctx.cfg.cache_max_create_time = 5; ctx.cfg.cache_root = CGIT_CACHE_ROOT; ctx.cfg.cache_about_ttl = 15; + ctx.cfg.cache_license_ttl = 15; ctx.cfg.cache_snapshot_ttl = 5; ctx.cfg.cache_repo_ttl = 5; ctx.cfg.cache_root_ttl = 5; @@ -494,46 +503,46 @@ static char *guess_defbranch(void) } /* The caller must free filename and ref after calling this. */ -static inline void parse_readme(const char *readme, char **filename, char **ref, struct cgit_repo *repo) +static inline void parse_info_file(const char *file, char **filename, char **ref, struct cgit_repo *repo) { const char *colon; *filename = NULL; *ref = NULL; - if (!readme || !readme[0]) + if (!file || !file[0]) return; - /* Check if the readme is tracked in the git repo. */ - colon = strchr(readme, ':'); + /* Check if the file is tracked in the git repo. */ + colon = strchr(file, ':'); if (colon && strlen(colon) > 1) { /* If it starts with a colon, we want to use * the default branch */ - if (colon == readme && repo->defbranch) + if (colon == file && repo->defbranch) *ref = xstrdup(repo->defbranch); else - *ref = xstrndup(readme, colon - readme); - readme = colon + 1; + *ref = xstrndup(file, colon - file); + file = colon + 1; } - /* Prepend repo path to relative readme path unless tracked. */ - if (!(*ref) && readme[0] != '/') - *filename = fmtalloc("%s/%s", repo->path, readme); + /* Prepend repo path to relative file path unless tracked. */ + if (!(*ref) && file[0] != '/') + *filename = fmtalloc("%s/%s", repo->path, file); else - *filename = xstrdup(readme); + *filename = xstrdup(file); } -static void choose_readme(struct cgit_repo *repo) +static void choose_string_list_item(struct cgit_repo *repo, struct string_list *file) { int found; char *filename, *ref; struct string_list_item *entry; - if (!repo->readme.nr) + if (!file->nr) return; found = 0; - for_each_string_list_item(entry, &repo->readme) { - parse_readme(entry->string, &filename, &ref, repo); + for_each_string_list_item(entry, file) { + parse_info_file(entry->string, &filename, &ref, repo); if (!filename) { free(filename); free(ref); @@ -552,11 +561,11 @@ static void choose_readme(struct cgit_repo *repo) free(filename); free(ref); } - repo->readme.strdup_strings = 1; - string_list_clear(&repo->readme, 0); - repo->readme.strdup_strings = 0; + file->strdup_strings = 1; + string_list_clear(file, 0); + file->strdup_strings = 0; if (found) - string_list_append(&repo->readme, filename)->util = ref; + string_list_append(file, filename)->util = ref; } static void print_no_repo_clone_urls(const char *url) @@ -636,7 +645,8 @@ static int prepare_repo_cmd(int nongit) } string_list_sort(&ctx.repo->submodules); cgit_prepare_repo_env(ctx.repo); - choose_readme(ctx.repo); + choose_string_list_item(ctx.repo, &ctx.repo->readme); + choose_string_list_item(ctx.repo, &ctx.repo->license); return 0; } @@ -804,6 +814,12 @@ static void print_repo(FILE *f, struct cgit_repo *repo) else fprintf(f, "repo.readme=%s\n", item->string); } + for_each_string_list_item(item, &repo->license) { + if (item->util) + fprintf(f, "repo.license=%s:%s\n", (char *)item->util, item->string); + else + fprintf(f, "repo.license=%s\n", item->string); + } if (repo->defbranch) fprintf(f, "repo.defbranch=%s\n", repo->defbranch); if (repo->extra_head_content) @@ -1034,6 +1050,9 @@ static int calc_ttl(void) if (!strcmp(ctx.qry.page, "about")) return ctx.cfg.cache_about_ttl; + if (!strcmp(ctx.qry.page, "license")) + return ctx.cfg.cache_license_ttl; + if (!strcmp(ctx.qry.page, "snapshot")) return ctx.cfg.cache_snapshot_ttl; @@ -88,6 +88,7 @@ struct cgit_repo { char *defbranch; char *module_link; struct string_list readme; + struct string_list license; char *section; char *clone_url; char *logo; @@ -206,6 +207,7 @@ struct cgit_config { char *module_link; char *project_list; struct string_list readme; + struct string_list license; char *robots; char *root_title; char *root_desc; @@ -223,6 +225,7 @@ struct cgit_config { int cache_scanrc_ttl; int cache_static_ttl; int cache_about_ttl; + int cache_license_ttl; int cache_snapshot_ttl; int case_sensitive_sort; int embedded; diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 33a6a8c..5a0e422 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt @@ -331,6 +331,12 @@ readme:: in this list. This is useful in conjunction with scan-path. Default value: none. See also: scan-path, repo.readme. +license:: + Text which will be used as default value for "repo.license". Multiple + config keys may be specified, and cgit will use the first found file + in this list. This is useful in conjunction with scan-path. Default + value: none. See also: scan-path, repo.license. + remove-suffix:: If set to "1" and scan-path is enabled, if any repositories are found with a suffix of ".git", this suffix will be removed for the url and @@ -585,6 +591,17 @@ repo.readme:: are no non-public files located in the same directory as the readme file. Default value: <readme>. +repo.license:: + A path (relative to <repo.path>) which specifies a file to include + verbatim as the "license" page for this repo. You may also specify a + git refspec by head or by hash by prepending the refspec followed by + a colon. For example, "master:LICENSE". If the value begins + with a colon, i.e. ":COPYING", the default branch of the + repository will be used. Sharing any file will expose that entire + directory tree to the "/license/PATH" endpoints, so be sure that there + are no non-public files located in the same directory as the license + file. Default value: <license>. + repo.section:: Override the current section name for this repository. Default value: none. @@ -669,7 +686,7 @@ Parameters are provided to filters as follows. about filter:: This filter is given a single parameter: the filename of the source file to filter. The filter can use the filename to determine (for - example) the type of syntax to follow when formatting the readme file. + example) the type of syntax to follow when formatting the readme/license file. The about text that is to be filtered is available on standard input and the filtered text is expected on standard output. @@ -930,6 +947,10 @@ readme=:install.txt readme=:INSTALL readme=:install +license=:LICENSE.md +license=:LICENSE +license=:COPYING.md +license=:COPYING ## ## List of repositories. @@ -946,6 +967,7 @@ repo.path=/pub/git/foo.git repo.desc=the master foo repository repo.owner=fooman@example.com repo.readme=info/web/about.html +repo.license=GPLv3.html repo.url=bar @@ -50,7 +50,7 @@ static void about_fn(void) free(currenturl); free(redirect); } else if (ctx.repo->readme.nr) - cgit_print_repo_readme(ctx.qry.path); + cgit_print_repo_info_file(ctx.repo->readme, ctx.qry.path); else if (ctx.repo->homepage) cgit_redirect(ctx.repo->homepage, false); else { @@ -97,6 +97,30 @@ static void info_fn(void) cgit_clone_info(); } +static void license_fn(void) +{ + if (ctx.repo) { + size_t path_info_len = ctx.env.path_info ? strlen(ctx.env.path_info) : 0; + if (!ctx.qry.path && + ctx.qry.url[strlen(ctx.qry.url) - 1] != '/' && + (!path_info_len || ctx.env.path_info[path_info_len - 1] != '/')) { + char *currenturl = cgit_currenturl(); + char *redirect = fmtalloc("%s/", currenturl); + cgit_redirect(redirect, true); + free(currenturl); + free(redirect); + } else if (ctx.repo->license.nr) + cgit_print_repo_info_file(ctx.repo->license, ctx.qry.path); + else { + char *currenturl = cgit_currenturl(); + char *redirect = fmtalloc("%s../", currenturl); + cgit_redirect(redirect, false); + free(currenturl); + free(redirect); + } + } +} + static void log_fn(void) { cgit_print_log(ctx.qry.oid, ctx.qry.ofs, ctx.cfg.max_commit_count, @@ -178,6 +202,7 @@ struct cgit_cmd *cgit_get_cmd(void) def_cmd(commit, 1, 1, 0), def_cmd(diff, 1, 1, 0), def_cmd(info, 1, 0, 1), + def_cmd(license, 1, 1, 0), def_cmd(log, 1, 1, 0), def_cmd(ls_cache, 0, 0, 0), def_cmd(objects, 1, 0, 1), @@ -70,6 +70,7 @@ struct cgit_repo *cgit_add_repo(const char *url) ret->commit_sort = ctx.cfg.commit_sort; ret->module_link = ctx.cfg.module_link; ret->readme = ctx.cfg.readme; + ret->license = ctx.cfg.license; ret->mtime = -1; ret->about_filter = ctx.cfg.about_filter; ret->commit_filter = ctx.cfg.commit_filter; diff --git a/ui-shared.c b/ui-shared.c index acd8ab5..207bf69 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -1056,6 +1056,10 @@ void cgit_print_pageheader(void) if (ctx.repo->max_stats) cgit_stats_link("stats", NULL, hc("stats"), ctx.qry.head, ctx.qry.vpath); + if (ctx.repo->license.nr) + reporevlink("license", "license", NULL, + hc("license"), ctx.qry.head, NULL, + NULL); if (ctx.repo->homepage) { html("<a href='"); html_attr(ctx.repo->homepage); diff --git a/ui-summary.c b/ui-summary.c index 947812a..dc4d0a6 100644 --- a/ui-summary.c +++ b/ui-summary.c @@ -66,11 +66,11 @@ void cgit_print_summary(void) } /* The caller must free the return value. */ -static char* append_readme_path(const char *filename, const char *ref, const char *path) +static char* append_file_path(const char *filename, const char *ref, const char *path) { char *file, *base_dir, *full_path, *resolved_base = NULL, *resolved_full = NULL; /* If a subpath is specified for the about page, make it relative - * to the directory containing the configured readme. */ + * to the directory containing the configured file. */ file = xstrdup(filename); base_dir = dirname(file); @@ -98,8 +98,7 @@ static char* append_readme_path(const char *filename, const char *ref, const cha return full_path; } - -void cgit_print_repo_readme(const char *path) +void cgit_print_repo_info_file(struct string_list file, const char *path) { char *filename, *ref, *mimetype; int free_filename = 0; @@ -115,20 +114,20 @@ void cgit_print_repo_readme(const char *path) free(mimetype); cgit_print_layout_start(); - if (ctx.repo->readme.nr == 0) + if (file.nr == 0) goto done; - filename = ctx.repo->readme.items[0].string; - ref = ctx.repo->readme.items[0].util; + filename = file.items[0].string; + ref = file.items[0].util; if (path) { free_filename = 1; - filename = append_readme_path(filename, ref, path); + filename = append_file_path(filename, ref, path); if (!filename) goto done; } - /* Print the calculated readme, either from the git repo or from the + /* Print the calculated file, either from the git repo or from the * filesystem, while applying the about-filter. */ html("<div id='summary'>"); diff --git a/ui-summary.h b/ui-summary.h index cba696a..9592802 100644 --- a/ui-summary.h +++ b/ui-summary.h @@ -1,7 +1,9 @@ #ifndef UI_SUMMARY_H #define UI_SUMMARY_H +#include <string-list.h> + extern void cgit_print_summary(void); -extern void cgit_print_repo_readme(const char *path); +extern void cgit_print_repo_info_file(struct string_list file, const char *path); #endif /* UI_SUMMARY_H */ |