diff options
Diffstat (limited to '')
| -rw-r--r-- | cgit.c | 35 | ||||
| -rw-r--r-- | ui-blob.c | 28 | ||||
| -rw-r--r-- | ui-blob.h | 1 | ||||
| -rw-r--r-- | ui-summary.c | 61 | ||||
| -rw-r--r-- | ui-summary.h | 1 | 
5 files changed, 95 insertions, 31 deletions
| @@ -14,6 +14,8 @@  #include "html.h"  #include "ui-shared.h"  #include "ui-stats.h" +#include "ui-blob.h" +#include "ui-summary.h"  #include "scan-tree.h"  const char *cgit_version = CGIT_VERSION; @@ -469,6 +471,38 @@ static char *guess_defbranch(void)  	return xstrdup(ref + 11);  } +static void choose_readme(struct cgit_repo *repo) +{ +	char *entry, *filename, *ref; + +	/* If there's no space, we skip the possibly expensive +	 * selection process. */ +	if (!repo->readme || !strchr(repo->readme, ' ')) +		return; + +	for (entry = strtok(repo->readme, " "); entry; entry = strtok(NULL, " ")) { +		cgit_parse_readme(entry, NULL, &filename, &ref, repo); +		if (!(*filename)) { +			free(filename); +			free(ref); +			continue; +		} +		if (*ref && cgit_ref_path_exists(filename, ref)) { +			free(filename); +			free(ref); +			break; +		} +		if (!access(filename, R_OK)) { +			free(filename); +			free(ref); +			break; +		} +		free(filename); +		free(ref); +	} +	repo->readme = entry; +} +  static int prepare_repo_cmd(struct cgit_context *ctx)  {  	unsigned char sha1[20]; @@ -537,6 +571,7 @@ static int prepare_repo_cmd(struct cgit_context *ctx)  	}  	sort_string_list(&ctx->repo->submodules);  	cgit_prepare_repo_env(ctx->repo); +	choose_readme(ctx->repo);  	return 0;  } @@ -13,7 +13,7 @@  #include "ui-shared.h"  struct walk_tree_context { -	char *match_path; +	const char *match_path;  	unsigned char *matched_sha1;  	int found_path;  }; @@ -31,6 +31,32 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,  	return 0;  } +int cgit_ref_path_exists(const char *path, const char *ref) +{ +        unsigned char sha1[20]; +        unsigned long size; +        struct pathspec_item path_items = { +                .match = path, +                .len = strlen(path) +        }; +        struct pathspec paths = { +                .nr = 1, +                .items = &path_items +        }; +        struct walk_tree_context walk_tree_ctx = { +                .match_path = path, +                .matched_sha1 = sha1, +                .found_path = 0 +        }; + +        if (get_sha1(ref, sha1)) +                return 0; +        if (sha1_object_info(sha1, &size) != OBJ_COMMIT)  +                return 0; +        read_tree_recursive(lookup_commit_reference(sha1)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); +        return walk_tree_ctx.found_path; +} +  int cgit_print_file(char *path, const char *head)  {  	unsigned char sha1[20]; @@ -1,6 +1,7 @@  #ifndef UI_BLOB_H  #define UI_BLOB_H +extern int cgit_ref_path_exists(const char *path, const char *ref);  extern int cgit_print_file(char *path, const char *head);  extern void cgit_print_blob(const char *hex, char *path, const char *head); diff --git a/ui-summary.c b/ui-summary.c index ffad4f2..2f8a822 100644 --- a/ui-summary.c +++ b/ui-summary.c @@ -95,70 +95,71 @@ void cgit_print_summary()  	html("</table>");  } -void cgit_print_repo_readme(char *path) +/* The caller must free filename and ref after calling this. */ +void cgit_parse_readme(const char *readme, const char *path, char **filename, char **ref, struct cgit_repo *repo)  { -	char *slash, *tmp, *colon, *ref; -	int free_filename = 0; +	const char *slash, *colon; -	if (!ctx.repo->readme || !(*ctx.repo->readme)) -		return; +	*filename = NULL; +	*ref = NULL; -	ref = NULL; +	if (!readme || !(*readme)) +		return;  	/* Check if the readme is tracked in the git repo. */ -	colon = strchr(ctx.repo->readme, ':'); +	colon = strchr(readme, ':');  	if (colon && strlen(colon) > 1) { -		*colon = '\0';  		/* If it starts with a colon, we want to use  		 * the default branch */ -		if (colon == ctx.repo->readme && ctx.repo->defbranch) -			ref = ctx.repo->defbranch; +		if (colon == readme && repo->defbranch) +			*ref = xstrdup(repo->defbranch);  		else -			ref = ctx.repo->readme; -		ctx.repo->readme = colon + 1; -		if (!(*ctx.repo->readme)) -			return; +			*ref = xstrndup(readme, colon - readme); +		readme = colon + 1;  	}  	/* Prepend repo path to relative readme path unless tracked. */ -	if (!ref && *ctx.repo->readme != '/') -		ctx.repo->readme = fmtalloc("%s/%s", ctx.repo->path, -						ctx.repo->readme); +	if (!(*ref) && *readme != '/') +		readme = fmtalloc("%s/%s", repo->path, readme);  	/* 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 readme. */  	if (path) { -		slash = strrchr(ctx.repo->readme, '/'); +		slash = strrchr(readme, '/');  		if (!slash) {  			if (!colon)  				return;  			slash = colon;  		} -		free_filename = 1; -		tmp = xmalloc(slash - ctx.repo->readme + 1 + strlen(path) + 1); -		strncpy(tmp, ctx.repo->readme, slash - ctx.repo->readme + 1); -		strcpy(tmp + (slash - ctx.repo->readme + 1), path); +		*filename = xmalloc(slash - readme + 1 + strlen(path) + 1); +		strncpy(*filename, readme, slash - readme + 1); +		strcpy(*filename + (slash - readme + 1), path);  	} else -		tmp = ctx.repo->readme; +		*filename = xstrdup(readme); +} + +void cgit_print_repo_readme(char *path) +{ +	char *filename, *ref; +	cgit_parse_readme(ctx.repo->readme, path, &filename, &ref, ctx.repo);  	/* Print the calculated readme, either from the git repo or from the  	 * filesystem, while applying the about-filter.  	 */  	html("<div id='summary'>");  	if (ctx.repo->about_filter) { -		ctx.repo->about_filter->argv[1] = tmp; +		ctx.repo->about_filter->argv[1] = filename;  		cgit_open_filter(ctx.repo->about_filter);  	}  	if (ref) -		cgit_print_file(tmp, ref); +		cgit_print_file(filename, ref);  	else -		html_include(tmp); +		html_include(filename);  	if (ctx.repo->about_filter) {  		cgit_close_filter(ctx.repo->about_filter);  		ctx.repo->about_filter->argv[1] = NULL;  	}  	html("</div>"); -	if (free_filename) -		free(tmp); +	free(filename); +	free(ref);  } diff --git a/ui-summary.h b/ui-summary.h index c01f560..d6dc5ba 100644 --- a/ui-summary.h +++ b/ui-summary.h @@ -1,6 +1,7 @@  #ifndef UI_SUMMARY_H  #define UI_SUMMARY_H +extern void cgit_parse_readme(const char *readme, const char *path, char **filename, char **ref, struct cgit_repo *repo);  extern void cgit_print_summary();  extern void cgit_print_repo_readme(char *path); | 
