about summary refs log tree commit diff
path: root/cgit.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2013-05-26 15:20:02 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2013-05-26 16:30:03 +0200
commitdcbc0438b2543a733858d62170f3110a89edbed6 (patch)
treebdacfe4546c88bf6b03860ea69a0cad885fa6af4 /cgit.c
parentui-summary: Disallow directory traversal (diff)
downloadcgit-pink-dcbc0438b2543a733858d62170f3110a89edbed6.tar.gz
cgit-pink-dcbc0438b2543a733858d62170f3110a89edbed6.zip
readme: use string_list instead of space deliminations
Now this is possible in cgitrc -

readme=:README.md
readme=:readme.md
readme=:README.mkd
readme=:readme.mkd
readme=:README.rst
readme=:readme.rst
readme=:README.html
readme=:readme.html
readme=:README.htm
readme=:readme.htm
readme=:README.txt
readme=:readme.txt
readme=:README
readme=:readme
readme=:INSTALL.txt
readme=:install.txt
readme=:INSTALL
readme=:install

Suggested-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'cgit.c')
-rw-r--r--cgit.c92
1 files changed, 69 insertions, 23 deletions
diff --git a/cgit.c b/cgit.c
index f738b83..f0a9acf 100644
--- a/cgit.c
+++ b/cgit.c
@@ -1,7 +1,7 @@
 /* cgit.c: cgi for the git scm
  *
  * Copyright (C) 2006 Lars Hjemli
- * Copyright (C) 2010, 2012 Jason A. Donenfeld <Jason@zx2c4.com>
+ * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com>
  *
  * Licensed under GNU General Public License v2
  *   (see COPYING for full license text)
@@ -101,13 +101,15 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
 	else if (!strcmp(name, "module-link"))
 		repo->module_link= xstrdup(value);
 	else if (!prefixcmp(name, "module-link.")) {
-		item = string_list_append(&repo->submodules, name + 12);
+		item = string_list_append(&repo->submodules, xstrdup(name + 12));
 		item->util = xstrdup(value);
 	} else if (!strcmp(name, "section"))
 		repo->section = xstrdup(value);
-	else if (!strcmp(name, "readme") && value != NULL)
-		repo->readme = xstrdup(value);
-	else if (!strcmp(name, "logo") && value != NULL)
+	else if (!strcmp(name, "readme") && value != NULL) {
+		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, "logo") && value != NULL)
 		repo->logo = xstrdup(value);
 	else if (!strcmp(name, "logo-link") && value != NULL)
 		repo->logo_link = xstrdup(value);
@@ -131,8 +133,8 @@ static void config_cb(const char *name, const char *value)
 		ctx.repo->path = trim_end(value, '/');
 	else if (ctx.repo && !prefixcmp(name, "repo."))
 		repo_config(ctx.repo, name + 5, value);
-	else if (!strcmp(name, "readme"))
-		ctx.cfg.readme = xstrdup(value);
+	else if (!strcmp(name, "readme") && value != NULL)
+		string_list_append(&ctx.cfg.readme, xstrdup(value));
 	else if (!strcmp(name, "root-title"))
 		ctx.cfg.root_title = xstrdup(value);
 	else if (!strcmp(name, "root-desc"))
@@ -470,37 +472,76 @@ static char *guess_defbranch(void)
 		return "master";
 	return xstrdup(ref + 11);
 }
+/* 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)
+{
+	const char *colon;
+
+	*filename = NULL;
+	*ref = NULL;
+
+	if (!readme || !readme[0])
+		return;
 
+	/* Check if the readme is tracked in the git repo. */
+	colon = strchr(readme, ':');
+	if (colon && strlen(colon) > 1) {
+		/* If it starts with a colon, we want to use
+		 * the default branch */
+		if (colon == readme && repo->defbranch)
+			*ref = xstrdup(repo->defbranch);
+		else
+			*ref = xstrndup(readme, colon - readme);
+		readme = colon + 1;
+	}
+
+	/* Prepend repo path to relative readme path unless tracked. */
+	if (!(*ref) && readme[0] != '/')
+		*filename = fmtalloc("%s/%s", repo->path, readme);
+	else
+		*filename = xstrdup(readme);
+}
 static void choose_readme(struct cgit_repo *repo)
 {
-	char *entry, *filename, *ref;
+	int found;
+	char *filename, *ref;
+	struct string_list_item *entry;
 
-	/* If there's no space, we skip the possibly expensive
-	 * selection process. */
-	if (!repo->readme || !strchr(repo->readme, ' '))
+	if (!repo->readme.nr)
 		return;
 
-	for (entry = strtok(repo->readme, " "); entry; entry = strtok(NULL, " ")) {
-		cgit_parse_readme(entry, NULL, &filename, &ref, repo);
-		if (!(*filename)) {
+	found = 0;
+	for_each_string_list_item(entry, &repo->readme) {
+		parse_readme(entry->string, &filename, &ref, repo);
+		if (!filename) {
 			free(filename);
 			free(ref);
 			continue;
 		}
-		if (*ref && cgit_ref_path_exists(filename, ref)) {
-			free(filename);
-			free(ref);
+		/* If there's only one item, we skip the possibly expensive
+		 * selection process. */
+		if (repo->readme.nr == 1) {
+			found = 1;
 			break;
 		}
-		if (!access(filename, R_OK)) {
-			free(filename);
-			free(ref);
+		if (ref) {
+			if (cgit_ref_path_exists(filename, ref, 1)) {
+				found = 1;
+				break;
+			}
+		}
+		else if (!access(filename, R_OK)) {
+			found = 1;
 			break;
 		}
 		free(filename);
 		free(ref);
 	}
-	repo->readme = entry;
+	repo->readme.strdup_strings = 1;
+	string_list_clear(&repo->readme, 0);
+	repo->readme.strdup_strings = 0;
+	if (found)
+		string_list_append(&repo->readme, filename)->util = ref;
 }
 
 static int prepare_repo_cmd(struct cgit_context *ctx)
@@ -660,6 +701,7 @@ static char *get_first_line(char *txt)
 
 static void print_repo(FILE *f, struct cgit_repo *repo)
 {
+	struct string_list_item *item;
 	fprintf(f, "repo.url=%s\n", repo->url);
 	fprintf(f, "repo.name=%s\n", repo->name);
 	fprintf(f, "repo.path=%s\n", repo->path);
@@ -670,8 +712,12 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
 		fprintf(f, "repo.desc=%s\n", tmp);
 		free(tmp);
 	}
-	if (repo->readme)
-		fprintf(f, "repo.readme=%s\n", repo->readme);
+	for_each_string_list_item(item, &repo->readme) {
+		if (item->util)
+			fprintf(f, "repo.readme=%s:%s\n", (char *)item->util, item->string);
+		else
+			fprintf(f, "repo.readme=%s\n", item->string);
+	}
 	if (repo->defbranch)
 		fprintf(f, "repo.defbranch=%s\n", repo->defbranch);
 	if (repo->module_link)