Skip to content

Commit 2452e71

Browse files
committed
Add script to keep .editorconfig in sync with .gitattributes
Our repo already contained an .editorconfig file, but it was not kept up to date with .gitattributes. This adds a script that keeps these files in sync. A big advantage of the editorconfig file is that it many editors/IDEs get automatically configured to trim trailing newlines and add a final newline on save, while .gitattributes only complains about these problems instead of automatically fixing them. This also adds rules to .gitattributes for Python files as well as for C files in pg_bsd_indent directory (which have a different tab_width than most C files due to being vendored in). Author: Jelte Fennema-Nio <[email protected]> Discussion: https://www.postgresql.org/message-id/flat/CAGECzQQGzbroAXi+Yicp3HvcCo4=g84kaOgjuvQ5MW9F0ubOGg@mail.gmail.com
1 parent 79e872f commit 2452e71

File tree

3 files changed

+266
-5
lines changed

3 files changed

+266
-5
lines changed

.editorconfig

+166-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,176 @@
11
root = true
22

3-
[*.{c,h,l,y,pl,pm}]
4-
indent_style = tab
3+
[*]
54
indent_size = tab
5+
6+
[*]
7+
trim_trailing_whitespace = true
8+
insert_final_newline = true
9+
indent_style = unset
10+
tab_width = unset
11+
12+
[*.[chly]]
13+
trim_trailing_whitespace = true
14+
insert_final_newline = true
15+
indent_style = tab
16+
tab_width = 4
17+
18+
[*.cpp]
19+
trim_trailing_whitespace = true
20+
insert_final_newline = true
21+
indent_style = tab
22+
tab_width = 4
23+
24+
[*.pl]
25+
trim_trailing_whitespace = true
26+
insert_final_newline = true
27+
indent_style = tab
628
tab_width = 4
729

8-
[*.{sgml,xml}]
30+
[*.pm]
31+
trim_trailing_whitespace = true
32+
insert_final_newline = true
33+
indent_style = tab
34+
tab_width = 4
35+
36+
[*.po]
37+
trim_trailing_whitespace = true
38+
insert_final_newline = unset
39+
indent_style = space
40+
tab_width = unset
41+
42+
[*.py]
43+
trim_trailing_whitespace = true
44+
insert_final_newline = true
945
indent_style = space
46+
tab_width = unset
47+
indent_size = 4
48+
49+
[*.sgml]
50+
trim_trailing_whitespace = true
51+
insert_final_newline = true
52+
indent_style = space
53+
tab_width = unset
1054
indent_size = 1
1155

12-
[*.xsl]
56+
[*.xml]
57+
trim_trailing_whitespace = true
58+
insert_final_newline = true
1359
indent_style = space
60+
tab_width = unset
1461
indent_size = 2
62+
63+
[*.xsl]
64+
trim_trailing_whitespace = true
65+
insert_final_newline = true
66+
indent_style = space
67+
tab_width = unset
68+
indent_size = 1
69+
70+
[*.data]
71+
indent_style = unset
72+
indent_size = unset
73+
trim_trailing_whitespace = unset
74+
insert_final_newline = unset
75+
76+
[contrib/pgcrypto/sql/pgp-armor.sql]
77+
trim_trailing_whitespace = unset
78+
insert_final_newline = true
79+
indent_style = unset
80+
tab_width = unset
81+
82+
[src/backend/catalog/sql_features.txt]
83+
trim_trailing_whitespace = unset
84+
insert_final_newline = true
85+
indent_style = unset
86+
tab_width = unset
87+
88+
[*.out]
89+
indent_style = unset
90+
indent_size = unset
91+
trim_trailing_whitespace = unset
92+
insert_final_newline = unset
93+
94+
[src/interfaces/ecpg/test/expected/*]
95+
indent_style = unset
96+
indent_size = unset
97+
trim_trailing_whitespace = unset
98+
insert_final_newline = unset
99+
100+
[configure]
101+
indent_style = unset
102+
indent_size = unset
103+
trim_trailing_whitespace = unset
104+
insert_final_newline = unset
105+
106+
[ppport.h]
107+
indent_style = unset
108+
indent_size = unset
109+
trim_trailing_whitespace = unset
110+
insert_final_newline = unset
111+
112+
[src/backend/jit/llvm/SectionMemoryManager.cpp]
113+
indent_style = unset
114+
indent_size = unset
115+
trim_trailing_whitespace = unset
116+
insert_final_newline = unset
117+
118+
[src/backend/jit/llvm/SectionMemoryManager.LICENSE]
119+
indent_style = unset
120+
indent_size = unset
121+
trim_trailing_whitespace = unset
122+
insert_final_newline = unset
123+
124+
[src/backend/regex/COPYRIGHT]
125+
indent_style = unset
126+
indent_size = unset
127+
trim_trailing_whitespace = unset
128+
insert_final_newline = unset
129+
130+
[src/backend/snowball/libstemmer/*.c]
131+
indent_style = unset
132+
indent_size = unset
133+
trim_trailing_whitespace = unset
134+
insert_final_newline = unset
135+
136+
[src/backend/utils/mb/Unicode/*-std.txt]
137+
indent_style = unset
138+
indent_size = unset
139+
trim_trailing_whitespace = unset
140+
insert_final_newline = unset
141+
142+
[src/include/jit/SectionMemoryManager.h]
143+
indent_style = unset
144+
indent_size = unset
145+
trim_trailing_whitespace = unset
146+
insert_final_newline = unset
147+
148+
[src/include/snowball/libstemmer/*]
149+
indent_style = unset
150+
indent_size = unset
151+
trim_trailing_whitespace = unset
152+
insert_final_newline = unset
153+
154+
[src/timezone/data/*]
155+
indent_style = unset
156+
indent_size = unset
157+
trim_trailing_whitespace = unset
158+
insert_final_newline = unset
159+
160+
[src/tools/pg_bsd_indent/*]
161+
indent_style = unset
162+
indent_size = unset
163+
trim_trailing_whitespace = unset
164+
insert_final_newline = unset
165+
166+
[src/tools/pg_bsd_indent/tests/*]
167+
indent_style = unset
168+
indent_size = unset
169+
trim_trailing_whitespace = unset
170+
insert_final_newline = unset
171+
172+
[src/tools/pg_bsd_indent/*.[ch]]
173+
trim_trailing_whitespace = unset
174+
insert_final_newline = unset
175+
indent_style = unset
176+
tab_width = 8

.gitattributes

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
# IMPORTANT: After updating this file, also run src/tools/generate_editorconfig.py
2+
13
* whitespace=space-before-tab,trailing-space
24
*.[chly] whitespace=space-before-tab,trailing-space,indent-with-non-tab,tabwidth=4
35
*.cpp whitespace=space-before-tab,trailing-space,indent-with-non-tab,tabwidth=4
46
*.pl whitespace=space-before-tab,trailing-space,tabwidth=4
57
*.pm whitespace=space-before-tab,trailing-space,tabwidth=4
68
*.po whitespace=space-before-tab,trailing-space,tab-in-indent,-blank-at-eof
9+
*.py whitespace=space-before-tab,trailing-space,tab-in-indent
710
*.sgml whitespace=space-before-tab,trailing-space,tab-in-indent
8-
*.x[ms]l whitespace=space-before-tab,trailing-space,tab-in-indent
11+
*.xml whitespace=space-before-tab,trailing-space,tab-in-indent
12+
*.xsl whitespace=space-before-tab,trailing-space,tab-in-indent
913

1014
# Avoid confusing ASCII underlines with leftover merge conflict markers
1115
README conflict-marker-size=32
@@ -33,3 +37,4 @@ src/include/snowball/libstemmer/* -whitespace
3337
src/timezone/data/* -whitespace
3438
src/tools/pg_bsd_indent/* -whitespace
3539
src/tools/pg_bsd_indent/tests/* -whitespace
40+
src/tools/pg_bsd_indent/*.[ch] whitespace=-blank-at-eol,-blank-at-eof,tabwidth=8

src/tools/generate_editorconfig.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
5+
6+
def cd_to_repo_root():
7+
abspath = os.path.abspath(__file__)
8+
dname = os.path.join(os.path.dirname(abspath), "..", "..")
9+
os.chdir(dname)
10+
11+
12+
# Space based indentation levels are not tracked in .gitattributes, so
13+
# we hardcode them here for the relevant filetypes.
14+
space_based_indent_sizes = {
15+
"*.py": 4,
16+
"*.sgml": 1,
17+
"*.xsl": 1,
18+
"*.xml": 2,
19+
}
20+
21+
22+
def main():
23+
cd_to_repo_root()
24+
25+
with open(".gitattributes", "r") as f:
26+
lines = f.read().splitlines()
27+
28+
new_contents = """root = true
29+
30+
[*]
31+
indent_size = tab
32+
"""
33+
34+
for line in lines:
35+
if line.startswith("#") or len(line) == 0:
36+
continue
37+
name, git_rules = line.split()
38+
if git_rules == "-whitespace":
39+
rules = [
40+
"indent_style = unset",
41+
"indent_size = unset",
42+
"trim_trailing_whitespace = unset",
43+
"insert_final_newline = unset",
44+
]
45+
elif git_rules.startswith("whitespace="):
46+
git_whitespace_rules = git_rules.replace("whitespace=", "").split(",")
47+
rules = []
48+
if "-blank-at-eol" in git_whitespace_rules:
49+
rules += ["trim_trailing_whitespace = unset"]
50+
else:
51+
rules += ["trim_trailing_whitespace = true"]
52+
53+
if "-blank-at-eof" in git_whitespace_rules:
54+
rules += ["insert_final_newline = unset"]
55+
else:
56+
rules += ["insert_final_newline = true"]
57+
58+
if "tab-in-indent" in git_whitespace_rules:
59+
rules += ["indent_style = space"]
60+
elif "indent-with-non-tab" in git_whitespace_rules:
61+
rules += ["indent_style = tab"]
62+
elif name in ["*.pl", "*.pm"]:
63+
# We want editors to use tabs for indenting Perl
64+
# files, but we cannot add it such a rule to
65+
# .gitattributes, because certain lines are still
66+
# indented with spaces (e.g. SYNOPSIS blocks). So we
67+
# hardcode the rule here.
68+
69+
rules += ["indent_style = tab"]
70+
else:
71+
rules += ["indent_style = unset"]
72+
73+
tab_width = "unset"
74+
for rule in git_whitespace_rules:
75+
if rule.startswith("tabwidth="):
76+
tab_width = rule.replace("tabwidth=", "")
77+
rules += [f"tab_width = {tab_width}"]
78+
79+
if name in space_based_indent_sizes:
80+
indent_size = space_based_indent_sizes[name]
81+
rules += [f"indent_size = {indent_size}"]
82+
83+
else:
84+
continue
85+
86+
rules = "\n".join(rules)
87+
new_contents += f"\n[{name}]\n{rules}\n"
88+
89+
with open(".editorconfig", "w") as f:
90+
f.write(new_contents)
91+
92+
93+
if __name__ == "__main__":
94+
main()

0 commit comments

Comments
 (0)