| #!/usr/bin/env python3 | |
| # Copyright (C) 2024 The Android Open Source Project | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """Helper tool for updating hooks from their various upstreams.""" | |
| import argparse | |
| import base64 | |
| import json | |
| from pathlib import Path | |
| import sys | |
| from typing import List, Optional | |
| import urllib.request | |
| assert sys.version_info >= (3, 9), "Release framework requires Python 3.9+" | |
| TOPDIR = Path(__file__).resolve().parent.parent | |
| HOOKS_DIR = TOPDIR / "hooks" | |
| def update_hook_commit_msg() -> None: | |
| """Update commit-msg hook from Gerrit.""" | |
| hook = HOOKS_DIR / "commit-msg" | |
| print( | |
| f"{hook.name}: Updating from https://gerrit.googlesource.com/gerrit/" | |
| "+/HEAD/resources/com/google/gerrit/server/tools/root/hooks/commit-msg" | |
| ) | |
| # Get the current commit. | |
| url = "https://gerrit.googlesource.com/gerrit/+/HEAD?format=JSON" | |
| with urllib.request.urlopen(url) as fp: | |
| data = fp.read() | |
| # Discard the xss protection. | |
| data = data.split(b"\n", 1)[1] | |
| data = json.loads(data) | |
| commit = data["commit"] | |
| # Fetch the data for that commit. | |
| url = ( | |
| f"https://gerrit.googlesource.com/gerrit/+/{commit}/" | |
| "resources/com/google/gerrit/server/tools/root/hooks/commit-msg" | |
| ) | |
| with urllib.request.urlopen(f"{url}?format=TEXT") as fp: | |
| data = fp.read() | |
| # gitiles base64 encodes text data. | |
| data = base64.b64decode(data) | |
| # Inject header into the hook. | |
| lines = data.split(b"\n") | |
| lines = ( | |
| lines[:1] | |
| + [ | |
| b"# DO NOT EDIT THIS FILE", | |
| ( | |
| b"# All updates should be sent upstream: " | |
| b"https://gerrit.googlesource.com/gerrit/" | |
| ), | |
| f"# This is synced from commit: {commit}".encode("utf-8"), | |
| b"# DO NOT EDIT THIS FILE", | |
| ] | |
| + lines[1:] | |
| ) | |
| data = b"\n".join(lines) | |
| # Update the hook. | |
| hook.write_bytes(data) | |
| hook.chmod(0o755) | |
| def update_hook_pre_auto_gc() -> None: | |
| """Update pre-auto-gc hook from git.""" | |
| hook = HOOKS_DIR / "pre-auto-gc" | |
| print( | |
| f"{hook.name}: Updating from https://github.com/git/git/" | |
| "HEAD/contrib/hooks/pre-auto-gc-battery" | |
| ) | |
| # Get the current commit. | |
| headers = { | |
| "Accept": "application/vnd.github+json", | |
| "X-GitHub-Api-Version": "2022-11-28", | |
| } | |
| url = "https://api.github.com/repos/git/git/git/refs/heads/master" | |
| req = urllib.request.Request(url, headers=headers) | |
| with urllib.request.urlopen(req) as fp: | |
| data = fp.read() | |
| data = json.loads(data) | |
| # Fetch the data for that commit. | |
| commit = data["object"]["sha"] | |
| url = ( | |
| f"https://raw.githubusercontent.com/git/git/{commit}/" | |
| "contrib/hooks/pre-auto-gc-battery" | |
| ) | |
| with urllib.request.urlopen(url) as fp: | |
| data = fp.read() | |
| # Inject header into the hook. | |
| lines = data.split(b"\n") | |
| lines = ( | |
| lines[:1] | |
| + [ | |
| b"# DO NOT EDIT THIS FILE", | |
| ( | |
| b"# All updates should be sent upstream: " | |
| b"https://github.com/git/git/" | |
| ), | |
| f"# This is synced from commit: {commit}".encode("utf-8"), | |
| b"# DO NOT EDIT THIS FILE", | |
| ] | |
| + lines[1:] | |
| ) | |
| data = b"\n".join(lines) | |
| # Update the hook. | |
| hook.write_bytes(data) | |
| hook.chmod(0o755) | |
| def main(argv: Optional[List[str]] = None) -> Optional[int]: | |
| parser = argparse.ArgumentParser(description=__doc__) | |
| parser.parse_args(argv) | |
| update_hook_commit_msg() | |
| update_hook_pre_auto_gc() | |
| if __name__ == "__main__": | |
| sys.exit(main(sys.argv[1:])) |