merge3: make identical changes merge cleanly

when making the same change on both the left and
right fork, this should not be a merge conflict.
Instead, the two changes should merge cleanly.
This commit is contained in:
Ori Bernstein 2024-01-21 02:44:42 +00:00
parent 4364b71ccc
commit c59eb6d117
12 changed files with 137 additions and 20 deletions

View file

@ -57,6 +57,7 @@ extern int anychange;
extern Biobuf stdout;
#define MAXPATHLEN 1024
#define MAXLINELEN 4096
#define DIRECTORY(s) ((s)->qid.type&QTDIR)
#define REGULAR_FILE(s) ((s)->type == 'M' && !DIRECTORY(s))
@ -76,3 +77,4 @@ void change(Diff *, int, int, int, int);
void freediff(Diff *);
void flushchanges(Diff *);
void fetch(Diff *d, long *f, int a, int b, Biobuf *bp, char *s);
int readline(Biobuf*, char*, int);

View file

@ -4,17 +4,16 @@
#include <ctype.h>
#include "diff.h"
#define MAXLINELEN 4096
#define MIN(x, y) ((x) < (y) ? (x): (y))
static int
readline(Biobuf *bp, char *buf)
int
readline(Biobuf *bp, char *buf, int nbuf)
{
int c;
char *p, *e;
p = buf;
e = p + MAXLINELEN-1;
e = p + nbuf-1;
do {
c = Bgetc(bp);
if (c < 0) {
@ -44,7 +43,7 @@ readline(Biobuf *bp, char *buf)
* summing 1-s complement in 16-bit hunks
*/
static int
readhash(Biobuf *bp, char *buf)
readhash(Biobuf *bp, char *buf, int nbuf)
{
long sum;
unsigned shift;
@ -53,7 +52,7 @@ readhash(Biobuf *bp, char *buf)
sum = 1;
shift = 0;
if ((len = readline(bp, buf)) == -1)
if ((len = readline(bp, buf, nbuf)) == -1)
return 0;
p = buf;
switch(bflag) /* various types of white space handling */
@ -138,7 +137,7 @@ prepare(Diff *d, int i, char *arg, char *orig)
Bseek(bp, 0, 0);
}
p = emalloc(3*sizeof(Line));
for (j = 0; h = readhash(bp, buf); p[j].value = h)
for (j = 0; h = readhash(bp, buf, sizeof(buf)); p[j].value = h)
p = erealloc(p, (++j+3)*sizeof(Line));
d->len[i] = j;
d->file[i] = p;
@ -179,12 +178,12 @@ check(Diff *d, Biobuf *bf, Biobuf *bt)
d->ixold[0] = 0;
d->ixnew[0] = 0;
for (f = t = 1; f < d->len[0]; f++) {
flen = readline(bf, fbuf);
flen = readline(bf, fbuf, sizeof(fbuf));
d->ixold[f] = d->ixold[f-1] + flen; /* ftell(bf) */
if (d->J[f] == 0)
continue;
do {
tlen = readline(bt, tbuf);
tlen = readline(bt, tbuf, sizeof(tbuf));
d->ixnew[t] = d->ixnew[t-1] + tlen; /* ftell(bt) */
} while (t++ < d->J[f]);
if (bflag) {
@ -195,7 +194,7 @@ check(Diff *d, Biobuf *bf, Biobuf *bt)
d->J[f] = 0;
}
while (t < d->len[1]) {
tlen = readline(bt, tbuf);
tlen = readline(bt, tbuf, sizeof(tbuf));
d->ixnew[t] = d->ixnew[t-1] + tlen; /* fseek(bt) */
t++;
}
@ -227,7 +226,7 @@ fetch(Diff *d, long *f, int a, int b, Biobuf *bp, char *s)
return;
Bseek(bp, f[a-1], 0);
while (a++ <= b) {
len = readline(bp, buf);
len = readline(bp, buf, sizeof(buf));
if(len == 0 || buf[len-1] != '\n'){
Bprint(&stdout, "%s%s\n", s, buf);
Bprint(&stdout, "\\ No newline at end of file\n");

View file

@ -58,6 +58,33 @@ overlaps(int lx, int ly, int rx, int ry)
return ry >= lx;
}
static int
same(Diff *l, Change *lc, Diff *r, Change *rc)
{
char lbuf[MAXLINELEN], rbuf[MAXLINELEN];
int i, ll, rl, lx, ly, rx, ry;
lx = lc->newx;
ly = lc->newy;
rx = rc->newx;
ry = rc->newy;
if(ly - lx != ry - rx)
return 0;
assert(lx <= ly && ly < l->len[1]);
assert(rx <= ry && ry < r->len[1]);
Bseek(l->input[1], l->ixnew[lx-1], 0);
Bseek(r->input[1], r->ixnew[rx-1], 0);
for(i = 0; i <= (ly - lx); i++){
ll = readline(l->input[1], lbuf, sizeof(lbuf));
rl = readline(r->input[1], rbuf, sizeof(rbuf));
if(ll != rl)
return 0;
if(memcmp(lbuf, rbuf, ll) != 0)
return 0;
}
return 1;
}
char*
merge(Diff *l, Diff *r)
{
@ -116,6 +143,10 @@ merge(Diff *l, Diff *r)
lc->oldy += δ;
lc->newy += δ;
}
if(same(l, lc, r, rc)){
fetch(l, l->ixold, ln, x-1, l->input[0], "");
fetch(l, l->ixnew, lc->newx, lc->newy, l->input[1], "");
}else{
fetch(l, l->ixold, ln, x-1, l->input[0], "");
Bprint(&stdout, "<<<<<<<<<< %s\n", l->file2);
fetch(l, l->ixnew, lc->newx, lc->newy, l->input[1], "");
@ -124,6 +155,7 @@ merge(Diff *l, Diff *r)
Bprint(&stdout, "========== %s\n", r->file2);
fetch(r, r->ixnew, rc->newx, rc->newy, r->input[1], "");
Bprint(&stdout, ">>>>>>>>>>\n");
}
ln = y+1;
il++;
ir++;

View file

@ -0,0 +1,10 @@
1
2
3
4
5
6
7
8
9
10

View file

@ -0,0 +1,10 @@
1
2
3
4
y
6
7
8
9
10

View file

@ -0,0 +1,10 @@
1
2
3
4
y
6
7
8
9
10

View file

@ -0,0 +1,10 @@
1
2
3
4
y
6
7
8
9
10

View file

@ -0,0 +1,10 @@
1
2
3
4
5
6
7
8
9
10

View file

@ -0,0 +1,12 @@
A
1
2
3
4
y
6
7
8
9
10
Z

View file

@ -0,0 +1,12 @@
A
1
2
3
4
y
6
7
8
9
10
Z

View file

@ -0,0 +1,10 @@
1
2
3
4
y
6
7
8
9
10

View file

@ -1,6 +1,6 @@
#!/bin/rc
tests=`{seq 9}
tests=`{seq 11}
for(t in $tests){
echo ../$O.merge3 merge-t$t.l merge-t$t.c merge-t$t.r
../$O.merge3 merge-t$t.l merge-t$t.c merge-t$t.r > merge-t$t.out