* 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;
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;
* 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;
*/
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 (k<m[j].al)
+ m[j].lo = k+1;
+ else
+ /* no start-of-line found */
+ m[j].lo = m[j].al+1;
}
- for (k=0; k<m[j].al; k++)
- if (ends_line(af.list[m[j].a+k]))
- break;
- if (k<m[j].al) {
- m[j].lo = k+1;
- break;
+ if (m[j].lo <= m[j].al+1 && m[j].type == Changed) {
+ /* this can only work if the end is a line break */
+ if (ends_line(af.list[m[j].a+m[j].al-1]) &&
+ ends_line(bf.list[m[j].b+m[j].bl-1]) &&
+ ends_line(cf.list[m[j].c+m[j].cl-1]))
+ /* ok */;
+ else
+ m[j].lo = m[j].al+1;
}
- /* no start-of-line found */
- m[j].lo = m[j].al+1;
+ if (m[j].lo < m[j].al+1)
+ break;
}
}
i = j;
* Unchanged which is < it's hi
*/
int st = m->hi;
+ 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)
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
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++;
}
*/
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:
mempool_destroy(conf->r1buf_pool);
conf->r1buf_pool = NULL;
}
+
+ print_conf(conf);
=======
+
+ print_conf(conf);
>>>>>>>
return err;
}
return -ENOMEM;
<<<<<<<
+ close_sync(conf);
+
+}
+
/*
* perform a "sync" on one "block"
*
return (bsize >> 9);
|||||||
+ close_sync(conf);
+
+}
+
static int init_resync(conf_t *conf)
{
*** 1170,9 **** 8
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)
{
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 \
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*);