Merge branch 'cw/ws-indent-with-tab'
* cw/ws-indent-with-tab: whitespace: tests for git-apply --whitespace=fix with tab-in-indent whitespace: add tab-in-indent support for --whitespace=fix whitespace: replumb ws_fix_copy to take a strbuf *dst instead of char *dst whitespace: tests for git-diff --check with tab-in-indent error class whitespace: add tab-in-indent error class whitespace: we cannot "catch all errors known to git" anymore
This commit is contained in:
commit
c58c5129d6
@ -481,6 +481,8 @@ core.whitespace::
|
|||||||
error (enabled by default).
|
error (enabled by default).
|
||||||
* `indent-with-non-tab` treats a line that is indented with 8 or more
|
* `indent-with-non-tab` treats a line that is indented with 8 or more
|
||||||
space characters as an error (not enabled by default).
|
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
|
* `blank-at-eof` treats blank lines added at the end of file as an error
|
||||||
(enabled by default).
|
(enabled by default).
|
||||||
* `trailing-space` is a short-hand to cover both `blank-at-eol` and
|
* `trailing-space` is a short-hand to cover both `blank-at-eol` and
|
||||||
|
@ -1854,6 +1854,8 @@ static int match_fragment(struct image *img,
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *fixed_buf, *buf, *orig, *target;
|
char *fixed_buf, *buf, *orig, *target;
|
||||||
|
struct strbuf fixed;
|
||||||
|
size_t fixed_len;
|
||||||
int preimage_limit;
|
int preimage_limit;
|
||||||
|
|
||||||
if (preimage->nr + try_lno <= img->nr) {
|
if (preimage->nr + try_lno <= img->nr) {
|
||||||
@ -1977,12 +1979,12 @@ static int match_fragment(struct image *img,
|
|||||||
* use the whitespace from the preimage.
|
* use the whitespace from the preimage.
|
||||||
*/
|
*/
|
||||||
extra_chars = preimage_end - preimage_eof;
|
extra_chars = preimage_end - preimage_eof;
|
||||||
fixed_buf = xmalloc(imgoff + extra_chars);
|
strbuf_init(&fixed, imgoff + extra_chars);
|
||||||
memcpy(fixed_buf, img->buf + try, imgoff);
|
strbuf_add(&fixed, img->buf + try, imgoff);
|
||||||
memcpy(fixed_buf + imgoff, preimage_eof, extra_chars);
|
strbuf_add(&fixed, preimage_eof, extra_chars);
|
||||||
imgoff += extra_chars;
|
fixed_buf = strbuf_detach(&fixed, &fixed_len);
|
||||||
update_pre_post_images(preimage, postimage,
|
update_pre_post_images(preimage, postimage,
|
||||||
fixed_buf, imgoff, postlen);
|
fixed_buf, fixed_len, postlen);
|
||||||
return 1;
|
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
|
* but in this loop we will only handle the part of the
|
||||||
* preimage that falls within the file.
|
* preimage that falls within the file.
|
||||||
*/
|
*/
|
||||||
fixed_buf = xmalloc(preimage->len + 1);
|
strbuf_init(&fixed, preimage->len + 1);
|
||||||
buf = fixed_buf;
|
|
||||||
orig = preimage->buf;
|
orig = preimage->buf;
|
||||||
target = img->buf + try;
|
target = img->buf + try;
|
||||||
for (i = 0; i < preimage_limit; i++) {
|
for (i = 0; i < preimage_limit; i++) {
|
||||||
size_t fixlen; /* length after fixing the preimage */
|
|
||||||
size_t oldlen = preimage->line[i].len;
|
size_t oldlen = preimage->line[i].len;
|
||||||
size_t tgtlen = img->line[try_lno + i].len;
|
size_t tgtlen = img->line[try_lno + i].len;
|
||||||
size_t tgtfixlen; /* length after fixing the target line */
|
size_t fixstart = fixed.len;
|
||||||
char tgtfixbuf[1024], *tgtfix;
|
struct strbuf tgtfix;
|
||||||
int match;
|
int match;
|
||||||
|
|
||||||
/* Try fixing the line in the preimage */
|
/* 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 */
|
/* Try fixing the line in the target */
|
||||||
if (sizeof(tgtfixbuf) > tgtlen)
|
strbuf_init(&tgtfix, tgtlen);
|
||||||
tgtfix = tgtfixbuf;
|
ws_fix_copy(&tgtfix, target, tgtlen, ws_rule, NULL);
|
||||||
else
|
|
||||||
tgtfix = xmalloc(tgtlen);
|
|
||||||
tgtfixlen = ws_fix_copy(tgtfix, target, tgtlen, ws_rule, NULL);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If they match, either the preimage was based on
|
* 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
|
* so we might as well take the fix together with their
|
||||||
* real change.
|
* 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)
|
strbuf_release(&tgtfix);
|
||||||
free(tgtfix);
|
|
||||||
if (!match)
|
if (!match)
|
||||||
goto unmatch_exit;
|
goto unmatch_exit;
|
||||||
|
|
||||||
orig += oldlen;
|
orig += oldlen;
|
||||||
buf += fixlen;
|
|
||||||
target += tgtlen;
|
target += tgtlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2051,19 +2048,18 @@ static int match_fragment(struct image *img,
|
|||||||
* false).
|
* false).
|
||||||
*/
|
*/
|
||||||
for ( ; i < preimage->nr; i++) {
|
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;
|
size_t oldlen = preimage->line[i].len;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
/* Try fixing the line in the preimage */
|
/* 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++)
|
for (j = fixstart; j < fixed.len; j++)
|
||||||
if (!isspace(buf[j]))
|
if (!isspace(fixed.buf[j]))
|
||||||
goto unmatch_exit;
|
goto unmatch_exit;
|
||||||
|
|
||||||
orig += oldlen;
|
orig += oldlen;
|
||||||
buf += fixlen;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2071,12 +2067,13 @@ static int match_fragment(struct image *img,
|
|||||||
* has whitespace breakages unfixed, and fixing them makes the
|
* has whitespace breakages unfixed, and fixing them makes the
|
||||||
* hunk match. Update the context lines in the postimage.
|
* hunk match. Update the context lines in the postimage.
|
||||||
*/
|
*/
|
||||||
|
fixed_buf = strbuf_detach(&fixed, &fixed_len);
|
||||||
update_pre_post_images(preimage, postimage,
|
update_pre_post_images(preimage, postimage,
|
||||||
fixed_buf, buf - fixed_buf, 0);
|
fixed_buf, fixed_len, 0);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
unmatch_exit:
|
unmatch_exit:
|
||||||
free(fixed_buf);
|
strbuf_release(&fixed);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2244,7 +2241,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
|
|||||||
int match_beginning, match_end;
|
int match_beginning, match_end;
|
||||||
const char *patch = frag->patch;
|
const char *patch = frag->patch;
|
||||||
int size = frag->size;
|
int size = frag->size;
|
||||||
char *old, *new, *oldlines, *newlines;
|
char *old, *oldlines;
|
||||||
|
struct strbuf newlines;
|
||||||
int new_blank_lines_at_end = 0;
|
int new_blank_lines_at_end = 0;
|
||||||
unsigned long leading, trailing;
|
unsigned long leading, trailing;
|
||||||
int pos, applied_pos;
|
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(&preimage, 0, sizeof(preimage));
|
||||||
memset(&postimage, 0, sizeof(postimage));
|
memset(&postimage, 0, sizeof(postimage));
|
||||||
oldlines = xmalloc(size);
|
oldlines = xmalloc(size);
|
||||||
newlines = xmalloc(size);
|
strbuf_init(&newlines, size);
|
||||||
|
|
||||||
old = oldlines;
|
old = oldlines;
|
||||||
new = newlines;
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
char first;
|
char first;
|
||||||
int len = linelen(patch, size);
|
int len = linelen(patch, size);
|
||||||
int plen, added;
|
int plen;
|
||||||
int added_blank_line = 0;
|
int added_blank_line = 0;
|
||||||
int is_blank_context = 0;
|
int is_blank_context = 0;
|
||||||
|
size_t start;
|
||||||
|
|
||||||
if (!len)
|
if (!len)
|
||||||
break;
|
break;
|
||||||
@ -2293,7 +2291,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
|
|||||||
/* ... followed by '\No newline'; nothing */
|
/* ... followed by '\No newline'; nothing */
|
||||||
break;
|
break;
|
||||||
*old++ = '\n';
|
*old++ = '\n';
|
||||||
*new++ = '\n';
|
strbuf_addch(&newlines, '\n');
|
||||||
add_line_info(&preimage, "\n", 1, LINE_COMMON);
|
add_line_info(&preimage, "\n", 1, LINE_COMMON);
|
||||||
add_line_info(&postimage, "\n", 1, LINE_COMMON);
|
add_line_info(&postimage, "\n", 1, LINE_COMMON);
|
||||||
is_blank_context = 1;
|
is_blank_context = 1;
|
||||||
@ -2315,18 +2313,17 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
|
|||||||
if (first == '+' && no_add)
|
if (first == '+' && no_add)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
start = newlines.len;
|
||||||
if (first != '+' ||
|
if (first != '+' ||
|
||||||
!whitespace_error ||
|
!whitespace_error ||
|
||||||
ws_error_action != correct_ws_error) {
|
ws_error_action != correct_ws_error) {
|
||||||
memcpy(new, patch + 1, plen);
|
strbuf_add(&newlines, patch + 1, plen);
|
||||||
added = plen;
|
|
||||||
}
|
}
|
||||||
else {
|
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));
|
(first == '+' ? 0 : LINE_COMMON));
|
||||||
new += added;
|
|
||||||
if (first == '+' &&
|
if (first == '+' &&
|
||||||
(ws_rule & WS_BLANK_AT_EOF) &&
|
(ws_rule & WS_BLANK_AT_EOF) &&
|
||||||
ws_blank_line(patch + 1, plen, ws_rule))
|
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 &&
|
if (inaccurate_eof &&
|
||||||
old > oldlines && old[-1] == '\n' &&
|
old > oldlines && old[-1] == '\n' &&
|
||||||
new > newlines && new[-1] == '\n') {
|
newlines.len > 0 && newlines.buf[newlines.len - 1] == '\n') {
|
||||||
old--;
|
old--;
|
||||||
new--;
|
strbuf_setlen(&newlines, newlines.len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
leading = frag->leading;
|
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;
|
pos = frag->newpos ? (frag->newpos - 1) : 0;
|
||||||
preimage.buf = oldlines;
|
preimage.buf = oldlines;
|
||||||
preimage.len = old - oldlines;
|
preimage.len = old - oldlines;
|
||||||
postimage.buf = newlines;
|
postimage.buf = newlines.buf;
|
||||||
postimage.len = new - newlines;
|
postimage.len = newlines.len;
|
||||||
preimage.line = preimage.line_allocated;
|
preimage.line = preimage.line_allocated;
|
||||||
postimage.line = postimage.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(oldlines);
|
||||||
free(newlines);
|
strbuf_release(&newlines);
|
||||||
free(preimage.line_allocated);
|
free(preimage.line_allocated);
|
||||||
free(postimage.line_allocated);
|
free(postimage.line_allocated);
|
||||||
|
|
||||||
|
3
cache.h
3
cache.h
@ -1042,6 +1042,7 @@ void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *
|
|||||||
#define WS_INDENT_WITH_NON_TAB 04
|
#define WS_INDENT_WITH_NON_TAB 04
|
||||||
#define WS_CR_AT_EOL 010
|
#define WS_CR_AT_EOL 010
|
||||||
#define WS_BLANK_AT_EOF 020
|
#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_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)
|
||||||
extern unsigned whitespace_rule_cfg;
|
extern unsigned whitespace_rule_cfg;
|
||||||
@ -1050,7 +1051,7 @@ extern unsigned parse_whitespace_rule(const char *);
|
|||||||
extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
|
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 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 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);
|
extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
|
||||||
|
|
||||||
/* ls-files */
|
/* ls-files */
|
||||||
|
@ -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' '
|
test_expect_success 'line numbers in --check output are correct' '
|
||||||
|
|
||||||
echo "" > x &&
|
echo "" > x &&
|
||||||
|
@ -11,21 +11,22 @@ prepare_test_file () {
|
|||||||
# ! trailing-space
|
# ! trailing-space
|
||||||
# @ space-before-tab
|
# @ space-before-tab
|
||||||
# # indent-with-non-tab
|
# # indent-with-non-tab
|
||||||
|
# % 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.
|
||||||
>A HT.
|
>A HT (%).
|
||||||
_>A SP and a HT (@).
|
_>A SP and a HT (@%).
|
||||||
_>_A SP, a HT and a SP (@).
|
_>_A SP, a HT and a SP (@%).
|
||||||
_______Seven SP.
|
_______Seven SP.
|
||||||
________Eight SP (#).
|
________Eight SP (#).
|
||||||
_______>Seven SP and a HT (@).
|
_______>Seven SP and a HT (@%).
|
||||||
________>Eight SP and a HT (@#).
|
________>Eight SP and a HT (@#%).
|
||||||
_______>_Seven SP, a HT and a SP (@).
|
_______>_Seven SP, a HT and a SP (@%).
|
||||||
________>_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>
|
||||||
@ -39,7 +40,6 @@ apply_patch () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_fix () {
|
test_fix () {
|
||||||
|
|
||||||
# fix should not barf
|
# fix should not barf
|
||||||
apply_patch --whitespace=fix || return 1
|
apply_patch --whitespace=fix || return 1
|
||||||
|
|
||||||
@ -130,20 +130,25 @@ do
|
|||||||
for i in - ''
|
for i in - ''
|
||||||
do
|
do
|
||||||
case "$i" in '') ti='#' ;; *) ti= ;; esac
|
case "$i" in '') ti='#' ;; *) ti= ;; esac
|
||||||
rule=${t}trailing,${s}space,${i}indent
|
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
|
rm -f .gitattributes
|
||||||
test_expect_success "rule=$rule" '
|
test_expect_success "rule=$rule" '
|
||||||
git config core.whitespace "$rule" &&
|
git config core.whitespace "$rule" &&
|
||||||
test_fix "$tt$ts$ti"
|
test_fix "$tt$ts$ti$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"
|
test_fix "$tt$ts$ti$th"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
done
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
66
ws.c
66
ws.c
@ -10,7 +10,8 @@
|
|||||||
static struct whitespace_rule {
|
static struct whitespace_rule {
|
||||||
const char *rule_name;
|
const char *rule_name;
|
||||||
unsigned rule_bits;
|
unsigned rule_bits;
|
||||||
unsigned loosens_error;
|
unsigned loosens_error:1,
|
||||||
|
exclude_default:1;
|
||||||
} whitespace_rule_names[] = {
|
} whitespace_rule_names[] = {
|
||||||
{ "trailing-space", WS_TRAILING_SPACE, 0 },
|
{ "trailing-space", WS_TRAILING_SPACE, 0 },
|
||||||
{ "space-before-tab", WS_SPACE_BEFORE_TAB, 0 },
|
{ "space-before-tab", WS_SPACE_BEFORE_TAB, 0 },
|
||||||
@ -18,6 +19,7 @@ static struct whitespace_rule {
|
|||||||
{ "cr-at-eol", WS_CR_AT_EOL, 1 },
|
{ "cr-at-eol", WS_CR_AT_EOL, 1 },
|
||||||
{ "blank-at-eol", WS_BLANK_AT_EOL, 0 },
|
{ "blank-at-eol", WS_BLANK_AT_EOL, 0 },
|
||||||
{ "blank-at-eof", WS_BLANK_AT_EOF, 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)
|
unsigned parse_whitespace_rule(const char *string)
|
||||||
@ -56,6 +58,9 @@ unsigned parse_whitespace_rule(const char *string)
|
|||||||
}
|
}
|
||||||
string = ep;
|
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;
|
return rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +87,8 @@ unsigned whitespace_rule(const char *pathname)
|
|||||||
unsigned all_rule = 0;
|
unsigned all_rule = 0;
|
||||||
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 &&
|
||||||
|
!whitespace_rule_names[i].exclude_default)
|
||||||
all_rule |= whitespace_rule_names[i].rule_bits;
|
all_rule |= whitespace_rule_names[i].rule_bits;
|
||||||
return all_rule;
|
return all_rule;
|
||||||
} else if (ATTR_FALSE(value)) {
|
} else if (ATTR_FALSE(value)) {
|
||||||
@ -125,6 +131,11 @@ char *whitespace_error_string(unsigned ws)
|
|||||||
strbuf_addstr(&err, ", ");
|
strbuf_addstr(&err, ", ");
|
||||||
strbuf_addstr(&err, "indent with spaces");
|
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);
|
return strbuf_detach(&err, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,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++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (line[i] == ' ')
|
if (line[i] == ' ')
|
||||||
continue;
|
continue;
|
||||||
@ -175,11 +186,19 @@ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
|
|||||||
fputs(ws, stream);
|
fputs(ws, stream);
|
||||||
fwrite(line + written, i - written, 1, stream);
|
fwrite(line + written, i - written, 1, stream);
|
||||||
fputs(reset, stream);
|
fputs(reset, stream);
|
||||||
|
fwrite(line + i, 1, 1, stream);
|
||||||
}
|
}
|
||||||
} else if (stream)
|
} else if (ws_rule & WS_TAB_IN_INDENT) {
|
||||||
fwrite(line + written, i - written, 1, stream);
|
result |= WS_TAB_IN_INDENT;
|
||||||
if (stream)
|
if (stream) {
|
||||||
fwrite(line + i, 1, 1, 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;
|
written = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,8 +271,8 @@ int ws_blank_line(const char *line, int len, unsigned ws_rule)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the line to the buffer while fixing whitespaces */
|
/* Copy the line onto the end of the strbuf while fixing whitespaces */
|
||||||
int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
|
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
|
* len is number of bytes to be copied from src, starting
|
||||||
@ -267,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_tab_in_indent = -1;
|
||||||
int last_space_in_indent = -1;
|
int last_space_in_indent = -1;
|
||||||
int need_fix_leading_space = 0;
|
int need_fix_leading_space = 0;
|
||||||
char *buf;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strip trailing whitespace
|
* Strip trailing whitespace
|
||||||
@ -307,7 +325,6 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = dst;
|
|
||||||
if (need_fix_leading_space) {
|
if (need_fix_leading_space) {
|
||||||
/* Process indent ourselves */
|
/* Process indent ourselves */
|
||||||
int consecutive_spaces = 0;
|
int consecutive_spaces = 0;
|
||||||
@ -329,28 +346,41 @@ int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *erro
|
|||||||
char ch = src[i];
|
char ch = src[i];
|
||||||
if (ch != ' ') {
|
if (ch != ' ') {
|
||||||
consecutive_spaces = 0;
|
consecutive_spaces = 0;
|
||||||
*dst++ = ch;
|
strbuf_addch(dst, ch);
|
||||||
} else {
|
} else {
|
||||||
consecutive_spaces++;
|
consecutive_spaces++;
|
||||||
if (consecutive_spaces == 8) {
|
if (consecutive_spaces == 8) {
|
||||||
*dst++ = '\t';
|
strbuf_addch(dst, '\t');
|
||||||
consecutive_spaces = 0;
|
consecutive_spaces = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (0 < consecutive_spaces--)
|
while (0 < consecutive_spaces--)
|
||||||
*dst++ = ' ';
|
strbuf_addch(dst, ' ');
|
||||||
|
len -= last;
|
||||||
|
src += last;
|
||||||
|
fixed = 1;
|
||||||
|
} else 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;
|
len -= last;
|
||||||
src += last;
|
src += last;
|
||||||
fixed = 1;
|
fixed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dst, src, len);
|
strbuf_add(dst, src, len);
|
||||||
if (add_cr_to_tail)
|
if (add_cr_to_tail)
|
||||||
dst[len++] = '\r';
|
strbuf_addch(dst, '\r');
|
||||||
if (add_nl_to_tail)
|
if (add_nl_to_tail)
|
||||||
dst[len++] = '\n';
|
strbuf_addch(dst, '\n');
|
||||||
if (fixed && error_count)
|
if (fixed && error_count)
|
||||||
(*error_count)++;
|
(*error_count)++;
|
||||||
return dst + len - buf;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user