-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmerge.py
139 lines (115 loc) · 4.6 KB
/
merge.py
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
"""Tool to merge cpython pot files to python-docs-tr po files for a
given branch.
This script is based on python-docs-fr. We may change some code.
It may be modified for our projects requirements.
"""
import re
import shutil
from pathlib import Path
import argparse
import subprocess
from subprocess import PIPE
from tqdm import tqdm
def run(*args: str, **kwargs) -> subprocess.CompletedProcess:
"""Run a shell command with subprocess.run() with check=True and
encoding="UTF-8".
"""
return subprocess.run(list(args), encoding="UTF-8", check=True, **kwargs)
def parse_args():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--cpython_repo",
default=Path("venv/cpython"),
type=Path,
help="Use this given cpython clone.",
)
parser.add_argument("branch", help="Merge from this branch")
return parser.parse_args()
def setup_repo(repo_path: Path, branch: str):
"""Ensure we're up-to-date."""
run("git", "-C", repo_path, "checkout", branch)
run("git", "-C", repo_path, "pull", "--ff-only")
def copy_new_files(new_files: Path, pot_path: Path) -> None:
"""Just copy new po files to our hierarchy."""
print(f"{len(new_files)} new files.")
for file in new_files:
file.parent.mkdir(parents=True, exist_ok=True)
src = (pot_path / file).with_suffix(".pot")
run("msgcat", "-o", file, src)
def update_known_files(known_files: Path, pot_path: Path) -> None:
"""msgmerge updated pot files in our po files."""
print(f"{len(known_files)} files to update.")
for file in tqdm(known_files, desc="merging pot files"):
src = (pot_path / file).with_suffix(".pot")
run("msgmerge", "-q", "--backup=off", "--force-po", "-U", file, src)
def remove_old_files(old_files: Path) -> None:
"""Remove files removed upstream."""
print(f"{len(old_files)} removed files.")
for file in old_files:
run("git", "rm", file)
def clean_paths(files: Path) -> None:
"""Ensure the path present in po files are always relative.
This avoid having diffs on those paths when we change something in
a script.
"""
for file in tqdm(files, desc="Cleaning rst path in pot files"):
contents = file.read_text(encoding="UTF-8")
contents = re.sub("^#: .*Doc/", "#: ", contents, flags=re.M)
file.write_text(contents, encoding="UTF-8")
def update_makefile(cpython_repo: Path) -> None:
"""Update CPYTHON_CURRENT_COMMIT in the Makefile.
So that when we run `make` it use the same commit than the one
used to generate the `po` files.
"""
makefile = Path("Makefile").read_text(encoding="UTF-8")
head = run("git", "-C", cpython_repo, "rev-parse", "HEAD", stdout=PIPE).stdout
makefile = re.sub(
"^CPYTHON_CURRENT_COMMIT :=.*$",
f"CPYTHON_CURRENT_COMMIT := {head}",
makefile,
flags=re.M,
)
Path("Makefile").write_text(makefile, encoding="UTF-8")
run("git", "add", "Makefile")
def git_add_relevant_files():
"""Add only files with relevant modifications.
This only add files with actual modifications, not just metadata
modifications, to avoid noise in history.
"""
modified_files = run("git", "ls-files", "-m", stdout=PIPE).stdout.split("\n")
modified_po_files = [line for line in modified_files if line.endswith(".po")]
for file in modified_po_files:
diff = run("git", "diff", "-U0", file, stdout=PIPE).stdout
if len(diff.split("\n")) > 8:
run("git", "add", file)
else:
run("git", "checkout", "--", file)
run("rm", "-f", "whatsnew/changelog.po") # We don't translate this file.
def main():
args = parse_args()
setup_repo(args.cpython_repo, args.branch)
run(
*["sphinx-build", "-jauto", "-QDgettext_compact=0", "-bgettext", ".", "../pot"],
cwd=args.cpython_repo / "Doc",
)
pot_path = args.cpython_repo / "pot"
upstream = {
file.relative_to(pot_path).with_suffix(".po")
for file in pot_path.glob("**/*.pot")
}
downstream = {
po
for po in Path(".").glob("**/*.po")
if not (po.is_relative_to(Path("locales")) or po.is_relative_to(Path(".git")))
}
copy_new_files(upstream - downstream, pot_path=pot_path)
update_known_files(upstream & downstream, pot_path=pot_path)
remove_old_files(downstream - upstream)
clean_paths((upstream - downstream) | (upstream & downstream))
shutil.rmtree(pot_path)
run("powrap", "-m")
update_makefile(args.cpython_repo)
git_add_relevant_files()
run("git", "commit", "-m", "Make merge")
if __name__ == "__main__":
main()