@@ -23,11 +23,20 @@ static int compare_paths(const struct combine_diff_path *one,
2323 two -> path , strlen (two -> path ), two -> mode );
2424}
2525
26- static struct combine_diff_path * intersect_paths (struct combine_diff_path * curr , int n , int num_parent )
26+ static int filename_changed (char status )
27+ {
28+ return status == 'R' || status == 'C' ;
29+ }
30+
31+ static struct combine_diff_path * intersect_paths (
32+ struct combine_diff_path * curr ,
33+ int n ,
34+ int num_parent ,
35+ int combined_all_paths )
2736{
2837 struct diff_queue_struct * q = & diff_queued_diff ;
2938 struct combine_diff_path * p , * * tail = & curr ;
30- int i , cmp ;
39+ int i , j , cmp ;
3140
3241 if (!n ) {
3342 for (i = 0 ; i < q -> nr ; i ++ ) {
@@ -50,6 +59,13 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
5059 oidcpy (& p -> parent [n ].oid , & q -> queue [i ]-> one -> oid );
5160 p -> parent [n ].mode = q -> queue [i ]-> one -> mode ;
5261 p -> parent [n ].status = q -> queue [i ]-> status ;
62+
63+ if (combined_all_paths &&
64+ filename_changed (p -> parent [n ].status )) {
65+ strbuf_init (& p -> parent [n ].path , 0 );
66+ strbuf_addstr (& p -> parent [n ].path ,
67+ q -> queue [i ]-> one -> path );
68+ }
5369 * tail = p ;
5470 tail = & p -> next ;
5571 }
@@ -68,6 +84,10 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
6884 if (cmp < 0 ) {
6985 /* p->path not in q->queue[]; drop it */
7086 * tail = p -> next ;
87+ for (j = 0 ; j < num_parent ; j ++ )
88+ if (combined_all_paths &&
89+ filename_changed (p -> parent [j ].status ))
90+ strbuf_release (& p -> parent [j ].path );
7191 free (p );
7292 continue ;
7393 }
@@ -81,6 +101,10 @@ static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr,
81101 oidcpy (& p -> parent [n ].oid , & q -> queue [i ]-> one -> oid );
82102 p -> parent [n ].mode = q -> queue [i ]-> one -> mode ;
83103 p -> parent [n ].status = q -> queue [i ]-> status ;
104+ if (combined_all_paths &&
105+ filename_changed (p -> parent [n ].status ))
106+ strbuf_addstr (& p -> parent [n ].path ,
107+ q -> queue [i ]-> one -> path );
84108
85109 tail = & p -> next ;
86110 i ++ ;
@@ -960,12 +984,25 @@ static void show_combined_header(struct combine_diff_path *elem,
960984 if (!show_file_header )
961985 return ;
962986
963- if (added )
964- dump_quoted_path ("--- " , "" , "/dev/null" ,
965- line_prefix , c_meta , c_reset );
966- else
967- dump_quoted_path ("--- " , a_prefix , elem -> path ,
968- line_prefix , c_meta , c_reset );
987+ if (rev -> combined_all_paths ) {
988+ for (i = 0 ; i < num_parent ; i ++ ) {
989+ char * path = filename_changed (elem -> parent [i ].status )
990+ ? elem -> parent [i ].path .buf : elem -> path ;
991+ if (elem -> parent [i ].status == DIFF_STATUS_ADDED )
992+ dump_quoted_path ("--- " , "" , "/dev/null" ,
993+ line_prefix , c_meta , c_reset );
994+ else
995+ dump_quoted_path ("--- " , a_prefix , path ,
996+ line_prefix , c_meta , c_reset );
997+ }
998+ } else {
999+ if (added )
1000+ dump_quoted_path ("--- " , "" , "/dev/null" ,
1001+ line_prefix , c_meta , c_reset );
1002+ else
1003+ dump_quoted_path ("--- " , a_prefix , elem -> path ,
1004+ line_prefix , c_meta , c_reset );
1005+ }
9691006 if (deleted )
9701007 dump_quoted_path ("+++ " , "" , "/dev/null" ,
9711008 line_prefix , c_meta , c_reset );
@@ -1227,6 +1264,15 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, struct re
12271264 putchar (inter_name_termination );
12281265 }
12291266
1267+ for (i = 0 ; i < num_parent ; i ++ )
1268+ if (rev -> combined_all_paths ) {
1269+ if (filename_changed (p -> parent [i ].status ))
1270+ write_name_quoted (p -> parent [i ].path .buf , stdout ,
1271+ inter_name_termination );
1272+ else
1273+ write_name_quoted (p -> path , stdout ,
1274+ inter_name_termination );
1275+ }
12301276 write_name_quoted (p -> path , stdout , line_termination );
12311277}
12321278
@@ -1332,7 +1378,9 @@ static const char *path_path(void *obj)
13321378
13331379/* find set of paths that every parent touches */
13341380static struct combine_diff_path * find_paths_generic (const struct object_id * oid ,
1335- const struct oid_array * parents , struct diff_options * opt )
1381+ const struct oid_array * parents ,
1382+ struct diff_options * opt ,
1383+ int combined_all_paths )
13361384{
13371385 struct combine_diff_path * paths = NULL ;
13381386 int i , num_parent = parents -> nr ;
@@ -1357,7 +1405,8 @@ static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
13571405 opt -> output_format = DIFF_FORMAT_NO_OUTPUT ;
13581406 diff_tree_oid (& parents -> oid [i ], oid , "" , opt );
13591407 diffcore_std (opt );
1360- paths = intersect_paths (paths , i , num_parent );
1408+ paths = intersect_paths (paths , i , num_parent ,
1409+ combined_all_paths );
13611410
13621411 /* if showing diff, show it in requested order */
13631412 if (opt -> output_format != DIFF_FORMAT_NO_OUTPUT &&
@@ -1467,7 +1516,8 @@ void diff_tree_combined(const struct object_id *oid,
14671516 * diff(sha1,parent_i) for all i to do the job, specifically
14681517 * for parent0.
14691518 */
1470- paths = find_paths_generic (oid , parents , & diffopts );
1519+ paths = find_paths_generic (oid , parents , & diffopts ,
1520+ rev -> combined_all_paths );
14711521 }
14721522 else {
14731523 int stat_opt ;
@@ -1540,6 +1590,10 @@ void diff_tree_combined(const struct object_id *oid,
15401590 while (paths ) {
15411591 struct combine_diff_path * tmp = paths ;
15421592 paths = paths -> next ;
1593+ for (i = 0 ; i < num_parent ; i ++ )
1594+ if (rev -> combined_all_paths &&
1595+ filename_changed (tmp -> parent [i ].status ))
1596+ strbuf_release (& tmp -> parent [i ].path );
15431597 free (tmp );
15441598 }
15451599
0 commit comments