@@ -271,21 +271,56 @@ static int interesting(struct sline *sline, unsigned long all_mask)
271271 return ((sline -> flag & all_mask ) != all_mask || sline -> lost_head );
272272}
273273
274- static unsigned long line_diff_parents (struct sline * sline , unsigned long all_mask )
274+ static unsigned long line_common_diff (struct sline * sline , unsigned long all_mask )
275275{
276276 /*
277- * Look at the line and see from which parents we have difference.
278- * Lower bits of sline->flag records if the parent had this line,
279- * so XOR with all_mask gives us on-bits for parents we have
280- * differences with.
277+ * Look at the line and see from which parents we have the
278+ * same difference.
281279 */
282- unsigned long parents = (sline -> flag ^ all_mask );
280+
281+ /* Lower bits of sline->flag records if the parent had this
282+ * line, so XOR with all_mask gives us on-bits for parents we
283+ * have differences with.
284+ */
285+ unsigned long common_adds = (sline -> flag ^ all_mask ) & all_mask ;
286+ unsigned long common_removes = all_mask ;
287+
288+ /* If all the parents have this line, that also counts as
289+ * having the same difference.
290+ */
291+ if (!common_adds )
292+ common_adds = all_mask ;
293+
294+ if (sline -> lost_head ) {
295+ /* Lost head list records the lines removed from
296+ * the parents, and parent_map records from which
297+ * parent the line was removed.
298+ */
299+ struct lline * ll ;
300+ for (ll = sline -> lost_head ; ll ; ll = ll -> next ) {
301+ common_removes &= ll -> parent_map ;
302+ }
303+ }
304+ return common_adds & common_removes ;
305+ }
306+
307+ static unsigned long line_all_diff (struct sline * sline , unsigned long all_mask )
308+ {
309+ /*
310+ * Look at the line and see from which parents we have some difference.
311+ */
312+ unsigned long different = (sline -> flag ^ all_mask ) & all_mask ;
283313 if (sline -> lost_head ) {
314+ /* Lost head list records the lines removed from
315+ * the parents, and parent_map records from which
316+ * parent the line was removed.
317+ */
284318 struct lline * ll ;
285- for (ll = sline -> lost_head ; ll ; ll = ll -> next )
286- parents |= ll -> parent_map ;
319+ for (ll = sline -> lost_head ; ll ; ll = ll -> next ) {
320+ different |= ll -> parent_map ;
321+ }
287322 }
288- return parents & all_mask ;
323+ return different ;
289324}
290325
291326static void make_hunks (struct sline * sline , unsigned long cnt ,
@@ -316,36 +351,38 @@ static void make_hunks(struct sline *sline, unsigned long cnt,
316351 if (!dense )
317352 return ;
318353
319- /* Look at each hunk, and if it contains changes from only
320- * one parent, mark that uninteresting.
354+ /* Look at each hunk, and if we have changes from only one
355+ * parent, or the changes are the same from all but one
356+ * parent, mark that uninteresting.
321357 */
322358 i = 0 ;
323359 while (i < cnt ) {
324- int j , hunk_end , diffs ;
325- unsigned long parents ;
360+ int j , hunk_end , same , diff ;
361+ unsigned long same_diff , all_diff , this_diff ;
326362 while (i < cnt && !(sline [i ].flag & mark ))
327363 i ++ ;
328364 if (cnt <= i )
329365 break ; /* No more interesting hunks */
330366 for (hunk_end = i + 1 ; hunk_end < cnt ; hunk_end ++ )
331367 if (!(sline [hunk_end ].flag & mark ))
332368 break ;
333- /* [i..hunk_end) are interesting. Now is it from
334- * only one parent?
335- * If lost lines are only from one parent and
336- * remaining lines existed in parents other than
337- * that parent, then the hunk is not that interesting.
369+ /* [i..hunk_end) are interesting. Now does it have
370+ * the same change with all but one parent?
338371 */
339- parents = 0 ;
340- diffs = 0 ;
341- for (j = i ; j < hunk_end ; j ++ )
342- parents |= line_diff_parents (sline + j , all_mask );
343- /* Now, how many bits from [0..num_parent) are on? */
372+ same_diff = all_mask ;
373+ all_diff = 0 ;
374+ for (j = i ; j < hunk_end ; j ++ ) {
375+ same_diff &= line_common_diff (sline + j , all_mask );
376+ all_diff |= line_all_diff (sline + j , all_mask );
377+ }
378+ diff = same = 0 ;
344379 for (j = 0 ; j < num_parent ; j ++ ) {
345- if (parents & (1UL <<j ))
346- diffs ++ ;
380+ if (same_diff & (1UL <<j ))
381+ same ++ ;
382+ if (all_diff & (1UL <<j ))
383+ diff ++ ;
347384 }
348- if (diffs < 2 ) {
385+ if (( num_parent - 1 <= same ) || ( diff == 1 ) ) {
349386 /* This hunk is not that interesting after all */
350387 for (j = i ; j < hunk_end ; j ++ )
351388 sline [j ].flag &= ~mark ;
0 commit comments