code: plan9front

Download patch

ref: c59eb6d117c6dc99bc6e4330d3a9a3453888dee7
parent: 4364b71cccf8353dc8f65a5e0db4041f6a0a1e53
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Jan 20 21:44:42 EST 2024

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.

--- a/sys/src/cmd/diff/diff.h
+++ b/sys/src/cmd/diff/diff.h
@@ -57,6 +57,7 @@
 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 freediff(Diff *);
 void flushchanges(Diff *);
 void fetch(Diff *d, long *f, int a, int b, Biobuf *bp, char *s);
+int readline(Biobuf*, char*, int);
--- a/sys/src/cmd/diff/diffio.c
+++ b/sys/src/cmd/diff/diffio.c
@@ -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 @@
  * 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 @@
 
 	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 @@
 		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 @@
 	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 @@
 			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 @@
 		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");
--- a/sys/src/cmd/diff/merge3.c
+++ b/sys/src/cmd/diff/merge3.c
@@ -58,6 +58,33 @@
 		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,14 +143,19 @@
 				lc->oldy += δ;
 				lc->newy += δ;
 			}
-			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], "");
-			Bprint(&stdout, "========== original\n");
-			fetch(l, l->ixold, x, y, l->input[0], "");
-			Bprint(&stdout, "========== %s\n", r->file2);
-			fetch(r, r->ixnew, rc->newx, rc->newy, r->input[1], "");
-			Bprint(&stdout, ">>>>>>>>>>\n");
+			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], "");
+				Bprint(&stdout, "========== original\n");
+				fetch(l, l->ixold, x, y, l->input[0], "");
+				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++;
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t10.c
@@ -1,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t10.expected
@@ -1,0 +1,10 @@
+1
+2
+3
+4
+y
+6
+7
+8
+9
+10
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t10.l
@@ -1,0 +1,10 @@
+1
+2
+3
+4
+y
+6
+7
+8
+9
+10
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t10.r
@@ -1,0 +1,10 @@
+1
+2
+3
+4
+y
+6
+7
+8
+9
+10
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t11.c
@@ -1,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t11.expected
@@ -1,0 +1,12 @@
+A
+1
+2
+3
+4
+y
+6
+7
+8
+9
+10
+Z
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t11.l
@@ -1,0 +1,12 @@
+A
+1
+2
+3
+4
+y
+6
+7
+8
+9
+10
+Z
--- /dev/null
+++ b/sys/src/cmd/diff/test/merge-t11.r
@@ -1,0 +1,10 @@
+1
+2
+3
+4
+y
+6
+7
+8
+9
+10
--- a/sys/src/cmd/diff/test/merge.rc
+++ b/sys/src/cmd/diff/test/merge.rc
@@ -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