diff options
Diffstat (limited to '')
| -rw-r--r-- | ui-tree.c | 194 | 
1 files changed, 152 insertions, 42 deletions
| @@ -9,14 +9,56 @@  #include "cgit.h"  char *curr_rev; +char *match_path; +int header = 0; -static int print_entry(const unsigned char *sha1, const char *base, -		       int baselen, const char *pathname, unsigned int mode, -		       int stage) +static void print_object(const unsigned char *sha1, char *path) +{ +	enum object_type type; +	unsigned char *buf; +	unsigned long size, lineno, start, idx; + +	type = sha1_object_info(sha1, &size); +	if (type == OBJ_BAD) { +		cgit_print_error(fmt("Bad object name: %s", +				     sha1_to_hex(sha1))); +		return; +	} + +	buf = read_sha1_file(sha1, &type, &size); +	if (!buf) { +		cgit_print_error(fmt("Error reading object %s", +				     sha1_to_hex(sha1))); +		return; +	} + +	html("<table class='blob'>\n"); +	idx = 0; +	start = 0; +	lineno = 0; +	while(idx < size) { +		if (buf[idx] == '\n') { +			buf[idx] = '\0'; +			htmlf("<tr><td class='no'>%d</td><td class='txt'>", +			      ++lineno); +			html_txt(buf + start); +			html("</td></tr>\n"); +			start = idx + 1; +		} +		idx++; +	} +	html("\n</td></tr>\n"); +	html("</table>\n"); +} + + +static int ls_item(const unsigned char *sha1, const char *base, int baselen, +		   const char *pathname, unsigned int mode, int stage)  {  	char *name;  	enum object_type type;  	unsigned long size = 0; +	char *url, *qry;  	name = xstrdup(pathname);  	type = sha1_object_info(sha1, &size); @@ -26,6 +68,10 @@ static int print_entry(const unsigned char *sha1, const char *base,  		      sha1_to_hex(sha1));  		return 0;  	} +	qry = fmt("h=%s&path=%s%s%s", curr_rev, +		  cgit_query_path ? cgit_query_path : "", +		  cgit_query_path ? "/" : "", pathname); +	url = cgit_pageurl(cgit_query_repo, "tree", qry);  	html("<tr><td class='filemode'>");  	html_filemode(mode);  	html("</td><td "); @@ -36,69 +82,133 @@ static int print_entry(const unsigned char *sha1, const char *base,  			      sha1_to_hex(sha1)));  	} else if (S_ISDIR(mode)) {  		html("class='ls-dir'><a href='"); -		html_attr(cgit_pageurl(cgit_query_repo, "tree", -				       fmt("h=%s&id=%s&path=%s%s/", -					   curr_rev, -					   sha1_to_hex(sha1), -					   cgit_query_path ? cgit_query_path : "", -					   pathname))); +		html_attr(url);  	} else {  		html("class='ls-blob'><a href='"); -		html_attr(cgit_pageurl(cgit_query_repo, "view", -				      fmt("h=%s&id=%s&path=%s%s", curr_rev, -					  sha1_to_hex(sha1), -					  cgit_query_path ? cgit_query_path : "", -					  pathname))); +		html_attr(url);  	}  	htmlf("'>%s</a></td>", name);  	htmlf("<td class='filesize'>%li</td>", size);  	html("<td class='links'><a href='"); -	html_attr(cgit_pageurl(cgit_query_repo, "log", -			       fmt("h=%s&path=%s%s", -				   curr_rev, -				   cgit_query_path ? cgit_query_path : "", -				   pathname))); -	html("'>history</a></td>"); +	qry = fmt("h=%s&path=%s%s%s", curr_rev, +		  cgit_query_path ? cgit_query_path : "", +		  cgit_query_path ? "/" : "", pathname); +	url = cgit_pageurl(cgit_query_repo, "log", qry); +	html_attr(url); +	html("' class='button'>H</a></td>");  	html("</tr>\n");  	free(name);  	return 0;  } -void cgit_print_tree(const char *rev, const char *hex, char *path) +static void ls_head() +{ +	html("<table class='list'>\n"); +	html("<tr class='nohover'>"); +	html("<th class='left'>Mode</th>"); +	html("<th class='left'>Name</th>"); +	html("<th class='right'>Size</th>"); +	html("<th/>"); +	html("</tr>\n"); +	header = 1; +} + +static void ls_tail() +{ +	if (!header) +		return; +	html("</table>\n"); +	header = 0; +} + +static void ls_tree(const unsigned char *sha1, char *path)  {  	struct tree *tree; + +	tree = parse_tree_indirect(sha1); +	if (!tree) { +		cgit_print_error(fmt("Not a tree object: %s", +				     sha1_to_hex(sha1))); +		return; +	} + +	ls_head(); +	read_tree_recursive(tree, "", 0, 1, NULL, ls_item); +	ls_tail(); +} + + +static int walk_tree(const unsigned char *sha1, const char *base, int baselen, +		     const char *pathname, unsigned mode, int stage) +{ +	static int state; +	static char buffer[PATH_MAX]; +	char *url; + +	if (state == 0) { +		memcpy(buffer, base, baselen); +		strcpy(buffer+baselen, pathname); +		url = cgit_pageurl(cgit_query_repo, "tree", +				   fmt("h=%s&path=%s", curr_rev, buffer)); +		htmlf(" / <a href='"); +		html_attr(url); +		html("'>"); +		html_txt(xstrdup(pathname)); +		html("</a>"); + +		if (strcmp(match_path, buffer)) +			return READ_TREE_RECURSIVE; + +		if (S_ISDIR(mode)) { +			state = 1; +			ls_head(); +			return READ_TREE_RECURSIVE; +		} else { +			print_object(sha1, buffer); +			return 0; +		} +	} +	ls_item(sha1, base, baselen, pathname, mode, stage); +	return 0; +} + + +/* + * Show a tree or a blob + *   rev:  the commit pointing at the root tree object + *   path: path to tree or blob + */ +void cgit_print_tree(const char *rev, char *path) +{  	unsigned char sha1[20];  	struct commit *commit; +	const char *paths[] = {path, NULL}; + +	if (!rev) +		rev = cgit_query_head;  	curr_rev = xstrdup(rev); -	get_sha1(rev, sha1); +	if (get_sha1(rev, sha1)) { +		cgit_print_error(fmt("Invalid revision name: %s", rev)); +		return; +	}  	commit = lookup_commit_reference(sha1);  	if (!commit || parse_commit(commit)) { -		cgit_print_error(fmt("Invalid head: %s", rev)); +		cgit_print_error(fmt("Invalid commit reference: %s", rev));  		return;  	} -	if (!hex) -		hex = sha1_to_hex(commit->tree->object.sha1); -	if (get_sha1_hex(hex, sha1)) { -		cgit_print_error(fmt("Invalid object id: %s", hex)); -		return; -	} -	tree = parse_tree_indirect(sha1); -	if (!tree) { -		cgit_print_error(fmt("Not a tree object: %s", hex)); +	html("path: <a href='"); +	html_attr(cgit_pageurl(cgit_query_repo, "tree", fmt("h=%s", rev))); +	html("'>root</a>"); + +	if (path == NULL) { +		ls_tree(commit->tree->object.sha1, NULL);  		return;  	} -	html_txt(path); -	html("<table class='list'>\n"); -	html("<tr class='nohover'>"); -	html("<th class='left'>Mode</th>"); -	html("<th class='left'>Name</th>"); -	html("<th class='right'>Size</th>"); -	html("<th/>"); -	html("</tr>\n"); -	read_tree_recursive(tree, "", 0, 1, NULL, print_entry); -	html("</table>\n"); +	match_path = path; +	read_tree_recursive(commit->tree, NULL, 0, 0, paths, walk_tree); +	ls_tail();  } | 
