| #!/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, 8), "Python 3.8+ required" |
| |
| |
| 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:])) |