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();