diff --git a/line-log.c b/line-log.c index 72a5fed661ca0a..0e09df9dba966d 100644 --- a/line-log.c +++ b/line-log.c @@ -68,7 +68,13 @@ void range_set_append_unsafe(struct range_set *rs, long a, long b) void range_set_append(struct range_set *rs, long a, long b) { - assert(rs->nr == 0 || rs->ranges[rs->nr-1].end <= a); + if (rs->nr > 0 && rs->ranges[rs->nr-1].end + 1 == a) { + rs->ranges[rs->nr-1].end = b; + return; + } + if (rs->nr > 0 && rs->ranges[rs->nr-1].end > a) + BUG("append %ld-%ld, after %ld-%ld?!?", a, b, + rs->ranges[rs->nr-1].start, rs->ranges[rs->nr-1].end); range_set_append_unsafe(rs, a, b); } @@ -427,7 +433,7 @@ static void range_set_shift_diff(struct range_set *out, struct diff_ranges *diff) { unsigned int i, j = 0; - long offset = 0; + long offset = 0, start_offset; struct range *src = rs->ranges; struct range *target = diff->target.ranges; struct range *parent = diff->parent.ranges; @@ -438,7 +444,13 @@ static void range_set_shift_diff(struct range_set *out, - (target[j].end-target[j].start); j++; } - range_set_append(out, src[i].start+offset, src[i].end+offset); + start_offset = offset; + while (j < diff->target.nr && src[i].end > target[j].end) { + offset += (parent[j].end-parent[j].start) + - (target[j].end-target[j].start); + j++; + } + range_set_append(out, src[i].start+start_offset, src[i].end+offset); } } diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index 436b13ad21d063..ebaf5ea8641b12 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -115,4 +115,21 @@ test_expect_success 'range_set_union' ' git log $(for x in $(test_seq 200); do echo -L $((2*x)),+1:c.c; done) ' +q_to_lf () { + tr Q '\012' +} + +test_expect_success 'close to overlapping ranges' ' + test_seq 5 >a1.c && + git add a1.c && + git commit -m "5 lines" a1.c && + sed s/3/3QaQb/ tmp && + mv tmp a1.c && + git commit -m "2 more lines" a1.c && + sed s/4/cQ4/ tmp && + mv tmp a1.c && + git commit -m "1 more line" a1.c && + git --no-pager log -L 1,3:a1.c -L 5,8:a1.c +' + test_done