shithub: riscv

Download patch

ref: 9e79d829051878f0f55a9836306ba206a264d5a8
parent: e0d12942e02b841d095c9b0a8ddb56c788a748b5
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Sep 10 19:46:55 EDT 2023

merge3: handle edge cases where we remove lines

--- a/sys/src/cmd/diff/diff.h
+++ b/sys/src/cmd/diff/diff.h
@@ -16,10 +16,10 @@
 
 struct Change
 {
-	int a;
-	int b;
-	int c;
-	int d;
+	int oldx;
+	int oldy;
+	int newx;
+	int newy;
 };
 
 struct Diff {
--- a/sys/src/cmd/diff/diffio.c
+++ b/sys/src/cmd/diff/diffio.c
@@ -130,7 +130,7 @@
 			 * brave new UNICODE world
 			 */
 			cp += chartorune(&r, cp);
-			if(r == 0 || r == Runeerror){
+			if (r == 0 || (r > 0x7f && r <= 0xa0)) {
 				d->binary++;
 				return bp;
 			}
@@ -283,10 +283,10 @@
 		if(df->nchanges%1024 == 0)
 			df->changes = erealloc(df->changes, (df->nchanges+1024)*sizeof(df->changes[0]));
 		ch = &df->changes[df->nchanges++];
-		ch->a = a;
-		ch->b = b;
-		ch->c = c;
-		ch->d = d;
+		ch->oldx = a;
+		ch->oldy = b;
+		ch->newx = c;
+		ch->newy = d;
 		return;
 	}
 	Bputc(&stdout, '\n');
@@ -308,7 +308,7 @@
 int
 changeset(Diff *d, int i)
 {
-	while(i < d->nchanges && d->changes[i].b + 1 + 2*Lines > d->changes[i+1].a)
+	while(i < d->nchanges && d->changes[i].oldy + 1 + 2*Lines > d->changes[i+1].oldx)
 		i++;
 	if(i < d->nchanges)
 		return i+1;
@@ -327,10 +327,10 @@
 	hdr = 0;
 	for(i=0; i < df->nchanges; ){
 		j = changeset(df, i);
-		a = df->changes[i].a - Lines;
-		b = df->changes[j-1].b + Lines;
-		c = df->changes[i].c - Lines;
-		d = df->changes[j-1].d + Lines;
+		a = df->changes[i].oldx - Lines;
+		b = df->changes[j-1].oldy + Lines;
+		c = df->changes[i].newx - Lines;
+		d = df->changes[j-1].newy + Lines;
 		if(a < 1)
 			a = 1;
 		if(c < 1)
@@ -363,10 +363,10 @@
 		}
 		at = a;
 		for(; i<j; i++){
-			fetch(df, df->ixold, at, df->changes[i].a-1, df->input[0], mode == 'u' ? " " : "  ");
-			fetch(df, df->ixold, df->changes[i].a, df->changes[i].b, df->input[0], mode == 'u' ? "-" : "- ");
-			fetch(df, df->ixnew, df->changes[i].c, df->changes[i].d, df->input[1], mode == 'u' ? "+" : "+ ");
-			at = df->changes[i].b+1;
+			fetch(df, df->ixold, at, df->changes[i].oldx-1, df->input[0], mode == 'u' ? " " : "  ");
+			fetch(df, df->ixold, df->changes[i].oldx, df->changes[i].oldy, df->input[0], mode == 'u' ? "-" : "- ");
+			fetch(df, df->ixnew, df->changes[i].newx, df->changes[i].newy, df->input[1], mode == 'u' ? "+" : "+ ");
+			at = df->changes[i].oldy+1;
 		}
 		fetch(df, df->ixold, at, b, df->input[0], mode == 'u' ? " " : "  ");
 	}
--- a/sys/src/cmd/diff/merge3.c
+++ b/sys/src/cmd/diff/merge3.c
@@ -6,7 +6,7 @@
 static int
 changecmp(void *a, void *b)
 {
-	return ((Change*)a)->a - ((Change*)b)->a;
+	return ((Change*)a)->oldx - ((Change*)b)->oldx;
 }
 
 static void
@@ -19,10 +19,10 @@
 	if(df->nchanges%1024 == 0)
 		df->changes = erealloc(df->changes, (df->nchanges+1024)*sizeof(df->changes[0]));
 	ch = &df->changes[df->nchanges++];
-	ch->a = a;
-	ch->b = b;
-	ch->c = c;
-	ch->d = d;
+	ch->oldx = a;
+	ch->oldy = b;
+	ch->newx = c;
+	ch->newy = d;
 }
 
 static void
@@ -50,19 +50,18 @@
 }
 
 static int
-overlaps(Change *l, Change *r)
+overlaps(int lx, int ly, int rx, int ry)
 {
-	if(l == nil || r == nil)
-		return 0;
-	if(l->c <= r->c)
-		return l->d >= r->c;
+	if(lx <= rx)
+		return ly >= rx;
 	else
-		return r->d >= l->c;
+		return ry >= lx;
 }
 
 char*
 merge(Diff *l, Diff *r)
 {
+	int lx, ly, rx, ry;
 	int il, ir, x, y, δ;
 	Change *lc, *rc;
 	char *status;
@@ -77,57 +76,68 @@
 	while(il < l->nchanges || ir < r->nchanges){
 		lc = nil;
 		rc = nil;
-		if(il < l->nchanges)
+		lx = -1;
+		ly = -1;
+		rx = -1;
+		ry = -1;
+		if(il < l->nchanges){
 			lc = &l->changes[il];
-		if(ir < r->nchanges)
+			lx = (lc->oldx < lc->oldy) ? lc->oldx : lc->oldy;
+			ly = (lc->oldx < lc->oldy) ? lc->oldy : lc->oldx;
+		}
+		if(ir < r->nchanges){
 			rc = &r->changes[ir];
-		if(overlaps(lc, rc)){
+			rx = (rc->oldx < rc->oldy) ? rc->oldx : rc->oldy;
+			ry = (rc->oldx < rc->oldy) ? rc->oldy : rc->oldx;
+		}
+		if(l != nil && r != nil && overlaps(lx, ly, rx, ry)){
 			/*
 			 * align the edges of the chunks
 			 */
-			if(lc->a < rc->a){
-				x = lc->c;
-				δ = rc->a - lc->a;
-				rc->a -= δ;
-				rc->c -= δ;
+			if(lc->oldx < rc->oldx){
+				x = lc->newx;
+				δ = rc->oldx - lc->oldx;
+				rc->oldx -= δ;
+				rc->newx -= δ;
 			}else{
-				x = rc->c;
-				δ = lc->a - rc->a;
-				lc->a -= δ;
-				lc->c -= δ;
+				x = rc->newx;
+				δ = lc->oldx - rc->oldx;
+				lc->oldx -= δ;
+				lc->newx -= δ;
 			}
-			if(lc->b > rc->b){
-				y = lc->d;
-				δ = lc->b - rc->b;
-				rc->b += δ;
-				rc->d += δ;
+			if(lc->oldy > rc->oldy){
+				y = lc->newy;
+				δ = lc->oldy - rc->oldy;
+				rc->oldy += δ;
+				rc->newy += δ;
 			}else{
-				y = rc->d;
-				δ = rc->b - lc->b;
-				lc->b += δ;
-				lc->d += δ;
+				y = rc->newy;
+				δ = rc->oldy - lc->oldy;
+				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->c, lc->d, l->input[1], "");
+			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->c, rc->d, r->input[1], "");
+			fetch(r, r->ixnew, rc->newx, rc->newy, r->input[1], "");
 			Bprint(&stdout, ">>>>>>>>>>\n");
 			ln = y+1;
 			il++;
 			ir++;
 			status = "conflict";
-		}else if(rc == nil || (lc != nil && lc->a < rc->a)){
-			fetch(l, l->ixold, ln, lc->a-1, l->input[0], "");
-			fetch(l, l->ixnew, lc->c, lc->d, l->input[1], "");
-			ln = lc->b+1;
+abort();
+		}else if(rc == nil || (lc != nil && lx < rx)){
+			fetch(l, l->ixold, ln, lc->oldx-1, l->input[0], "");
+			fetch(l, l->ixnew, lc->newx, lc->newy, l->input[1], "");
+			ln = lc->oldy+1;
 			il++;
-		}else if(lc == nil || (rc != nil && rc->a < lc->a)){
-			fetch(l, l->ixold, ln, rc->a-1, l->input[0], "");
-			fetch(r, r->ixnew, rc->c, rc->d, r->input[1], "");
-			ln = rc->b+1;
+		}else if(lc == nil || (rc != nil && rx < lx)){
+			fetch(l, l->ixold, ln, rc->oldx-1, l->input[0], "");
+			fetch(r, r->ixnew, rc->newx, rc->newy, r->input[1], "");
+			ln = rc->oldy+1;
 			ir++;
 		}else
 			abort();