[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Compatibility for patch



Hello all,

NetBSD updated their patch to include support for patches 
created by GNU diff on files without ending newlines a few 
months ago. Relatively small diff, the change was here:

http://cvsweb.netbsd.org/bsdweb.cgi/basesrc/usr.bin/patch/pch.c

and the original commit message here (pch.c was the only file
modified):

http://mail-index.netbsd.org/source-changes/2002/03/24/0011.html

Their diff applies pretty cleanly to our patch, only 1 reject 
which was because they have changed a comment from the looks.
The patch to ours is included. Note I haven't extensively 
tested this at all, so don't take it like it has been. 

It does work at least for a quick test though, which is 
promising. It would be nice if anyone has the time to check
more into this that they would. I don't have the time during
this summer as I'm more than a bit busy. The patch code is a
bit frightening at first glance as well (so its hard to tell
if this is a complete hack or what.) It doesn't do a very 
hard match (just looks for a first character of \, but this
might be sufficient?) 

The benefit is obvious though.. I've often had cvs diff's 
give me patches with the comment and it would be nice to 
have our patch be able to handle it. As a bonus, it would 
also resolve the 2nd item on Larry's todo list in the 
README file (only been there for like 15 years ;-)

2.  Correctly handle patches produced by GNU diff for files that do
not end with a newline.



-b 

Index: pch.c
===================================================================
RCS file: /cvs/src/usr.bin/patch/pch.c,v
retrieving revision 1.11
diff -u -r1.11 pch.c
--- pch.c	2000/12/14 00:02:19	1.11
+++ pch.c	2002/06/10 04:17:18
@@ -404,6 +404,30 @@
 		/* about as informative as "Syntax error" in C */
 }
 
+/*
+ * True if the line has been discarded (i.e. it is a line saying
+ *  "\ No newline at end of file".)
+ */
+static bool
+remove_special_line(void)
+{
+	int c;
+
+	c = fgetc(pfp);
+	if (c == '\\') {
+		do {
+			c = fgetc(pfp);
+		} while (c != EOF && c != '\n');
+
+		return TRUE;
+	}
+
+	if (c != EOF)
+		fseek(pfp, -1, SEEK_CUR);
+
+	return FALSE;
+}
+
 /* True if there is more of the current diff listing to process. */
 
 bool
@@ -611,6 +635,15 @@
 		    p_end--;
 		    return FALSE;
 		}
+		if (p_end == p_ptrn_lines)
+		{
+			if (remove_special_line()) {
+				int len;
+
+				len = strlen(p_line[p_end]) - 1;
+				(p_line[p_end])[len] = 0;
+			}
+		}
 		break;
 	    case '\t': case '\n':	/* assume the 2 spaces got eaten */
 		if (repl_beginning && repl_could_be_missing &&
@@ -738,6 +771,14 @@
 	    assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
 	    assert(filldst==p_end+1 || filldst==repl_beginning);
 	}
+
+	if (p_line[p_end] != NULL)
+	{
+		if (remove_special_line()) {
+			p_len[p_end] -= 1;
+			(p_line[p_end])[p_len[p_end]] = 0;
+		}
+	}
     }
     else if (diff_type == UNI_DIFF) {
 	long line_beginning = ftell(pfp);
@@ -837,6 +878,12 @@
 		p_char[fillsrc] = ch;
 		p_line[fillsrc] = s;
 		p_len[fillsrc++] = strlen(s);
+		if (fillsrc > p_ptrn_lines) {
+			if (remove_special_line()) {
+				p_len[fillsrc - 1] -= 1;
+				s[p_len[fillsrc - 1]] = 0;
+			}
+		}
 		break;
 	    case '=':
 		ch = ' ';
@@ -872,6 +919,12 @@
 		p_char[filldst] = ch;
 		p_line[filldst] = s;
 		p_len[filldst++] = strlen(s);
+		if (fillsrc > p_ptrn_lines) {
+			if (remove_special_line()) {
+				p_len[filldst - 1] -= 1;
+				s[p_len[filldst - 1]] = 0;
+			}
+		}
 		break;
 	    default:
 		p_end = filldst;
@@ -948,6 +1001,12 @@
 	    p_len[i] = strlen(p_line[i]);
 	    p_char[i] = '-';
 	}
+
+	if (remove_special_line()) {
+		p_len[i-1] -= 1;
+		(p_line[i-1])[p_len[i-1]] = 0;
+	}
+
 	if (hunk_type == 'c') {
 	    ret = pgets(buf, sizeof buf, pfp);
 	    p_input_line++;
@@ -979,6 +1038,11 @@
 	    }
 	    p_len[i] = strlen(p_line[i]);
 	    p_char[i] = '+';
+	}
+
+	if (remove_special_line()) {
+		p_len[i-1] -= 1;
+		(p_line[i-1])[p_len[i-1]] = 0;
 	}
     }
     if (reverse)			/* backwards patch? */