diff options
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | cache.c | 22 | ||||
| -rw-r--r-- | cgit.c | 74 | ||||
| -rw-r--r-- | cgit.h | 17 | ||||
| m--------- | git | 0 | ||||
| -rw-r--r-- | html.c | 14 | ||||
| -rw-r--r-- | parsing.c | 44 | ||||
| -rw-r--r-- | shared.c | 33 | ||||
| -rw-r--r-- | ui-repolist.c | 5 | ||||
| -rw-r--r-- | ui-shared.c | 5 | 
10 files changed, 166 insertions, 56 deletions
| @@ -31,14 +31,12 @@ CFLAGS += -DCGIT_SCRIPT_NAME='"$(CGIT_SCRIPT_NAME)"'  # -# If make is run on a nongit platform, we need to get the git sources as a tarball. -# But there is currently no recent enough tarball available on kernel.org, so download -# a zipfile from hjemli.net instead +# If make is run on a nongit platform, get the git sources as a tarball.  #  GITVER = $(shell git version 2>/dev/null || echo nogit)  ifeq ($(GITVER),nogit) -GITURL = http://hjemli.net/git/git/snapshot/?id=v1.5.2-rc2 -INITGIT = test -e git/git.c || (curl "$(GITURL)" > tmp.zip && unzip tmp.zip) +GITURL = http://www.kernel.org/pub/software/scm/git/git-1.5.2.tar.bz2 +INITGIT = test -e git/git.c || ((curl "$(GITURL)" | tar -xj) && mv git-1.5.2 git)  else  INITGIT = ./submodules.sh -i  endif @@ -12,18 +12,23 @@ const int NOLOCK = -1;  char *cache_safe_filename(const char *unsafe)  { -	static char buf[PATH_MAX]; -	char *s = buf; +	static char buf[4][PATH_MAX]; +	static int bufidx; +	char *s;  	char c; +	bufidx++; +	bufidx &= 3; +	s = buf[bufidx]; +  	while(unsafe && (c = *unsafe++) != 0) { -		if (c == '/' || c == ' ' || c == '&' || c == '|' ||  +		if (c == '/' || c == ' ' || c == '&' || c == '|' ||  		    c == '>' || c == '<' || c == '.')  			c = '_';  		*s++ = c;  	}  	*s = '\0'; -	return buf; +	return buf[bufidx];  }  int cache_exist(struct cacheitem *item) @@ -43,15 +48,18 @@ int cache_create_dirs()  	if (mkdir(path, S_IRWXU) && errno!=EEXIST)  		return 0; -	if (!cgit_query_repo) +	if (!cgit_repo)  		return 0; -	path = fmt("%s/%s", cgit_cache_root, cgit_query_repo); +	path = fmt("%s/%s", cgit_cache_root, +		   cache_safe_filename(cgit_repo->url)); +  	if (mkdir(path, S_IRWXU) && errno!=EEXIST)  		return 0;  	if (cgit_query_page) { -		path = fmt("%s/%s/%s", cgit_cache_root, cgit_query_repo,  +		path = fmt("%s/%s/%s", cgit_cache_root, +			   cache_safe_filename(cgit_repo->url),  			   cgit_query_page);  		if (mkdir(path, S_IRWXU) && errno!=EEXIST)  			return 0; @@ -11,29 +11,9 @@  const char cgit_version[] = CGIT_VERSION; -static struct repoinfo *cgit_get_repoinfo(char *url) -{ -	int i; -	struct repoinfo *repo; - -	for (i=0; i<cgit_repolist.count; i++) { -		repo = &cgit_repolist.repos[i]; -		if (!strcmp(repo->url, url)) -			return repo; -	} -	return NULL; -} - -  static int cgit_prepare_cache(struct cacheitem *item)  { -	if (!cgit_query_repo) { -		item->name = xstrdup(fmt("%s/index.html", cgit_cache_root)); -		item->ttl = cgit_cache_root_ttl; -		return 1; -	} -	cgit_repo = cgit_get_repoinfo(cgit_query_repo); -	if (!cgit_repo) { +	if (!cgit_repo && cgit_query_repo) {  		char *title = fmt("%s - %s", cgit_root_title, "Bad request");  		cgit_print_docstart(title, item);  		cgit_print_pageheader(title, 0); @@ -42,13 +22,19 @@ static int cgit_prepare_cache(struct cacheitem *item)  		return 0;  	} -	if (!cgit_query_page) { +	if (!cgit_repo) { +		item->name = xstrdup(fmt("%s/index.html", cgit_cache_root)); +		item->ttl = cgit_cache_root_ttl; +		return 1; +	} + +	if (!cgit_cmd) {  		item->name = xstrdup(fmt("%s/%s/index.html", cgit_cache_root, -			   cgit_repo->url)); +			   cache_safe_filename(cgit_repo->url)));  		item->ttl = cgit_cache_repo_ttl;  	} else {  		item->name = xstrdup(fmt("%s/%s/%s/%s.html", cgit_cache_root, -			   cgit_repo->url, cgit_query_page, +			   cache_safe_filename(cgit_repo->url), cgit_query_page,  			   cache_safe_filename(cgit_querystring)));  		if (cgit_query_has_symref)  			item->ttl = cgit_cache_dynamic_ttl; @@ -82,25 +68,20 @@ static void cgit_print_repo_page(struct cacheitem *item)  	show_search = 0;  	setenv("GIT_DIR", cgit_repo->path, 1); -	if (cgit_query_page) { -	    if (cgit_repo->snapshots && !strcmp(cgit_query_page, "snapshot")) { +	if ((cgit_cmd == CMD_SNAPSHOT) && cgit_repo->snapshots) {  		cgit_print_snapshot(item, cgit_query_sha1, "zip",  				    cgit_repo->url, cgit_query_name);  		return; -	    } -	    if (!strcmp(cgit_query_page, "blob")) { -		    cgit_print_blob(item, cgit_query_sha1, cgit_query_path); -		    return; -	    }  	} -	if (cgit_query_page && !strcmp(cgit_query_page, "log")) -		show_search = 1; +	if (cgit_cmd == CMD_BLOB) { +		cgit_print_blob(item, cgit_query_sha1, cgit_query_path); +		return; +	} +	show_search = (cgit_cmd == CMD_LOG);  	cgit_print_docstart(title, item); - - -	if (!cgit_query_page) { +	if (!cgit_cmd) {  		cgit_print_pageheader("summary", show_search);  		cgit_print_summary();  		cgit_print_docend(); @@ -109,20 +90,26 @@ static void cgit_print_repo_page(struct cacheitem *item)  	cgit_print_pageheader(cgit_query_page, show_search); -	if (!strcmp(cgit_query_page, "log")) { +	switch(cgit_cmd) { +	case CMD_LOG:  		cgit_print_log(cgit_query_head, cgit_query_ofs,  			       cgit_max_commit_count, cgit_query_search,  			       cgit_query_path); -	} else if (!strcmp(cgit_query_page, "tree")) { +		break; +	case CMD_TREE:  		cgit_print_tree(cgit_query_head, cgit_query_sha1, cgit_query_path); -	} else if (!strcmp(cgit_query_page, "commit")) { +		break; +	case CMD_COMMIT:  		cgit_print_commit(cgit_query_head); -	} else if (!strcmp(cgit_query_page, "view")) { +		break; +	case CMD_VIEW:  		cgit_print_view(cgit_query_sha1, cgit_query_path); -	} else if (!strcmp(cgit_query_page, "diff")) { +		break; +	case CMD_DIFF:  		cgit_print_diff(cgit_query_head, cgit_query_sha1, cgit_query_sha2,  				cgit_query_path); -	} else { +		break; +	default:  		cgit_print_error("Invalid request");  	}  	cgit_print_docend(); @@ -143,7 +130,7 @@ static void cgit_fill_cache(struct cacheitem *item, int use_cache)  		chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)");  	} -	if (cgit_query_repo) +	if (cgit_repo)  		cgit_print_repo_page(item);  	else  		cgit_print_repolist(item); @@ -248,6 +235,7 @@ int main(int argc, const char **argv)  	cgit_repolist.repos = NULL;  	cgit_read_config(CGIT_CONFIG, cgit_global_config_cb); +	cgit_repo = NULL;  	if (getenv("SCRIPT_NAME"))  		cgit_script_name = xstrdup(getenv("SCRIPT_NAME"));  	if (getenv("QUERY_STRING")) @@ -18,6 +18,17 @@  #include <xdiff/xdiff.h> +/* + * The valid cgit repo-commands + */ +#define CMD_LOG      1 +#define CMD_COMMIT   2 +#define CMD_DIFF     3 +#define CMD_TREE     4 +#define CMD_VIEW     5 +#define CMD_BLOB     6 +#define CMD_SNAPSHOT 7 +  typedef void (*configfn)(const char *name, const char *value);  typedef void (*filepair_fn)(struct diff_filepair *pair);  typedef void (*linediff_fn)(char *line, int len); @@ -72,10 +83,12 @@ extern const char cgit_version[];  extern struct repolist cgit_repolist;  extern struct repoinfo *cgit_repo; +extern int cgit_cmd;  extern char *cgit_root_title;  extern char *cgit_css;  extern char *cgit_logo; +extern char *cgit_index_header;  extern char *cgit_logo_link;  extern char *cgit_module_link;  extern char *cgit_virtual_root; @@ -114,6 +127,8 @@ extern int   cgit_query_ofs;  extern int htmlfd; +extern int cgit_get_cmd_index(const char *cmd); +extern struct repoinfo *cgit_get_repoinfo(const char *url);  extern void cgit_global_config_cb(const char *name, const char *value);  extern void cgit_repo_config_cb(const char *name, const char *value);  extern void cgit_querystring_cb(const char *name, const char *value); @@ -146,11 +161,13 @@ extern void html_hidden(char *name, char *value);  extern void html_link_open(char *url, char *title, char *class);  extern void html_link_close(void);  extern void html_filemode(unsigned short mode); +extern int html_include(const char *filename);  extern int cgit_read_config(const char *filename, configfn fn);  extern int cgit_parse_query(char *txt, configfn fn);  extern struct commitinfo *cgit_parse_commit(struct commit *commit);  extern struct taginfo *cgit_parse_tag(struct tag *tag); +extern void cgit_parse_url(const char *url);  extern char *cache_safe_filename(const char *unsafe);  extern int cache_lock(struct cacheitem *item); diff --git a/git b/git -Subproject 9159afbfce955db86373dab95b5f8e31fb763da +Subproject aba170cdb4874b72dd619e6f7bbc13c33295f83 @@ -166,3 +166,17 @@ void html_filemode(unsigned short mode)  	html_fileperm(mode >> 3);  	html_fileperm(mode);  } + +int html_include(const char *filename) +{ +	FILE *f; +	char buf[4096]; +	size_t len; + +	if (!(f = fopen(filename, "r"))) +		return -1; +	while((len = fread(buf, 1, 4096, f)) > 0) +		write(htmlfd, buf, len); +	fclose(f); +	return 0; +} @@ -132,6 +132,50 @@ int cgit_parse_query(char *txt, configfn fn)  	return 0;  } +/* + * url syntax: [repo ['/' cmd [ '/' path]]] + *   repo: any valid repo url, may contain '/' + *   cmd:  log | commit | diff | tree | view | blob | snapshot + *   path: any valid path, may contain '/' + * + */ +void cgit_parse_url(const char *url) +{ +	char *cmd, *p; + +	cgit_repo = NULL; +	if (!url || url[0] == '\0') +		return; + +	cgit_repo = cgit_get_repoinfo(url); +	if (cgit_repo) { +		cgit_query_repo = cgit_repo->url; +		return; +	} + +	cmd = strchr(url, '/'); +	while (!cgit_repo && cmd) { +		cmd[0] = '\0'; +		cgit_repo = cgit_get_repoinfo(url); +		if (cgit_repo == NULL) { +			cmd[0] = '/'; +			cmd = strchr(cmd + 1, '/'); +			continue; +		} + +		cgit_query_repo = cgit_repo->url; +		p = strchr(cmd + 1, '/'); +		if (p) { +			p[0] = '\0'; +			if (p[1]) +				cgit_query_path = xstrdup(p + 1); +		} +		cgit_cmd = cgit_get_cmd_index(cmd + 1); +		cgit_query_page = xstrdup(cmd + 1); +		return; +	} +} +  char *substr(const char *head, const char *tail)  {  	char *buf; @@ -10,10 +10,12 @@  struct repolist cgit_repolist;  struct repoinfo *cgit_repo; +int cgit_cmd;  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_virtual_root = NULL; @@ -52,6 +54,18 @@ int   cgit_query_ofs    = 0;  int htmlfd = 0; + +int cgit_get_cmd_index(const char *cmd) +{ +	static char *cmds[] = {"log", "commit", "diff", "tree", "view", "blob", "snapshot", 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) @@ -95,6 +109,19 @@ struct repoinfo *add_repo(const char *url)  	return ret;  } +struct repoinfo *cgit_get_repoinfo(const char *url) +{ +	int i; +	struct repoinfo *repo; + +	for (i=0; i<cgit_repolist.count; i++) { +		repo = &cgit_repolist.repos[i]; +		if (!strcmp(repo->url, url)) +			return repo; +	} +	return NULL; +} +  void cgit_global_config_cb(const char *name, const char *value)  {  	if (!strcmp(name, "root-title")) @@ -103,6 +130,8 @@ void cgit_global_config_cb(const char *name, const char *value)  		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")) @@ -163,8 +192,12 @@ 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")) { diff --git a/ui-repolist.c b/ui-repolist.c index 8724589..33e3e7f 100644 --- a/ui-repolist.c +++ b/ui-repolist.c @@ -18,6 +18,11 @@ void cgit_print_repolist(struct cacheitem *item)  	cgit_print_pageheader(cgit_root_title, 0);  	html("<table class='list nowrap'>"); +	if (cgit_index_header) { +		html("<tr class='nohover'><td colspan='4' class='include-block'>"); +		html_include(cgit_index_header); +		html("</td></tr>"); +	}  	html("<tr class='nohover'>"  	     "<th class='left'>Name</th>"  	     "<th class='left'>Description</th>" diff --git a/ui-shared.c b/ui-shared.c index 6211056..c7fbc5e 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -68,7 +68,10 @@ char *cgit_pageurl(const char *reponame, const char *pagename,  			return fmt("%s/%s/%s/", cgit_virtual_root, reponame,  				   pagename);  	} else { -		return fmt("?r=%s&p=%s&%s", reponame, pagename, query); +		if (query) +			return fmt("?r=%s&p=%s&%s", reponame, pagename, query); +		else +			return fmt("?r=%s&p=%s", reponame, pagename);  	}  } | 
