@@ -323,52 +323,141 @@ static unsigned long line_all_diff(struct sline *sline, unsigned long all_mask)
323323 return different ;
324324}
325325
326- static int make_hunks (struct sline * sline , unsigned long cnt ,
327- int num_parent , int dense )
326+ static unsigned long adjust_hunk_tail (struct sline * sline ,
327+ unsigned long all_mask ,
328+ unsigned long hunk_begin ,
329+ unsigned long i )
330+ {
331+ /* i points at the first uninteresting line.
332+ * If the last line of the hunk was interesting
333+ * only because it has some deletion, then
334+ * it is not all that interesting for the
335+ * purpose of giving trailing context lines.
336+ */
337+ if ((hunk_begin + 1 <= i ) &&
338+ ((sline [i - 1 ].flag & all_mask ) == all_mask ))
339+ i -- ;
340+ return i ;
341+ }
342+
343+ static unsigned long next_interesting (struct sline * sline ,
344+ unsigned long mark ,
345+ unsigned long i ,
346+ unsigned long cnt ,
347+ int uninteresting )
348+ {
349+ while (i < cnt )
350+ if (uninteresting ?
351+ !(sline [i ].flag & mark ) :
352+ (sline [i ].flag & mark ))
353+ return i ;
354+ else
355+ i ++ ;
356+ return cnt ;
357+ }
358+
359+ static int give_context (struct sline * sline , unsigned long cnt , int num_parent )
328360{
329361 unsigned long all_mask = (1UL <<num_parent ) - 1 ;
330362 unsigned long mark = (1UL <<num_parent );
331363 unsigned long i ;
332- int has_interesting = 0 ;
333364
334- i = 0 ;
365+ i = next_interesting (sline , mark , 0 , cnt , 0 );
366+ if (cnt <= i )
367+ return 0 ;
368+
335369 while (i < cnt ) {
336- if (interesting (& sline [i ], all_mask )) {
337- unsigned long j = (context < i ) ? i - context : 0 ;
338- while (j <= i )
370+ unsigned long j = (context < i ) ? (i - context ) : 0 ;
371+ unsigned long k ;
372+ while (j < i )
373+ sline [j ++ ].flag |= mark ;
374+
375+ again :
376+ j = next_interesting (sline , mark , i , cnt , 1 );
377+ if (cnt <= j )
378+ break ; /* the rest are all interesting */
379+
380+ /* lookahead context lines */
381+ k = next_interesting (sline , mark , j , cnt , 0 );
382+ j = adjust_hunk_tail (sline , all_mask , i , j );
383+
384+ if (k < j + context ) {
385+ /* k is interesting and [j,k) are not, but
386+ * paint them interesting because the gap is small.
387+ */
388+ while (j < k )
339389 sline [j ++ ].flag |= mark ;
340- while (++ i < cnt ) {
341- if (!interesting (& sline [i ], all_mask ))
342- break ;
343- sline [i ].flag |= mark ;
344- }
345- j = (i + context < cnt ) ? i + context : cnt ;
346- while (i < j )
347- sline [i ++ ].flag |= mark ;
348- has_interesting = 1 ;
349- continue ;
390+ i = k ;
391+ goto again ;
350392 }
351- i ++ ;
393+
394+ /* j is the first uninteresting line and there is
395+ * no overlap beyond it within context lines.
396+ */
397+ i = k ;
398+ k = (j + context < cnt ) ? j + context : cnt ;
399+ while (j < k )
400+ sline [j ++ ].flag |= mark ;
401+ }
402+ return 1 ;
403+ }
404+
405+ static int make_hunks (struct sline * sline , unsigned long cnt ,
406+ int num_parent , int dense )
407+ {
408+ unsigned long all_mask = (1UL <<num_parent ) - 1 ;
409+ unsigned long mark = (1UL <<num_parent );
410+ unsigned long i ;
411+ int has_interesting = 0 ;
412+
413+ for (i = 0 ; i < cnt ; i ++ ) {
414+ if (interesting (& sline [i ], all_mask ))
415+ sline [i ].flag |= mark ;
416+ else
417+ sline [i ].flag &= ~mark ;
352418 }
353419 if (!dense )
354- return has_interesting ;
420+ return give_context ( sline , cnt , num_parent ) ;
355421
356422 /* Look at each hunk, and if we have changes from only one
357423 * parent, or the changes are the same from all but one
358424 * parent, mark that uninteresting.
359425 */
360- has_interesting = 0 ;
361426 i = 0 ;
362427 while (i < cnt ) {
363- int j , hunk_end , same , diff ;
428+ unsigned long j , hunk_begin , hunk_end ;
429+ int same , diff ;
364430 unsigned long same_diff , all_diff ;
365431 while (i < cnt && !(sline [i ].flag & mark ))
366432 i ++ ;
367433 if (cnt <= i )
368434 break ; /* No more interesting hunks */
369- for (hunk_end = i + 1 ; hunk_end < cnt ; hunk_end ++ )
370- if (!(sline [hunk_end ].flag & mark ))
371- break ;
435+ hunk_begin = i ;
436+ for (j = i + 1 ; j < cnt ; j ++ ) {
437+ if (!(sline [j ].flag & mark )) {
438+ /* Look beyond the end to see if there
439+ * is an interesting line after this
440+ * hunk within context span.
441+ */
442+ unsigned long la ; /* lookahead */
443+ int contin = 0 ;
444+ la = adjust_hunk_tail (sline , all_mask ,
445+ hunk_begin , j );
446+ la = (la + context < cnt ) ?
447+ (la + context ) : cnt ;
448+ while (j <= -- la ) {
449+ if (sline [la ].flag & mark ) {
450+ contin = 1 ;
451+ break ;
452+ }
453+ }
454+ if (!contin )
455+ break ;
456+ j = la ;
457+ }
458+ }
459+ hunk_end = j ;
460+
372461 /* [i..hunk_end) are interesting. Now does it have
373462 * the same change with all but one parent?
374463 */
@@ -387,13 +476,13 @@ static int make_hunks(struct sline *sline, unsigned long cnt,
387476 }
388477 if ((num_parent - 1 <= same ) || (diff == 1 )) {
389478 /* This hunk is not that interesting after all */
390- for (j = i ; j < hunk_end ; j ++ )
479+ for (j = hunk_begin ; j < hunk_end ; j ++ )
391480 sline [j ].flag &= ~mark ;
392481 }
393- else
394- has_interesting = 1 ;
395482 i = hunk_end ;
396483 }
484+
485+ has_interesting = give_context (sline , cnt , num_parent );
397486 return has_interesting ;
398487}
399488
0 commit comments