code: plan9front

Download patch

ref: 0123946b8df36a0215861b66f4fdba42e3c2dc49
parent: ab50c202547195701c82c8351464cd30e39ecd0d
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Sep 21 12:55:06 EDT 2023

patch: support no-newline directives

When we get a patch with a:

  \ No newline at end of file

directive, we now apply it correctly,
removing the newline. We generalize
a bit, allowing any line to trim a
newline, giving a primitive form of
line splitting

--- a/sys/src/cmd/patch.c
+++ b/sys/src/cmd/patch.c
@@ -265,10 +265,23 @@
 	*b = t;
 }
 
+void
+trimhunk(char c, Hunk *h)
+{
+	if((c == ' ' || c == '-') && h->oldlen > 0 && h->old[h->oldlen-1] == '\n'){
+		h->oldcnt--;
+		h->oldlen--;
+	}
+	if((c == ' ' || c == '+') && h->newlen > 0 && h->new[h->newlen-1] == '\n'){
+		h->newcnt--;
+		h->newlen--;
+	}
+}
+
 Patch*
 parse(Biobuf *f, char *name)
 {
-	char *ln, *old, *new;
+	char *ln, *old, *new, c;
 	int i, oldcnt, newcnt, lnum;
 	Patch *p;
 	Hunk h, *ph;
@@ -316,10 +329,16 @@
 			addhunk(p, &h);
 			break;
 		}
+		c = ln[0];
 		switch(ln[0]){
 		default:
 			sysfatal("%s:%d: malformed hunk: leading junk", name, lnum);
 			goto out;
+		case '\\':
+			if(strncmp(ln, "\\ No newline", nelem("\\ No newline")-1) == 0)
+				trimhunk(c, &h);
+			/* ignore unknown directives */
+			break;
 		case '-':
 			addold(&h, ln);
 			oldcnt++;
@@ -350,6 +369,8 @@
 		addhunk(p, &h);
 		if((ln = readline(f, &lnum)) == nil)
 			goto out;
+		if(strncmp(ln, "\\ No newline", nelem("\\ No newline")-1) == 0)
+			trimhunk(c, &p->hunk[p->nhunk-1]);
 		if(strncmp(ln, "--- ", 4) == 0)
 			goto patch;
 		if(strncmp(ln, "@@ ", 3) == 0)
@@ -542,6 +563,7 @@
 searchln(Fbuf *f, Hunk *h, int ln)
 {
 	int off;
+int n;
 
 	off = f->lines[ln];
 	if(off + h->oldlen > f->len)