mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-08 14:23:19 +00:00
204 lines
6.0 KiB
Python
204 lines
6.0 KiB
Python
|
#!/usr/bin/env python3
|
||
|
# SPDX-License-Identifier: GPL-2.0
|
||
|
|
||
|
"""
|
||
|
This script helps track the translation status of the documentation
|
||
|
in different locales, e.g., zh_CN. More specially, it uses `git log`
|
||
|
commit to find the latest english commit from the translation commit
|
||
|
(order by author date) and the latest english commits from HEAD. If
|
||
|
differences occur, report the file and commits that need to be updated.
|
||
|
|
||
|
The usage is as follows:
|
||
|
- ./scripts/checktransupdate.py -l zh_CN
|
||
|
This will print all the files that need to be updated in the zh_CN locale.
|
||
|
- ./scripts/checktransupdate.py Documentation/translations/zh_CN/dev-tools/testing-overview.rst
|
||
|
This will only print the status of the specified file.
|
||
|
|
||
|
The output is something like:
|
||
|
Documentation/translations/zh_CN/dev-tools/testing-overview.rst (1 commits)
|
||
|
commit 42fb9cfd5b18 ("Documentation: dev-tools: Add link to RV docs")
|
||
|
"""
|
||
|
|
||
|
import os
|
||
|
from argparse import ArgumentParser, BooleanOptionalAction
|
||
|
from datetime import datetime
|
||
|
|
||
|
flag_p_c = False
|
||
|
flag_p_uf = False
|
||
|
flag_debug = False
|
||
|
|
||
|
|
||
|
def dprint(*args, **kwargs):
|
||
|
if flag_debug:
|
||
|
print("[DEBUG] ", end="")
|
||
|
print(*args, **kwargs)
|
||
|
|
||
|
|
||
|
def get_origin_path(file_path):
|
||
|
paths = file_path.split("/")
|
||
|
tidx = paths.index("translations")
|
||
|
opaths = paths[:tidx]
|
||
|
opaths += paths[tidx + 2 :]
|
||
|
return "/".join(opaths)
|
||
|
|
||
|
|
||
|
def get_latest_commit_from(file_path, commit):
|
||
|
command = "git log --pretty=format:%H%n%aD%n%cD%n%n%B {} -1 -- {}".format(
|
||
|
commit, file_path
|
||
|
)
|
||
|
dprint(command)
|
||
|
pipe = os.popen(command)
|
||
|
result = pipe.read()
|
||
|
result = result.split("\n")
|
||
|
if len(result) <= 1:
|
||
|
return None
|
||
|
|
||
|
dprint("Result: {}".format(result[0]))
|
||
|
|
||
|
return {
|
||
|
"hash": result[0],
|
||
|
"author_date": datetime.strptime(result[1], "%a, %d %b %Y %H:%M:%S %z"),
|
||
|
"commit_date": datetime.strptime(result[2], "%a, %d %b %Y %H:%M:%S %z"),
|
||
|
"message": result[4:],
|
||
|
}
|
||
|
|
||
|
|
||
|
def get_origin_from_trans(origin_path, t_from_head):
|
||
|
o_from_t = get_latest_commit_from(origin_path, t_from_head["hash"])
|
||
|
while o_from_t is not None and o_from_t["author_date"] > t_from_head["author_date"]:
|
||
|
o_from_t = get_latest_commit_from(origin_path, o_from_t["hash"] + "^")
|
||
|
if o_from_t is not None:
|
||
|
dprint("tracked origin commit id: {}".format(o_from_t["hash"]))
|
||
|
return o_from_t
|
||
|
|
||
|
|
||
|
def get_commits_count_between(opath, commit1, commit2):
|
||
|
command = "git log --pretty=format:%H {}...{} -- {}".format(commit1, commit2, opath)
|
||
|
dprint(command)
|
||
|
pipe = os.popen(command)
|
||
|
result = pipe.read().split("\n")
|
||
|
# filter out empty lines
|
||
|
result = list(filter(lambda x: x != "", result))
|
||
|
return result
|
||
|
|
||
|
|
||
|
def pretty_output(commit):
|
||
|
command = "git log --pretty='format:%h (\"%s\")' -1 {}".format(commit)
|
||
|
dprint(command)
|
||
|
pipe = os.popen(command)
|
||
|
return pipe.read()
|
||
|
|
||
|
|
||
|
def check_per_file(file_path):
|
||
|
opath = get_origin_path(file_path)
|
||
|
|
||
|
if not os.path.isfile(opath):
|
||
|
dprint("Error: Cannot find the origin path for {}".format(file_path))
|
||
|
return
|
||
|
|
||
|
o_from_head = get_latest_commit_from(opath, "HEAD")
|
||
|
t_from_head = get_latest_commit_from(file_path, "HEAD")
|
||
|
|
||
|
if o_from_head is None or t_from_head is None:
|
||
|
print("Error: Cannot find the latest commit for {}".format(file_path))
|
||
|
return
|
||
|
|
||
|
o_from_t = get_origin_from_trans(opath, t_from_head)
|
||
|
|
||
|
if o_from_t is None:
|
||
|
print("Error: Cannot find the latest origin commit for {}".format(file_path))
|
||
|
return
|
||
|
|
||
|
if o_from_head["hash"] == o_from_t["hash"]:
|
||
|
if flag_p_uf:
|
||
|
print("No update needed for {}".format(file_path))
|
||
|
return
|
||
|
else:
|
||
|
print("{}".format(file_path), end="\t")
|
||
|
commits = get_commits_count_between(
|
||
|
opath, o_from_t["hash"], o_from_head["hash"]
|
||
|
)
|
||
|
print("({} commits)".format(len(commits)))
|
||
|
if flag_p_c:
|
||
|
for commit in commits:
|
||
|
msg = pretty_output(commit)
|
||
|
if "Merge tag" not in msg:
|
||
|
print("commit", msg)
|
||
|
|
||
|
|
||
|
def main():
|
||
|
script_path = os.path.dirname(os.path.abspath(__file__))
|
||
|
linux_path = os.path.join(script_path, "..")
|
||
|
|
||
|
parser = ArgumentParser(description="Check the translation update")
|
||
|
parser.add_argument(
|
||
|
"-l",
|
||
|
"--locale",
|
||
|
help="Locale to check when files are not specified",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"--print-commits",
|
||
|
action=BooleanOptionalAction,
|
||
|
default=True,
|
||
|
help="Print commits between the origin and the translation",
|
||
|
)
|
||
|
|
||
|
parser.add_argument(
|
||
|
"--print-updated-files",
|
||
|
action=BooleanOptionalAction,
|
||
|
default=False,
|
||
|
help="Print files that do no need to be updated",
|
||
|
)
|
||
|
|
||
|
parser.add_argument(
|
||
|
"--debug",
|
||
|
action=BooleanOptionalAction,
|
||
|
help="Print debug information",
|
||
|
default=False,
|
||
|
)
|
||
|
|
||
|
parser.add_argument(
|
||
|
"files", nargs="*", help="Files to check, if not specified, check all files"
|
||
|
)
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
global flag_p_c, flag_p_uf, flag_debug
|
||
|
flag_p_c = args.print_commits
|
||
|
flag_p_uf = args.print_updated_files
|
||
|
flag_debug = args.debug
|
||
|
|
||
|
# get files related to linux path
|
||
|
files = args.files
|
||
|
if len(files) == 0:
|
||
|
if args.locale is not None:
|
||
|
files = (
|
||
|
os.popen(
|
||
|
"find {}/Documentation/translations/{} -type f".format(
|
||
|
linux_path, args.locale
|
||
|
)
|
||
|
)
|
||
|
.read()
|
||
|
.split("\n")
|
||
|
)
|
||
|
else:
|
||
|
files = (
|
||
|
os.popen(
|
||
|
"find {}/Documentation/translations -type f".format(linux_path)
|
||
|
)
|
||
|
.read()
|
||
|
.split("\n")
|
||
|
)
|
||
|
|
||
|
files = list(filter(lambda x: x != "", files))
|
||
|
files = list(map(lambda x: os.path.relpath(os.path.abspath(x), linux_path), files))
|
||
|
|
||
|
# cd to linux root directory
|
||
|
os.chdir(linux_path)
|
||
|
|
||
|
for file in files:
|
||
|
check_per_file(file)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|