aboutsummaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorTom Jones <thj@FreeBSD.org>2022-04-19 15:20:24 +0000
committerTom Jones <thj@FreeBSD.org>2022-04-19 15:20:24 +0000
commit034dd2d54f2e7e33897cfd5ede7c50b3d67d18d3 (patch)
tree31cd37cadc9fc1776bcc9ea4dab98ee6c10b6509 /usr.bin
parentf45f90c5d6f0f0d53998476281d42d857adf98c7 (diff)
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/diff3/diff3.14
-rw-r--r--usr.bin/diff3/diff3.c85
-rw-r--r--usr.bin/diff3/tests/Makefile3
-rwxr-xr-xusr.bin/diff3/tests/diff3_test.sh13
-rw-r--r--usr.bin/diff3/tests/long-merge.out35
5 files changed, 137 insertions, 3 deletions
diff --git a/usr.bin/diff3/diff3.1 b/usr.bin/diff3/diff3.1
index f0fd481c75f1..6968af44bfbd 100644
--- a/usr.bin/diff3/diff3.1
+++ b/usr.bin/diff3/diff3.1
@@ -38,7 +38,7 @@
.Nd 3-way differential file comparison
.Sh SYNOPSIS
.Nm diff3
-.Op Fl 3AaEeiTXx
+.Op Fl 3AaEeimTXx
.Op Fl Fl diff-program Ar program
.Op Fl Fl strip-trailing-cr
.Op Fl L | Fl Fl label Ar label1
@@ -117,6 +117,8 @@ Defines labels to print instead of file names
.Ar file2
and
.Ar file3 .
+.It Fl m, Fl Fl merge
+Merge output instead of generating ed script.
.It Fl T, Fl Fl initial-tab
In the normal listing,
use a tab instead of two spaces
diff --git a/usr.bin/diff3/diff3.c b/usr.bin/diff3/diff3.c
index 5df6357065fc..629e23288875 100644
--- a/usr.bin/diff3/diff3.c
+++ b/usr.bin/diff3/diff3.c
@@ -153,6 +153,7 @@ static void prange(struct range *, bool);
static void repos(int);
static void edscript(int) __dead2;
static void Ascript(int) __dead2;
+static void mergescript(int) __dead2;
static void increase(void);
static void usage(void) __dead2;
static void printrange(FILE *, struct range *);
@@ -389,7 +390,9 @@ merge(int m1, int m2)
}
}
- if (Aflag)
+ if (mflag)
+ mergescript(j);
+ else if (Aflag)
Ascript(j);
else if (eflag)
edscript(j);
@@ -687,6 +690,86 @@ Ascript(int n)
exit(overlapcnt > 0);
}
+/*
+ * Output the merged file directly (don't generate an ed script). When
+ * regurgitating diffs we need to walk forward through the file and print any
+ * inbetween lines.
+ */
+static void
+mergescript(int i)
+{
+ struct range r;
+ int n;
+
+ r.from = 1;
+ r.to = 1;
+
+ for (n = 1; n < i+1; n++) {
+ /* print any lines leading up to here */
+ r.to = de[n].old.from;
+ printrange(fp[0], &r);
+
+ if (de[n].type == DIFF_TYPE2) {
+ printf("%s %s\n", oldmark, f2mark);
+ printrange(fp[1], &de[n].old);
+ printf("=======\n");
+ printrange(fp[2], &de[n].new);
+ printf("%s %s\n", newmark, f3mark);
+ } else if (de[n].type == DIFF_TYPE3) {
+ if (!oflag || !overlap[n]) {
+ printrange(fp[2], &de[n].new);
+ } else {
+
+ printf("%s %s\n", oldmark, f1mark);
+ printrange(fp[0], &de[n].old);
+
+ printf("%s %s\n", orgmark, f2mark);
+ if (de[n].old.from == de[n].old.to) {
+ struct range or;
+ or.from = de[n].old.from -1;
+ or.to = de[n].new.to;
+ printrange(fp[1], &or);
+ } else
+ printrange(fp[1], &de[n].old);
+
+ printf("=======\n");
+
+ printrange(fp[2], &de[n].new);
+ printf("%s %s\n", newmark, f3mark);
+ }
+ }
+
+ if (de[n].old.from == de[n].old.to)
+ r.from = de[n].new.to;
+ else
+ r.from = de[n].old.to;
+ }
+ /*
+ * Print from the final range to the end of 'myfile'. Any deletions or
+ * additions to this file should have been handled by now.
+ *
+ * If the ranges are the same we need to rewind a line.
+ * If the new range is 0 length (from == to), we need to use the old
+ * range.
+ */
+ if ((de[n-1].old.from == de[n-1].new.from) &&
+ (de[n-1].old.to == de[n-1].new.to))
+ r.from--;
+ else if (de[n-1].new.from == de[n-1].new.to)
+ r.from = de[n-1].old.from;
+
+ /*
+ * If the range is a 3 way merge then we need to skip a line in the
+ * trailing output.
+ */
+ if (de[n-1].type == DIFF_TYPE3)
+ r.from++;
+
+ r.to = INT_MAX;
+ printrange(fp[0], &r);
+ exit(overlapcnt > 0);
+}
+
static void
increase(void)
{
diff --git a/usr.bin/diff3/tests/Makefile b/usr.bin/diff3/tests/Makefile
index fc69dea260e8..0785e78aaee3 100644
--- a/usr.bin/diff3/tests/Makefile
+++ b/usr.bin/diff3/tests/Makefile
@@ -22,6 +22,7 @@ ${PACKAGE}FILES+= \
8.out \
9.out \
long-ed.out \
- long-A.out
+ long-A.out \
+ long-merge.out \
.include <bsd.test.mk>
diff --git a/usr.bin/diff3/tests/diff3_test.sh b/usr.bin/diff3/tests/diff3_test.sh
index 8df84b0d8ff2..c30f258128af 100755
--- a/usr.bin/diff3/tests/diff3_test.sh
+++ b/usr.bin/diff3/tests/diff3_test.sh
@@ -4,6 +4,7 @@ atf_test_case diff3
atf_test_case diff3_lesssimple
atf_test_case diff3_ed
atf_test_case diff3_A
+atf_test_case diff3_merge
diff3_body()
{
@@ -56,10 +57,22 @@ diff3_A_body()
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
}
+
+diff3_merge_body()
+{
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/9.out \
+ diff3 -m -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)/tao-merge.out \
+ diff3 -m -L lao.txt -L tzu.txt -L tao.txt $(atf_get_srcdir)/lao.txt $(atf_get_srcdir)/tzu.txt $(atf_get_srcdir)/tao.txt
+ atf_check -s exit:1 -o file:$(atf_get_srcdir)/long-merge.out \
+ diff3 -m -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
+ atf_add_test_case diff3_merge
}
diff --git a/usr.bin/diff3/tests/long-merge.out b/usr.bin/diff3/tests/long-merge.out
new file mode 100644
index 000000000000..5139a48fa429
--- /dev/null
+++ b/usr.bin/diff3/tests/long-merge.out
@@ -0,0 +1,35 @@
+This is a long file
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in mine, not better
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+This line is different in yours, much butter
+These lines are the same in all three files
+These lines are the same in all three files
+<<<<<<< long-o.txt
+This line is different in yours and mine, but the same
+=======
+This line is different in yours and mine, the same is in both
+>>>>>>> long-y.txt
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+<<<<<<< long-m.txt
+This line is different in yours and mine, best change in mine
+||||||| 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
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files
+These lines are the same in all three files