Merge branch 'js/configurable-tab'
* js/configurable-tab: Make the tab width used for whitespace checks configurable apply --whitespace=fix: fix tab-in-indentmaint
commit
47bfb3d946
|
@ -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.
|
||||||
|
|
|
@ -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
17
cache.h
|
@ -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);
|
||||||
|
|
|
@ -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" &&
|
||||||
|
|
|
@ -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 &&
|
||||||
|
|
|
@ -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
23
ws.c
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue