From nobody Tue Apr 19 14:55:06 2022 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id AE28511D10A3; Tue, 19 Apr 2022 14:55:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4KjRfy4RrZz4sr4; Tue, 19 Apr 2022 14:55:06 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650380106; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=9VAfA9UwdkK5a/bH4KkylCYSem/KbaluG9FZY2NTQHA=; b=QR3OYPPmijLZMIMAvQ/EzmLSavsddX7XK5zX7vMLQ1Qg904ZX2PNOvFJDqoaX1IM5LBE2v PxkPs77b4j55Y8rGJvU0oKxHh0cGg0EtIpL3iXj3Ry4qBWuEPlgDcdTnm662BvmGc3ZpE4 0ZT34J1krDRLLrMtaBf5br8XCXhz+w8/R1gVfyUg5dK0UiFNZu+zG3EQD22QHxjotblvVq Crd5752VW7NAJMarMfJOqCB1AE7yOI2MeSgqZGGhpoikxMV+H9PSZan+ZQWC5vIFIqUeQg ZvcxVONsnM2Eanox0MBkObpYoJMnq8n6yah2Z4eoL0gWUfjlUkySLYgLjLfJJg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 77FDC2978F; Tue, 19 Apr 2022 14:55:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 23JEt62K006430; Tue, 19 Apr 2022 14:55:06 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 23JEt6Ad006429; Tue, 19 Apr 2022 14:55:06 GMT (envelope-from git) Date: Tue, 19 Apr 2022 14:55:06 GMT Message-Id: <202204191455.23JEt6Ad006429@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Tom Jones Subject: git: 9ab079c5e810 - main - diff3: Add support for -A List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: thj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 9ab079c5e81098c81e8b25f26a3b56392eac5463 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1650380106; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=9VAfA9UwdkK5a/bH4KkylCYSem/KbaluG9FZY2NTQHA=; b=UEQjBEaTsALTUVzSz0XfxP5vhhqFLyevy6NojYxx2jY0R6gY0Zw5KOMhJpERLC0/VbQyJO DfQ+XQDzWaVcSOdU7x8ofVctu4EAqzk1JYbBTL2E0EtWwHN3D26P2nvQ3JV5QoG8Dhr9Vn dCUljCuj1STtItwI1cjFLUyE5eg0Xv6ny4jm4W98MCwvE19gUb/aUJ3g/z+eooKvFu814Z aQU0cIyUfUaXbTAIXNhdGsegofo1f5H7HY181Hwa5FmXqMjAL9IyCojWgQFRZ6dyd0uea2 UlF6PKXtRCTgNuptuMQOR1VvvqYX7P9FjiF/SzLHrpgawh5KOaUxlPXjXZ6psg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1650380106; a=rsa-sha256; cv=none; b=DQ+XUSqXbZuu9ce0mxkNgbW20LukX1XwEynkK2RxSYyX8jYfSBmBw5jQJiJHpFY6gxQolI 93l8GeeCflUAkZSD0KH+M6DLw1scBHOT1hT1xAyed2VOhpvfhXOOk25XFED8/A0mGirmlp /m3kmm6ASQhKRmb09XKO+WpTlWDsS2v/2nKIDA0IKWuDo4xJY8P72zF7jPabi0uIWbhcO6 6Kpv1PXMse7OhtK6cCbwxfAbZ370XLEIMrPwb+a306GhrTHDSdqr8R1qQBjLEBVQSE9ruY u20QuQFLhl8alCyk7gEPACWypw4z/ULrMOP3CxLLf++oMipVv8farkzveEC/Vw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by thj: URL: https://cgit.FreeBSD.org/src/commit/?id=9ab079c5e81098c81e8b25f26a3b56392eac5463 commit 9ab079c5e81098c81e8b25f26a3b56392eac5463 Author: Tom Jones AuthorDate: 2022-04-19 14:43:35 +0000 Commit: Tom Jones CommitDate: 2022-04-19 14:54:32 +0000 diff3: Add support for -A Diff3 in -A mode generates an ed script to show how the 3 files and brackets changes that conflict. The ed script generated should when applied leave familiar merge conflict markers in a patched file. Diff3 output is not documented, this feature has been arrived at by comparing bsd diff3 output to gnu diff3 output until they were made to agree. There are likely to still be differences between these formats. The gnu diff3 guide is actually quite good at explaining how diff3 output should appear, but it doesn't cover every form of output from diff3. https://www.gnu.org/software/diffutils/manual/diffutils.html#Comparing-Three-Files Discussed with: pstef, kevans Sponsored by: Klara, Inc. --- usr.bin/diff3/diff3.1 | 6 +- usr.bin/diff3/diff3.c | 123 ++++++++++++++++++++++++++++++++++++-- usr.bin/diff3/tests/Makefile | 3 +- usr.bin/diff3/tests/diff3_test.sh | 11 ++++ usr.bin/diff3/tests/long-A.out | 22 +++++++ 5 files changed, 157 insertions(+), 8 deletions(-) diff --git a/usr.bin/diff3/diff3.1 b/usr.bin/diff3/diff3.1 index 2cf1e57cb74e..f0fd481c75f1 100644 --- a/usr.bin/diff3/diff3.1 +++ b/usr.bin/diff3/diff3.1 @@ -30,7 +30,7 @@ .\" @(#)diff3.1 8.2 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd August 23, 2021 +.Dd April 19, 2022 .Dt DIFF3 1 .Os .Sh NAME @@ -38,7 +38,7 @@ .Nd 3-way differential file comparison .Sh SYNOPSIS .Nm diff3 -.Op Fl 3aEeiTXx +.Op Fl 3AaEeiTXx .Op Fl Fl diff-program Ar program .Op Fl Fl strip-trailing-cr .Op Fl L | Fl Fl label Ar label1 @@ -71,6 +71,8 @@ Produces an output script suitable for with changes specific only to .Ar file3 . +.It Fl A Fl Fl show-all +Output all changes, bracketing conflicts. .It Fl a , Fl Fl text Treat all files as ASCII. .It Fl E , Fl Fl show-overlap diff --git a/usr.bin/diff3/diff3.c b/usr.bin/diff3/diff3.c index 97fccc739ebe..5df6357065fc 100644 --- a/usr.bin/diff3/diff3.c +++ b/usr.bin/diff3/diff3.c @@ -100,6 +100,14 @@ struct range { }; struct diff { +#define DIFF_TYPE2 2 +#define DIFF_TYPE3 3 + int type; +#if DEBUG + char *line; +#endif /* DEBUG */ + + /* Ranges as lines */ struct range old; struct range new; }; @@ -129,10 +137,11 @@ static int oflag; /* indicates whether to mark overlaps (-E or -X) */ static int strip_cr; static char *f1mark, *f2mark, *f3mark; static const char *oldmark = "<<<<<<<"; +static const char *orgmark = "|||||||"; static const char *newmark = ">>>>>>>"; static bool duplicate(struct range *, struct range *); -static int edit(struct diff *, bool, int); +static int edit(struct diff *, bool, int, int); static char *getchange(FILE *); static char *get_line(FILE *, size_t *); static int readin(int fd, struct diff **); @@ -143,6 +152,7 @@ static void merge(int, int); static void prange(struct range *, bool); static void repos(int); static void edscript(int) __dead2; +static void Ascript(int) __dead2; static void increase(void); static void usage(void) __dead2; static void printrange(FILE *, struct range *); @@ -189,6 +199,10 @@ readin(int fd, struct diff **dd) if (f == NULL) err(2, "fdopen"); for (i = 0; (p = getchange(f)); i++) { +#if DEBUG + (*dd)[i].line = strdup(p); +#endif /* DEBUG */ + if (i >= szchanges - 1) increase(); a = b = (int)strtoimax(p, &p, 10); @@ -309,6 +323,9 @@ merge(int m1, int m2) keep(1, &d2->new); change(3, &d2->new, false); change(2, &d2->old, false); + } else if (Aflag || mflag) { + // XXX-THJ: What does it mean for the second file to differ? + j = edit(d2, dup, j, DIFF_TYPE2); } d2++; continue; @@ -344,8 +361,10 @@ merge(int m1, int m2) change(2, &d2->old, false); d3 = d1->old.to > d1->old.from ? d1 : d2; change(3, &d3->new, false); - } else - j = edit(d1, dup, j); + } else { + j = edit(d1, dup, j, DIFF_TYPE3); + } + dup = false; d1++; d2++; continue; @@ -369,7 +388,10 @@ merge(int m1, int m2) d1->new.to = d2->new.to; } } - if (eflag) + + if (Aflag) + Ascript(j); + else if (eflag) edscript(j); } @@ -498,7 +520,7 @@ repos(int nchar) * collect an editing script for later regurgitation */ static int -edit(struct diff *diff, bool dup, int j) +edit(struct diff *diff, bool dup, int j, int difftype) { if (((dup + 1) & eflag) == 0) @@ -507,6 +529,12 @@ edit(struct diff *diff, bool dup, int j) overlap[j] = !dup; if (!dup) overlapcnt++; + + de[j].type = difftype; +#if DEBUG + de[j].line = diff->line; +#endif /* DEBUG */ + de[j].old.from = diff->old.from; de[j].old.to = diff->old.to; de[j].new.from = diff->new.from; @@ -574,6 +602,91 @@ edscript(int n) exit(eflag == 0 ? overlapcnt : 0); } +/* + * Output an edit script to turn mine into yours, when there is a conflict + * between the 3 files bracket the changes. Regurgitate the diffs in reverse + * order to allow the ed script to track down where the lines are as changes + * are made. + */ +static void +Ascript(int n) +{ + int startmark; + bool deletenew; + bool deleteold; + + for (; n > 0; n--) { + + deletenew = (de[n].new.from == de[n].new.to); + deleteold = (de[n].old.from == de[n].old.to); + startmark = de[n].old.from + (de[n].old.to - de[n].old.from) - 1; + + if (de[n].type == DIFF_TYPE2) { + if (!oflag || !overlap[n]) { + prange(&de[n].old, deletenew); + printrange(fp[2], &de[n].new); + } else { + startmark = de[n].new.from + + (de[n].new.to - de[n].new.from); + + if (!deletenew) + startmark--; + + printf("%da\n", startmark); + printf("%s %s\n", newmark, f3mark); + + printf(".\n"); + + printf("%da\n", startmark - + (de[n].new.to - de[n].new.from)); + printf("%s %s\n", oldmark, f2mark); + if (!deleteold) + printrange(fp[1], &de[n].old); + printf("=======\n.\n"); + } + + } else if (de[n].type == DIFF_TYPE3) { + if (!oflag || !overlap[n]) { + prange(&de[n].old, deletenew); + printrange(fp[2], &de[n].new); + } else { + printf("%da\n", startmark); + printf("%s %s\n", orgmark, f2mark); + + if (deleteold) { + struct range r; + r.from = de[n].old.from-1; + r.to = de[n].new.to; + printrange(fp[1], &r); + } else + printrange(fp[1], &de[n].old); + + printf("=======\n"); + printrange(fp[2], &de[n].new); + } + + if (!oflag || !overlap[n]) { + if (!deletenew) + printf(".\n"); + } else { + printf("%s %s\n.\n", newmark, f3mark); + + /* + * Go to the start of the conflict in original + * file and append lines + */ + printf("%da\n%s %s\n.\n", + startmark - (de[n].old.to - de[n].old.from), + oldmark, f1mark); + } + } + } + if (iflag) + printf("w\nq\n"); + + exit(overlapcnt > 0); +} + static void increase(void) { diff --git a/usr.bin/diff3/tests/Makefile b/usr.bin/diff3/tests/Makefile index 91af4d1a6237..fc69dea260e8 100644 --- a/usr.bin/diff3/tests/Makefile +++ b/usr.bin/diff3/tests/Makefile @@ -21,6 +21,7 @@ ${PACKAGE}FILES+= \ 7.out \ 8.out \ 9.out \ - long-ed.out + long-ed.out \ + long-A.out .include diff --git a/usr.bin/diff3/tests/diff3_test.sh b/usr.bin/diff3/tests/diff3_test.sh index 0eb08f46a803..8df84b0d8ff2 100755 --- a/usr.bin/diff3/tests/diff3_test.sh +++ b/usr.bin/diff3/tests/diff3_test.sh @@ -3,6 +3,7 @@ atf_test_case diff3 atf_test_case diff3_lesssimple atf_test_case diff3_ed +atf_test_case diff3_A diff3_body() { @@ -46,9 +47,19 @@ diff3_ed_body() diff3 -e $(atf_get_srcdir)/long-m.txt $(atf_get_srcdir)/long-o.txt $(atf_get_srcdir)/long-y.txt } +diff3_A_body() +{ + atf_check -s exit:1 -o file:$(atf_get_srcdir)/8.out \ + diff3 -A -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt + + atf_check -s exit:1 -o file:$(atf_get_srcdir)/long-A.out \ + diff3 -A -L long-m.txt -L long-o.txt -L long-y.txt $(atf_get_srcdir)/long-m.txt $(atf_get_srcdir)/long-o.txt $(atf_get_srcdir)/long-y.txt +} + atf_init_test_cases() { atf_add_test_case diff3 # atf_add_test_case diff3_lesssimple atf_add_test_case diff3_ed + atf_add_test_case diff3_A } diff --git a/usr.bin/diff3/tests/long-A.out b/usr.bin/diff3/tests/long-A.out new file mode 100644 index 000000000000..2a2e4cbb112d --- /dev/null +++ b/usr.bin/diff3/tests/long-A.out @@ -0,0 +1,22 @@ +24d +16a +||||||| long-o.txt +This line is different in yours and mine, but the different in each +======= +This line is different in yours and mine, but the best in yours +>>>>>>> long-y.txt +. +15a +<<<<<<< long-m.txt +. +11a +>>>>>>> long-y.txt +. +10a +<<<<<<< long-o.txt +This line is different in yours and mine, but the same +======= +. +8c +This line is different in yours, much butter +.