diff-files: -c and --cc options.
This ports the "combined diff" to diff-files so that differences to the working tree files since stage 2 and stage 3 are shown the same way as combined diff output from diff-tree for the merge commit would be shown if the current working tree files are committed. Signed-off-by: Junio C Hamano <junkio@cox.net>maint
							parent
							
								
									3ec1909fda
								
							
						
					
					
						commit
						ea726d02e9
					
				|  | @ -4,14 +4,6 @@ | ||||||
| #include "diffcore.h" | #include "diffcore.h" | ||||||
| #include "quote.h" | #include "quote.h" | ||||||
|  |  | ||||||
| struct path_list { |  | ||||||
| 	struct path_list *next; |  | ||||||
| 	int len; |  | ||||||
| 	char *path; |  | ||||||
| 	unsigned char sha1[20]; |  | ||||||
| 	unsigned char parent_sha1[FLEX_ARRAY][20]; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| static int uninteresting(struct diff_filepair *p) | static int uninteresting(struct diff_filepair *p) | ||||||
| { | { | ||||||
| 	if (diff_unmodified_pair(p)) | 	if (diff_unmodified_pair(p)) | ||||||
|  | @ -21,15 +13,14 @@ static int uninteresting(struct diff_filepair *p) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static struct path_list *intersect_paths(struct path_list *curr, | static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent) | ||||||
| 					 int n, int num_parent) |  | ||||||
| { | { | ||||||
| 	struct diff_queue_struct *q = &diff_queued_diff; | 	struct diff_queue_struct *q = &diff_queued_diff; | ||||||
| 	struct path_list *p; | 	struct combine_diff_path *p; | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	if (!n) { | 	if (!n) { | ||||||
| 		struct path_list *list = NULL, **tail = &list; | 		struct combine_diff_path *list = NULL, **tail = &list; | ||||||
| 		for (i = 0; i < q->nr; i++) { | 		for (i = 0; i < q->nr; i++) { | ||||||
| 			int len; | 			int len; | ||||||
| 			const char *path; | 			const char *path; | ||||||
|  | @ -532,18 +523,52 @@ static void dump_sline(struct sline *sline, int cnt, int num_parent) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static int show_combined_diff(struct path_list *elem, int num_parent, | int show_combined_diff(struct combine_diff_path *elem, int num_parent, | ||||||
| 			      int dense, const char *header, int show_empty) | 		       int dense, const char *header, int show_empty) | ||||||
| { | { | ||||||
| 	unsigned long size, cnt, lno; | 	unsigned long size, cnt, lno; | ||||||
| 	char *result, *cp, *ep; | 	char *result, *cp, *ep; | ||||||
| 	struct sline *sline; /* survived lines */ | 	struct sline *sline; /* survived lines */ | ||||||
| 	int i, show_hunks, shown_header = 0; | 	int i, show_hunks, shown_header = 0; | ||||||
| 	char ourtmp[TMPPATHLEN]; | 	char ourtmp_buf[TMPPATHLEN]; | ||||||
|  | 	char *ourtmp = ourtmp_buf; | ||||||
|  |  | ||||||
| 	/* Read the result of merge first */ | 	/* Read the result of merge first */ | ||||||
| 	result = grab_blob(elem->sha1, &size); | 	if (memcmp(elem->sha1, null_sha1, 20)) { | ||||||
| 	write_to_temp_file(ourtmp, result, size); | 		result = grab_blob(elem->sha1, &size); | ||||||
|  | 		write_to_temp_file(ourtmp, result, size); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		struct stat st; | ||||||
|  | 		int fd; | ||||||
|  | 		ourtmp = elem->path; | ||||||
|  | 		if (0 <= (fd = open(ourtmp, O_RDONLY)) && | ||||||
|  | 		    !fstat(fd, &st)) { | ||||||
|  | 			int len = st.st_size; | ||||||
|  | 			int cnt = 0; | ||||||
|  |  | ||||||
|  | 			size = len; | ||||||
|  | 			result = xmalloc(len + 1); | ||||||
|  | 			while (cnt < len) { | ||||||
|  | 				int done = xread(fd, result+cnt, len-cnt); | ||||||
|  | 				if (done == 0) | ||||||
|  | 					break; | ||||||
|  | 				if (done < 0) | ||||||
|  | 					die("read error '%s'", ourtmp); | ||||||
|  | 				cnt += done; | ||||||
|  | 			} | ||||||
|  | 			result[len] = 0; | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			/* deleted file */ | ||||||
|  | 			size = 0; | ||||||
|  | 			result = xmalloc(1); | ||||||
|  | 			result[0] = 0; | ||||||
|  | 			ourtmp = "/dev/null"; | ||||||
|  | 		} | ||||||
|  | 		if (0 <= fd) | ||||||
|  | 			close(fd); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	for (cnt = 0, cp = result; cp - result < size; cp++) { | 	for (cnt = 0, cp = result; cp - result < size; cp++) { | ||||||
| 		if (*cp == '\n') | 		if (*cp == '\n') | ||||||
|  | @ -589,7 +614,8 @@ static int show_combined_diff(struct path_list *elem, int num_parent, | ||||||
| 		putchar('\n'); | 		putchar('\n'); | ||||||
| 		dump_sline(sline, cnt, num_parent); | 		dump_sline(sline, cnt, num_parent); | ||||||
| 	} | 	} | ||||||
| 	unlink(ourtmp); | 	if (ourtmp == ourtmp_buf) | ||||||
|  | 		unlink(ourtmp); | ||||||
| 	free(result); | 	free(result); | ||||||
|  |  | ||||||
| 	for (i = 0; i < cnt; i++) { | 	for (i = 0; i < cnt; i++) { | ||||||
|  | @ -613,7 +639,7 @@ int diff_tree_combined_merge(const unsigned char *sha1, | ||||||
| 	struct commit *commit = lookup_commit(sha1); | 	struct commit *commit = lookup_commit(sha1); | ||||||
| 	struct diff_options diffopts; | 	struct diff_options diffopts; | ||||||
| 	struct commit_list *parents; | 	struct commit_list *parents; | ||||||
| 	struct path_list *p, *paths = NULL; | 	struct combine_diff_path *p, *paths = NULL; | ||||||
| 	int num_parent, i, num_paths; | 	int num_parent, i, num_paths; | ||||||
|  |  | ||||||
| 	diff_setup(&diffopts); | 	diff_setup(&diffopts); | ||||||
|  | @ -654,7 +680,7 @@ int diff_tree_combined_merge(const unsigned char *sha1, | ||||||
|  |  | ||||||
| 	/* Clean things up */ | 	/* Clean things up */ | ||||||
| 	while (paths) { | 	while (paths) { | ||||||
| 		struct path_list *tmp = paths; | 		struct combine_diff_path *tmp = paths; | ||||||
| 		paths = paths->next; | 		paths = paths->next; | ||||||
| 		free(tmp); | 		free(tmp); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								diff-files.c
								
								
								
								
							
							
						
						
									
										45
									
								
								diff-files.c
								
								
								
								
							|  | @ -7,12 +7,14 @@ | ||||||
| #include "diff.h" | #include "diff.h" | ||||||
|  |  | ||||||
| static const char diff_files_usage[] = | static const char diff_files_usage[] = | ||||||
| "git-diff-files [-q] [-0/-1/2/3] [<common diff options>] [<path>...]" | "git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]" | ||||||
| COMMON_DIFF_OPTIONS_HELP; | COMMON_DIFF_OPTIONS_HELP; | ||||||
|  |  | ||||||
| static struct diff_options diff_options; | static struct diff_options diff_options; | ||||||
| static int silent = 0; | static int silent = 0; | ||||||
| static int diff_unmerged_stage = 2; | static int diff_unmerged_stage = 2; | ||||||
|  | static int combine_merges = 0; | ||||||
|  | static int dense_combined_merges = 0; | ||||||
|  |  | ||||||
| static void show_unmerge(const char *path) | static void show_unmerge(const char *path) | ||||||
| { | { | ||||||
|  | @ -66,6 +68,10 @@ int main(int argc, const char **argv) | ||||||
| 			; /* no-op */ | 			; /* no-op */ | ||||||
| 		else if (!strcmp(argv[1], "-s")) | 		else if (!strcmp(argv[1], "-s")) | ||||||
| 			; /* no-op */ | 			; /* no-op */ | ||||||
|  | 		else if (!strcmp(argv[1], "-c")) | ||||||
|  | 			combine_merges = 1; | ||||||
|  | 		else if (!strcmp(argv[1], "--cc")) | ||||||
|  | 			dense_combined_merges = combine_merges = 1; | ||||||
| 		else { | 		else { | ||||||
| 			int diff_opt_cnt; | 			int diff_opt_cnt; | ||||||
| 			diff_opt_cnt = diff_opt_parse(&diff_options, | 			diff_opt_cnt = diff_opt_parse(&diff_options, | ||||||
|  | @ -82,6 +88,9 @@ int main(int argc, const char **argv) | ||||||
| 		} | 		} | ||||||
| 		argv++; argc--; | 		argv++; argc--; | ||||||
| 	} | 	} | ||||||
|  | 	if (combine_merges) { | ||||||
|  | 		diff_options.output_format = DIFF_FORMAT_PATCH; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	/* Find the directory, and set up the pathspec */ | 	/* Find the directory, and set up the pathspec */ | ||||||
| 	pathspec = get_pathspec(prefix, argv + 1); | 	pathspec = get_pathspec(prefix, argv + 1); | ||||||
|  | @ -108,14 +117,35 @@ int main(int argc, const char **argv) | ||||||
| 			continue; | 			continue; | ||||||
|  |  | ||||||
| 		if (ce_stage(ce)) { | 		if (ce_stage(ce)) { | ||||||
| 			show_unmerge(ce->name); | 			struct { | ||||||
|  | 				struct combine_diff_path p; | ||||||
|  | 				unsigned char fill[4][20]; | ||||||
|  | 			} combine; | ||||||
|  |  | ||||||
|  | 			combine.p.next = NULL; | ||||||
|  | 			combine.p.len = ce_namelen(ce); | ||||||
|  | 			combine.p.path = xmalloc(combine.p.len + 1); | ||||||
|  | 			memcpy(combine.p.path, ce->name, combine.p.len); | ||||||
|  | 			combine.p.path[combine.p.len] = 0; | ||||||
|  | 			memset(combine.p.sha1, 0, 100); | ||||||
|  |  | ||||||
| 			while (i < entries) { | 			while (i < entries) { | ||||||
| 				struct cache_entry *nce = active_cache[i]; | 				struct cache_entry *nce = active_cache[i]; | ||||||
|  | 				int stage; | ||||||
|  |  | ||||||
| 				if (strcmp(ce->name, nce->name)) | 				if (strcmp(ce->name, nce->name)) | ||||||
| 					break; | 					break; | ||||||
|  |  | ||||||
|  | 				/* Stage #2 (ours) is the first parent, | ||||||
|  | 				 * stage #3 (theirs) is the second. | ||||||
|  | 				 */ | ||||||
|  | 				stage = ce_stage(nce); | ||||||
|  | 				if (2 <= stage) | ||||||
|  | 					memcpy(combine.p.parent_sha1[stage-2], | ||||||
|  | 					       nce->sha1, 20); | ||||||
|  |  | ||||||
| 				/* diff against the proper unmerged stage */ | 				/* diff against the proper unmerged stage */ | ||||||
| 				if (ce_stage(nce) == diff_unmerged_stage) | 				if (stage == diff_unmerged_stage) | ||||||
| 					ce = nce; | 					ce = nce; | ||||||
| 				i++; | 				i++; | ||||||
| 			} | 			} | ||||||
|  | @ -123,10 +153,19 @@ int main(int argc, const char **argv) | ||||||
| 			 * Compensate for loop update | 			 * Compensate for loop update | ||||||
| 			 */ | 			 */ | ||||||
| 			i--; | 			i--; | ||||||
|  |  | ||||||
|  | 			if (combine_merges) { | ||||||
|  | 				show_combined_diff(&combine.p, 2, | ||||||
|  | 						   dense_combined_merges, | ||||||
|  | 						   NULL, 0); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			/* | 			/* | ||||||
| 			 * Show the diff for the 'ce' if we found the one | 			 * Show the diff for the 'ce' if we found the one | ||||||
| 			 * from the desired stage. | 			 * from the desired stage. | ||||||
| 			 */ | 			 */ | ||||||
|  | 			show_unmerge(ce->name); | ||||||
| 			if (ce_stage(ce) != diff_unmerged_stage) | 			if (ce_stage(ce) != diff_unmerged_stage) | ||||||
| 				continue; | 				continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								diff.h
								
								
								
								
							
							
						
						
									
										11
									
								
								diff.h
								
								
								
								
							|  | @ -56,6 +56,17 @@ extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2, | ||||||
| extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new, | extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new, | ||||||
| 			  const char *base, struct diff_options *opt); | 			  const char *base, struct diff_options *opt); | ||||||
|  |  | ||||||
|  | struct combine_diff_path { | ||||||
|  | 	struct combine_diff_path *next; | ||||||
|  | 	int len; | ||||||
|  | 	char *path; | ||||||
|  | 	unsigned char sha1[20]; | ||||||
|  | 	unsigned char parent_sha1[FLEX_ARRAY][20]; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | int show_combined_diff(struct combine_diff_path *elem, int num_parent, | ||||||
|  | 		       int dense, const char *header, int show_empty); | ||||||
|  |  | ||||||
| extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int, int); | extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int, int); | ||||||
|  |  | ||||||
| extern void diff_addremove(struct diff_options *, | extern void diff_addremove(struct diff_options *, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano