Skip to content

Commit ea726d0

Browse files
author
Junio C Hamano
committed
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>
1 parent 3ec1909 commit ea726d0

File tree

3 files changed

+99
-23
lines changed

3 files changed

+99
-23
lines changed

combine-diff.c

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@
44
#include "diffcore.h"
55
#include "quote.h"
66

7-
struct path_list {
8-
struct path_list *next;
9-
int len;
10-
char *path;
11-
unsigned char sha1[20];
12-
unsigned char parent_sha1[FLEX_ARRAY][20];
13-
};
14-
157
static int uninteresting(struct diff_filepair *p)
168
{
179
if (diff_unmodified_pair(p))
@@ -21,15 +13,14 @@ static int uninteresting(struct diff_filepair *p)
2113
return 0;
2214
}
2315

24-
static struct path_list *intersect_paths(struct path_list *curr,
25-
int n, int num_parent)
16+
static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
2617
{
2718
struct diff_queue_struct *q = &diff_queued_diff;
28-
struct path_list *p;
19+
struct combine_diff_path *p;
2920
int i;
3021

3122
if (!n) {
32-
struct path_list *list = NULL, **tail = &list;
23+
struct combine_diff_path *list = NULL, **tail = &list;
3324
for (i = 0; i < q->nr; i++) {
3425
int len;
3526
const char *path;
@@ -532,18 +523,52 @@ static void dump_sline(struct sline *sline, int cnt, int num_parent)
532523
}
533524
}
534525

535-
static int show_combined_diff(struct path_list *elem, int num_parent,
536-
int dense, const char *header, int show_empty)
526+
int show_combined_diff(struct combine_diff_path *elem, int num_parent,
527+
int dense, const char *header, int show_empty)
537528
{
538529
unsigned long size, cnt, lno;
539530
char *result, *cp, *ep;
540531
struct sline *sline; /* survived lines */
541532
int i, show_hunks, shown_header = 0;
542-
char ourtmp[TMPPATHLEN];
533+
char ourtmp_buf[TMPPATHLEN];
534+
char *ourtmp = ourtmp_buf;
543535

544536
/* Read the result of merge first */
545-
result = grab_blob(elem->sha1, &size);
546-
write_to_temp_file(ourtmp, result, size);
537+
if (memcmp(elem->sha1, null_sha1, 20)) {
538+
result = grab_blob(elem->sha1, &size);
539+
write_to_temp_file(ourtmp, result, size);
540+
}
541+
else {
542+
struct stat st;
543+
int fd;
544+
ourtmp = elem->path;
545+
if (0 <= (fd = open(ourtmp, O_RDONLY)) &&
546+
!fstat(fd, &st)) {
547+
int len = st.st_size;
548+
int cnt = 0;
549+
550+
size = len;
551+
result = xmalloc(len + 1);
552+
while (cnt < len) {
553+
int done = xread(fd, result+cnt, len-cnt);
554+
if (done == 0)
555+
break;
556+
if (done < 0)
557+
die("read error '%s'", ourtmp);
558+
cnt += done;
559+
}
560+
result[len] = 0;
561+
}
562+
else {
563+
/* deleted file */
564+
size = 0;
565+
result = xmalloc(1);
566+
result[0] = 0;
567+
ourtmp = "/dev/null";
568+
}
569+
if (0 <= fd)
570+
close(fd);
571+
}
547572

548573
for (cnt = 0, cp = result; cp - result < size; cp++) {
549574
if (*cp == '\n')
@@ -589,7 +614,8 @@ static int show_combined_diff(struct path_list *elem, int num_parent,
589614
putchar('\n');
590615
dump_sline(sline, cnt, num_parent);
591616
}
592-
unlink(ourtmp);
617+
if (ourtmp == ourtmp_buf)
618+
unlink(ourtmp);
593619
free(result);
594620

595621
for (i = 0; i < cnt; i++) {
@@ -613,7 +639,7 @@ int diff_tree_combined_merge(const unsigned char *sha1,
613639
struct commit *commit = lookup_commit(sha1);
614640
struct diff_options diffopts;
615641
struct commit_list *parents;
616-
struct path_list *p, *paths = NULL;
642+
struct combine_diff_path *p, *paths = NULL;
617643
int num_parent, i, num_paths;
618644

619645
diff_setup(&diffopts);
@@ -654,7 +680,7 @@ int diff_tree_combined_merge(const unsigned char *sha1,
654680

655681
/* Clean things up */
656682
while (paths) {
657-
struct path_list *tmp = paths;
683+
struct combine_diff_path *tmp = paths;
658684
paths = paths->next;
659685
free(tmp);
660686
}

diff-files.c

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
#include "diff.h"
88

99
static const char diff_files_usage[] =
10-
"git-diff-files [-q] [-0/-1/2/3] [<common diff options>] [<path>...]"
10+
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
1111
COMMON_DIFF_OPTIONS_HELP;
1212

1313
static struct diff_options diff_options;
1414
static int silent = 0;
1515
static int diff_unmerged_stage = 2;
16+
static int combine_merges = 0;
17+
static int dense_combined_merges = 0;
1618

1719
static void show_unmerge(const char *path)
1820
{
@@ -66,6 +68,10 @@ int main(int argc, const char **argv)
6668
; /* no-op */
6769
else if (!strcmp(argv[1], "-s"))
6870
; /* no-op */
71+
else if (!strcmp(argv[1], "-c"))
72+
combine_merges = 1;
73+
else if (!strcmp(argv[1], "--cc"))
74+
dense_combined_merges = combine_merges = 1;
6975
else {
7076
int diff_opt_cnt;
7177
diff_opt_cnt = diff_opt_parse(&diff_options,
@@ -82,6 +88,9 @@ int main(int argc, const char **argv)
8288
}
8389
argv++; argc--;
8490
}
91+
if (combine_merges) {
92+
diff_options.output_format = DIFF_FORMAT_PATCH;
93+
}
8594

8695
/* Find the directory, and set up the pathspec */
8796
pathspec = get_pathspec(prefix, argv + 1);
@@ -108,25 +117,55 @@ int main(int argc, const char **argv)
108117
continue;
109118

110119
if (ce_stage(ce)) {
111-
show_unmerge(ce->name);
120+
struct {
121+
struct combine_diff_path p;
122+
unsigned char fill[4][20];
123+
} combine;
124+
125+
combine.p.next = NULL;
126+
combine.p.len = ce_namelen(ce);
127+
combine.p.path = xmalloc(combine.p.len + 1);
128+
memcpy(combine.p.path, ce->name, combine.p.len);
129+
combine.p.path[combine.p.len] = 0;
130+
memset(combine.p.sha1, 0, 100);
131+
112132
while (i < entries) {
113133
struct cache_entry *nce = active_cache[i];
134+
int stage;
114135

115136
if (strcmp(ce->name, nce->name))
116137
break;
138+
139+
/* Stage #2 (ours) is the first parent,
140+
* stage #3 (theirs) is the second.
141+
*/
142+
stage = ce_stage(nce);
143+
if (2 <= stage)
144+
memcpy(combine.p.parent_sha1[stage-2],
145+
nce->sha1, 20);
146+
117147
/* diff against the proper unmerged stage */
118-
if (ce_stage(nce) == diff_unmerged_stage)
148+
if (stage == diff_unmerged_stage)
119149
ce = nce;
120150
i++;
121151
}
122152
/*
123153
* Compensate for loop update
124154
*/
125155
i--;
156+
157+
if (combine_merges) {
158+
show_combined_diff(&combine.p, 2,
159+
dense_combined_merges,
160+
NULL, 0);
161+
continue;
162+
}
163+
126164
/*
127165
* Show the diff for the 'ce' if we found the one
128166
* from the desired stage.
129167
*/
168+
show_unmerge(ce->name);
130169
if (ce_stage(ce) != diff_unmerged_stage)
131170
continue;
132171
}

diff.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
5656
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
5757
const char *base, struct diff_options *opt);
5858

59+
struct combine_diff_path {
60+
struct combine_diff_path *next;
61+
int len;
62+
char *path;
63+
unsigned char sha1[20];
64+
unsigned char parent_sha1[FLEX_ARRAY][20];
65+
};
66+
67+
int show_combined_diff(struct combine_diff_path *elem, int num_parent,
68+
int dense, const char *header, int show_empty);
69+
5970
extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int, int);
6071

6172
extern void diff_addremove(struct diff_options *,

0 commit comments

Comments
 (0)