]> Git Repo - linux.git/blob - scripts/checktransupdate.py
Merge tag 'input-for-v6.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / scripts / checktransupdate.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: GPL-2.0
3
4 """
5 This script helps track the translation status of the documentation
6 in different locales, e.g., zh_CN. More specially, it uses `git log`
7 commit to find the latest english commit from the translation commit
8 (order by author date) and the latest english commits from HEAD. If
9 differences occur, report the file and commits that need to be updated.
10
11 The usage is as follows:
12 - ./scripts/checktransupdate.py -l zh_CN
13 This will print all the files that need to be updated in the zh_CN locale.
14 - ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst
15 This will only print the status of the specified file.
16
17 The output is something like:
18 Documentation/translations/zh_CN/dev-tools/testing-overview.rst (1 commits)
19 commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs")
20 """
21
22 import os
23 from argparse import ArgumentParser, BooleanOptionalAction
24 from datetime import datetime
25
26 flag_p_c = False
27 flag_p_uf = False
28 flag_debug = False
29
30
31 def dprint(*args, **kwargs):
32     if flag_debug:
33         print("[DEBUG] ", end="")
34         print(*args, **kwargs)
35
36
37 def get_origin_path(file_path):
38     paths = file_path.split("/")
39     tidx = paths.index("translations")
40     opaths = paths[:tidx]
41     opaths += paths[tidx + 2 :]
42     return "/".join(opaths)
43
44
45 def get_latest_commit_from(file_path, commit):
46     command = "git log --pretty=format:%H%n%aD%n%cD%n%n%B {} -1 -- {}".format(
47         commit, file_path
48     )
49     dprint(command)
50     pipe = os.popen(command)
51     result = pipe.read()
52     result = result.split("\n")
53     if len(result) <= 1:
54         return None
55
56     dprint("Result: {}".format(result[0]))
57
58     return {
59         "hash": result[0],
60         "author_date": datetime.strptime(result[1], "%a, %d %b %Y %H:%M:%S %z"),
61         "commit_date": datetime.strptime(result[2], "%a, %d %b %Y %H:%M:%S %z"),
62         "message": result[4:],
63     }
64
65
66 def get_origin_from_trans(origin_path, t_from_head):
67     o_from_t = get_latest_commit_from(origin_path, t_from_head["hash"])
68     while o_from_t is not None and o_from_t["author_date"] > t_from_head["author_date"]:
69         o_from_t = get_latest_commit_from(origin_path, o_from_t["hash"] + "^")
70     if o_from_t is not None:
71         dprint("tracked origin commit id: {}".format(o_from_t["hash"]))
72     return o_from_t
73
74
75 def get_commits_count_between(opath, commit1, commit2):
76     command = "git log --pretty=format:%H {}...{} -- {}".format(commit1, commit2, opath)
77     dprint(command)
78     pipe = os.popen(command)
79     result = pipe.read().split("\n")
80     # filter out empty lines
81     result = list(filter(lambda x: x != "", result))
82     return result
83
84
85 def pretty_output(commit):
86     command = "git log --pretty='format:%h (\"%s\")' -1 {}".format(commit)
87     dprint(command)
88     pipe = os.popen(command)
89     return pipe.read()
90
91
92 def check_per_file(file_path):
93     opath = get_origin_path(file_path)
94
95     if not os.path.isfile(opath):
96         dprint("Error: Cannot find the origin path for {}".format(file_path))
97         return
98
99     o_from_head = get_latest_commit_from(opath, "HEAD")
100     t_from_head = get_latest_commit_from(file_path, "HEAD")
101
102     if o_from_head is None or t_from_head is None:
103         print("Error: Cannot find the latest commit for {}".format(file_path))
104         return
105
106     o_from_t = get_origin_from_trans(opath, t_from_head)
107
108     if o_from_t is None:
109         print("Error: Cannot find the latest origin commit for {}".format(file_path))
110         return
111
112     if o_from_head["hash"] == o_from_t["hash"]:
113         if flag_p_uf:
114             print("No update needed for {}".format(file_path))
115         return
116     else:
117         print("{}".format(file_path), end="\t")
118         commits = get_commits_count_between(
119             opath, o_from_t["hash"], o_from_head["hash"]
120         )
121         print("({} commits)".format(len(commits)))
122         if flag_p_c:
123             for commit in commits:
124                 msg = pretty_output(commit)
125                 if "Merge tag" not in msg:
126                     print("commit", msg)
127
128
129 def main():
130     script_path = os.path.dirname(os.path.abspath(__file__))
131     linux_path = os.path.join(script_path, "..")
132
133     parser = ArgumentParser(description="Check the translation update")
134     parser.add_argument(
135         "-l",
136         "--locale",
137         help="Locale to check when files are not specified",
138     )
139     parser.add_argument(
140         "--print-commits",
141         action=BooleanOptionalAction,
142         default=True,
143         help="Print commits between the origin and the translation",
144     )
145
146     parser.add_argument(
147         "--print-updated-files",
148         action=BooleanOptionalAction,
149         default=False,
150         help="Print files that do no need to be updated",
151     )
152
153     parser.add_argument(
154         "--debug",
155         action=BooleanOptionalAction,
156         help="Print debug information",
157         default=False,
158     )
159
160     parser.add_argument(
161         "files", nargs="*", help="Files to check, if not specified, check all files"
162     )
163     args = parser.parse_args()
164
165     global flag_p_c, flag_p_uf, flag_debug
166     flag_p_c = args.print_commits
167     flag_p_uf = args.print_updated_files
168     flag_debug = args.debug
169
170     # get files related to linux path
171     files = args.files
172     if len(files) == 0:
173         if args.locale is not None:
174             files = (
175                 os.popen(
176                     "find {}/Documentation/translations/{} -type f".format(
177                         linux_path, args.locale
178                     )
179                 )
180                 .read()
181                 .split("\n")
182             )
183         else:
184             files = (
185                 os.popen(
186                     "find {}/Documentation/translations -type f".format(linux_path)
187                 )
188                 .read()
189                 .split("\n")
190             )
191
192     files = list(filter(lambda x: x != "", files))
193     files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files))
194
195     # cd to linux root directory
196     os.chdir(linux_path)
197
198     for file in files:
199         check_per_file(file)
200
201
202 if __name__ == "__main__":
203     main()
This page took 0.039403 seconds and 4 git commands to generate.