shithub: riscv

Download patch

ref: 8fe1d622b5b46dee51db6581282ec1fba76782b1
parent: aa7c8cac1145d0cd6e9117deaa1f8c9f418bca17
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Sep 21 05:40:42 EDT 2020

diff: support unified diff via -u

The format produced by `diff -u` is inferior to that
produced by `diff -c`, but it's what ape/patch and
unix patch expect, so it's useful to generate it.

This patch adds `diff -u`.

--- a/sys/man/1/diff
+++ b/sys/man/1/diff
@@ -4,7 +4,7 @@
 .SH SYNOPSIS
 .B diff
 [
-.B -abcefmnrw
+.B -abcefmnruw
 ] 
 .I file1 ... file2
 .SH DESCRIPTION
@@ -142,6 +142,24 @@
 The
 .B -a
 flag displays the entire file as context.
+.PP
+The
+.B -u
+option provides a unix-compatible unified diff.
+This format is similar to that provided by
+.BR -c .
+However, the
+.L +
+and
+.L -
+prefixes are not separated from the rest of the line by spaces,
+and the file header is in the following format:
+.IP
+.EX
+--- filename.old
++++ filename.new
+@@ -line,len +line,len @@
+.EE
 .PP
 Except in rare circumstances,
 .I diff
--- a/sys/src/cmd/diff/diff.h
+++ b/sys/src/cmd/diff/diff.h
@@ -22,5 +22,6 @@
 void panic(int, char *, ...);
 void check(Biobuf *, Biobuf *);
 void change(int, int, int, int);
+void fileheader(void);
 void flushchanges(void);
 
--- a/sys/src/cmd/diff/diffio.c
+++ b/sys/src/cmd/diff/diffio.c
@@ -303,6 +303,7 @@
 		break;
 	case 'c':
 	case 'a':
+	case 'u':
 		if(nchanges%1024 == 0)
 			changes = erealloc(changes, (nchanges+1024)*sizeof(changes[0]));
 		ch = &changes[nchanges++];
@@ -339,6 +340,15 @@
 }
 
 void
+fileheader(void)
+{
+	if(mode != 'u')
+		return;
+	Bprint(&stdout, "--- %s\n", file1);
+	Bprint(&stdout, "+++ %s\n", file2);
+}
+
+void
 flushchanges(void)
 {
 	int a, b, c, d, at;
@@ -368,20 +378,24 @@
 			d = len[1];
 			j = nchanges;
 		}
-		Bprint(&stdout, "%s:", file1);
-		range(a, b, ",");
-		Bprint(&stdout, " - ");
-		Bprint(&stdout, "%s:", file2);
-		range(c, d, ",");
-		Bputc(&stdout, '\n');
+		if(mode == 'u'){
+			Bprint(&stdout, "@@ -%d,%d +%d,%d @@\n", a, b-a+1, c, d-c+1);
+		}else{
+			Bprint(&stdout, "%s:", file1);
+			range(a, b, ",");
+			Bprint(&stdout, " - ");
+			Bprint(&stdout, "%s:", file2);
+			range(c, d, ",");
+			Bputc(&stdout, '\n');
+		}
 		at = a;
 		for(; i<j; i++){
-			fetch(ixold, at, changes[i].a-1, input[0], "  ");
-			fetch(ixold, changes[i].a, changes[i].b, input[0], "- ");
-			fetch(ixnew, changes[i].c, changes[i].d, input[1], "+ ");
+			fetch(ixold, at, changes[i].a-1, input[0], mode == 'u' ? " " : "  ");
+			fetch(ixold, changes[i].a, changes[i].b, input[0], mode == 'u' ? "-" : "- ");
+			fetch(ixnew, changes[i].c, changes[i].d, input[1], mode == 'u' ? "+" : "- ");
 			at = changes[i].b+1;
 		}
-		fetch(ixold, at, b, input[0], "  ");
+		fetch(ixold, at, b, input[0], mode == 'u' ? " " : "  ");
 	}
 	nchanges = 0;
 }
--- a/sys/src/cmd/diff/diffreg.c
+++ b/sys/src/cmd/diff/diffreg.c
@@ -285,6 +285,7 @@
 	m = len[0];
 	J[0] = 0;
 	J[m+1] = len[1]+1;
+	fileheader();
 	if (mode != 'e') {
 		for (i0 = 1; i0 <= m; i0 = i1+1) {
 			while (i0 <= m && J[i0] == J[i0-1]+1)
--- a/sys/src/cmd/diff/main.c
+++ b/sys/src/cmd/diff/main.c
@@ -192,6 +192,7 @@
 			case 'n':
 			case 'c':
 			case 'a':
+			case 'u':
 				mode = *p;
 				break;