@@ -278,7 +278,25 @@ static int interesting(struct sline *sline, unsigned long all_mask)
278278 return ((sline -> flag & all_mask ) != all_mask || sline -> lost_head );
279279}
280280
281- static void make_hunks (struct sline * sline , unsigned long cnt , int num_parent )
281+ static unsigned long line_diff_parents (struct sline * sline , unsigned long all_mask )
282+ {
283+ /*
284+ * Look at the line and see from which parents we have difference.
285+ * Lower bits of sline->flag records if the parent had this line,
286+ * so XOR with all_mask gives us on-bits for parents we have
287+ * differences with.
288+ */
289+ unsigned long parents = (sline -> flag ^ all_mask );
290+ if (sline -> lost_head ) {
291+ struct lline * ll ;
292+ for (ll = sline -> lost_head ; ll ; ll = ll -> next )
293+ parents |= ll -> parent_map ;
294+ }
295+ return parents & all_mask ;
296+ }
297+
298+ static void make_hunks (struct sline * sline , unsigned long cnt ,
299+ int num_parent , int dense )
282300{
283301 unsigned long all_mask = (1UL <<num_parent ) - 1 ;
284302 unsigned long mark = (1UL <<num_parent );
@@ -302,6 +320,45 @@ static void make_hunks(struct sline *sline, unsigned long cnt, int num_parent)
302320 }
303321 i ++ ;
304322 }
323+ if (!dense )
324+ return ;
325+
326+ /* Look at each hunk, and if it contains changes from only
327+ * one parent, mark that uninteresting.
328+ */
329+ i = 0 ;
330+ while (i < cnt ) {
331+ int j , hunk_end , diffs ;
332+ unsigned long parents ;
333+ while (i < cnt && !(sline [i ].flag & mark ))
334+ i ++ ;
335+ if (cnt <= i )
336+ break ; /* No more interesting hunks */
337+ for (hunk_end = i + 1 ; hunk_end < cnt ; hunk_end ++ )
338+ if (!(sline [hunk_end ].flag & mark ))
339+ break ;
340+ /* [i..hunk_end) are interesting. Now is it from
341+ * only one parent?
342+ * If lost lines are only from one parent and
343+ * remaining lines existed in parents other than
344+ * that parent, then the hunk is not that interesting.
345+ */
346+ parents = 0 ;
347+ diffs = 0 ;
348+ for (j = i ; j < hunk_end ; j ++ )
349+ parents |= line_diff_parents (sline + j , all_mask );
350+ /* Now, how many bits from [0..num_parent) are on? */
351+ for (j = 0 ; j < num_parent ; j ++ ) {
352+ if (parents & (1UL <<j ))
353+ diffs ++ ;
354+ }
355+ if (diffs < 2 ) {
356+ /* This hunk is not that interesting after all */
357+ for (j = i ; j < hunk_end ; j ++ )
358+ sline [j ].flag &= ~mark ;
359+ }
360+ i = hunk_end ;
361+ }
305362}
306363
307364static void dump_sline (struct sline * sline , int cnt , int num_parent )
@@ -351,7 +408,8 @@ static void dump_sline(struct sline *sline, int cnt, int num_parent)
351408 }
352409}
353410
354- static void show_combined_diff (struct path_list * elem , int num_parent )
411+ static void show_combined_diff (struct path_list * elem , int num_parent ,
412+ int dense )
355413{
356414 unsigned long size , cnt , lno ;
357415 char * result , * cp , * ep ;
@@ -390,7 +448,7 @@ static void show_combined_diff(struct path_list *elem, int num_parent)
390448 for (i = 0 ; i < num_parent ; i ++ )
391449 combine_diff (elem -> parent_sha1 [i ], ourtmp , sline , cnt , i );
392450
393- make_hunks (sline , cnt , num_parent );
451+ make_hunks (sline , cnt , num_parent , dense );
394452
395453 dump_sline (sline , cnt , num_parent );
396454 unlink (ourtmp );
@@ -410,7 +468,8 @@ static void show_combined_diff(struct path_list *elem, int num_parent)
410468}
411469
412470int diff_tree_combined_merge (const unsigned char * sha1 ,
413- const char * header , int show_empty_merge )
471+ const char * header ,
472+ int show_empty_merge , int dense )
414473{
415474 struct commit * commit = lookup_commit (sha1 );
416475 struct diff_options diffopts ;
@@ -455,7 +514,7 @@ int diff_tree_combined_merge(const unsigned char *sha1,
455514 else
456515 printf ("%s" , p -> path );
457516 putchar ('\n' );
458- show_combined_diff (p , num_parent );
517+ show_combined_diff (p , num_parent , dense );
459518 }
460519 }
461520
0 commit comments