scripts/git-cherry-gerrit.py | 94 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
New commits: commit 64b7a54156a3864effbd311992d42586d46c6989 Author: Miklos Vajna <[email protected]> AuthorDate: Mon Jan 11 09:12:26 2021 +0100 Commit: Miklos Vajna <[email protected]> CommitDate: Mon Jan 11 10:30:06 2021 +0100 git-cherry-gerrit.py: add a python version of the bash script A functional change from the bash version is that we stop after the first Change-Id when reading a commit message. This should not cause too much problems (only happens when directly pushing multiple commits to e.g. help.git and gerrit generating a submodule update for core.git), and simplifies the code. The benefit is that it's easy to use 'git cat-file --batch' from Python, which gives a performance boost: 28,140 vs 6,105 seconds when comparing e.g. distro/collabora/cp-6.4 and master of core.git (roughly 5 times faster). Change-Id: I9ec91ed28bfdbc843f53a9e9f1a7ddd853e63082 Reviewed-on: https://gerrit.libreoffice.org/c/dev-tools/+/109077 Tested-by: Miklos Vajna <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/scripts/git-cherry-gerrit.py b/scripts/git-cherry-gerrit.py new file mode 100755 index 0000000..6a0cf9e --- /dev/null +++ b/scripts/git-cherry-gerrit.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# + +""" +A version of 'git cherry' that works with change-ids, so it can pair patches +even if their patch id changed. +""" + +from typing import List +import subprocess +import sys + + +def from_pipe(argv: List[str]) -> str: + """Executes argv as a command and returns its stdout.""" + result = subprocess.check_output(argv) + return result.strip().decode("utf-8") + + +def get_change_id(git_cat_file: subprocess.Popen, hash_string: str) -> str: + """Looks up the change-id for a git hash.""" + git_cat_file.stdin.write((hash_string + "\n").encode("utf-8")) + git_cat_file.stdin.flush() + first_line = git_cat_file.stdout.readline().decode("utf-8") + size = first_line.strip().split(" ")[2] + commit_msg = git_cat_file.stdout.read(int(size)).decode("utf-8") + git_cat_file.stdout.readline() + for line in commit_msg.split("\n"): + if "Change-Id:" in line: + return line + return "" + + +def main() -> None: + """Commandline interface.""" + cherry_from = "" + if len(sys.argv) >= 2: + cherry_from = sys.argv[1] + cherry_to = "" + if len(sys.argv) >= 3: + cherry_to = sys.argv[2] + + branch_point = "" + if len(sys.argv) >= 4: + branch_point = sys.argv[3] + + whitelist_file = "" + if len(sys.argv) >= 5: + whitelist_file = sys.argv[4] + + if not cherry_from: + print("Usage: git-cherry-gerrit.py cherry_from cherry_to [branch_point_from] [whitelist_file]") + sys.exit(1) + + merge_base = from_pipe(["git", "merge-base", cherry_from, cherry_to]) + + if not branch_point: + branch_point = merge_base + + to_change_ids = [] + to_hashes = from_pipe(["git", "rev-list", merge_base + ".." + cherry_to]).split("\n") + git_cat_file = subprocess.Popen(['git', 'cat-file', '--batch'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) + for to_hash in to_hashes: + to_change_ids.append(get_change_id(git_cat_file, to_hash)) + + from_hashes = from_pipe(["git", "rev-list", branch_point + ".." + cherry_from]).split("\n") + whitelist: List[str] = [] + if whitelist_file: + with open(whitelist_file, "r") as stream: + whitelist = stream.read().strip().split("\n") + for from_hash in from_hashes: + changeid = get_change_id(git_cat_file, from_hash) + pretty = from_pipe(["git", "--no-pager", "log", "-1", "--format=format:%h%x09%an%x09%s%x0a", from_hash]) + if not changeid: + if not whitelist_file or not [entry for entry in whitelist if pretty in entry]: + print("WARNING: commit '" + pretty + "' has no Change-Id, assuming it has to be cherry-picked.") + continue + + if changeid not in to_change_ids: + if not whitelist_file or not [entry for entry in whitelist if pretty in entry]: + print(pretty) + + git_cat_file.stdin.close() + git_cat_file.terminate() + + +if __name__ == '__main__': + main() + +# vim:set shiftwidth=4 softtabstop=4 expandtab: _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
