summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-07-19 01:54:16 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2024-07-19 01:54:16 +0300
commitcf05e93af423b225fb3e3237e7d46493c7909f2b (patch)
tree8eadf02e46fb36faf6d5a3467b35bdf4d15e75ff /scripts
parent7dd894c1bf65a9591ba27f6175cf3238748deb47 (diff)
parent702418f7559fb1828646f0b51d9ca7c8b9ee7bff (diff)
downloadlinux-cf05e93af423b225fb3e3237e7d46493c7909f2b.tar.xz
Merge tag 'docs-6.11' of git://git.lwn.net/linux
Pull documentation updates from Jonathan Corbet: "Nothing hugely exciting happening in the documentation tree this time around, mostly more of the usual: - More Spanish, Italian, and Chinese translations - A new script, scripts/checktransupdate.py, can be used to see which commits have touched an (English) document since a given translation was last updated. - A couple of "best practices" suggestions (on Link: tags and off-list discussions) that were not entirely at consensus level, but I concluded they were close enough to accept. - Some nice cleanups removing documentation for kernel parameters that have not been recognized for ... a long time. ...along with the usual updates, typo fixes, and such" * tag 'docs-6.11' of git://git.lwn.net/linux: (57 commits) Documentation: Document user_events ioctl code docs/pinctrl: fix typo in mapping example docs: maintainer: discourage taking conversations off-list docs: driver-model: platform: update the definition of platform_driver docs/sp_SP: Add translation for scheduler/sched-design-CFS.rst writing_musb_glue_layer.rst: Fix broken URL zh_CN/admin-guide: one typo fix docs/zh_CN/virt: Update the translation of guest-halt-polling.rst Documentation: add reference from dynamic debug to loglevel kernel params Documentation: best practices for using Link trailers Documentation: fix links to mailing list services Documentation: exception-tables.rst: Fix the wrong steps referenced docs/zh_CN: add process/researcher-guidelines Chinese translation Documentation/tools/rv: fix document header docs/sp_SP: Add translation of process/maintainer-kvm-x86.rst docs/admin-guide/mm: correct typo 'quired' to 'queried' Add libps2 to the input section of driver-api Docs/mm/index: move allocation profiling document to unsorted documents chapter Docs/mm/index: rename 'Legacy Documentation' to 'Unsorted Documentation' Docs/mm/index: Remove 'Memory Management Guide' chapter marker ...
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/checktransupdate.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/scripts/checktransupdate.py b/scripts/checktransupdate.py
new file mode 100755
index 000000000000..5a0fc99e3f93
--- /dev/null
+++ b/scripts/checktransupdate.py
@@ -0,0 +1,203 @@
+#!/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()