mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-10-12 08:01:29 +08:00
129 lines
3.8 KiB
Python
129 lines
3.8 KiB
Python
"""Search for MRs and issues related to a list of commits."""
|
|
|
|
import argparse
|
|
import json
|
|
import sys
|
|
import subprocess
|
|
import re
|
|
|
|
|
|
def find_cherry_pick_source(commit_hash: str):
|
|
"""
|
|
For a given commit hash, find the original commit it was cherry-picked from.
|
|
|
|
Args:
|
|
commit_hash: The commit hash to inspect.
|
|
|
|
Returns:
|
|
The full hash of the original commit if found, otherwise None.
|
|
"""
|
|
try:
|
|
# Use 'git show' to get the full commit message for the given hash.
|
|
# The '-s' flag suppresses the diff output.
|
|
# The '--format=%B' flag prints only the raw commit body/message.
|
|
commit_message = subprocess.check_output(
|
|
["git", "show", "-s", "--format=%B", commit_hash.strip()],
|
|
text=True,
|
|
stderr=subprocess.PIPE,
|
|
).strip()
|
|
|
|
# This regex looks for the specific line Git adds during a cherry-pick.
|
|
# It captures the full 40-character SHA-1 hash.
|
|
cherry_pick_pattern = re.compile(
|
|
r"\(cherry picked from commit ([a-f0-9]{40})\)"
|
|
)
|
|
|
|
# Search the entire commit message for the pattern.
|
|
match = cherry_pick_pattern.search(commit_message)
|
|
|
|
if match:
|
|
# If a match is found, return the captured group (the original commit hash).
|
|
return match.group(1)
|
|
else:
|
|
return None
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
# This error occurs if the git command fails, e.g., for an invalid hash.
|
|
print(
|
|
f"Error processing commit '{commit_hash.strip()}': {e.stderr.strip()}",
|
|
file=sys.stderr,
|
|
)
|
|
return None
|
|
except FileNotFoundError:
|
|
# This error occurs if the 'git' command itself isn't found.
|
|
print(
|
|
"Error: 'git' command not found. Please ensure Git is installed and in your PATH.",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
|
|
|
|
def main():
|
|
"""
|
|
Main function to read commit hashes from stdin and process them.
|
|
"""
|
|
parser = argparse.ArgumentParser(
|
|
description="A script to download all MRs from GitLab matching specified criteria."
|
|
)
|
|
parser.add_argument(
|
|
"--merge_requests_file",
|
|
type=str,
|
|
required=True,
|
|
help="JSON file containing all the merge request information extracted via the GitLab API.",
|
|
)
|
|
|
|
# E.g. git log --pretty=%H 3e819d83bf52abda16bb53565f6801df40d071f1..3.4.1
|
|
parser.add_argument(
|
|
"--commits",
|
|
required=True,
|
|
help="List of commits, '-' for stdin.",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
mrs = []
|
|
with open(args.merge_requests_file, "r") as file:
|
|
mrs = json.load(file)
|
|
mrs_by_commit = {}
|
|
|
|
if args.commits == "-":
|
|
commit_hashes = sys.stdin.readlines()
|
|
else:
|
|
with open(args.commits, "r") as file:
|
|
commit_hashes = file.readlines()
|
|
|
|
# Arrange commits by SHA.
|
|
for mr in mrs:
|
|
for key in ["sha", "merge_commit_sha", "squash_commit_sha"]:
|
|
sha = mr[key]
|
|
if sha:
|
|
mrs_by_commit[sha] = mr
|
|
|
|
# Find the MRs and issues related to each commit.
|
|
info = {}
|
|
for sha in commit_hashes:
|
|
sha = sha.strip()
|
|
if not sha:
|
|
continue
|
|
|
|
# If a cherry-pick, extract the original hash.
|
|
sha = find_cherry_pick_source(sha) or sha
|
|
mr = mrs_by_commit.get(sha)
|
|
|
|
commit_info = {}
|
|
if mr:
|
|
commit_info["merge_request"] = mr["iid"]
|
|
commit_info["related_issues"] = [
|
|
issue["iid"] for issue in mr["related_issues"]
|
|
]
|
|
commit_info["closes_issues"] = [
|
|
issue["iid"] for issue in mr["closes_issues"]
|
|
]
|
|
|
|
info[sha] = commit_info
|
|
|
|
print(json.dumps(info, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|