diff options
| author | Lars Hjemli <hjemli@gmail.com> | 2007-02-08 13:53:13 +0100 | 
|---|---|---|
| committer | Lars Hjemli <hjemli@gmail.com> | 2007-02-08 13:58:58 +0100 | 
| commit | ab2ab95f09994560f62fd631f07d3b6e3577aa6e (patch) | |
| tree | 846763c1bcb78bd27dc37c99e5f6d703ca5ab179 | |
| parent | cgit v0.2 (diff) | |
| download | cgit-ab2ab95f09994560f62fd631f07d3b6e3577aa6e.tar.gz cgit-ab2ab95f09994560f62fd631f07d3b6e3577aa6e.tar.bz2 cgit-ab2ab95f09994560f62fd631f07d3b6e3577aa6e.zip | |
Add support for snapshots
Make a link from the commit viewer to a snapshot of the corresponding tree.
Currently only zip-format is supported.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | cgit.c | 39 | ||||
| -rw-r--r-- | cgit.h | 10 | ||||
| -rw-r--r-- | git.h | 27 | ||||
| -rw-r--r-- | shared.c | 17 | ||||
| -rw-r--r-- | ui-commit.c | 7 | ||||
| -rw-r--r-- | ui-shared.c | 11 | ||||
| -rw-r--r-- | ui-snapshot.c | 47 | 
8 files changed, 153 insertions, 8 deletions
| @@ -6,7 +6,8 @@ gitsrc = ../git  CACHE_ROOT = /var/cache/cgit  EXTLIBS = $(gitsrc)/libgit.a $(gitsrc)/xdiff/lib.a -lz -lcrypto  OBJECTS = shared.o cache.o parsing.o html.o ui-shared.o ui-repolist.o \ -	ui-summary.o ui-log.o ui-view.c ui-tree.c ui-commit.c ui-diff.o +	ui-summary.o ui-log.o ui-view.c ui-tree.c ui-commit.c ui-diff.o \ +	ui-snapshot.o  CFLAGS += -Wall @@ -78,6 +78,13 @@ static void cgit_print_repo_page(struct cacheitem *item)  	title = fmt("%s - %s", cgit_repo->name, cgit_repo->desc);  	show_search = 0;  	setenv("GIT_DIR", cgit_repo->path, 1); + +	if (cgit_query_page && !strcmp(cgit_query_page, "snapshot")) { +		cgit_print_snapshot(item, cgit_query_sha1, "zip",  +				    cgit_repo->url, cgit_query_name); +		return; +	} +  	if (cgit_query_page && !strcmp(cgit_query_page, "log"))  		show_search = 1;  	cgit_print_docstart(title, item); @@ -85,7 +92,8 @@ static void cgit_print_repo_page(struct cacheitem *item)  	if (!cgit_query_page) {  		cgit_print_summary();  	} else if (!strcmp(cgit_query_page, "log")) { -		cgit_print_log(cgit_query_head, cgit_query_ofs, 100, cgit_query_search); +		cgit_print_log(cgit_query_head, cgit_query_ofs, 100,  +			       cgit_query_search);  	} else if (!strcmp(cgit_query_page, "tree")) {  		cgit_print_tree(cgit_query_sha1, cgit_query_path);  	} else if (!strcmp(cgit_query_page, "commit")) { @@ -94,21 +102,39 @@ static void cgit_print_repo_page(struct cacheitem *item)  		cgit_print_view(cgit_query_sha1);  	} else if (!strcmp(cgit_query_page, "diff")) {  		cgit_print_diff(cgit_query_sha1, cgit_query_sha2); +	} else { +		cgit_print_error("Invalid request");  	}  	cgit_print_docend();  } -static void cgit_fill_cache(struct cacheitem *item) +static void cgit_fill_cache(struct cacheitem *item, int use_cache)  {  	static char buf[PATH_MAX]; +	int stdout2;  	getcwd(buf, sizeof(buf)); -	htmlfd = item->fd;  	item->st.st_mtime = time(NULL); + +	if (use_cache) { +		stdout2 = chk_positive(dup(STDOUT_FILENO),  +				       "Preserving STDOUT"); +		chk_zero(close(STDOUT_FILENO), "Closing STDOUT"); +		chk_positive(dup2(item->fd, STDOUT_FILENO), "Dup2(cachefile)"); +	} +  	if (cgit_query_repo)  		cgit_print_repo_page(item);  	else  		cgit_print_repolist(item); + +	if (use_cache) { +		chk_zero(close(STDOUT_FILENO), "Close redirected STDOUT"); +		chk_positive(dup2(stdout2, STDOUT_FILENO),  +			     "Restoring original STDOUT"); +		chk_zero(close(stdout2), "Closing temporary STDOUT"); +	} +  	chdir(buf);  } @@ -127,14 +153,14 @@ static void cgit_check_cache(struct cacheitem *item)  			goto top;  		}  		if (!cache_exist(item)) { -			cgit_fill_cache(item); +			cgit_fill_cache(item, 1);  			cache_unlock(item);  		} else {  			cache_cancel_lock(item);  		}  	} else if (cache_expired(item) && cache_lock(item)) {  		if (cache_expired(item)) { -			cgit_fill_cache(item); +			cgit_fill_cache(item, 1);  			cache_unlock(item);  		} else {  			cache_cancel_lock(item); @@ -209,8 +235,7 @@ int main(int argc, const char **argv)  	if (!cgit_prepare_cache(&item))  		return 0;  	if (cgit_nocache) { -		item.fd = STDOUT_FILENO; -		cgit_fill_cache(&item); +		cgit_fill_cache(&item, 0);  	} else {  		cgit_check_cache(&item);  		cgit_print_cache(&item); @@ -85,6 +85,7 @@ extern char *cgit_query_head;  extern char *cgit_query_sha1;  extern char *cgit_query_sha2;  extern char *cgit_query_path; +extern char *cgit_query_name;  extern int   cgit_query_ofs;  extern int htmlfd; @@ -93,6 +94,9 @@ 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); +extern int chk_zero(int result, char *msg); +extern int chk_positive(int result, char *msg); +  extern int hextoint(char c);  extern void *cgit_free_commitinfo(struct commitinfo *info); @@ -130,6 +134,9 @@ extern void cgit_print_date(unsigned long secs);  extern void cgit_print_docstart(char *title, struct cacheitem *item);  extern void cgit_print_docend();  extern void cgit_print_pageheader(char *title, int show_search); +extern void cgit_print_snapshot_start(const char *mimetype,  +				      const char *filename,  +				      struct cacheitem *item);  extern void cgit_print_repolist(struct cacheitem *item);  extern void cgit_print_summary(); @@ -138,5 +145,8 @@ extern void cgit_print_view(const char *hex);  extern void cgit_print_tree(const char *hex, char *path);  extern void cgit_print_commit(const char *hex);  extern void cgit_print_diff(const char *old_hex, const char *new_hex); +extern void cgit_print_snapshot(struct cacheitem *item, const char *hex,  +				const char *format, const char *prefix, +				const char *filename);  #endif /* CGIT_H */ @@ -669,4 +669,31 @@ int log_tree_commit(struct rev_info *, struct commit *); +/* from git:archive.h */ + +struct archiver_args { +	const char *base; +	struct tree *tree; +	const unsigned char *commit_sha1; +	time_t time; +	const char **pathspec; +	unsigned int verbose : 1; +	void *extra; +}; + +typedef int (*write_archive_fn_t)(struct archiver_args *); + +typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv); + +struct archiver { +	const char *name; +	struct archiver_args args; +	write_archive_fn_t write_archive; +	parse_extra_args_fn_t parse_extra; +}; + +extern int write_tar_archive(struct archiver_args *); +extern int write_zip_archive(struct archiver_args *); +extern void *parse_extra_zip_args(int argc, const char **argv); +  #endif /* GIT_H */ @@ -44,10 +44,25 @@ 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 htmlfd = 0; +int chk_zero(int result, char *msg) +{ +	if (result != 0) +		die("%s: %s", msg, strerror(errno)); +	return result; +} + +int chk_positive(int result, char *msg) +{ +	if (result <= 0) +		die("%s: %s", msg, strerror(errno)); +	return result; +} +  struct repoinfo *add_repo(const char *url)  {  	struct repoinfo *ret; @@ -140,6 +155,8 @@ void cgit_querystring_cb(const char *name, const char *value)  		cgit_query_ofs = atoi(value);  	} else if (!strcmp(name, "path")) {  		cgit_query_path = xstrdup(value); +	} else if (!strcmp(name, "name")) { +		cgit_query_name = xstrdup(value);  	}  } diff --git a/ui-commit.c b/ui-commit.c index 73fa104..de3f2cf 100644 --- a/ui-commit.c +++ b/ui-commit.c @@ -128,6 +128,7 @@ void cgit_print_commit(const char *hex)  	struct commit_list *p;  	unsigned char sha1[20];  	char *query; +	char *filename;  	if (get_sha1(hex, sha1)) {  		cgit_print_error(fmt("Bad object id: %s", hex)); @@ -168,6 +169,12 @@ void cgit_print_commit(const char *hex)  		htmlf("'>%s</a></td></tr>\n",   		      sha1_to_hex(p->item->object.sha1));  	} +	htmlf("<tr><th>download</th><td colspan='2' class='sha1'><a href='"); +	filename = fmt("%s-%s.zip", cgit_query_repo, hex); +	html_attr(cgit_pageurl(cgit_query_repo, "snapshot",  +			       fmt("id=%s&name=%s", hex, filename))); +	htmlf("'>%s</a></td></tr>", filename); +	  	html("</table>\n");  	html("<div class='commit-subject'>");  	html_txt(info->subject); diff --git a/ui-shared.c b/ui-shared.c index 3322561..172499c 100644 --- a/ui-shared.c +++ b/ui-shared.c @@ -144,3 +144,14 @@ void cgit_print_pageheader(char *title, int show_search)  		html("</a>");  	html("</td></tr><tr><td id='content'>");  } + +void cgit_print_snapshot_start(const char *mimetype, const char *filename,  +			       struct cacheitem *item) +{ +	htmlf("Content-Type: %s\n", mimetype); +	htmlf("Content-Disposition: inline; filename=\"%s\"\n", filename); +	htmlf("Last-Modified: %s\n", http_date(item->st.st_mtime)); +	htmlf("Expires: %s\n", http_date(item->st.st_mtime + +					 ttl_seconds(item->ttl))); +	html("\n"); +} diff --git a/ui-snapshot.c b/ui-snapshot.c new file mode 100644 index 0000000..2257d6b --- /dev/null +++ b/ui-snapshot.c @@ -0,0 +1,47 @@ +/* ui-snapshot.c: generate snapshot of a commit + * + * Copyright (C) 2006 Lars Hjemli + * + * Licensed under GNU General Public License v2 + *   (see COPYING for full license text) + */ + +#include "cgit.h" + +static void cgit_print_zip(struct cacheitem *item, const char *hex,  +			   const char *prefix, const char *filename) +{ +	struct archiver_args args; +	struct commit *commit; +	unsigned char sha1[20]; + +	if (get_sha1(hex, sha1)) { +		cgit_print_error(fmt("Bad object id: %s", hex)); +		return; +	} +	commit = lookup_commit_reference(sha1); + +	if (!commit) { +		cgit_print_error(fmt("Not a commit reference: %s", hex)); +		return; +	} + +	memset(&args, 0, sizeof(args)); +	args.base = fmt("%s/", prefix); +	args.tree = commit->tree; +	 +	cgit_print_snapshot_start("application/x-zip", filename, item); +	write_zip_archive(&args); +} + + +void cgit_print_snapshot(struct cacheitem *item, const char *hex,  +			 const char *format, const char *prefix, +			 const char *filename) +{ +	if (!strcmp(format, "zip")) +		cgit_print_zip(item, hex, prefix, filename); +	else +		cgit_print_error(fmt("Unsupported snapshot format: %s",  +				     format)); +} | 
