Skip to content
This repository was archived by the owner on Aug 25, 2024. It is now read-only.

Commit c4f27f6

Browse files
committed
scripts: Helper for maintaining lines of literalincludes
Signed-off-by: John Andersen <[email protected]>
1 parent e5e41b2 commit c4f27f6

File tree

3 files changed

+92
-1
lines changed

3 files changed

+92
-1
lines changed

.ci/run.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ function run_docs() {
224224
git checkout master
225225
}
226226

227+
function run_lines() {
228+
"${PYTHON}" ./scripts/check_literalincludes.py
229+
}
230+
227231
function cleanup_temp_dirs() {
228232
if [ "x${NO_RM_TEMP}" != "x" ]; then
229233
return
@@ -246,4 +250,6 @@ elif [ "x${STYLE}" != "x" ]; then
246250
run_style
247251
elif [ "x${DOCS}" != "x" ]; then
248252
run_docs
253+
elif [ "x${LINES}" != "x" ]; then
254+
run_lines
249255
fi

.github/workflows/testing.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
fail-fast: false
1010
max-parallel: 40
1111
matrix:
12-
check: [CHANGELOG, WHITESPACE, STYLE, DOCS]
12+
check: [CHANGELOG, WHITESPACE, STYLE, DOCS, LINES]
1313
python-version: [3.7]
1414
node-version: [12.x]
1515

scripts/check_literalincludes.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import sys
2+
import pathlib
3+
import itertools
4+
import subprocess
5+
6+
7+
def literalinclude_blocks():
8+
literalincludes = subprocess.check_output(
9+
["git", "grep", "-A", "10", ".. literalinclude::"]
10+
)
11+
literalincludes = literalincludes.decode()
12+
section = []
13+
for line in "\n".join(literalincludes.split("\n--\n")).split("\n"):
14+
if not line.strip():
15+
continue
16+
# If literalinclude is in the output git grep will separate with :
17+
# instead of -
18+
if ".. literalinclude::" in line:
19+
line = line.split(":", maxsplit=1)
20+
else:
21+
line = line.split("-", maxsplit=1)
22+
# For blank lines
23+
if section and (len(line) != 2 or not line[1]):
24+
yield section
25+
section = []
26+
continue
27+
contains_literalinclude, filecontents = line
28+
if ".. literalinclude::" in filecontents:
29+
section = [contains_literalinclude, [filecontents]]
30+
elif section:
31+
section[1].append(filecontents)
32+
33+
34+
def main():
35+
# Map filenames that might have changed to the file which references it's
36+
# line numbers
37+
check_changed = {}
38+
for contains_literalinclude, lines in literalinclude_blocks():
39+
# Skip blocks that don't reference specific lines
40+
if not ":lines:" in "\n".join(lines):
41+
continue
42+
# Grab the file being referenced
43+
# Remove /../ used by sphinx docs to reference files outside docs dir
44+
referenced = lines[0].split()[-1].replace("/../", "", 1)
45+
check_changed.setdefault(referenced, {})
46+
check_changed[referenced].setdefault(contains_literalinclude, False)
47+
# Get the list of changed files
48+
changed_files = subprocess.check_output(
49+
["git", "diff-index", "origin/master"]
50+
)
51+
changed_files = changed_files.decode()
52+
changed_files = list(
53+
map(
54+
lambda line: line.split()[-1],
55+
filter(bool, changed_files.split("\n")),
56+
)
57+
)
58+
rm_paths = []
59+
for filepath in check_changed:
60+
if not filepath in changed_files:
61+
rm_paths.append(filepath)
62+
for filepath in rm_paths:
63+
del check_changed[filepath]
64+
for filepath in check_changed:
65+
if filepath in changed_files:
66+
for has_been_updated in check_changed[filepath]:
67+
if has_been_updated in changed_files:
68+
check_changed[filepath][has_been_updated] = True
69+
# Fail if any are referenced_by
70+
fail = False
71+
for referenced_changed, should_have_changed in check_changed.items():
72+
for filepath, was_changed in should_have_changed.items():
73+
if not was_changed:
74+
fail = True
75+
print(
76+
f"{filepath!r} might need updating as line numbers of "
77+
+ f"{referenced_changed!r} may have changed"
78+
)
79+
if not fail:
80+
return
81+
sys.exit(1)
82+
83+
84+
if __name__ == "__main__":
85+
main()

0 commit comments

Comments
 (0)