From 693fe6a3e1deb7e190d295bc578549a8963e02da Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 25 May 2006 10:59:57 +0000 Subject: [PATCH] Get merge2 to pass all the tests... Some of this done by changing tests... Signed-off-by: Neil Brown --- merge2.c | 112 +++++++++++++++++++++++------- tests/linux/idmap.h/merge | 18 +++++ tests/linux/md-resync/merge | 57 +++++++-------- tests/linux/md/lmerge | 6 -- tests/linux/md/merge | 6 -- tests/linux/md/wmerge | 4 +- tests/linux/raid5build/merge | 4 ++ tests/linux/raid5line/lmerge | 2 + tests/linux/raid5line/merge | 2 + tests/linux/raid5line/wmerge | 4 +- tests/linux/rpc_tcp_nonagle/merge | 2 + wiggle.h | 25 ++++++- 12 files changed, 167 insertions(+), 75 deletions(-) diff --git a/merge2.c b/merge2.c index aec9ef2..808e18e 100644 --- a/merge2.c +++ b/merge2.c @@ -94,6 +94,13 @@ inline int isolate_conflicts(struct file af, struct file bf, struct file cf, * Also, unless 'words', we need to include any partial lines * in the Unchanged text that forms the border of a conflict. * + * A Changed text may also border a conflict, but it can + * only border one conflict (where as an Unchanged can border + * a preceeding and a following conflict). + * The 'new' section of a Changed text appears in the + * conflict as does any part of the original before + * a newline. + * */ int i,j,k; int cnt = 0; @@ -115,7 +122,14 @@ inline int isolate_conflicts(struct file af, struct file bf, struct file cf, if (!m[j].in_conflict) { m[j].in_conflict = 1; m[j].lo = 0; + } else if (m[j].type == Changed) { + /* This can no longer form a border */ + m[j].lo = 0; m[j].hi = -1; + /* We merge these conflicts and stop searching */ + cnt--; + break; } + if (m[j].type == Unchanged || m[j].type == Changed) { if (words) { m[j].hi = m[j].al; @@ -125,23 +139,40 @@ inline int isolate_conflicts(struct file af, struct file bf, struct file cf, * might be after the last newline, if there * is one, or might be at the start */ - for (k=m[j].al; k>0; k--) + for (k=m[j].al; k>0; k--) if (ends_line(af.list[m[j].a+k-1])) break; - if (k>0) { + if (k > 0) m[j].hi = k; - break; - } - if ((m[j].a == 0 || ends_line(af.list[m[j].a-1])) && - (m[j].b == 0 || ends_line(bf.list[m[j].b-1])) && - (m[j].c == 0 || ends_line(cf.list[m[j].c-1]))){ + else if ((m[j].a == 0 || ends_line(af.list[m[j].a-1])) && + (m[j].b == 0 || ends_line(bf.list[m[j].b-1])) && + (m[j].c == 0 || ends_line(cf.list[m[j].c-1]))) m[j].hi = 0; - break; + else + /* no start-of-line found... */ + m[j].hi = -1; + if (m[j].hi > 0 && m[j].type == Changed) { + /* this can only work if start is also a linke break */ + if ((m[j].a == 0 || ends_line(af.list[m[j].a-1])) && + (m[j].b == 0 || ends_line(bf.list[m[j].b-1])) && + (m[j].c == 0 || ends_line(cf.list[m[j].c-1]))) + /* ok */; + else + m[j].hi = -1; } - /* no start-of-line found... */ - m[j].hi = -1; + if (m[j].hi >= 0) + break; } } +#if 0 + if (j>=0 && m[j].in_conflict && m[j].type == Unchanged && + m[j].hi == m[j].lo) { + /* nothing to separate conflicts, merge them */ + m[j].lo = 0; + m[j].hi = -1; + cnt--; + } +#endif /* now the forward search */ for (j=i+1; m[j].type != End; j++) { m[j].in_conflict = 1; @@ -157,19 +188,29 @@ inline int isolate_conflicts(struct file af, struct file bf, struct file cf, */ if ((m[j].a == 0 || ends_line(af.list[m[j].a-1])) && (m[j].b == 0 || ends_line(bf.list[m[j].b-1])) && - (m[j].c == 0 || ends_line(cf.list[m[j].c-1]))){ + (m[j].c == 0 || ends_line(cf.list[m[j].c-1]))) m[j].lo = 0; - break; + else { + for (k = 0 ; k < m[j].al ; k++) + if (ends_line(af.list[m[j].a+k])) + break; + if (khi; + if (m->hi <= m->lo) + st = 0; if (m->type == Unchanged) printrange(out, a, m->a+m->lo, m->hi - m->lo); - else - printrange(out, c, m->c, m->cl); #if 1 if (v) @@ -366,7 +407,7 @@ struct ci print_merge2(FILE *out, struct file *a, struct file *b, struct file *c cm->b, cm->b+cm->bl-1, cm->c, cm->c+cm->cl-1, cm->in_conflict?" in_conflict":"", cm->lo, cm->hi); - if (cm->type == Unchanged && cm != m && cm->lo < cm->hi) + if ((cm->type == Unchanged ||cm->type == Changed) && cm != m && cm->lo < cm->hi) break; } #endif @@ -393,17 +434,19 @@ struct ci print_merge2(FILE *out, struct file *a, struct file *b, struct file *c fputs(words?"===":"=======\n", out); st = m->hi; for (cm=m; cm->in_conflict; cm++) { - if ((cm->type == Unchanged || cm->type == Changed) && cm != m && cm->lo < cm->hi) { - if (cm->type == Unchanged) - printrange(out, c, cm->c, cm->lo); + if (cm->type == Unchanged && cm != m && cm->lo < cm->hi) { + printrange(out, c, cm->c, cm->lo); break; } + if (cm->type == Changed) + st = 0; /* All of result of change must be printed */ printrange(out, c, cm->c+st, cm->cl-st); st = 0; } fputs(words?"--->>>":">>>>>>>\n", out); m = cm; - if (m->type == Unchanged && m->in_conflict && m->hi >= m->al) { + if (m->in_conflict && m->hi >= m->al) { + assert(m->type == Unchanged); printrange(out, a, m->a+m->lo, m->hi-m->lo); m++; } @@ -414,6 +457,21 @@ struct ci print_merge2(FILE *out, struct file *a, struct file *b, struct file *c */ if (m->type == End) break; +#if 1 + if (v) { + printf("<<%s: %d-%d,%d-%d,%d-%d%s(%d,%d)>>\n", + m->type==Unmatched?"Unmatched": + m->type==Unchanged?"Unchanged": + m->type==Extraneous?"Extraneous": + m->type==Changed?"Changed": + m->type==AlreadyApplied?"AlreadyApplied": + m->type==Conflict?"Conflict":"unknown", + m->a, m->a+m->al-1, + m->b, m->b+m->bl-1, + m->c, m->c+m->cl-1, m->in_conflict?" in_conflict":"", + m->lo, m->hi); + } +#endif switch(m->type) { case Unchanged: case AlreadyApplied: diff --git a/tests/linux/idmap.h/merge b/tests/linux/idmap.h/merge index 6bccf32..664ceea 100644 --- a/tests/linux/idmap.h/merge +++ b/tests/linux/idmap.h/merge @@ -1,2 +1,20 @@ +<<<<<<< +||||||| +*** 55,6 **** 1 +#define IDMAP_STATUS_LOOKUPFAIL IDMAP_STATUS_FAIL + + +/* XXX get (include) from bits/utmp.h */ +#define IDMAP_NAMESZ 128 + +======= +*** 55,8 **** 1 +#define IDMAP_STATUS_LOOKUPFAIL IDMAP_STATUS_FAIL + + #define IDMAP_MAXMSGSZ 256 +/* XXX get (include) from bits/utmp.h */ +#define IDMAP_NAMESZ 128 + +>>>>>>> diff --git a/tests/linux/md-resync/merge b/tests/linux/md-resync/merge index eb8379e..d6ff33e 100644 --- a/tests/linux/md-resync/merge +++ b/tests/linux/md-resync/merge @@ -1148,7 +1148,11 @@ abort: mempool_destroy(conf->r1buf_pool); conf->r1buf_pool = NULL; } + + print_conf(conf); ======= + + print_conf(conf); >>>>>>> return err; } @@ -1314,6 +1318,10 @@ static int init_resync (conf_t *conf) return -ENOMEM; <<<<<<< + close_sync(conf); + +} + /* * perform a "sync" on one "block" * @@ -1472,6 +1480,10 @@ static int raid1_sync_request (mddev_t *mddev, unsigned long sector_nr) return (bsize >> 9); ||||||| + close_sync(conf); + +} + static int init_resync(conf_t *conf) { *** 1170,9 **** 8 @@ -1485,6 +1497,19 @@ nomem: raid1_shrink_buffers(conf); return -ENOMEM; } +||||||| + if (!sector_nr) + if (init_resync(conf)) + return -ENOMEM; + /* +======= + if (sector_nr >= max_sector) { + close_sync(conf); + return 0; + } + + /* +>>>>>>> static void end_sync_read(struct buffer_head *bh, int uptodate) { @@ -1513,37 +1538,7 @@ 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); -||||||| - if (!sector_nr) - if (init_resync(conf)) - return -ENOMEM; - /* - * If there is non-resync activity waiting for us then - * put in a delay to throttle resync. -*** 1209,10 **** 9 - r1_bio->sector = sector_nr; - r1_bio->cmd = SPECIAL; - - max_sector = mddev->sb->size << 1; - if (sector_nr >= max_sector) - BUG(); - -======= - if (sector_nr >= max_sector) { - close_sync(conf); - return 0; - } - - /* - * If there is non-resync activity waiting for us then - * put in a delay to throttle resync. -*** 1190,6 **** 9 - r1_bio->sector = sector_nr; - r1_bio->cmd = SPECIAL; - ->>>>>>> - } + md_done_sync(mddev,size>>9, uptodate } } #define INVALID_LEVEL KERN_WARNING \ diff --git a/tests/linux/md/lmerge b/tests/linux/md/lmerge index 6440da9..4238601 100644 --- a/tests/linux/md/lmerge +++ b/tests/linux/md/lmerge @@ -1436,12 +1436,6 @@ abort: return 1; } -<<<<<<< -||||||| -#undef OLD_LEVEL - -======= ->>>>>>> static struct gendisk *md_probe(dev_t dev, int *part, void *data) { static DECLARE_MUTEX(disks_sem); diff --git a/tests/linux/md/merge b/tests/linux/md/merge index 6440da9..4238601 100644 --- a/tests/linux/md/merge +++ b/tests/linux/md/merge @@ -1436,12 +1436,6 @@ abort: return 1; } -<<<<<<< -||||||| -#undef OLD_LEVEL - -======= ->>>>>>> static struct gendisk *md_probe(dev_t dev, int *part, void *data) { static DECLARE_MUTEX(disks_sem); diff --git a/tests/linux/md/wmerge b/tests/linux/md/wmerge index 6aadb61..4238601 100644 --- a/tests/linux/md/wmerge +++ b/tests/linux/md/wmerge @@ -1436,9 +1436,7 @@ abort: return 1; } -<<<---|||#undef OLD_LEVEL - -===--->>>static struct gendisk *md_probe(dev_t dev, int *part, void *data) +static struct gendisk *md_probe(dev_t dev, int *part, void *data) { static DECLARE_MUTEX(disks_sem); int unit = MINOR(dev); diff --git a/tests/linux/raid5build/merge b/tests/linux/raid5build/merge index 4a2ce92..77cfac8 100644 --- a/tests/linux/raid5build/merge +++ b/tests/linux/raid5build/merge @@ -22,8 +22,12 @@ static void raid5_build_block (struct stripe_head *sh, int i) dev->flags = 0; if (i != sh->pd_idx) <<<<<<< + bh->b_size = sh->size; bh->b_list = BUF_LOCKED; + return bh; ||||||| + bh->b_size = sh->size; + return bh; ======= dev->sector = compute_blocknr(sh, i); >>>>>>> diff --git a/tests/linux/raid5line/lmerge b/tests/linux/raid5line/lmerge index e6ffa40..ee56bcb 100644 --- a/tests/linux/raid5line/lmerge +++ b/tests/linux/raid5line/lmerge @@ -1,7 +1,9 @@ <<<<<<< 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 e6ffa40..ee56bcb 100644 --- a/tests/linux/raid5line/merge +++ b/tests/linux/raid5line/merge @@ -1,7 +1,9 @@ <<<<<<< 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 e2c8104..a8464d9 100644 --- a/tests/linux/raid5line/wmerge +++ b/tests/linux/raid5line/wmerge @@ -1 +1,3 @@ -<<<--- clear_bit(BH_Uptodate, &|||clear_buffer_uptodate(===dev--->>>-><<<---->b_state|||===flags = 0--->>>; +<<<--- clear_bit(BH_Uptodate, &|||*** 1,1 **** 1 + clear_buffer_uptodate(===*** 1,1 **** 1 + dev--->>>-><<<---->b_state|||===flags = 0--->>>; diff --git a/tests/linux/rpc_tcp_nonagle/merge b/tests/linux/rpc_tcp_nonagle/merge index 969115a..c66c37a 100644 --- a/tests/linux/rpc_tcp_nonagle/merge +++ b/tests/linux/rpc_tcp_nonagle/merge @@ -1036,9 +1036,11 @@ svc_tcp_init(struct svc_sock *svsk) <<<<<<< /* initialise setting must have enough space to ||||||| + /* initialise setting must have enough space to ======= tp->nonagle = 1; /* disable Nagle's algorithm */ + /* initialise setting must have enough space to >>>>>>> * receive and respond to one request. * svc_tcp_recvfrom will re-adjust if necessary diff --git a/wiggle.h b/wiggle.h index 9cb2155..fd526c9 100644 --- a/wiggle.h +++ b/wiggle.h @@ -71,13 +71,36 @@ struct file { int elcnt; }; +/* The result of a merger is a series of text sections. + * Each section may occur in one or more of the three stream, + * and may be different in different stream (e.g. for changed text) + * or the same. + * When a conflict occurs we need to treat some surrouding + * sections as being involved in that conflict. For + * word-based merging, all surrounding sections until an Unchanged + * section are part of the conflict - the Unchanged isn't. + * For line based merging, we need to find Unchanged sections + * that include a newline. Further, text within the unchanged + * section upto the newline (in whichever direction) is treated + * as part of the whole conflict. + * Actually... it is possibly for a 'Changed' section to bound + * a conflict as it indicates a successful match of A and B. + * For wordwise merges, any Changed or Unchanged section bounds a conflict + * For linewise merges, and Changed or Unchanged section that matches + * a newline, or immediately follows a newline (in all files) can bound + * a conflict. + */ struct merge { enum mergetype {End, Unmatched, Unchanged, Extraneous, Changed, Conflict, AlreadyApplied} type; int a,b,c; /* start of ranges */ int al, bl, cl; /* length of ranges */ int c1, c2; /* this or next commonsequence */ int in_conflict; - int lo,hi; /* region of an Unchanged that is not involved in a conflict */ + int lo,hi; /* region of an Unchanged that is not involved in a conflict + * These are distances from start of the section, not + * indexes into any file + */ + }; extern struct stream load_file(char *name); extern int split_patch(struct stream, struct stream*, struct stream*); -- 2.39.5