git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] apply --whitespace fixes and enhancements.

From
Junio C Hamano <junkio@cox.net>
Date
Feb 27, 2006, 02:14 UTC
Message-ID
<7v8xrx4kf8.fsf_-_@assigned-by-dhcp.cox.net>
In-Reply-To
<7vr75p4ojt.fsf@assigned-by-dhcp.cox.net>

In addition to fixing obvious command line parsing bugs in the previous round, this changes the following:

 * Adds "--whitespace=strip".  This applies after stripping the
   new trailing whitespaces introduced to the patch.
 * The output error message format is changed to say
   "patch-filename:linenumber:contents of the line".  This makes
   it similar to typical compiler error message format, and
   helps C-x ` (next-error) in Emacs compilation buffer.
 * --whitespace=error and --whitespace=warn do not stop at the
   first error.  We might want to limit the output to say first
   20 such lines to prevent cluttering, but on the other hand if
   you are willing to hand-fix after inspecting them, getting
   everything with a single run might be easier to work with.
   After all, somebody has to do the clean-up work somewhere.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 Junio C Hamano <junkio@cox.net> writes:
 > Regarding git-apply change, I suspect warn_on_whitespace should
 > not squelch itself after the first one, and error_on_whitespace
 > should not die instantly.  The sample pre-applypatch hook (it
 > was missing code to figure out where GIT_DIR was so it never
 > worked as shipped; corrected in "master") shows line numbers of
 > suspicious lines from the files being patched.  They can be
 > manually fixed up, and then "git am --resolved", if the
 > integrator is in a better mood.
 >
 > The error messages from pre-commit/pre-applypatch hook mimic the
 > way compiler errors are spit out, so that it works well in Emacs
 > compilation buffer -- doing C-x ` (next-error) takes you the
 > line the error appears and lets you edit it.
 apply.c |   77 ++++++++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 54 insertions(+), 23 deletions(-)
e0af70a72d4115c32a1f9b91f1cf4556bbd014b6
diff --git a/apply.c b/apply.c
index e7b3dca..7dbbeb4 100644
--- a/apply.c
+++ b/apply.c
@@ -37,8 +37,11 @@ static const char apply_usage[] =
 static enum whitespace_eol {
 	nowarn,
 	warn_on_whitespace,
-	error_on_whitespace
+	error_on_whitespace,
+	strip_and_apply,
 } new_whitespace = nowarn;
+static int whitespace_error = 0;
+static const char *patch_input_file = NULL;
 
 /*
  * For "diff-stat" like behaviour, we keep track of the biggest change
@@ -823,19 +826,17 @@ static int parse_fragment(char *line, un
 		case '+':
 			/*
 			 * We know len is at least two, since we have a '+' and
-			 * we checked that the last character was a '\n' above
+			 * we checked that the last character was a '\n' above.
+			 * That is, an addition of an empty line would check
+			 * the '+' here.  Sneaky...
 			 */
-			if (isspace(line[len-2])) {
-				switch (new_whitespace) {
-				case nowarn:
-					break;
-				case warn_on_whitespace:
-					new_whitespace = nowarn;	/* Just once */
-					error("Added whitespace at end of line at line %d", linenr);
-					break;
-				case error_on_whitespace:
-					die("Added whitespace at end of line at line %d", linenr);
-				}
+			if ((new_whitespace != nowarn) &&
+			    isspace(line[len-2])) {
+				fprintf(stderr, "Added whitespace\n");
+				fprintf(stderr, "%s:%d:%.*s\n",
+					patch_input_file,
+					linenr, len-2, line+1);
+				whitespace_error = 1;
 			}
 			added++;
 			newlines--;
@@ -1114,6 +1115,27 @@ struct buffer_desc {
 	unsigned long alloc;
 };
 
+static int apply_line(char *output, const char *patch, int plen)
+{
+	/* plen is number of bytes to be copied from patch,
+	 * starting at patch+1 (patch[0] is '+').  Typically
+	 * patch[plen] is '\n'.
+	 */
+	int add_nl_to_tail = 0;
+	if ((new_whitespace == strip_and_apply) &&
+	    1 < plen && isspace(patch[plen-1])) {
+		if (patch[plen] == '\n')
+			add_nl_to_tail = 1;
+		plen--;
+		while (0 < plen && isspace(patch[plen]))
+			plen--;
+	}
+	memcpy(output, patch + 1, plen);
+	if (add_nl_to_tail)
+		output[plen++] = '\n';
+	return plen;
+}
+
 static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
 {
 	char *buf = desc->buffer;
@@ -1149,10 +1171,9 @@ static int apply_one_fragment(struct buf
 				break;
 		/* Fall-through for ' ' */
 		case '+':
-			if (*patch != '+' || !no_add) {
-				memcpy(new + newsize, patch + 1, plen);
-				newsize += plen;
-			}
+			if (*patch != '+' || !no_add)
+				newsize += apply_line(new + newsize, patch,
+						      plen);
 			break;
 		case '@': case '\\':
 			/* Ignore it, we already handled it */
@@ -1721,7 +1742,7 @@ static int use_patch(struct patch *p)
 	return 1;
 }
 
-static int apply_patch(int fd)
+static int apply_patch(int fd, const char *filename)
 {
 	int newfd;
 	unsigned long offset, size;
@@ -1729,6 +1750,7 @@ static int apply_patch(int fd)
 	struct patch *list = NULL, **listp = &list;
 	int skipped_patch = 0;
 
+	patch_input_file = filename;
 	if (!buffer)
 		return -1;
 	offset = 0;
@@ -1755,6 +1777,9 @@ static int apply_patch(int fd)
 	}
 
 	newfd = -1;
+	if (whitespace_error && (new_whitespace == error_on_whitespace))
+		apply = 0;
+
 	write_index = check_index && apply;
 	if (write_index)
 		newfd = hold_index_file_for_update(&cache_file, get_index_file());
@@ -1801,7 +1826,7 @@ int main(int argc, char **argv)
 		int fd;
 
 		if (!strcmp(arg, "-")) {
-			apply_patch(0);
+			apply_patch(0, "<stdin>");
 			read_stdin = 0;
 			continue;
 		}
@@ -1862,14 +1887,18 @@ int main(int argc, char **argv)
 			continue;
 		}
 		if (!strncmp(arg, "--whitespace=", 13)) {
-			if (strcmp(arg+13, "warn")) {
+			if (!strcmp(arg+13, "warn")) {
 				new_whitespace = warn_on_whitespace;
 				continue;
 			}
-			if (strcmp(arg+13, "error")) {
+			if (!strcmp(arg+13, "error")) {
 				new_whitespace = error_on_whitespace;
 				continue;
 			}
+			if (!strcmp(arg+13, "strip")) {
+				new_whitespace = strip_and_apply;
+				continue;
+			}
 			die("unrecognixed whitespace option '%s'", arg+13);
 		}
 
@@ -1885,10 +1914,12 @@ int main(int argc, char **argv)
 		if (fd < 0)
 			usage(apply_usage);
 		read_stdin = 0;
-		apply_patch(fd);
+		apply_patch(fd, arg);
 		close(fd);
 	}
 	if (read_stdin)
-		apply_patch(0);
+		apply_patch(0, "<stdin>");
+	if (whitespace_error && new_whitespace == error_on_whitespace)
+		return 1;
 	return 0;
 }
-- 
1.2.3.gac5f
Previous: Junio C HamanoNext: Junio C Hamano
Message 38 of 40 in “the war on trailing whitespace”
  1. Andrew MortonFeb 26, 2006
  2. Junio C HamanoFeb 26, 2006
  3. Andrew MortonFeb 26, 2006
  4. Linus TorvaldsFeb 26, 2006
  5. Andrew MortonFeb 26, 2006
  6. Linus TorvaldsFeb 26, 2006
  7. Dave JonesFeb 26, 2006
  8. Dave JonesFeb 26, 2006
  9. MIke GalbraithFeb 27, 2006
  10. Johannes SchindelinFeb 27, 2006
  11. Andrew MortonFeb 27, 2006
  12. Junio C HamanoFeb 27, 2006
  13. Peter WilliamsFeb 27, 2006
  14. Junio C HamanoFeb 28, 2006
  15. Andrew MortonFeb 27, 2006
  16. git-apply: war on whitespace -- finishing touches.Junio C Hamano, Feb 28, 2006
  17. 1/3 apply: squelch excessive errors and --whitespace=error-allJunio C Hamano, Feb 28, 2006
  18. 2/3 apply --whitespace: configuration option.Junio C Hamano, Feb 28, 2006
  19. Andreas EricssonFeb 28, 2006
  20. Junio C HamanoFeb 28, 2006
  21. Andreas EricssonFeb 28, 2006
  22. 3/3 git-apply --whitespace=nowarnJunio C Hamano, Feb 28, 2006
  23. A Large Angry SCMFeb 28, 2006
  24. Junio C HamanoFeb 28, 2006
  25. Adrien BeauFeb 27, 2006
  26. Andreas EricssonFeb 27, 2006
  27. Uwe ZeisbergerFeb 27, 2006
  28. Andreas EricssonFeb 27, 2006
  29. Peter HagervallFeb 27, 2006
  30. Johannes SchindelinFeb 27, 2006
  31. Randal L. SchwartzFeb 27, 2006
  32. Josef WeidendorferFeb 27, 2006
  33. Adrien BeauFeb 27, 2006
  34. Uwe ZeisbergerFeb 27, 2006
  35. Andreas EricssonFeb 27, 2006
  36. Johannes SchindelinFeb 27, 2006
  37. Junio C HamanoFeb 27, 2006
  38. apply --whitespace fixes and enhancements.Junio C Hamano, Feb 27, 2006
  39. Junio C HamanoFeb 26, 2006
  40. Sam RavnborgFeb 26, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.