From: Neil Brown Date: Tue, 8 May 2012 07:09:07 +0000 (+1000) Subject: Improve handling of hunk-header when merging. X-Git-Tag: v0.9~32 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=6ca62c923077121006743deef392bbe78af7f6a6;p=wiggle.git Improve handling of hunk-header when merging. If we are merging a patch, the patch will contain a number of hunk-headers (essentially the @@ NN,MM @@) lines. These should never appear in the merge, and must always line up with end-of-line in the original as they represent a number of lines having been deleted. So: Cause these to each create a simple Extraneous merger, never combined with adjacent texts exclude them from any conflicts in isolate_conflict, so they can never appear in a merge Ensure that a preceeding 'Unmatched' finishes on an end-of-line. Also update lots of self tests with improved results. Signed-off-by: NeilBrown --- diff --git a/merge2.c b/merge2.c index 83be6f1..3b4a96b 100644 --- a/merge2.c +++ b/merge2.c @@ -131,6 +131,10 @@ static int isolate_conflicts(struct file af, struct file bf, struct file cf, m[i].in_conflict = 1; j = i; while (--j >= 0) { + if (m[j].type == Extraneous && + bf.list[m[j].b].start[0] == '\0') + /* hunk header - not conflict any more */ + break; if (!m[j].in_conflict) { m[j].in_conflict = 1; m[j].lo = 0; @@ -179,6 +183,10 @@ static int isolate_conflicts(struct file af, struct file bf, struct file cf, /* now the forward search */ for (j = i+1; m[j].type != End; j++) { + if (m[j].type == Extraneous && + bf.list[m[j].b].start[0] == '\0') + /* hunk header - not conflict any more */ + break; m[j].in_conflict = 1; if (m[j].type == Unchanged || m[j].type == Changed) { m[j].hi = m[j].al; @@ -266,10 +274,22 @@ struct ci make_merger(struct file af, struct file bf, struct file cf, rv.merger[i].in_conflict = 0; if (!match1 && match2) { - if (a < csl1[c1].a) { + /* This is either Unmatched or Extraneous - probably both. + * If the match2 is a hunk-header Extraneous, it must + * align with an end-of-line in 'a', so adjust endpoint + */ + int newa = csl1[c1].a; + if (bf.list[b].start && bf.list[b].start[0] == '\0') { + while (newa > a && + !ends_line(af.list[newa-1])) + newa--; + while (newa < af.elcnt && !(newa == 0 || ends_line(af.list[newa-1]))) + newa++; + } + if (a < newa) { /* some unmatched text */ rv.merger[i].type = Unmatched; - rv.merger[i].al = csl1[c1].a - a; + rv.merger[i].al = newa - a; rv.merger[i].bl = 0; rv.merger[i].cl = 0; wiggle_found++; @@ -280,15 +300,19 @@ struct ci make_merger(struct file af, struct file bf, struct file cf, /* some Extraneous text */ /* length is min of unmatched on left * and matched on right. - * However a hunk-header is not allowed - * in the middle of an extraneous section, - * only at the start. + * However a hunk-header must be an + * Extraneous section by itself, so if this + * start with one, the length is 1, and if + * there is one in the middle, only take the + * text up to there for now. */ rv.merger[i].type = Extraneous; rv.merger[i].al = 0; newb = b + min(csl1[c1].b - b, csl2[c2].len - (b-csl2[c2].a)); + if (bf.list[b].start[0] == '\0') + newb = b + 1; for (j = b; j < newb; j++) { if (bf.list[j].start[0] == '\0') { if (wiggle_found > 1) diff --git a/tests/linux/idmap.h/merge b/tests/linux/idmap.h/merge index 664ceea..52028f8 100644 --- a/tests/linux/idmap.h/merge +++ b/tests/linux/idmap.h/merge @@ -1,6 +1,5 @@ <<<<<<< ||||||| -*** 55,6 **** 1 #define IDMAP_STATUS_LOOKUPFAIL IDMAP_STATUS_FAIL @@ -8,7 +7,6 @@ #define IDMAP_NAMESZ 128 ======= -*** 55,8 **** 1 #define IDMAP_STATUS_LOOKUPFAIL IDMAP_STATUS_FAIL diff --git a/tests/linux/md-resync/merge b/tests/linux/md-resync/merge index d6ff33e..7960304 100644 --- a/tests/linux/md-resync/merge +++ b/tests/linux/md-resync/merge @@ -1538,7 +1538,8 @@ static void end_sync_write(struct buffer_head *bh, int uptodate) int size = bh->b_size; raid1_free_buf(r1_bh); sync_request_done(sect, mddev_to_conf(mddev)); - md_done_sync(mddev,size>>9, uptodate } + md_done_sync(mddev,size>>9, uptodate); + } } #define INVALID_LEVEL KERN_WARNING \ diff --git a/tests/linux/raid5line/lmerge b/tests/linux/raid5line/lmerge index ee56bcb..4d8dba6 100644 --- a/tests/linux/raid5line/lmerge +++ b/tests/linux/raid5line/lmerge @@ -1,9 +1,7 @@ -<<<<<<< clear_bit(BH_Uptodate, &sh->bh_cache[i]->b_state); +<<<<<<< ||||||| -*** 1,1 **** 1 clear_buffer_uptodate(sh->bh_cache[i]); ======= -*** 1,1 **** 1 dev->flags = 0; >>>>>>> diff --git a/tests/linux/raid5line/merge b/tests/linux/raid5line/merge index ee56bcb..e6ffa40 100644 --- a/tests/linux/raid5line/merge +++ b/tests/linux/raid5line/merge @@ -1,9 +1,7 @@ <<<<<<< clear_bit(BH_Uptodate, &sh->bh_cache[i]->b_state); ||||||| -*** 1,1 **** 1 clear_buffer_uptodate(sh->bh_cache[i]); ======= -*** 1,1 **** 1 dev->flags = 0; >>>>>>> diff --git a/tests/linux/raid5line/wmerge b/tests/linux/raid5line/wmerge index a8464d9..e0b1530 100644 --- a/tests/linux/raid5line/wmerge +++ b/tests/linux/raid5line/wmerge @@ -1,3 +1 @@ -<<<--- clear_bit(BH_Uptodate, &|||*** 1,1 **** 1 - clear_buffer_uptodate(===*** 1,1 **** 1 - dev--->>>-><<<---->b_state|||===flags = 0--->>>; +<<<--- clear_bit(BH_Uptodate, &||| clear_buffer_uptodate(=== dev--->>>-><<<---->b_state|||===flags = 0--->>>; diff --git a/tests/simple/trivial-conflict/merge b/tests/simple/trivial-conflict/merge index 8308b25..4e532df 100644 --- a/tests/simple/trivial-conflict/merge +++ b/tests/simple/trivial-conflict/merge @@ -1,9 +1,7 @@ <<<<<<< c ||||||| -*** 1,1 **** 1 a ======= -*** 1,1 **** 1 b >>>>>>>