All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Add tab-in-indent whitespace rule
@ 2010-04-02 23:36 Chris Webb
  2010-04-02 23:37 ` [PATCH 1/6] whitespace: we cannot "catch all errors known to git" anymore Chris Webb
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

This patch set introduces a new whitespace error/fix class for projects and
languages with a coding style where no tab character is used to indent the
lines.

To implement this feature, we need to rework ws_fix_copy() to append to a
strbuf rather than write into a fixed-size output buffer, because tabs may
be expanded into multiple spaces when tab-in-indent is applied. We also have
to change the "catch all errors known to git" to exclude tab-in-indent,
which directly conflicts with the existing indent-with-non-tab rule.


Junio C Hamano (1):
  whitespace: we cannot "catch all errors known to git" anymore

Chris Webb (5):
  whitespace: add tab-in-indent error class
  whitespace: tests for git-diff --check with tab-in-indent error class
  whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst
  whitespace: add tab-in-indent support for --whitespace=fix
  whitespace: tests for git-apply --whitespace=fix with tab-in-indent

 Documentation/config.txt   |    2 +
 builtin/apply.c            |   81 +++++++++++++++++++++-----------------------
 cache.h                    |    3 +-
 t/t4015-diff-whitespace.sh |   42 +++++++++++++++++++++++
 t/t4124-apply-ws-rule.sh   |   53 ++++++++++++++++-------------
 ws.c                       |   73 ++++++++++++++++++++++++++++-----------
 6 files changed, 166 insertions(+), 88 deletions(-)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/6] whitespace: we cannot "catch all errors known to git" anymore
  2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
@ 2010-04-02 23:37 ` Chris Webb
  2010-04-02 23:37 ` [PATCH 2/6] whitespace: add tab-in-indent error class Chris Webb
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

From: Junio C Hamano <gitster@pobox.com>

Traditionally, "*.txt whitespace" in .gitattributes file has been an
instruction to catch _all_ classes of whitespace errors known to git.

This has to change, however, in order to introduce "tab-in-indent" which
is inherently incompatible with "indent-with-non-tab".  As we do not want
to break configuration of existing users, add a mechanism to allow marking
selected rules to be excluded from "all rules known to git".

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Chris Webb <chris@arachsys.com>
---
 ws.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/ws.c b/ws.c
index c089338..f4afcdd 100644
--- a/ws.c
+++ b/ws.c
@@ -10,7 +10,8 @@
 static struct whitespace_rule {
 	const char *rule_name;
 	unsigned rule_bits;
-	unsigned loosens_error;
+	unsigned loosens_error:1,
+		exclude_default:1;
 } whitespace_rule_names[] = {
 	{ "trailing-space", WS_TRAILING_SPACE, 0 },
 	{ "space-before-tab", WS_SPACE_BEFORE_TAB, 0 },
@@ -82,7 +83,8 @@ unsigned whitespace_rule(const char *pathname)
 			unsigned all_rule = 0;
 			int i;
 			for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++)
-				if (!whitespace_rule_names[i].loosens_error)
+				if (!whitespace_rule_names[i].loosens_error &&
+				    !whitespace_rule_names[i].exclude_default)
 					all_rule |= whitespace_rule_names[i].rule_bits;
 			return all_rule;
 		} else if (ATTR_FALSE(value)) {
-- 
1.7.0.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/6] whitespace: add tab-in-indent error class
  2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
  2010-04-02 23:37 ` [PATCH 1/6] whitespace: we cannot "catch all errors known to git" anymore Chris Webb
@ 2010-04-02 23:37 ` Chris Webb
  2010-04-03 10:02   ` Martin Mares
  2010-04-02 23:37 ` [PATCH 3/6] whitespace: tests for git-diff --check with " Chris Webb
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Some projects and languages use coding style where no tab character is used to
indent the lines.

This only adds support and documentation for "apply --whitespace=warn" and
"diff --check"; later patches add "apply --whitespace=fix" and tests.

Signed-off-by: Chris Webb <chris@arachsys.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt |    2 ++
 cache.h                  |    1 +
 ws.c                     |   27 ++++++++++++++++++++++-----
 3 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 06b2f82..9bb8f3d 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -481,6 +481,8 @@ core.whitespace::
   error (enabled by default).
 * `indent-with-non-tab` treats a line that is indented with 8 or more
   space characters as an error (not enabled by default).
+* `tab-in-indent` treats a tab character in the initial indent part of
+  the line as an error (not enabled by default).
 * `blank-at-eof` treats blank lines added at the end of file as an error
   (enabled by default).
 * `trailing-space` is a short-hand to cover both `blank-at-eol` and
diff --git a/cache.h b/cache.h
index 6dcb100..030af32 100644
--- a/cache.h
+++ b/cache.h
@@ -1040,6 +1040,7 @@ void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *
 #define WS_INDENT_WITH_NON_TAB	04
 #define WS_CR_AT_EOL           010
 #define WS_BLANK_AT_EOF        020
+#define WS_TAB_IN_INDENT       040
 #define WS_TRAILING_SPACE      (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
 #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
 extern unsigned whitespace_rule_cfg;
diff --git a/ws.c b/ws.c
index f4afcdd..0302ef5 100644
--- a/ws.c
+++ b/ws.c
@@ -19,6 +19,7 @@ static struct whitespace_rule {
 	{ "cr-at-eol", WS_CR_AT_EOL, 1 },
 	{ "blank-at-eol", WS_BLANK_AT_EOL, 0 },
 	{ "blank-at-eof", WS_BLANK_AT_EOF, 0 },
+	{ "tab-in-indent", WS_TAB_IN_INDENT, 0, 1 },
 };
 
 unsigned parse_whitespace_rule(const char *string)
@@ -57,6 +58,9 @@ unsigned parse_whitespace_rule(const char *string)
 		}
 		string = ep;
 	}
+
+	if (rule & WS_TAB_IN_INDENT && rule & WS_INDENT_WITH_NON_TAB)
+		die("cannot enforce both tab-in-indent and indent-with-non-tab");
 	return rule;
 }
 
@@ -127,6 +131,11 @@ char *whitespace_error_string(unsigned ws)
 			strbuf_addstr(&err, ", ");
 		strbuf_addstr(&err, "indent with spaces");
 	}
+	if (ws & WS_TAB_IN_INDENT) {
+		if (err.len)
+			strbuf_addstr(&err, ", ");
+		strbuf_addstr(&err, "tab in indent");
+	}
 	return strbuf_detach(&err, NULL);
 }
 
@@ -165,7 +174,7 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
 		}
 	}
 
-	/* Check for space before tab in initial indent. */
+	/* Check indentation */
 	for (i = 0; i < len; i++) {
 		if (line[i] == ' ')
 			continue;
@@ -177,11 +186,19 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
 				fputs(ws, stream);
 				fwrite(line + written, i - written, 1, stream);
 				fputs(reset, stream);
+				fwrite(line + i, 1, 1, stream);
 			}
-		} else if (stream)
-			fwrite(line + written, i - written, 1, stream);
-		if (stream)
-			fwrite(line + i, 1, 1, stream);
+		} else if (ws_rule & WS_TAB_IN_INDENT) {
+			result |= WS_TAB_IN_INDENT;
+			if (stream) {
+				fwrite(line + written, i - written, 1, stream);
+				fputs(ws, stream);
+				fwrite(line + i, 1, 1, stream);
+				fputs(reset, stream);
+			}
+		} else if (stream) {
+			fwrite(line + written, i - written + 1, 1, stream);
+		}
 		written = i + 1;
 	}
 
-- 
1.7.0.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/6] whitespace: tests for git-diff --check with tab-in-indent error class
  2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
  2010-04-02 23:37 ` [PATCH 1/6] whitespace: we cannot "catch all errors known to git" anymore Chris Webb
  2010-04-02 23:37 ` [PATCH 2/6] whitespace: add tab-in-indent error class Chris Webb
@ 2010-04-02 23:37 ` Chris Webb
  2010-04-02 23:37 ` [PATCH 4/6] whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst Chris Webb
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Signed-off-by: Chris Webb <chris@arachsys.com>
---
 t/t4015-diff-whitespace.sh |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 90f3342..9e57f80 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -352,6 +352,48 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab:
 
 '
 
+test_expect_success 'check tabs as indentation (tab-in-indent: off)' '
+
+	git config core.whitespace "-tab-in-indent"
+	echo "	foo ();" > x &&
+	git diff --check
+
+'
+
+test_expect_success 'check tabs as indentation (tab-in-indent: on)' '
+
+	git config core.whitespace "tab-in-indent" &&
+	echo "	foo ();" > x &&
+	test_must_fail git diff --check
+
+'
+
+test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '
+
+	git config core.whitespace "tab-in-indent" &&
+	echo "	                foo ();" > x &&
+	test_must_fail git diff --check
+
+'
+
+test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '
+
+	git config core.whitespace "tab-in-indent,indent-with-non-tab"
+	echo "foo ();" > x &&
+	test_must_fail git diff --check
+
+'
+
+test_expect_success 'check tab-in-indent excluded from wildcard whitespace attribute' '
+
+	git config --unset core.whitespace
+	echo "x whitespace" > .gitattributes &&
+	echo "	  foo ();" > x &&
+	git diff --check &&
+	rm -f .gitattributes
+
+'
+
 test_expect_success 'line numbers in --check output are correct' '
 
 	echo "" > x &&
-- 
1.7.0.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/6] whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst
  2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
                   ` (2 preceding siblings ...)
  2010-04-02 23:37 ` [PATCH 3/6] whitespace: tests for git-diff --check with " Chris Webb
@ 2010-04-02 23:37 ` Chris Webb
  2010-04-02 23:37 ` [PATCH 5/6] whitespace: add tab-in-indent support for --whitespace=fix Chris Webb
  2010-04-02 23:37 ` [PATCH 6/6] whitespace: tests for git-apply --whitespace=fix with tab-in-indent Chris Webb
  5 siblings, 0 replies; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

To implement --whitespace=fix for tab-in-indent, we have to allow for the
possibility that whitespace can increase in size when it is fixed, expanding
tabs to to multiple spaces in the initial indent.

Signed-off-by: Chris Webb <chris@arachsys.com>
---
 builtin/apply.c |   81 ++++++++++++++++++++++++++----------------------------
 cache.h         |    2 +-
 ws.c            |   19 +++++-------
 3 files changed, 48 insertions(+), 54 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index 7ca9047..db9cbdd 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1854,6 +1854,8 @@ static int match_fragment(struct image *img,
 {
 	int i;
 	char *fixed_buf, *buf, *orig, *target;
+	struct strbuf fixed;
+	size_t fixed_len;
 	int preimage_limit;
 
 	if (preimage->nr + try_lno <= img->nr) {
@@ -1977,12 +1979,12 @@ static int match_fragment(struct image *img,
 		 * use the whitespace from the preimage.
 		 */
 		extra_chars = preimage_end - preimage_eof;
-		fixed_buf = xmalloc(imgoff + extra_chars);
-		memcpy(fixed_buf, img->buf + try, imgoff);
-		memcpy(fixed_buf + imgoff, preimage_eof, extra_chars);
-		imgoff += extra_chars;
+		strbuf_init(&fixed, imgoff + extra_chars);
+		strbuf_add(&fixed, img->buf + try, imgoff);
+		strbuf_add(&fixed, preimage_eof, extra_chars);
+		fixed_buf = strbuf_detach(&fixed, &fixed_len);
 		update_pre_post_images(preimage, postimage,
-				fixed_buf, imgoff, postlen);
+				fixed_buf, fixed_len, postlen);
 		return 1;
 	}
 
@@ -1999,27 +2001,22 @@ static int match_fragment(struct image *img,
 	 * but in this loop we will only handle the part of the
 	 * preimage that falls within the file.
 	 */
-	fixed_buf = xmalloc(preimage->len + 1);
-	buf = fixed_buf;
+	strbuf_init(&fixed, preimage->len + 1);
 	orig = preimage->buf;
 	target = img->buf + try;
 	for (i = 0; i < preimage_limit; i++) {
-		size_t fixlen; /* length after fixing the preimage */
 		size_t oldlen = preimage->line[i].len;
 		size_t tgtlen = img->line[try_lno + i].len;
-		size_t tgtfixlen; /* length after fixing the target line */
-		char tgtfixbuf[1024], *tgtfix;
+		size_t fixstart = fixed.len;
+		struct strbuf tgtfix;
 		int match;
 
 		/* Try fixing the line in the preimage */
-		fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
+		ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL);
 
 		/* Try fixing the line in the target */
-		if (sizeof(tgtfixbuf) > tgtlen)
-			tgtfix = tgtfixbuf;
-		else
-			tgtfix = xmalloc(tgtlen);
-		tgtfixlen = ws_fix_copy(tgtfix, target, tgtlen, ws_rule, NULL);
+		strbuf_init(&tgtfix, tgtlen);
+		ws_fix_copy(&tgtfix, target, tgtlen, ws_rule, NULL);
 
 		/*
 		 * If they match, either the preimage was based on
@@ -2031,15 +2028,15 @@ static int match_fragment(struct image *img,
 		 * so we might as well take the fix together with their
 		 * real change.
 		 */
-		match = (tgtfixlen == fixlen && !memcmp(tgtfix, buf, fixlen));
+		match = (tgtfix.len == fixed.len - fixstart &&
+			 !memcmp(tgtfix.buf, fixed.buf + fixstart,
+					     fixed.len - fixstart));
 
-		if (tgtfix != tgtfixbuf)
-			free(tgtfix);
+		strbuf_release(&tgtfix);
 		if (!match)
 			goto unmatch_exit;
 
 		orig += oldlen;
-		buf += fixlen;
 		target += tgtlen;
 	}
 
@@ -2051,19 +2048,18 @@ static int match_fragment(struct image *img,
 	 * false).
 	 */
 	for ( ; i < preimage->nr; i++) {
-		size_t fixlen; /* length after fixing the preimage */
+		size_t fixstart = fixed.len; /* start of the fixed preimage */
 		size_t oldlen = preimage->line[i].len;
 		int j;
 
 		/* Try fixing the line in the preimage */
-		fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
+		ws_fix_copy(&fixed, orig, oldlen, ws_rule, NULL);
 
-		for (j = 0; j < fixlen; j++)
-			if (!isspace(buf[j]))
+		for (j = fixstart; j < fixed.len; j++)
+			if (!isspace(fixed.buf[j]))
 				goto unmatch_exit;
 
 		orig += oldlen;
-		buf += fixlen;
 	}
 
 	/*
@@ -2071,12 +2067,13 @@ static int match_fragment(struct image *img,
 	 * has whitespace breakages unfixed, and fixing them makes the
 	 * hunk match.  Update the context lines in the postimage.
 	 */
+	fixed_buf = strbuf_detach(&fixed, &fixed_len);
 	update_pre_post_images(preimage, postimage,
-			       fixed_buf, buf - fixed_buf, 0);
+			       fixed_buf, fixed_len, 0);
 	return 1;
 
  unmatch_exit:
-	free(fixed_buf);
+	strbuf_release(&fixed);
 	return 0;
 }
 
@@ -2244,7 +2241,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 	int match_beginning, match_end;
 	const char *patch = frag->patch;
 	int size = frag->size;
-	char *old, *new, *oldlines, *newlines;
+	char *old, *oldlines;
+	struct strbuf newlines;
 	int new_blank_lines_at_end = 0;
 	unsigned long leading, trailing;
 	int pos, applied_pos;
@@ -2254,16 +2252,16 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 	memset(&preimage, 0, sizeof(preimage));
 	memset(&postimage, 0, sizeof(postimage));
 	oldlines = xmalloc(size);
-	newlines = xmalloc(size);
+	strbuf_init(&newlines, size);
 
 	old = oldlines;
-	new = newlines;
 	while (size > 0) {
 		char first;
 		int len = linelen(patch, size);
-		int plen, added;
+		int plen;
 		int added_blank_line = 0;
 		int is_blank_context = 0;
+		size_t start;
 
 		if (!len)
 			break;
@@ -2293,7 +2291,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 				/* ... followed by '\No newline'; nothing */
 				break;
 			*old++ = '\n';
-			*new++ = '\n';
+			strbuf_addch(&newlines, '\n');
 			add_line_info(&preimage, "\n", 1, LINE_COMMON);
 			add_line_info(&postimage, "\n", 1, LINE_COMMON);
 			is_blank_context = 1;
@@ -2315,18 +2313,17 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 			if (first == '+' && no_add)
 				break;
 
+			start = newlines.len;
 			if (first != '+' ||
 			    !whitespace_error ||
 			    ws_error_action != correct_ws_error) {
-				memcpy(new, patch + 1, plen);
-				added = plen;
+				strbuf_add(&newlines, patch + 1, plen);
 			}
 			else {
-				added = ws_fix_copy(new, patch + 1, plen, ws_rule, &applied_after_fixing_ws);
+				ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &applied_after_fixing_ws);
 			}
-			add_line_info(&postimage, new, added,
+			add_line_info(&postimage, newlines.buf + start, newlines.len - start,
 				      (first == '+' ? 0 : LINE_COMMON));
-			new += added;
 			if (first == '+' &&
 			    (ws_rule & WS_BLANK_AT_EOF) &&
 			    ws_blank_line(patch + 1, plen, ws_rule))
@@ -2351,9 +2348,9 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 	}
 	if (inaccurate_eof &&
 	    old > oldlines && old[-1] == '\n' &&
-	    new > newlines && new[-1] == '\n') {
+	    newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') {
 		old--;
-		new--;
+		strbuf_setlen(&newlines, newlines.len - 1);
 	}
 
 	leading = frag->leading;
@@ -2385,8 +2382,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 	pos = frag->newpos ? (frag->newpos - 1) : 0;
 	preimage.buf = oldlines;
 	preimage.len = old - oldlines;
-	postimage.buf = newlines;
-	postimage.len = new - newlines;
+	postimage.buf = newlines.buf;
+	postimage.len = newlines.len;
 	preimage.line = preimage.line_allocated;
 	postimage.line = postimage.line_allocated;
 
@@ -2462,7 +2459,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
 	}
 
 	free(oldlines);
-	free(newlines);
+	strbuf_release(&newlines);
 	free(preimage.line_allocated);
 	free(postimage.line_allocated);
 
diff --git a/cache.h b/cache.h
index 030af32..3b7f3b0 100644
--- a/cache.h
+++ b/cache.h
@@ -1049,7 +1049,7 @@ extern unsigned parse_whitespace_rule(const char *);
 extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
 extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
 extern char *whitespace_error_string(unsigned ws);
-extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
+extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
 extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 
 /* ls-files */
diff --git a/ws.c b/ws.c
index 0302ef5..897ff56 100644
--- a/ws.c
+++ b/ws.c
@@ -271,8 +271,8 @@ int ws_blank_line(const char *line, int len, unsigned ws_rule)
 	return 1;
 }
 
-/* Copy the line to the buffer while fixing whitespaces */
-int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
+/* Copy the line onto the end of the strbuf while fixing whitespaces */
+void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule, int *error_count)
 {
 	/*
 	 * len is number of bytes to be copied from src, starting
@@ -286,7 +286,6 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
 	int last_tab_in_indent = -1;
 	int last_space_in_indent = -1;
 	int need_fix_leading_space = 0;
-	char *buf;
 
 	/*
 	 * Strip trailing whitespace
@@ -326,7 +325,6 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
 			break;
 	}
 
-	buf = dst;
 	if (need_fix_leading_space) {
 		/* Process indent ourselves */
 		int consecutive_spaces = 0;
@@ -348,28 +346,27 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
 			char ch = src[i];
 			if (ch != ' ') {
 				consecutive_spaces = 0;
-				*dst++ = ch;
+				strbuf_addch(dst, ch);
 			} else {
 				consecutive_spaces++;
 				if (consecutive_spaces == 8) {
-					*dst++ = '\t';
+					strbuf_addch(dst, '\t');
 					consecutive_spaces = 0;
 				}
 			}
 		}
 		while (0 < consecutive_spaces--)
-			*dst++ = ' ';
+			strbuf_addch(dst, ' ');
 		len -= last;
 		src += last;
 		fixed = 1;
 	}
 
-	memcpy(dst, src, len);
+	strbuf_add(dst, src, len);
 	if (add_cr_to_tail)
-		dst[len++] = '\r';
+		strbuf_addch(dst, '\r');
 	if (add_nl_to_tail)
-		dst[len++] = '\n';
+		strbuf_addch(dst, '\n');
 	if (fixed && error_count)
 		(*error_count)++;
-	return dst + len - buf;
 }
-- 
1.7.0.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 5/6] whitespace: add tab-in-indent support for --whitespace=fix
  2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
                   ` (3 preceding siblings ...)
  2010-04-02 23:37 ` [PATCH 4/6] whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst Chris Webb
@ 2010-04-02 23:37 ` Chris Webb
  2010-04-02 23:37 ` [PATCH 6/6] whitespace: tests for git-apply --whitespace=fix with tab-in-indent Chris Webb
  5 siblings, 0 replies; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

If tab-in-indent is set, --whitespace=fix will ensure that any stray tabs in
the initial indent are expanded to the correct number of space characters.

Signed-off-by: Chris Webb <chris@arachsys.com>
---
 ws.c |   21 ++++++++++++++++++---
 1 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/ws.c b/ws.c
index 897ff56..e581535 100644
--- a/ws.c
+++ b/ws.c
@@ -313,8 +313,9 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
 		char ch = src[i];
 		if (ch == '\t') {
 			last_tab_in_indent = i;
-			if ((ws_rule & WS_SPACE_BEFORE_TAB) &&
-			    0 <= last_space_in_indent)
+			if ((ws_rule & WS_TAB_IN_INDENT) ||
+			    ((ws_rule & WS_SPACE_BEFORE_TAB) &&
+			     0 <= last_space_in_indent))
 			    need_fix_leading_space = 1;
 		} else if (ch == ' ') {
 			last_space_in_indent = i;
@@ -325,7 +326,21 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
 			break;
 	}
 
-	if (need_fix_leading_space) {
+	if ((ws_rule & WS_TAB_IN_INDENT) && last_tab_in_indent >= 0) {
+		/* Expand tabs into spaces */
+		int last = last_tab_in_indent + 1;
+		for (i = 0; i < last; i++) {
+			if (src[i] == '\t')
+				do {
+					strbuf_addch(dst, ' ');
+				} while (dst->len % 8);
+			else
+				strbuf_addch(dst, src[i]);
+		}
+		len -= last;
+		src += last;
+		fixed = 1;
+	} else if (need_fix_leading_space) {
 		/* Process indent ourselves */
 		int consecutive_spaces = 0;
 		int last = last_tab_in_indent + 1;
-- 
1.7.0.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 6/6] whitespace: tests for git-apply --whitespace=fix with tab-in-indent
  2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
                   ` (4 preceding siblings ...)
  2010-04-02 23:37 ` [PATCH 5/6] whitespace: add tab-in-indent support for --whitespace=fix Chris Webb
@ 2010-04-02 23:37 ` Chris Webb
  5 siblings, 0 replies; 8+ messages in thread
From: Chris Webb @ 2010-04-02 23:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Signed-off-by: Chris Webb <chris@arachsys.com>
---
 t/t4124-apply-ws-rule.sh |   53 +++++++++++++++++++++++++--------------------
 1 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index fb9ad24..8d46df6 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -11,21 +11,22 @@ prepare_test_file () {
 	#   	!  trailing-space
 	#   	@  space-before-tab
 	#   	#  indent-with-non-tab
+	#   	%  tab-in-indent
 	sed -e "s/_/ /g" -e "s/>/	/" <<-\EOF
 		An_SP in an ordinary line>and a HT.
-		>A HT.
-		_>A SP and a HT (@).
-		_>_A SP, a HT and a SP (@).
+		>A HT (%).
+		_>A SP and a HT (@%).
+		_>_A SP, a HT and a SP (@%).
 		_______Seven SP.
 		________Eight SP (#).
-		_______>Seven SP and a HT (@).
-		________>Eight SP and a HT (@#).
-		_______>_Seven SP, a HT and a SP (@).
-		________>_Eight SP, a HT and a SP (@#).
+		_______>Seven SP and a HT (@%).
+		________>Eight SP and a HT (@#%).
+		_______>_Seven SP, a HT and a SP (@%).
+		________>_Eight SP, a HT and a SP (@#%).
 		_______________Fifteen SP (#).
-		_______________>Fifteen SP and a HT (@#).
+		_______________>Fifteen SP and a HT (@#%).
 		________________Sixteen SP (#).
-		________________>Sixteen SP and a HT (@#).
+		________________>Sixteen SP and a HT (@#%).
 		_____a__Five SP, a non WS, two SP.
 		A line with a (!) trailing SP_
 		A line with a (!) trailing HT>
@@ -39,7 +40,6 @@ apply_patch () {
 }
 
 test_fix () {
-
 	# fix should not barf
 	apply_patch --whitespace=fix || return 1
 
@@ -130,20 +130,25 @@ do
 		for i in - ''
 		do
 			case "$i" in '') ti='#' ;; *) ti= ;; esac
-			rule=${t}trailing,${s}space,${i}indent
-
-			rm -f .gitattributes
-			test_expect_success "rule=$rule" '
-				git config core.whitespace "$rule" &&
-				test_fix "$tt$ts$ti"
-			'
-
-			test_expect_success "rule=$rule (attributes)" '
-				git config --unset core.whitespace &&
-				echo "target whitespace=$rule" >.gitattributes &&
-				test_fix "$tt$ts$ti"
-			'
-
+			for h in - ''
+			do
+				[ -z "$h$i" ] && continue
+				case "$h" in '') th='%' ;; *) th= ;; esac
+				rule=${t}trailing,${s}space,${i}indent,${h}tab
+
+				rm -f .gitattributes
+				test_expect_success "rule=$rule" '
+					git config core.whitespace "$rule" &&
+					test_fix "$tt$ts$ti$th"
+				'
+
+				test_expect_success "rule=$rule (attributes)" '
+					git config --unset core.whitespace &&
+					echo "target whitespace=$rule" >.gitattributes &&
+					test_fix "$tt$ts$ti$th"
+				'
+
+			done
 		done
 	done
 done
-- 
1.7.0.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/6] whitespace: add tab-in-indent error class
  2010-04-02 23:37 ` [PATCH 2/6] whitespace: add tab-in-indent error class Chris Webb
@ 2010-04-03 10:02   ` Martin Mares
  0 siblings, 0 replies; 8+ messages in thread
From: Martin Mares @ 2010-04-03 10:02 UTC (permalink / raw)
  To: Chris Webb; +Cc: Junio C Hamano, git

Hello!

> +	if (rule & WS_TAB_IN_INDENT && rule & WS_INDENT_WITH_NON_TAB)
> +		die("cannot enforce both tab-in-indent and indent-with-non-tab");

Well, it would forbid any indented lines, which could possible make
sense for some file formats.

				Have a nice fortnight
-- 
Martin `MJ' Mares                          <mj@ucw.cz>   http://mj.ucw.cz/
Faculty of Math and Physics, Charles University, Prague, Czech Rep., Earth
"This is an object-oriented system. If we change anything, the users object."

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-04-03 10:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-02 23:36 [PATCH 0/6] Add tab-in-indent whitespace rule Chris Webb
2010-04-02 23:37 ` [PATCH 1/6] whitespace: we cannot "catch all errors known to git" anymore Chris Webb
2010-04-02 23:37 ` [PATCH 2/6] whitespace: add tab-in-indent error class Chris Webb
2010-04-03 10:02   ` Martin Mares
2010-04-02 23:37 ` [PATCH 3/6] whitespace: tests for git-diff --check with " Chris Webb
2010-04-02 23:37 ` [PATCH 4/6] whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst Chris Webb
2010-04-02 23:37 ` [PATCH 5/6] whitespace: add tab-in-indent support for --whitespace=fix Chris Webb
2010-04-02 23:37 ` [PATCH 6/6] whitespace: tests for git-apply --whitespace=fix with tab-in-indent Chris Webb

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.