diff options
Diffstat (limited to '')
| -rw-r--r-- | cgit.css | 51 | ||||
| -rw-r--r-- | cgit.h | 1 | ||||
| -rw-r--r-- | git.h | 106 | ||||
| -rw-r--r-- | html.c | 20 | ||||
| -rw-r--r-- | ui-commit.c | 111 | 
5 files changed, 281 insertions, 8 deletions
| @@ -3,7 +3,7 @@ body {  	font-size: normal;  	background: white;  	padding: 0em; -	margin: 0.5em; +	margin: 0.5em 1em;  } @@ -50,16 +50,19 @@ img {  div#header { -	background-color: #ddd; +	background-color: #eee;  	padding: 0.25em 0.25em 0.25em 0.5em;  	font-size: 150%;  	font-weight: bold; -	border: solid 1px #aaa; +	border: solid 1px #ccc;  	vertical-align: middle;  }  div#header img#logo {  	float: right;  } +div#header a { +	color: black; +}  div#content {  	margin: 0.5em 0.5em; @@ -97,8 +100,7 @@ table.log td {  table.commit-info {  	border-collapse: collapse; -	margin-top: 1em; -	 +	margin-top: 1.5em;  }  table.commit-info th {  	text-align: left; @@ -111,14 +113,47 @@ table.commit-info td {  }  div.commit-subject {  	font-weight: bold; -	font-size: 110%; -	margin: 1em 0em 1em; +	font-size: 125%; +	margin: 1.5em 0em 0.5em 0em; +	padding: 0em;  }  div.commit-msg {  	white-space: pre; -	font-family: courier; +	font-family: monospace; +} +table.diffstat { +	border-collapse: collapse; +	margin-top: 1.5em; +} +table.diffstat th { +	font-weight: normal; +	text-align: left; +	text-decoration: underline; +	padding: 0.1em 1em 0.1em 0.1em;  	font-size: 100%;  } +table.diffstat td { +	padding: 0.1em 1em 0.1em 0.1em; +	font-size: 100%; +} +table.diffstat td span.modechange { +	padding-left: 1em; +	color: red; +} +table.diffstat td.add a { +	color: green; +} +table.diffstat td.del a { +	color: red; +} +table.diffstat td.upd a { +	color: blue; +} +table.diffstat td.summary { +	/* border-top: solid 1px black; */ +	color: #888; +	padding-top: 0.5em; +}  .sha1 {  	font-family: courier;  	font-size: 90%; @@ -75,6 +75,7 @@ extern void html_txt(char *txt);  extern void html_attr(char *txt);  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 cgit_read_config(const char *filename, configfn fn);  extern int cgit_parse_query(char *txt, configfn fn); @@ -128,6 +128,8 @@ static inline ssize_t xwrite(int fd, const void *buf, size_t len)  #define MINIMUM_ABBREV 4  #define DEFAULT_ABBREV 7 +extern const unsigned char null_sha1[20]; +  extern int sha1_object_info(const unsigned char *, char *, unsigned long *);  extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size); @@ -136,6 +138,24 @@ extern int get_sha1(const char *str, unsigned char *sha1);  extern int get_sha1_hex(const char *hex, unsigned char *sha1);  extern char *sha1_to_hex(const unsigned char *sha1);	/* static buffer result! */ +static inline int is_null_sha1(const unsigned char *sha1) +{ +	return !memcmp(sha1, null_sha1, 20); +} +static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2) +{ +	return memcmp(sha1, sha2, 20); +} +static inline void hashcpy(unsigned char *sha_dst, const unsigned char *sha_src) +{ +	memcpy(sha_dst, sha_src, 20); +} +static inline void hashclr(unsigned char *hash) +{ +	memset(hash, 0, 20); +} + +  /* @@ -257,6 +277,61 @@ typedef void* (*topo_sort_get_fn_t)(struct commit*); +/* + * from git:diffcore.h + */ + +struct diff_filespec { +	unsigned char sha1[20]; +	char *path; +	void *data; +	void *cnt_data; +	unsigned long size; +	int xfrm_flags;		 /* for use by the xfrm */ +	unsigned short mode;	 /* file mode */ +	unsigned sha1_valid : 1; /* if true, use sha1 and trust mode; +				  * if false, use the name and read from +				  * the filesystem. +				  */ +#define DIFF_FILE_VALID(spec) (((spec)->mode) != 0) +	unsigned should_free : 1; /* data should be free()'ed */ +	unsigned should_munmap : 1; /* data should be munmap()'ed */ +}; + +struct diff_filepair { +	struct diff_filespec *one; +	struct diff_filespec *two; +	unsigned short int score; +	char status; /* M C R N D U (see Documentation/diff-format.txt) */ +	unsigned source_stays : 1; /* all of R/C are copies */ +	unsigned broken_pair : 1; +	unsigned renamed_pair : 1; +}; + +#define DIFF_PAIR_UNMERGED(p) \ +	(!DIFF_FILE_VALID((p)->one) && !DIFF_FILE_VALID((p)->two)) + +#define DIFF_PAIR_RENAME(p) ((p)->renamed_pair) + +#define DIFF_PAIR_BROKEN(p) \ +	( (!DIFF_FILE_VALID((p)->one) != !DIFF_FILE_VALID((p)->two)) && \ +	  ((p)->broken_pair != 0) ) + +#define DIFF_PAIR_TYPE_CHANGED(p) \ +	((S_IFMT & (p)->one->mode) != (S_IFMT & (p)->two->mode)) + +#define DIFF_PAIR_MODE_CHANGED(p) ((p)->one->mode != (p)->two->mode) + +extern void diff_free_filepair(struct diff_filepair *); + +extern int diff_unmodified_pair(struct diff_filepair *); + +struct diff_queue_struct { +	struct diff_filepair **queue; +	int alloc; +	int nr; +}; +  /*   *  from git:diff.h @@ -352,6 +427,32 @@ enum color_diff {  }; +extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new, +			  const char *base, struct diff_options *opt); + +extern int diff_root_tree_sha1(const unsigned char *new, const char *base, +			       struct diff_options *opt); + +extern int git_diff_ui_config(const char *var, const char *value); +extern void diff_setup(struct diff_options *); +extern int diff_opt_parse(struct diff_options *, const char **, int); +extern int diff_setup_done(struct diff_options *); + + +extern void diffcore_std(struct diff_options *); +extern void diff_flush(struct diff_options*); + + +/* diff-raw status letters */ +#define DIFF_STATUS_ADDED		'A' +#define DIFF_STATUS_COPIED		'C' +#define DIFF_STATUS_DELETED		'D' +#define DIFF_STATUS_MODIFIED		'M' +#define DIFF_STATUS_RENAMED		'R' +#define DIFF_STATUS_TYPE_CHANGED	'T' +#define DIFF_STATUS_UNKNOWN		'X' +#define DIFF_STATUS_UNMERGED		'U' +  /* @@ -458,5 +559,10 @@ extern struct commit *get_revision(struct rev_info *revs); +/* from git:log-tree.h */ + +int log_tree_commit(struct rev_info *, struct commit *); + +  #endif /* GIT_H */ @@ -108,3 +108,23 @@ void html_link_close(void)  {  	html("</a>");  } + +void html_fileperm(unsigned short mode) +{ +	htmlf("%c%c%c", (mode & 4 ? 'r' : '-'),  +	      (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-')); +} + +void html_filemode(unsigned short mode) +{ +	if (S_ISDIR(mode)) +		html("d"); +	else if (S_ISLNK(mode)) +		html("l"); +	else +		html("-"); +	html_fileperm(mode >> 6); +	html_fileperm(mode >> 3); +	html_fileperm(mode); +} + diff --git a/ui-commit.c b/ui-commit.c index 8916212..c5ee8e7 100644 --- a/ui-commit.c +++ b/ui-commit.c @@ -8,6 +8,111 @@  #include "cgit.h" +int files = 0; + +void print_filepair(struct diff_filepair *pair) +{ +	char *query; +	char *class; +	 +	switch (pair->status) { +	case DIFF_STATUS_ADDED: +		class = "add"; +		break; +	case DIFF_STATUS_COPIED: +		class = "cpy"; +		break; +	case DIFF_STATUS_DELETED: +		class = "del"; +		break; +	case DIFF_STATUS_MODIFIED: +		class = "upd"; +		break; +	case DIFF_STATUS_RENAMED: +		class = "mov"; +		break; +	case DIFF_STATUS_TYPE_CHANGED: +		class = "typ"; +		break; +	case DIFF_STATUS_UNKNOWN: +		class = "unk"; +		break; +	case DIFF_STATUS_UNMERGED: +		class = "stg"; +		break; +	default: +		die("bug: unhandled diff status %c", pair->status); +	} + +	html("<tr>"); +	htmlf("<td class='mode'>"); +	html_filemode(pair->two->mode); +	if (pair->one->mode != pair->two->mode) { +		html("<span class='modechange'>["); +		html_filemode(pair->one->mode); +		html("]</span>"); +	} +	htmlf("</td><td class='%s'>", class); +	query = fmt("id=%s", sha1_to_hex(pair->two->sha1));	 +	html_link_open(cgit_pageurl(cgit_query_repo, "view", query),  +		       NULL, NULL); +	if (pair->status == DIFF_STATUS_COPIED ||  +	    pair->status == DIFF_STATUS_RENAMED) { +		html_txt(pair->two->path); +		htmlf("</a> (%s from ", pair->status == DIFF_STATUS_COPIED ?  +		      "copied" : "renamed"); +		query = fmt("id=%s", sha1_to_hex(pair->one->sha1));	 +		html_link_open(cgit_pageurl(cgit_query_repo, "view", query),  +			       NULL, NULL); +		html_txt(pair->one->path); +		html("</a>)"); +	} else { +		html_txt(pair->two->path); +		html("</a>"); +	} +	html("<td>"); + +	//TODO: diffstat graph +	 +	html("</td></tr>\n"); +	files++;	 +} + +void diff_format_cb(struct diff_queue_struct *q, +		    struct diff_options *options, void *data) +{ +	int i; + +	for (i = 0; i < q->nr; i++) { +		if (q->queue[i]->status == 'U') +			continue; +		print_filepair(q->queue[i]); +	} +} + +void cgit_diffstat(struct commit *commit) +{ +	struct diff_options opt; +	int ret; + +	diff_setup(&opt); +	opt.output_format = DIFF_FORMAT_CALLBACK; +	opt.detect_rename = 1; +	opt.recursive = 1; +	opt.format_callback = diff_format_cb; +	diff_setup_done(&opt); +	 +	if (commit->parents) +		ret = diff_tree_sha1(commit->parents->item->object.sha1, +				     commit->object.sha1, +				     "", &opt); +	else +		ret = diff_root_tree_sha1(commit->object.sha1, "", &opt); + +	diffcore_std(&opt); +	diff_flush(&opt); +} +  void cgit_print_commit(const char *hex)  {  	struct commit *commit; @@ -62,5 +167,11 @@ void cgit_print_commit(const char *hex)  	html("<div class='commit-msg'>");  	html_txt(info->msg);  	html("</div>"); +	html("<table class='diffstat'>"); +	html("<tr><th colspan='3'>Affected files</tr>\n"); +	cgit_diffstat(commit); +	htmlf("<tr><td colspan='3' class='summary'>" +	      "%d file%s changed</td></tr>\n", files, files > 1 ? "s" : ""); +	html("</table>");  	cgit_free_commitinfo(info);  } | 
