Merge branch 'js/configurable-tab'

* js/configurable-tab:
  Make the tab width used for whitespace checks configurable
  apply --whitespace=fix: fix tab-in-indent
maint
Junio C Hamano 2010-12-12 21:49:52 -08:00
commit 47bfb3d946
7 changed files with 190 additions and 19 deletions

View File

@ -522,6 +522,9 @@ core.whitespace::
part of the line terminator, i.e. with it, `trailing-space` part of the line terminator, i.e. with it, `trailing-space`
does not trigger if the character before such a carriage-return does not trigger if the character before such a carriage-return
is not a whitespace (not enabled by default). is not a whitespace (not enabled by default).
* `tabwidth=<n>` tells how many character positions a tab occupies; this
is relevant for `indent-with-non-tab` and when git fixes `tab-in-indent`
errors. The default tab width is 8. Allowed values are 1 to 63.


core.fsyncobjectfiles:: core.fsyncobjectfiles::
This boolean will enable 'fsync()' when writing object files. This boolean will enable 'fsync()' when writing object files.

View File

@ -723,6 +723,8 @@ control per path.
Set:: Set::


Notice all types of potential whitespace errors known to git. Notice all types of potential whitespace errors known to git.
The tab width is taken from the value of the `core.whitespace`
configuration variable.


Unset:: Unset::


@ -730,13 +732,13 @@ Unset::


Unspecified:: Unspecified::


Use the value of `core.whitespace` configuration variable to Use the value of the `core.whitespace` configuration variable to
decide what to notice as error. decide what to notice as error.


String:: String::


Specify a comma separate list of common whitespace problems to Specify a comma separate list of common whitespace problems to
notice in the same format as `core.whitespace` configuration notice in the same format as the `core.whitespace` configuration
variable. variable.





17
cache.h
View File

@ -1091,15 +1091,17 @@ void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *
/* /*
* whitespace rules. * whitespace rules.
* used by both diff and apply * used by both diff and apply
* last two digits are tab width
*/ */
#define WS_BLANK_AT_EOL 01 #define WS_BLANK_AT_EOL 0100
#define WS_SPACE_BEFORE_TAB 02 #define WS_SPACE_BEFORE_TAB 0200
#define WS_INDENT_WITH_NON_TAB 04 #define WS_INDENT_WITH_NON_TAB 0400
#define WS_CR_AT_EOL 010 #define WS_CR_AT_EOL 01000
#define WS_BLANK_AT_EOF 020 #define WS_BLANK_AT_EOF 02000
#define WS_TAB_IN_INDENT 040 #define WS_TAB_IN_INDENT 04000
#define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF) #define WS_TRAILING_SPACE (WS_BLANK_AT_EOL|WS_BLANK_AT_EOF)
#define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB) #define WS_DEFAULT_RULE (WS_TRAILING_SPACE|WS_SPACE_BEFORE_TAB|8)
#define WS_TAB_WIDTH_MASK 077
extern unsigned whitespace_rule_cfg; extern unsigned whitespace_rule_cfg;
extern unsigned whitespace_rule(const char *); extern unsigned whitespace_rule(const char *);
extern unsigned parse_whitespace_rule(const char *); extern unsigned parse_whitespace_rule(const char *);
@ -1108,6 +1110,7 @@ extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *str
extern char *whitespace_error_string(unsigned ws); extern char *whitespace_error_string(unsigned ws);
extern void ws_fix_copy(struct strbuf *, 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); extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
#define ws_tab_width(rule) ((rule) & WS_TAB_WIDTH_MASK)


/* ls-files */ /* ls-files */
int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset); int report_path_error(const char *ps_matched, const char **pathspec, int prefix_offset);

View File

@ -344,6 +344,13 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '


' '


test_expect_success 'ditto, but tabwidth=9' '

git config core.whitespace "indent-with-non-tab,tabwidth=9" &&
git diff --check

'

test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' ' test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab: on)' '


git config core.whitespace "indent-with-non-tab" && 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:


' '


test_expect_success 'ditto, but tabwidth=10' '

git config core.whitespace "indent-with-non-tab,tabwidth=10" &&
test_must_fail git diff --check

'

test_expect_success 'ditto, but tabwidth=20' '

git config core.whitespace "indent-with-non-tab,tabwidth=20" &&
git diff --check

'

test_expect_success 'check tabs as indentation (tab-in-indent: off)' ' test_expect_success 'check tabs as indentation (tab-in-indent: off)' '


git config core.whitespace "-tab-in-indent" && git config core.whitespace "-tab-in-indent" &&
@ -376,6 +397,13 @@ test_expect_success 'check tabs and spaces as indentation (tab-in-indent: on)' '


' '


test_expect_success 'ditto, but tabwidth=1 (must be irrelevant)' '

git config core.whitespace "tab-in-indent,tabwidth=1" &&
test_must_fail git diff --check

'

test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' ' test_expect_success 'check tab-in-indent and indent-with-non-tab conflict' '


git config core.whitespace "tab-in-indent,indent-with-non-tab" && git config core.whitespace "tab-in-indent,indent-with-non-tab" &&

View File

@ -51,8 +51,65 @@ test_expect_success default '


' '


test_expect_success 'default (attribute)' '

test_might_fail git config --unset core.whitespace &&
echo "F whitespace" >.gitattributes &&
prepare_output &&

grep Eight error >/dev/null &&
grep HT error >/dev/null &&
grep With error >/dev/null &&
grep Return error >/dev/null &&
grep No normal >/dev/null

'

test_expect_success 'default, tabwidth=10 (attribute)' '

git config core.whitespace "tabwidth=10" &&
echo "F whitespace" >.gitattributes &&
prepare_output &&

grep Eight normal >/dev/null &&
grep HT error >/dev/null &&
grep With error >/dev/null &&
grep Return error >/dev/null &&
grep No normal >/dev/null

'

test_expect_success 'no check (attribute)' '

test_might_fail git config --unset core.whitespace &&
echo "F -whitespace" >.gitattributes &&
prepare_output &&

grep Eight normal >/dev/null &&
grep HT normal >/dev/null &&
grep With normal >/dev/null &&
grep Return normal >/dev/null &&
grep No normal >/dev/null

'

test_expect_success 'no check, tabwidth=10 (attribute), must be irrelevant' '

git config core.whitespace "tabwidth=10" &&
echo "F -whitespace" >.gitattributes &&
prepare_output &&

grep Eight normal >/dev/null &&
grep HT normal >/dev/null &&
grep With normal >/dev/null &&
grep Return normal >/dev/null &&
grep No normal >/dev/null

'

test_expect_success 'without -trail' ' test_expect_success 'without -trail' '


rm -f .gitattributes &&
git config core.whitespace -trail && git config core.whitespace -trail &&
prepare_output && prepare_output &&


@ -134,6 +191,34 @@ test_expect_success 'with indent-non-tab only (attribute)' '


' '


test_expect_success 'with indent-non-tab only, tabwidth=10' '

rm -f .gitattributes &&
git config core.whitespace indent,tabwidth=10,-trailing,-space &&
prepare_output &&

grep Eight normal >/dev/null &&
grep HT normal >/dev/null &&
grep With normal >/dev/null &&
grep Return normal >/dev/null &&
grep No normal >/dev/null

'

test_expect_success 'with indent-non-tab only, tabwidth=10 (attribute)' '

test_might_fail git config --unset core.whitespace &&
echo "F whitespace=indent,-trailing,-space,tabwidth=10" >.gitattributes &&
prepare_output &&

grep Eight normal >/dev/null &&
grep HT normal >/dev/null &&
grep With normal >/dev/null &&
grep Return normal >/dev/null &&
grep No normal >/dev/null

'

test_expect_success 'with cr-at-eol' ' test_expect_success 'with cr-at-eol' '


rm -f .gitattributes && rm -f .gitattributes &&

View File

@ -10,7 +10,8 @@ prepare_test_file () {
# X RULE # X RULE
# ! trailing-space # ! trailing-space
# @ space-before-tab # @ space-before-tab
# # indent-with-non-tab # # indent-with-non-tab (default tab width 8)
# = indent-with-non-tab,tabwidth=16
# % tab-in-indent # % tab-in-indent
sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF
An_SP in an ordinary line>and a HT. An_SP in an ordinary line>and a HT.
@ -25,8 +26,8 @@ prepare_test_file () {
________>_Eight SP, a HT and a SP (@#%). ________>_Eight SP, a HT and a SP (@#%).
_______________Fifteen SP (#). _______________Fifteen SP (#).
_______________>Fifteen SP and a HT (@#%). _______________>Fifteen SP and a HT (@#%).
________________Sixteen SP (#). ________________Sixteen SP (#=).
________________>Sixteen SP and a HT (@#%). ________________>Sixteen SP and a HT (@#%=).
_____a__Five SP, a non WS, two SP. _____a__Five SP, a non WS, two SP.
A line with a (!) trailing SP_ A line with a (!) trailing SP_
A line with a (!) trailing HT> A line with a (!) trailing HT>
@ -121,6 +122,34 @@ test_expect_success 'whitespace=error-all, no rule (attribute)' '


' '


test_expect_success 'spaces inserted by tab-in-indent' '

git config core.whitespace -trailing,-space,-indent,tab &&
rm -f .gitattributes &&
test_fix % &&
sed -e "s/_/ /g" -e "s/>/ /" <<-\EOF >expect &&
An_SP in an ordinary line>and a HT.
________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 (@#%).
_______________Fifteen SP (#).
________________Fifteen SP and a HT (@#%).
________________Sixteen SP (#=).
________________________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>
EOF
test_cmp expect target

'

for t in - '' for t in - ''
do do
case "$t" in '') tt='!' ;; *) tt= ;; esac case "$t" in '') tt='!' ;; *) tt= ;; esac
@ -129,7 +158,7 @@ do
case "$s" in '') ts='@' ;; *) ts= ;; esac case "$s" in '') ts='@' ;; *) ts= ;; esac
for i in - '' for i in - ''
do do
case "$i" in '') ti='#' ;; *) ti= ;; esac case "$i" in '') ti='#' ti16='=';; *) ti= ti16= ;; esac
for h in - '' for h in - ''
do do
[ -z "$h$i" ] && continue [ -z "$h$i" ] && continue
@ -142,12 +171,22 @@ do
test_fix "$tt$ts$ti$th" test_fix "$tt$ts$ti$th"
' '


test_expect_success "rule=$rule,tabwidth=16" '
git config core.whitespace "$rule,tabwidth=16" &&
test_fix "$tt$ts$ti16$th"
'

test_expect_success "rule=$rule (attributes)" ' test_expect_success "rule=$rule (attributes)" '
git config --unset core.whitespace && git config --unset core.whitespace &&
echo "target whitespace=$rule" >.gitattributes && echo "target whitespace=$rule" >.gitattributes &&
test_fix "$tt$ts$ti$th" test_fix "$tt$ts$ti$th"
' '


test_expect_success "rule=$rule,tabwidth=16 (attributes)" '
echo "target whitespace=$rule,tabwidth=16" >.gitattributes &&
test_fix "$tt$ts$ti16$th"
'

done done
done done
done done

23
ws.c
View File

@ -56,6 +56,16 @@ unsigned parse_whitespace_rule(const char *string)
rule |= whitespace_rule_names[i].rule_bits; rule |= whitespace_rule_names[i].rule_bits;
break; break;
} }
if (strncmp(string, "tabwidth=", 9) == 0) {
unsigned tabwidth = atoi(string + 9);
if (0 < tabwidth && tabwidth < 0100) {
rule &= ~WS_TAB_WIDTH_MASK;
rule |= tabwidth;
}
else
warning("tabwidth %.*s out of range",
(int)(len - 9), string + 9);
}
string = ep; string = ep;
} }


@ -84,7 +94,7 @@ unsigned whitespace_rule(const char *pathname)
value = attr_whitespace_rule.value; value = attr_whitespace_rule.value;
if (ATTR_TRUE(value)) { if (ATTR_TRUE(value)) {
/* true (whitespace) */ /* true (whitespace) */
unsigned all_rule = 0; unsigned all_rule = ws_tab_width(whitespace_rule_cfg);
int i; int i;
for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); 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 &&
@ -93,7 +103,7 @@ unsigned whitespace_rule(const char *pathname)
return all_rule; return all_rule;
} else if (ATTR_FALSE(value)) { } else if (ATTR_FALSE(value)) {
/* false (-whitespace) */ /* false (-whitespace) */
return 0; return ws_tab_width(whitespace_rule_cfg);
} else if (ATTR_UNSET(value)) { } else if (ATTR_UNSET(value)) {
/* reset to default (!whitespace) */ /* reset to default (!whitespace) */
return whitespace_rule_cfg; return whitespace_rule_cfg;
@ -206,7 +216,7 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
} }


/* Check for indent using non-tab. */ /* Check for indent using non-tab. */
if ((ws_rule & WS_INDENT_WITH_NON_TAB) && i - written >= 8) { if ((ws_rule & WS_INDENT_WITH_NON_TAB) && i - written >= ws_tab_width(ws_rule)) {
result |= WS_INDENT_WITH_NON_TAB; result |= WS_INDENT_WITH_NON_TAB;
if (stream) { if (stream) {
fputs(ws, stream); fputs(ws, stream);
@ -320,7 +330,7 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
} else if (ch == ' ') { } else if (ch == ' ') {
last_space_in_indent = i; last_space_in_indent = i;
if ((ws_rule & WS_INDENT_WITH_NON_TAB) && if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
8 <= i - last_tab_in_indent) ws_tab_width(ws_rule) <= i - last_tab_in_indent)
need_fix_leading_space = 1; need_fix_leading_space = 1;
} else } else
break; break;
@ -350,7 +360,7 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
strbuf_addch(dst, ch); strbuf_addch(dst, ch);
} else { } else {
consecutive_spaces++; consecutive_spaces++;
if (consecutive_spaces == 8) { if (consecutive_spaces == ws_tab_width(ws_rule)) {
strbuf_addch(dst, '\t'); strbuf_addch(dst, '\t');
consecutive_spaces = 0; consecutive_spaces = 0;
} }
@ -363,12 +373,13 @@ void ws_fix_copy(struct strbuf *dst, const char *src, int len, unsigned ws_rule,
fixed = 1; fixed = 1;
} else if ((ws_rule & WS_TAB_IN_INDENT) && last_tab_in_indent >= 0) { } else if ((ws_rule & WS_TAB_IN_INDENT) && last_tab_in_indent >= 0) {
/* Expand tabs into spaces */ /* Expand tabs into spaces */
int start = dst->len;
int last = last_tab_in_indent + 1; int last = last_tab_in_indent + 1;
for (i = 0; i < last; i++) { for (i = 0; i < last; i++) {
if (src[i] == '\t') if (src[i] == '\t')
do { do {
strbuf_addch(dst, ' '); strbuf_addch(dst, ' ');
} while (dst->len % 8); } while ((dst->len - start) % ws_tab_width(ws_rule));
else else
strbuf_addch(dst, src[i]); strbuf_addch(dst, src[i]);
} }