7 #include "xdiff/xdiff.h"
9 static int uninteresting(struct diff_filepair
*p
)
11 if (diff_unmodified_pair(p
))
16 static struct combine_diff_path
*intersect_paths(struct combine_diff_path
*curr
, int n
, int num_parent
)
18 struct diff_queue_struct
*q
= &diff_queued_diff
;
19 struct combine_diff_path
*p
;
23 struct combine_diff_path
*list
= NULL
, **tail
= &list
;
24 for (i
= 0; i
< q
->nr
; i
++) {
27 if (uninteresting(q
->queue
[i
]))
29 path
= q
->queue
[i
]->two
->path
;
31 p
= xmalloc(combine_diff_path_size(num_parent
, len
));
32 p
->path
= (char*) &(p
->parent
[num_parent
]);
33 memcpy(p
->path
, path
, len
);
38 sizeof(p
->parent
[0]) * num_parent
);
40 memcpy(p
->sha1
, q
->queue
[i
]->two
->sha1
, 20);
41 p
->mode
= q
->queue
[i
]->two
->mode
;
42 memcpy(p
->parent
[n
].sha1
, q
->queue
[i
]->one
->sha1
, 20);
43 p
->parent
[n
].mode
= q
->queue
[i
]->one
->mode
;
44 p
->parent
[n
].status
= q
->queue
[i
]->status
;
51 for (p
= curr
; p
; p
= p
->next
) {
55 for (i
= 0; i
< q
->nr
; i
++) {
59 if (uninteresting(q
->queue
[i
]))
61 path
= q
->queue
[i
]->two
->path
;
63 if (len
== p
->len
&& !memcmp(path
, p
->path
, len
)) {
65 memcpy(p
->parent
[n
].sha1
,
66 q
->queue
[i
]->one
->sha1
, 20);
67 p
->parent
[n
].mode
= q
->queue
[i
]->one
->mode
;
68 p
->parent
[n
].status
= q
->queue
[i
]->status
;
78 /* Lines lost from parent */
82 unsigned long parent_map
;
83 char line
[FLEX_ARRAY
];
86 /* Lines surviving in the merge result */
88 struct lline
*lost_head
, **lost_tail
;
91 /* bit 0 up to (N-1) are on if the parent has this line (i.e.
92 * we did not change it).
93 * bit N is used for "interesting" lines, including context.
99 static char *grab_blob(const unsigned char *sha1
, unsigned long *size
)
103 if (!memcmp(sha1
, null_sha1
, 20)) {
106 return xcalloc(1, 1);
108 blob
= read_sha1_file(sha1
, type
, size
);
109 if (strcmp(type
, blob_type
))
110 die("object '%s' is not a blob!", sha1_to_hex(sha1
));
114 static int parse_num(char **cp_p
, unsigned int *num_p
)
117 unsigned int num
= 0;
120 while ('0' <= *cp
&& *cp
<= '9')
121 num
= num
* 10 + *cp
++ - '0';
122 if (!(read_some
= cp
- *cp_p
))
129 static int parse_hunk_header(char *line
, int len
,
130 unsigned int *ob
, unsigned int *on
,
131 unsigned int *nb
, unsigned int *nn
)
135 if (parse_num(&cp
, ob
)) {
137 return error("malformed diff output: %s", line
);
141 if (parse_num(&cp
, on
))
146 if (*cp
++ != ' ' || *cp
++ != '+')
148 if (parse_num(&cp
, nb
))
152 if (parse_num(&cp
, nn
))
157 return -!!memcmp(cp
, " @@", 3);
160 static void append_lost(struct sline
*sline
, int n
, const char *line
, int len
)
163 unsigned long this_mask
= (1UL<<n
);
164 if (line
[len
-1] == '\n')
167 /* Check to see if we can squash things */
168 if (sline
->lost_head
) {
169 struct lline
*last_one
= NULL
;
170 /* We cannot squash it with earlier one */
171 for (lline
= sline
->lost_head
;
174 if (lline
->parent_map
& this_mask
)
176 lline
= last_one
? last_one
->next
: sline
->lost_head
;
178 if (lline
->len
== len
&&
179 !memcmp(lline
->line
, line
, len
)) {
180 lline
->parent_map
|= this_mask
;
187 lline
= xmalloc(sizeof(*lline
) + len
+ 1);
190 lline
->parent_map
= this_mask
;
191 memcpy(lline
->line
, line
, len
);
192 lline
->line
[len
] = 0;
193 *sline
->lost_tail
= lline
;
194 sline
->lost_tail
= &lline
->next
;
197 struct combine_diff_state
{
199 unsigned long remainder_size
;
200 unsigned int lno
, ob
, on
, nb
, nn
;
205 struct sline
*lost_bucket
;
208 static void consume_line(struct combine_diff_state
*state
,
212 if (5 < len
&& !memcmp("@@ -", line
, 4)) {
213 if (parse_hunk_header(line
, len
,
214 &state
->ob
, &state
->on
,
215 &state
->nb
, &state
->nn
))
217 state
->lno
= state
->nb
;
219 /* @@ -1,2 +0,0 @@ to remove the
224 /* @@ -X,Y +N,0 @@ removed Y lines
225 * that would have come *after* line N
226 * in the result. Our lost buckets hang
227 * to the line after the removed lines,
229 state
->lost_bucket
= &state
->sline
[state
->nb
];
231 state
->lost_bucket
= &state
->sline
[state
->nb
-1];
232 if (!state
->sline
[state
->nb
-1].p_lno
)
233 state
->sline
[state
->nb
-1].p_lno
=
234 xcalloc(state
->num_parent
,
235 sizeof(unsigned long));
236 state
->sline
[state
->nb
-1].p_lno
[state
->n
] = state
->ob
;
239 if (!state
->lost_bucket
)
240 return; /* not in any hunk yet */
243 append_lost(state
->lost_bucket
, state
->n
, line
+1, len
-1);
246 state
->sline
[state
->lno
-1].flag
|= state
->nmask
;
252 static int combine_diff_outf(void *priv_
, mmbuffer_t
*mb
, int nbuf
)
254 struct combine_diff_state
*priv
= priv_
;
256 for (i
= 0; i
< nbuf
; i
++) {
257 if (mb
[i
].ptr
[mb
[i
].size
-1] != '\n') {
258 /* Incomplete line */
259 priv
->remainder
= realloc(priv
->remainder
,
260 priv
->remainder_size
+
262 memcpy(priv
->remainder
+ priv
->remainder_size
,
263 mb
[i
].ptr
, mb
[i
].size
);
264 priv
->remainder_size
+= mb
[i
].size
;
268 /* we have a complete line */
269 if (!priv
->remainder
) {
270 consume_line(priv
, mb
[i
].ptr
, mb
[i
].size
);
273 priv
->remainder
= realloc(priv
->remainder
,
274 priv
->remainder_size
+
276 memcpy(priv
->remainder
+ priv
->remainder_size
,
277 mb
[i
].ptr
, mb
[i
].size
);
278 consume_line(priv
, priv
->remainder
,
279 priv
->remainder_size
+ mb
[i
].size
);
280 free(priv
->remainder
);
281 priv
->remainder
= NULL
;
282 priv
->remainder_size
= 0;
287 static void combine_diff(const unsigned char *parent
, mmfile_t
*result_file
,
288 struct sline
*sline
, int cnt
, int n
, int num_parent
)
290 unsigned int p_lno
, lno
;
291 unsigned long nmask
= (1UL << n
);
294 mmfile_t parent_file
;
296 struct combine_diff_state state
;
300 return; /* result deleted */
302 parent_file
.ptr
= grab_blob(parent
, &sz
);
303 parent_file
.size
= sz
;
304 xpp
.flags
= XDF_NEED_MINIMAL
;
307 ecb
.outf
= combine_diff_outf
;
309 memset(&state
, 0, sizeof(state
));
313 state
.num_parent
= num_parent
;
316 xdl_diff(&parent_file
, result_file
, &xpp
, &xecfg
, &ecb
);
317 if (state
.remainder
&& state
.remainder_size
)
318 consume_line(&state
, state
.remainder
, state
.remainder_size
);
319 free(state
.remainder
);
320 free(parent_file
.ptr
);
322 /* Assign line numbers for this parent.
324 * sline[lno].p_lno[n] records the first line number
325 * (counting from 1) for parent N if the final hunk display
326 * started by showing sline[lno] (possibly showing the lost
327 * lines attached to it first).
329 for (lno
= 0, p_lno
= 1; lno
< cnt
; lno
++) {
331 sline
[lno
].p_lno
[n
] = p_lno
;
333 /* How many lines would this sline advance the p_lno? */
334 ll
= sline
[lno
].lost_head
;
336 if (ll
->parent_map
& nmask
)
337 p_lno
++; /* '-' means parent had it */
340 if (!(sline
[lno
].flag
& nmask
))
341 p_lno
++; /* no '+' means parent had it */
343 sline
[lno
].p_lno
[n
] = p_lno
; /* trailer */
346 static unsigned long context
= 3;
347 static char combine_marker
= '@';
349 static int interesting(struct sline
*sline
, unsigned long all_mask
)
351 /* If some parents lost lines here, or if we have added to
352 * some parent, it is interesting.
354 return ((sline
->flag
& all_mask
) || sline
->lost_head
);
357 static unsigned long adjust_hunk_tail(struct sline
*sline
,
358 unsigned long all_mask
,
359 unsigned long hunk_begin
,
362 /* i points at the first uninteresting line. If the last line
363 * of the hunk was interesting only because it has some
364 * deletion, then it is not all that interesting for the
365 * purpose of giving trailing context lines. This is because
366 * we output '-' line and then unmodified sline[i-1] itself in
367 * that case which gives us one extra context line.
369 if ((hunk_begin
+ 1 <= i
) && !(sline
[i
-1].flag
& all_mask
))
374 static unsigned long find_next(struct sline
*sline
,
380 /* We have examined up to i-1 and are about to look at i.
381 * Find next interesting or uninteresting line. Here,
382 * "interesting" does not mean interesting(), but marked by
383 * the give_context() function below (i.e. it includes context
384 * lines that are not interesting to interesting() function
385 * that are surrounded by interesting() ones.
389 ? !(sline
[i
].flag
& mark
)
390 : (sline
[i
].flag
& mark
))
397 static int give_context(struct sline
*sline
, unsigned long cnt
, int num_parent
)
399 unsigned long all_mask
= (1UL<<num_parent
) - 1;
400 unsigned long mark
= (1UL<<num_parent
);
403 /* Two groups of interesting lines may have a short gap of
404 * unintersting lines. Connect such groups to give them a
407 * We first start from what the interesting() function says,
408 * and mark them with "mark", and paint context lines with the
409 * mark. So interesting() would still say false for such context
410 * lines but they are treated as "interesting" in the end.
412 i
= find_next(sline
, mark
, 0, cnt
, 0);
417 unsigned long j
= (context
< i
) ? (i
- context
) : 0;
420 /* Paint a few lines before the first interesting line. */
422 sline
[j
++].flag
|= mark
;
425 /* we know up to i is to be included. where does the
426 * next uninteresting one start?
428 j
= find_next(sline
, mark
, i
, cnt
, 1);
430 break; /* the rest are all interesting */
432 /* lookahead context lines */
433 k
= find_next(sline
, mark
, j
, cnt
, 0);
434 j
= adjust_hunk_tail(sline
, all_mask
, i
, j
);
436 if (k
< j
+ context
) {
437 /* k is interesting and [j,k) are not, but
438 * paint them interesting because the gap is small.
441 sline
[j
++].flag
|= mark
;
446 /* j is the first uninteresting line and there is
447 * no overlap beyond it within context lines. Paint
448 * the trailing edge a bit.
451 k
= (j
+ context
< cnt
) ? j
+ context
: cnt
;
453 sline
[j
++].flag
|= mark
;
458 static int make_hunks(struct sline
*sline
, unsigned long cnt
,
459 int num_parent
, int dense
)
461 unsigned long all_mask
= (1UL<<num_parent
) - 1;
462 unsigned long mark
= (1UL<<num_parent
);
464 int has_interesting
= 0;
466 for (i
= 0; i
< cnt
; i
++) {
467 if (interesting(&sline
[i
], all_mask
))
468 sline
[i
].flag
|= mark
;
470 sline
[i
].flag
&= ~mark
;
473 return give_context(sline
, cnt
, num_parent
);
475 /* Look at each hunk, and if we have changes from only one
476 * parent, or the changes are the same from all but one
477 * parent, mark that uninteresting.
481 unsigned long j
, hunk_begin
, hunk_end
;
482 unsigned long same_diff
;
483 while (i
< cnt
&& !(sline
[i
].flag
& mark
))
486 break; /* No more interesting hunks */
488 for (j
= i
+ 1; j
< cnt
; j
++) {
489 if (!(sline
[j
].flag
& mark
)) {
490 /* Look beyond the end to see if there
491 * is an interesting line after this
492 * hunk within context span.
494 unsigned long la
; /* lookahead */
496 la
= adjust_hunk_tail(sline
, all_mask
,
498 la
= (la
+ context
< cnt
) ?
499 (la
+ context
) : cnt
;
501 if (sline
[la
].flag
& mark
) {
513 /* [i..hunk_end) are interesting. Now is it really
514 * interesting? We check if there are only two versions
515 * and the result matches one of them. That is, we look
517 * (+) line, which records lines added to which parents;
518 * this line appears in the result.
519 * (-) line, which records from what parents the line
520 * was removed; this line does not appear in the result.
521 * then check the set of parents the result has difference
522 * from, from all lines. If there are lines that has
523 * different set of parents that the result has differences
524 * from, that means we have more than two versions.
526 * Even when we have only two versions, if the result does
527 * not match any of the parents, the it should be considered
528 * interesting. In such a case, we would have all '+' line.
529 * After passing the above "two versions" test, that would
530 * appear as "the same set of parents" to be "all parents".
534 for (j
= i
; j
< hunk_end
&& !has_interesting
; j
++) {
535 unsigned long this_diff
= sline
[j
].flag
& all_mask
;
536 struct lline
*ll
= sline
[j
].lost_head
;
538 /* This has some changes. Is it the
542 same_diff
= this_diff
;
543 else if (same_diff
!= this_diff
) {
548 while (ll
&& !has_interesting
) {
549 /* Lost this line from these parents;
550 * who are they? Are they the same?
552 this_diff
= ll
->parent_map
;
554 same_diff
= this_diff
;
555 else if (same_diff
!= this_diff
) {
562 if (!has_interesting
&& same_diff
!= all_mask
) {
563 /* This hunk is not that interesting after all */
564 for (j
= hunk_begin
; j
< hunk_end
; j
++)
565 sline
[j
].flag
&= ~mark
;
570 has_interesting
= give_context(sline
, cnt
, num_parent
);
571 return has_interesting
;
574 static void show_parent_lno(struct sline
*sline
, unsigned long l0
, unsigned long l1
, unsigned long cnt
, int n
)
576 l0
= sline
[l0
].p_lno
[n
];
577 l1
= sline
[l1
].p_lno
[n
];
578 printf(" -%lu,%lu", l0
, l1
-l0
);
581 static void dump_sline(struct sline
*sline
, unsigned long cnt
, int num_parent
)
583 unsigned long mark
= (1UL<<num_parent
);
585 unsigned long lno
= 0;
588 return; /* result deleted */
591 struct sline
*sl
= &sline
[lno
];
593 while (lno
< cnt
&& !(sline
[lno
].flag
& mark
))
597 for (hunk_end
= lno
+ 1; hunk_end
< cnt
; hunk_end
++)
598 if (!(sline
[hunk_end
].flag
& mark
))
600 for (i
= 0; i
<= num_parent
; i
++) putchar(combine_marker
);
601 for (i
= 0; i
< num_parent
; i
++)
602 show_parent_lno(sline
, lno
, hunk_end
, cnt
, i
);
603 printf(" +%lu,%lu ", lno
+1, hunk_end
-lno
);
604 for (i
= 0; i
<= num_parent
; i
++) putchar(combine_marker
);
606 while (lno
< hunk_end
) {
609 unsigned long p_mask
;
613 for (j
= 0; j
< num_parent
; j
++) {
614 if (ll
->parent_map
& (1UL<<j
))
623 for (j
= 0; j
< num_parent
; j
++) {
624 if (p_mask
& sl
->flag
)
630 printf("%.*s\n", sl
->len
, sl
->bol
);
635 static void reuse_combine_diff(struct sline
*sline
, unsigned long cnt
,
638 /* We have already examined parent j and we know parent i
639 * and parent j are the same, so reuse the combined result
640 * of parent j for parent i.
642 unsigned long lno
, imask
, jmask
;
646 for (lno
= 0; lno
< cnt
; lno
++) {
647 struct lline
*ll
= sline
->lost_head
;
648 sline
->p_lno
[i
] = sline
->p_lno
[j
];
650 if (ll
->parent_map
& jmask
)
651 ll
->parent_map
|= imask
;
654 if (sline
->flag
& jmask
)
655 sline
->flag
|= imask
;
658 /* the overall size of the file (sline[cnt]) */
659 sline
->p_lno
[i
] = sline
->p_lno
[j
];
662 static int show_patch_diff(struct combine_diff_path
*elem
, int num_parent
,
663 int dense
, const char *header
,
664 struct diff_options
*opt
)
666 unsigned long result_size
, cnt
, lno
;
667 char *result
, *cp
, *ep
;
668 struct sline
*sline
; /* survived lines */
669 int mode_differs
= 0;
670 int i
, show_hunks
, shown_header
= 0;
671 int working_tree_file
= !memcmp(elem
->sha1
, null_sha1
, 20);
672 int abbrev
= opt
->full_index
? 40 : DEFAULT_ABBREV
;
673 mmfile_t result_file
;
675 /* Read the result of merge first */
676 if (!working_tree_file
)
677 result
= grab_blob(elem
->sha1
, &result_size
);
679 /* Used by diff-tree to read from the working tree */
682 if (0 <= (fd
= open(elem
->path
, O_RDONLY
)) &&
684 int len
= st
.st_size
;
687 elem
->mode
= canon_mode(st
.st_mode
);
689 result
= xmalloc(len
+ 1);
691 int done
= xread(fd
, result
+cnt
, len
-cnt
);
695 die("read error '%s'", elem
->path
);
711 for (cnt
= 0, cp
= result
; cp
- result
< result_size
; cp
++) {
715 if (result_size
&& result
[result_size
-1] != '\n')
716 cnt
++; /* incomplete line */
718 sline
= xcalloc(cnt
+1, sizeof(*sline
));
720 sline
[0].bol
= result
;
721 for (lno
= 0; lno
<= cnt
; lno
++) {
722 sline
[lno
].lost_tail
= &sline
[lno
].lost_head
;
725 for (lno
= 0, cp
= result
; cp
- result
< result_size
; cp
++) {
727 sline
[lno
].len
= cp
- sline
[lno
].bol
;
730 sline
[lno
].bol
= cp
+ 1;
733 if (result_size
&& result
[result_size
-1] != '\n')
734 sline
[cnt
-1].len
= result_size
- (sline
[cnt
-1].bol
- result
);
736 result_file
.ptr
= result
;
737 result_file
.size
= result_size
;
739 sline
[0].p_lno
= xcalloc((cnt
+1) * num_parent
, sizeof(unsigned long));
740 for (lno
= 0; lno
< cnt
; lno
++)
741 sline
[lno
+1].p_lno
= sline
[lno
].p_lno
+ num_parent
;
743 for (i
= 0; i
< num_parent
; i
++) {
745 for (j
= 0; j
< i
; j
++) {
746 if (!memcmp(elem
->parent
[i
].sha1
,
747 elem
->parent
[j
].sha1
, 20)) {
748 reuse_combine_diff(sline
, cnt
, i
, j
);
753 combine_diff(elem
->parent
[i
].sha1
, &result_file
, sline
,
755 if (elem
->parent
[i
].mode
!= elem
->mode
)
759 show_hunks
= make_hunks(sline
, cnt
, num_parent
, dense
);
761 if (show_hunks
|| mode_differs
|| working_tree_file
) {
766 printf("%s%c", header
, opt
->line_termination
);
768 printf("diff --%s ", dense
? "cc" : "combined");
769 if (quote_c_style(elem
->path
, NULL
, NULL
, 0))
770 quote_c_style(elem
->path
, NULL
, stdout
, 0);
772 printf("%s", elem
->path
);
775 for (i
= 0; i
< num_parent
; i
++) {
776 abb
= find_unique_abbrev(elem
->parent
[i
].sha1
,
778 printf("%s%s", i
? "," : "", abb
);
780 abb
= find_unique_abbrev(elem
->sha1
, abbrev
);
781 printf("..%s\n", abb
);
784 int added
= !!elem
->mode
;
785 for (i
= 0; added
&& i
< num_parent
; i
++)
786 if (elem
->parent
[i
].status
!=
790 printf("new file mode %06o", elem
->mode
);
793 printf("deleted file ");
795 for (i
= 0; i
< num_parent
; i
++) {
796 printf("%s%06o", i
? "," : "",
797 elem
->parent
[i
].mode
);
800 printf("..%06o", elem
->mode
);
804 dump_sline(sline
, cnt
, num_parent
);
808 for (i
= 0; i
< cnt
; i
++) {
809 if (sline
[i
].lost_head
) {
810 struct lline
*ll
= sline
[i
].lost_head
;
812 struct lline
*tmp
= ll
;
818 free(sline
[0].p_lno
);
823 #define COLONS "::::::::::::::::::::::::::::::::"
825 static void show_raw_diff(struct combine_diff_path
*p
, int num_parent
, const char *header
, struct diff_options
*opt
)
827 int i
, offset
, mod_type
= 'A';
829 int line_termination
, inter_name_termination
;
831 line_termination
= opt
->line_termination
;
832 inter_name_termination
= '\t';
833 if (!line_termination
)
834 inter_name_termination
= 0;
837 printf("%s%c", header
, line_termination
);
839 for (i
= 0; i
< num_parent
; i
++) {
840 if (p
->parent
[i
].mode
)
846 if (opt
->output_format
== DIFF_FORMAT_RAW
) {
847 offset
= strlen(COLONS
) - num_parent
;
850 prefix
= COLONS
+ offset
;
853 for (i
= 0; i
< num_parent
; i
++) {
854 printf("%s%06o", prefix
, p
->parent
[i
].mode
);
857 printf("%s%06o", prefix
, p
->mode
);
860 for (i
= 0; i
< num_parent
; i
++)
861 printf(" %s", diff_unique_abbrev(p
->parent
[i
].sha1
,
863 printf(" %s ", diff_unique_abbrev(p
->sha1
, opt
->abbrev
));
866 if (opt
->output_format
== DIFF_FORMAT_RAW
||
867 opt
->output_format
== DIFF_FORMAT_NAME_STATUS
) {
868 for (i
= 0; i
< num_parent
; i
++)
869 putchar(p
->parent
[i
].status
);
870 putchar(inter_name_termination
);
873 if (line_termination
) {
874 if (quote_c_style(p
->path
, NULL
, NULL
, 0))
875 quote_c_style(p
->path
, NULL
, stdout
, 0);
877 printf("%s", p
->path
);
878 putchar(line_termination
);
881 printf("%s%c", p
->path
, line_termination
);
885 int show_combined_diff(struct combine_diff_path
*p
,
889 struct diff_options
*opt
)
893 switch (opt
->output_format
) {
894 case DIFF_FORMAT_RAW
:
895 case DIFF_FORMAT_NAME_STATUS
:
896 case DIFF_FORMAT_NAME
:
897 show_raw_diff(p
, num_parent
, header
, opt
);
901 case DIFF_FORMAT_PATCH
:
902 return show_patch_diff(p
, num_parent
, dense
, header
, opt
);
906 const char *diff_tree_combined_merge(const unsigned char *sha1
,
907 const char *header
, int dense
,
908 struct diff_options
*opt
)
910 struct commit
*commit
= lookup_commit(sha1
);
911 struct diff_options diffopts
;
912 struct commit_list
*parents
;
913 struct combine_diff_path
*p
, *paths
= NULL
;
914 int num_parent
, i
, num_paths
;
917 diffopts
.output_format
= DIFF_FORMAT_NO_OUTPUT
;
918 diffopts
.recursive
= 1;
921 for (parents
= commit
->parents
, num_parent
= 0;
923 parents
= parents
->next
, num_parent
++)
926 /* find set of paths that everybody touches */
927 for (parents
= commit
->parents
, i
= 0;
929 parents
= parents
->next
, i
++) {
930 struct commit
*parent
= parents
->item
;
931 diff_tree_sha1(parent
->object
.sha1
, commit
->object
.sha1
, "",
933 diffcore_std(&diffopts
);
934 paths
= intersect_paths(paths
, i
, num_parent
);
935 diff_flush(&diffopts
);
938 /* find out surviving paths */
939 for (num_paths
= 0, p
= paths
; p
; p
= p
->next
) {
944 for (p
= paths
; p
; p
= p
->next
) {
945 if (show_combined_diff(p
, num_parent
, dense
,
951 /* Clean things up */
953 struct combine_diff_path
*tmp
= paths
;