Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
git
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
Files
8f5e3ca
Documentation
arm
compat
contrib
git-gui
gitk-git
gitweb
mozilla-sha1
perl
ppc
t
templates
xdiff
.gitattributes
.gitignore
.mailmap
COPYING
GIT-VERSION-GEN
INSTALL
Makefile
README
RelNotes
abspath.c
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c
archive.h
attr.c
attr.h
base85.c
bisect.c
bisect.h
blob.c
blob.h
branch.c
branch.h
builtin-add.c
builtin-annotate.c
builtin-apply.c
builtin-archive.c
builtin-bisect--helper.c
builtin-blame.c
builtin-branch.c
builtin-bundle.c
builtin-cat-file.c
builtin-check-attr.c
builtin-check-ref-format.c
builtin-checkout-index.c
builtin-checkout.c
builtin-clean.c
builtin-clone.c
builtin-commit-tree.c
builtin-commit.c
builtin-config.c
builtin-count-objects.c
builtin-describe.c
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-tree.c
builtin-diff.c
builtin-fast-export.c
builtin-fetch--tool.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-fmt-merge-msg.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-gc.c
builtin-grep.c
builtin-help.c
builtin-http-fetch.c
builtin-init-db.c
builtin-log.c
builtin-ls-files.c
builtin-ls-remote.c
builtin-ls-tree.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-merge-base.c
builtin-merge-file.c
builtin-merge-ours.c
builtin-merge-recursive.c
builtin-merge.c
builtin-mktree.c
builtin-mv.c
builtin-name-rev.c
builtin-pack-objects.c
builtin-pack-refs.c
builtin-prune-packed.c
builtin-prune.c
builtin-push.c
builtin-read-tree.c
builtin-receive-pack.c
builtin-reflog.c
builtin-remote.c
builtin-rerere.c
builtin-reset.c
builtin-rev-list.c
builtin-rev-parse.c
builtin-revert.c
builtin-rm.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-show-ref.c
builtin-stripspace.c
builtin-symbolic-ref.c
builtin-tag.c
builtin-tar-tree.c
builtin-unpack-objects.c
builtin-update-index.c
builtin-update-ref.c
builtin-upload-archive.c
builtin-verify-pack.c
builtin-verify-tag.c
builtin-write-tree.c
builtin.h
bundle.c
bundle.h
cache-tree.c
cache-tree.h
cache.h
check-builtins.sh
check-racy.c
check_bindir
color.c
color.h
combine-diff.c
command-list.txt
commit.c
commit.h
config.c
config.mak.in
configure.ac
connect.c
convert.c
copy.c
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c
decorate.c
decorate.h
delta.h
diff-delta.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
editor.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.h
fixup-builtins
fsck.c
fsck.h
generate-cmdlist.sh
git-add--interactive.perl
git-am.sh
git-archimport.perl
git-bisect.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-difftool.perl
git-filter-branch.sh
git-instaweb.sh
git-lost-found.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase--interactive.sh
git-rebase.sh
git-relink.perl
git-repack.sh
git-request-pull.sh
git-send-email.perl
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.spec.in
graph.c
graph.h
grep.c
grep.h
hash-object.c
hash.c
hash.h
help.c
help.h
http-push.c
http-walker.c
http.c
http.h
ident.c
imap-send.c
index-pack.c
levenshtein.c
levenshtein.h
list-objects.c
list-objects.h
ll-merge.c
ll-merge.h
lockfile.c
log-tree.c
log-tree.h
mailmap.c
mailmap.h
match-trees.c
merge-file.c
merge-index.c
merge-recursive.c
merge-recursive.h
merge-tree.c
mktag.c
name-hash.c
object.c
object.h
pack-check.c
pack-redundant.c
pack-refs.c
pack-refs.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options.c
parse-options.h
patch-delta.c
patch-id.c
patch-ids.c
patch-ids.h
path.c
pkt-line.c
pkt-line.h
preload-index.c
pretty.c
progress.c
progress.h
quote.c
quote.h
reachable.c
reachable.h
read-cache.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote.c
remote.h
rerere.c
rerere.h
revision.c
revision.h
run-command.c
run-command.h
send-pack.h
server-info.c
setup.c
sha1-lookup.c
sha1-lookup.h
sha1_file.c
sha1_name.c
shallow.c
shell.c
shortlog.h
show-index.c
sideband.c
sideband.h
sigchain.c
sigchain.h
strbuf.c
strbuf.h
string-list.c
string-list.h
symlinks.c
tag.c
tag.h
tar.h
test-chmtime.c
test-ctype.c
test-date.c
test-delta.c
test-dump-cache-tree.c
test-genrandom.c
test-match-trees.c
test-parse-options.c
test-path-utils.c
test-sha1.c
test-sha1.sh
test-sigchain.c
thread-utils.c
thread-utils.h
trace.c
transport.c
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unimplemented.sh
unpack-file.c
unpack-trees.c
unpack-trees.h
update-server-info.c
upload-pack.c
usage.c
userdiff.c
userdiff.h
utf8.c
utf8.h
var.c
walker.c
walker.h
wrapper.c
write_or_die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
Breadcrumbs
git
/
ws.c
Blame
Blame
Latest commit
History
History
345 lines (315 loc) · 7.91 KB
Breadcrumbs
git
/
ws.c
Top
File metadata and controls
Code
Blame
345 lines (315 loc) · 7.91 KB
Raw
/* * Whitespace rules * * Copyright (c) 2007 Junio C Hamano */ #include "cache.h" #include "attr.h" static struct whitespace_rule { const char *rule_name; unsigned rule_bits; unsigned loosens_error; } whitespace_rule_names[] = { { "trailing-space", WS_TRAILING_SPACE, 0 }, { "space-before-tab", WS_SPACE_BEFORE_TAB, 0 }, { "indent-with-non-tab", WS_INDENT_WITH_NON_TAB, 0 }, { "cr-at-eol", WS_CR_AT_EOL, 1 }, }; unsigned parse_whitespace_rule(const char *string) { unsigned rule = WS_DEFAULT_RULE; while (string) { int i; size_t len; const char *ep; int negated = 0; string = string + strspn(string, ", \t\n\r"); ep = strchr(string, ','); if (!ep) len = strlen(string); else len = ep - string; if (*string == '-') { negated = 1; string++; len--; } if (!len) break; for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) { if (strncmp(whitespace_rule_names[i].rule_name, string, len)) continue; if (negated) rule &= ~whitespace_rule_names[i].rule_bits; else rule |= whitespace_rule_names[i].rule_bits; break; } string = ep; } return rule; } static void setup_whitespace_attr_check(struct git_attr_check *check) { static struct git_attr *attr_whitespace; if (!attr_whitespace) attr_whitespace = git_attr("whitespace", 10); check[0].attr = attr_whitespace; } unsigned whitespace_rule(const char *pathname) { struct git_attr_check attr_whitespace_rule; setup_whitespace_attr_check(&attr_whitespace_rule); if (!git_checkattr(pathname, 1, &attr_whitespace_rule)) { const char *value; value = attr_whitespace_rule.value; if (ATTR_TRUE(value)) { /* true (whitespace) */ unsigned all_rule = 0; int i; for (i = 0; i < ARRAY_SIZE(whitespace_rule_names); i++) if (!whitespace_rule_names[i].loosens_error) all_rule |= whitespace_rule_names[i].rule_bits; return all_rule; } else if (ATTR_FALSE(value)) { /* false (-whitespace) */ return 0; } else if (ATTR_UNSET(value)) { /* reset to default (!whitespace) */ return whitespace_rule_cfg; } else { /* string */ return parse_whitespace_rule(value); } } else { return whitespace_rule_cfg; } } /* The returned string should be freed by the caller. */ char *whitespace_error_string(unsigned ws) { struct strbuf err = STRBUF_INIT; if (ws & WS_TRAILING_SPACE) strbuf_addstr(&err, "trailing whitespace"); if (ws & WS_SPACE_BEFORE_TAB) { if (err.len) strbuf_addstr(&err, ", "); strbuf_addstr(&err, "space before tab in indent"); } if (ws & WS_INDENT_WITH_NON_TAB) { if (err.len) strbuf_addstr(&err, ", "); strbuf_addstr(&err, "indent with spaces"); } return strbuf_detach(&err, NULL); } /* If stream is non-NULL, emits the line after checking. */ static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws) { unsigned result = 0; int written = 0; int trailing_whitespace = -1; int trailing_newline = 0; int trailing_carriage_return = 0; int i; /* Logic is simpler if we temporarily ignore the trailing newline. */ if (len > 0 && line[len - 1] == '\n') { trailing_newline = 1; len--; } if ((ws_rule & WS_CR_AT_EOL) && len > 0 && line[len - 1] == '\r') { trailing_carriage_return = 1; len--; } /* Check for trailing whitespace. */ if (ws_rule & WS_TRAILING_SPACE) { for (i = len - 1; i >= 0; i--) { if (isspace(line[i])) { trailing_whitespace = i; result |= WS_TRAILING_SPACE; } else break; } } /* Check for space before tab in initial indent. */ for (i = 0; i < len; i++) { if (line[i] == ' ') continue; if (line[i] != '\t') break; if ((ws_rule & WS_SPACE_BEFORE_TAB) && written < i) { result |= WS_SPACE_BEFORE_TAB; if (stream) { fputs(ws, stream); fwrite(line + written, i - written, 1, stream); fputs(reset, stream); } } else if (stream) fwrite(line + written, i - written, 1, stream); if (stream) fwrite(line + i, 1, 1, stream); written = i + 1; } /* Check for indent using non-tab. */ if ((ws_rule & WS_INDENT_WITH_NON_TAB) && i - written >= 8) { result |= WS_INDENT_WITH_NON_TAB; if (stream) { fputs(ws, stream); fwrite(line + written, i - written, 1, stream); fputs(reset, stream); } written = i; } if (stream) { /* * Now the rest of the line starts at "written". * The non-highlighted part ends at "trailing_whitespace". */ if (trailing_whitespace == -1) trailing_whitespace = len; /* Emit non-highlighted (middle) segment. */ if (trailing_whitespace - written > 0) { fputs(set, stream); fwrite(line + written, trailing_whitespace - written, 1, stream); fputs(reset, stream); } /* Highlight errors in trailing whitespace. */ if (trailing_whitespace != len) { fputs(ws, stream); fwrite(line + trailing_whitespace, len - trailing_whitespace, 1, stream); fputs(reset, stream); } if (trailing_carriage_return) fputc('\r', stream); if (trailing_newline) fputc('\n', stream); } return result; } void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws) { (void)ws_check_emit_1(line, len, ws_rule, stream, set, reset, ws); } unsigned ws_check(const char *line, int len, unsigned ws_rule) { return ws_check_emit_1(line, len, ws_rule, NULL, NULL, NULL, NULL); } int ws_blank_line(const char *line, int len, unsigned ws_rule) { /* * We _might_ want to treat CR differently from other * whitespace characters when ws_rule has WS_CR_AT_EOL, but * for now we just use this stupid definition. */ while (len-- > 0) { if (!isspace(*line)) return 0; line++; } 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) { /* * len is number of bytes to be copied from src, starting * at src. Typically src[len-1] is '\n', unless this is * the incomplete last line. */ int i; int add_nl_to_tail = 0; int add_cr_to_tail = 0; int fixed = 0; int last_tab_in_indent = -1; int last_space_in_indent = -1; int need_fix_leading_space = 0; char *buf; /* * Strip trailing whitespace */ if (ws_rule & WS_TRAILING_SPACE) { if (0 < len && src[len - 1] == '\n') { add_nl_to_tail = 1; len--; if (0 < len && src[len - 1] == '\r') { add_cr_to_tail = !!(ws_rule & WS_CR_AT_EOL); len--; } } if (0 < len && isspace(src[len - 1])) { while (0 < len && isspace(src[len-1])) len--; fixed = 1; } } /* * Check leading whitespaces (indent) */ for (i = 0; i < len; i++) { char ch = src[i]; if (ch == '\t') { last_tab_in_indent = i; if ((ws_rule & WS_SPACE_BEFORE_TAB) && 0 <= last_space_in_indent) need_fix_leading_space = 1; } else if (ch == ' ') { last_space_in_indent = i; if ((ws_rule & WS_INDENT_WITH_NON_TAB) && 8 <= i - last_tab_in_indent) need_fix_leading_space = 1; } else break; } buf = dst; if (need_fix_leading_space) { /* Process indent ourselves */ int consecutive_spaces = 0; int last = last_tab_in_indent + 1; if (ws_rule & WS_INDENT_WITH_NON_TAB) { /* have "last" point at one past the indent */ if (last_tab_in_indent < last_space_in_indent) last = last_space_in_indent + 1; else last = last_tab_in_indent + 1; } /* * between src[0..last-1], strip the funny spaces, * updating them to tab as needed. */ for (i = 0; i < last; i++) { char ch = src[i]; if (ch != ' ') { consecutive_spaces = 0; *dst++ = ch; } else { consecutive_spaces++; if (consecutive_spaces == 8) { *dst++ = '\t'; consecutive_spaces = 0; } } } while (0 < consecutive_spaces--) *dst++ = ' '; len -= last; src += last; fixed = 1; } memcpy(dst, src, len); if (add_cr_to_tail) dst[len++] = '\r'; if (add_nl_to_tail) dst[len++] = '\n'; if (fixed && error_count) (*error_count)++; return dst + len - buf; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
You can’t perform that action at this time.