@matheusbsbs / matheus-bagliano / commits / f4b05a4947
Fork 0

Make the tab width used for whitespace checks configurable

A new whitespace "rule" is added that sets the tab width to use for whitespace checks and fix-ups and replaces the hard-coded constant 8. Since the setting is part of the rules, it can be set per file using .gitattributes. The new configuration is backwards compatible because older git versions simply ignore unknown whitespace rules. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Sixt committed Nov 30, 2010 at 09:29 UTC f4b05a4947f5f1cf3e01fb61ec5919cc28fe11f7
7 files changed +163 -21
Documentation/config.txt
+3
@@ -513,6 +513,9 @@ core.whitespace::
513 part of the line terminator, i.e. with it, `trailing-space`
514 does not trigger if the character before such a carriage-return
515 is not a whitespace (not enabled by default).
516 +* `tabwidth=<n>` tells how many character positions a tab occupies; this
517 + is relevant for `indent-with-non-tab` and when git fixes `tab-in-indent`
518 + errors. The default tab width is 8. Allowed values are 1 to 63.
519
520 core.fsyncobjectfiles::
521 This boolean will enable 'fsync()' when writing object files.
Documentation/gitattributes.txt
+4 -2
@@ -723,6 +723,8 @@ control per path.
723 Set::
724
725 Notice all types of potential whitespace errors known to git.
726 + The tab width is taken from the value of the `core.whitespace`
727 + configuration variable.
728
729 Unset::
730
@@ -730,13 +732,13 @@ Unset::
732
733 Unspecified::
734
733 - Use the value of `core.whitespace` configuration variable to
735 + Use the value of the `core.whitespace` configuration variable to
736 decide what to notice as error.
737
738 String::
739
740 Specify a comma separate list of common whitespace problems to
739 - notice in the same format as `core.whitespace` configuration
741 + notice in the same format as the `core.whitespace` configuration
742 variable.
743
744
cache.h
+10 -7
@@ -1087,15 +1087,17 @@ void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *
1087 /*
1088 * whitespace rules.
1089 * used by both diff and apply
1090 + * last two digits are tab width
1091 */
1091 -#define WS_BLANK_AT_EOL 01
1092 -#define WS_SPACE_BEFORE_TAB 02
1093 -#define WS_INDENT_WITH_NON_TAB 04
1094 -#define WS_CR_AT_EOL 010
1095 -#define WS_BLANK_AT_EOF 020
1096 -#define WS_TAB_IN_INDENT 040
1092 +#define WS_BLANK_AT_EOL 0100
1093 +#define WS_SPACE_BEFORE_TAB 0200
1094 +#define WS_INDENT_WITH_NON_TAB 0400
1095 +#define WS_CR_AT_EOL 01000
1096 +#define WS_BLANK_AT_EOF 02000
1097 +#define WS_TAB_IN_INDENT 04000
1098 #define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
1098 -#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB)
1099 +#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
1100 +#define WS_TAB_WIDTH_MASK 077
1101 extern unsigned whitespace_rule_cfg;
1102 extern unsigned whitespace_rule(const char *);
1103 extern unsigned parse_whitespace_rule(const char *);
@@ -1104,6 +1106,7 @@ extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *str
1106 extern char *whitespace_error_string(unsigned ws);
1107 extern void ws_fix_copy(struct strbuf *, const char *, int, unsigned, int *);
1108 extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
1109 +#define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK)
1110
1111 /* ls-files */
1112 int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);
t/t4015-diff-whitespace.sh
+28
@@ -344,6 +344,13 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
344
345 '
346
347 +test_expect_success 'ditto, but tabwidth=9' '
348 +
349 + git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
350 + git diff --check
351 +
352 +'
353 +
354 test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '
355
356 git config core.whitespace "indent-with-non-tab" &&
@@ -352,6 +359,20 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab:
359
360 '
361
362 +test_expect_success 'ditto, but tabwidth=10' '
363 +
364 + git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
365 + test_must_fail git diff --check
366 +
367 +'
368 +
369 +test_expect_success 'ditto, but tabwidth=20' '
370 +
371 + git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
372 + git diff --check
373 +
374 +'
375 +
376 test_expect_success 'check tabs as indentation (tab-in-indent: off)' '
377
378 git config core.whitespace "-tab-in-indent" &&
@@ -376,6 +397,13 @@ test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '
397
398 '
399
400 +test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' '
401 +
402 + git config core.whitespace "tab-in-indent,tabwidth=1" &&
403 + test_must_fail git diff --check
404 +
405 +'
406 +
407 test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '
408
409 git config core.whitespace "tab-in-indent,indent-with-non-tab" &&
t/t4019-diff-wserror.sh
+85
@@ -51,8 +51,65 @@ test_expect_success default '
51
52 '
53
54 +test_expect_success 'default (attribute)' '
55 +
56 + test_might_fail git config --unset core.whitespace &&
57 + echo "F whitespace" >.gitattributes &&
58 + prepare_output &&
59 +
60 + grep Eight error >/dev/null &&
61 + grep HT error >/dev/null &&
62 + grep With error >/dev/null &&
63 + grep Return error >/dev/null &&
64 + grep No normal >/dev/null
65 +
66 +'
67 +
68 +test_expect_success 'default, tabwidth=10 (attribute)' '
69 +
70 + git config core.whitespace "tabwidth=10" &&
71 + echo "F whitespace" >.gitattributes &&
72 + prepare_output &&
73 +
74 + grep Eight normal >/dev/null &&
75 + grep HT error >/dev/null &&
76 + grep With error >/dev/null &&
77 + grep Return error >/dev/null &&
78 + grep No normal >/dev/null
79 +
80 +'
81 +
82 +test_expect_success 'no check (attribute)' '
83 +
84 + test_might_fail git config --unset core.whitespace &&
85 + echo "F -whitespace" >.gitattributes &&
86 + prepare_output &&
87 +
88 + grep Eight normal >/dev/null &&
89 + grep HT normal >/dev/null &&
90 + grep With normal >/dev/null &&
91 + grep Return normal >/dev/null &&
92 + grep No normal >/dev/null
93 +
94 +'
95 +
96 +test_expect_success 'no check, tabwidth=10 (attribute), must be irrelevant' '
97 +
98 + git config core.whitespace "tabwidth=10" &&
99 + echo "F -whitespace" >.gitattributes &&
100 + prepare_output &&
101 +
102 + grep Eight normal >/dev/null &&
103 + grep HT normal >/dev/null &&
104 + grep With normal >/dev/null &&
105 + grep Return normal >/dev/null &&
106 + grep No normal >/dev/null
107 +
108 +'
109 +
110 test_expect_success 'without -trail' '
111
112 + rm -f .gitattributes &&
113 git config core.whitespace -trail &&
114 prepare_output &&
115
@@ -134,6 +191,34 @@ test_expect_success 'with indent-non-tab only (attribute)' '
191
192 '
193
194 +test_expect_success 'with indent-non-tab only, tabwidth=10' '
195 +
196 + rm -f .gitattributes &&
197 + git config core.whitespace indent,tabwidth=10,-trailing,-space &&
198 + prepare_output &&
199 +
200 + grep Eight normal >/dev/null &&
201 + grep HT normal >/dev/null &&
202 + grep With normal >/dev/null &&
203 + grep Return normal >/dev/null &&
204 + grep No normal >/dev/null
205 +
206 +'
207 +
208 +test_expect_success 'with indent-non-tab only, tabwidth=10 (attribute)' '
209 +
210 + test_might_fail git config --unset core.whitespace &&
211 + echo "F whitespace=indent,-trailing,-space,tabwidth=10" >.gitattributes &&
212 + prepare_output &&
213 +
214 + grep Eight normal >/dev/null &&
215 + grep HT normal >/dev/null &&
216 + grep With normal >/dev/null &&
217 + grep Return normal >/dev/null &&
218 + grep No normal >/dev/null
219 +
220 +'
221 +
222 test_expect_success 'with cr-at-eol' '
223
224 rm -f .gitattributes &&
t/t4124-apply-ws-rule.sh
+17 -6
@@ -10,7 +10,8 @@ prepare_test_file () {
10 # X RULE
11 # ! trailing-space
12 # @ space-before-tab
13 - # # indent-with-non-tab
13 + # # indent-with-non-tab (default tab width 8)
14 + # = indent-with-non-tab,tabwidth=16
15 # % tab-in-indent
16 sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF
17 An_SP in an ordinary line>and a HT.
@@ -25,8 +26,8 @@ prepare_test_file () {
26 ________>_Eight SP, a HT and a SP (@#%).
27 _______________Fifteen SP (#).
28 _______________>Fifteen SP and a HT (@#%).
28 - ________________Sixteen SP (#).
29 - ________________>Sixteen SP and a HT (@#%).
29 + ________________Sixteen SP (#=).
30 + ________________>Sixteen SP and a HT (@#%=).
31 _____a__Five SP, a non WS, two SP.
32 A line with a (!) trailing SP_
33 A line with a (!) trailing HT>
@@ -139,8 +140,8 @@ test_expect_success 'spaces inserted by tab-in-indent' '
140 _________________Eight SP, a HT and a SP (@#%).
141 _______________Fifteen SP (#).
142 ________________Fifteen SP and a HT (@#%).
142 - ________________Sixteen SP (#).
143 - ________________________Sixteen SP and a HT (@#%).
143 + ________________Sixteen SP (#=).
144 + ________________________Sixteen SP and a HT (@#%=).
145 _____a__Five SP, a non WS, two SP.
146 A line with a (!) trailing SP_
147 A line with a (!) trailing HT>
@@ -157,7 +158,7 @@ do
158 case "$s" in '') ts='@' ;; *) ts= ;; esac
159 for i in - ''
160 do
160 - case "$i" in '') ti='#' ;; *) ti= ;; esac
161 + case "$i" in '') ti='#' ti16='=';; *) ti= ti16= ;; esac
162 for h in - ''
163 do
164 [ -z "$h$i" ] && continue
@@ -170,12 +171,22 @@ do
171 test_fix "$tt$ts$ti$th"
172 '
173
174 + test_expect_success "rule=$rule,tabwidth=16" '
175 + git config core.whitespace "$rule,tabwidth=16" &&
176 + test_fix "$tt$ts$ti16$th"
177 + '
178 +
179 test_expect_success "rule=$rule (attributes)" '
180 git config --unset core.whitespace &&
181 echo "target whitespace=$rule" >.gitattributes &&
182 test_fix "$tt$ts$ti$th"
183 '
184
185 + test_expect_success "rule=$rule,tabwidth=16 (attributes)" '
186 + echo "target whitespace=$rule,tabwidth=16" >.gitattributes &&
187 + test_fix "$tt$ts$ti16$th"
188 + '
189 +
190 done
191 done
192 done
ws.c
+16 -6
@@ -56,6 +56,16 @@ unsigned parse_whitespace_rule(const char *string)
56 rule |= whitespace_rule_names[i].rule_bits;
57 break;
58 }
59 + if (strncmp(string, "tabwidth=", 9) == 0) {
60 + unsigned tabwidth = atoi(string + 9);
61 + if (0 < tabwidth && tabwidth < 0100) {
62 + rule &= ~WS_TAB_WIDTH_MASK;
63 + rule |= tabwidth;
64 + }
65 + else
66 + warning("tabwidth %.*s out of range",
67 + (int)(len - 9), string + 9);
68 + }
69 string = ep;
70 }
71
@@ -84,7 +94,7 @@ unsigned whitespace_rule(const char *pathname)
94 value = attr_whitespace_rule.value;
95 if (ATTR_TRUE(value)) {
96 /* true (whitespace) */
87 - unsigned all_rule = 0;
97 + unsigned all_rule = ws_tab_width(whitespace_rule_cfg);
98 int i;
99 for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++)
100 if (!whitespace_rule_names[i].loosens_error &&
@@ -93,7 +103,7 @@ unsigned whitespace_rule(const char *pathname)
103 return all_rule;
104 } else if (ATTR_FALSE(value)) {
105 /* false (-whitespace) */
96 - return 0;
106 + return ws_tab_width(whitespace_rule_cfg);
107 } else if (ATTR_UNSET(value)) {
108 /* reset to default (!whitespace) */
109 return whitespace_rule_cfg;
@@ -206,7 +216,7 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
216 }
217
218 /* Check for indent using non-tab. */
209 - if ((ws_rule & WS_INDENT_WITH_NON_TAB) && i - written >= 8) {
219 + if ((ws_rule & WS_INDENT_WITH_NON_TAB) && i - written >= ws_tab_width(ws_rule)) {
220 result |= WS_INDENT_WITH_NON_TAB;
221 if (stream) {
222 fputs(ws, stream);
@@ -320,7 +330,7 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
330 } else if (ch == ' ') {
331 last_space_in_indent = i;
332 if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
323 - 8 <= i - last_tab_in_indent)
333 + ws_tab_width(ws_rule) <= i - last_tab_in_indent)
334 need_fix_leading_space = 1;
335 } else
336 break;
@@ -350,7 +360,7 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
360 strbuf_addch(dst, ch);
361 } else {
362 consecutive_spaces++;
353 - if (consecutive_spaces == 8) {
363 + if (consecutive_spaces == ws_tab_width(ws_rule)) {
364 strbuf_addch(dst, '\t');
365 consecutive_spaces = 0;
366 }
@@ -369,7 +379,7 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
379 if (src[i] == '\t')
380 do {
381 strbuf_addch(dst, ' ');
372 - } while ((dst->len - start) % 8);
382 + } while ((dst->len - start) % ws_tab_width(ws_rule));
383 else
384 strbuf_addch(dst, src[i]);
385 }