diff options
author | Mike Frysinger <vapier@google.com> | 2024-04-23 12:17:13 -0400 |
---|---|---|
committer | LUCI <gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-04-23 18:31:51 +0000 |
commit | 5591d99ee239be9116f4879bfea4a538b0b89e9c (patch) | |
tree | 282752df0312e75204026badcc72acc9901e3222 /release/update-hooks | |
parent | 9d865454aaf0ea41927332768e55b5b2f56e2533 (diff) | |
download | git-repo-5591d99ee239be9116f4879bfea4a538b0b89e9c.tar.gz |
release: update-hooks: helper for automatically syncing hooks
These hooks are maintained in other projects. Add a script to automate
their import so people don't send us changes directly, and we can try to
steer them to the correct place.
Change-Id: Iac0bdb3aae84dda43a1600e73107555b513ce82b
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/422177
Commit-Queue: Mike Frysinger <vapier@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
Diffstat (limited to 'release/update-hooks')
-rwxr-xr-x | release/update-hooks | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/release/update-hooks b/release/update-hooks new file mode 100755 index 00000000..def4bba9 --- /dev/null +++ b/release/update-hooks | |||
@@ -0,0 +1,143 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # Copyright (C) 2024 The Android Open Source Project | ||
3 | # | ||
4 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | # you may not use this file except in compliance with the License. | ||
6 | # You may obtain a copy of the License at | ||
7 | # | ||
8 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | # | ||
10 | # Unless required by applicable law or agreed to in writing, software | ||
11 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | # See the License for the specific language governing permissions and | ||
14 | # limitations under the License. | ||
15 | |||
16 | """Helper tool for updating hooks from their various upstreams.""" | ||
17 | |||
18 | import argparse | ||
19 | import base64 | ||
20 | import json | ||
21 | from pathlib import Path | ||
22 | import sys | ||
23 | from typing import List, Optional | ||
24 | import urllib.request | ||
25 | |||
26 | |||
27 | assert sys.version_info >= (3, 8), "Python 3.8+ required" | ||
28 | |||
29 | |||
30 | TOPDIR = Path(__file__).resolve().parent.parent | ||
31 | HOOKS_DIR = TOPDIR / "hooks" | ||
32 | |||
33 | |||
34 | def update_hook_commit_msg() -> None: | ||
35 | """Update commit-msg hook from Gerrit.""" | ||
36 | hook = HOOKS_DIR / "commit-msg" | ||
37 | print( | ||
38 | f"{hook.name}: Updating from https://gerrit.googlesource.com/gerrit/" | ||
39 | "+/HEAD/resources/com/google/gerrit/server/tools/root/hooks/commit-msg" | ||
40 | ) | ||
41 | |||
42 | # Get the current commit. | ||
43 | url = "https://gerrit.googlesource.com/gerrit/+/HEAD?format=JSON" | ||
44 | with urllib.request.urlopen(url) as fp: | ||
45 | data = fp.read() | ||
46 | # Discard the xss protection. | ||
47 | data = data.split(b"\n", 1)[1] | ||
48 | data = json.loads(data) | ||
49 | commit = data["commit"] | ||
50 | |||
51 | # Fetch the data for that commit. | ||
52 | url = ( | ||
53 | f"https://gerrit.googlesource.com/gerrit/+/{commit}/" | ||
54 | "resources/com/google/gerrit/server/tools/root/hooks/commit-msg" | ||
55 | ) | ||
56 | with urllib.request.urlopen(f"{url}?format=TEXT") as fp: | ||
57 | data = fp.read() | ||
58 | |||
59 | # gitiles base64 encodes text data. | ||
60 | data = base64.b64decode(data) | ||
61 | |||
62 | # Inject header into the hook. | ||
63 | lines = data.split(b"\n") | ||
64 | lines = ( | ||
65 | lines[:1] | ||
66 | + [ | ||
67 | b"# DO NOT EDIT THIS FILE", | ||
68 | ( | ||
69 | b"# All updates should be sent upstream: " | ||
70 | b"https://gerrit.googlesource.com/gerrit/" | ||
71 | ), | ||
72 | f"# This is synced from commit: {commit}".encode("utf-8"), | ||
73 | b"# DO NOT EDIT THIS FILE", | ||
74 | ] | ||
75 | + lines[1:] | ||
76 | ) | ||
77 | data = b"\n".join(lines) | ||
78 | |||
79 | # Update the hook. | ||
80 | hook.write_bytes(data) | ||
81 | hook.chmod(0o755) | ||
82 | |||
83 | |||
84 | def update_hook_pre_auto_gc() -> None: | ||
85 | """Update pre-auto-gc hook from git.""" | ||
86 | hook = HOOKS_DIR / "pre-auto-gc" | ||
87 | print( | ||
88 | f"{hook.name}: Updating from https://github.com/git/git/" | ||
89 | "HEAD/contrib/hooks/pre-auto-gc-battery" | ||
90 | ) | ||
91 | |||
92 | # Get the current commit. | ||
93 | headers = { | ||
94 | "Accept": "application/vnd.github+json", | ||
95 | "X-GitHub-Api-Version": "2022-11-28", | ||
96 | } | ||
97 | url = "https://api.github.com/repos/git/git/git/refs/heads/master" | ||
98 | req = urllib.request.Request(url, headers=headers) | ||
99 | with urllib.request.urlopen(req) as fp: | ||
100 | data = fp.read() | ||
101 | data = json.loads(data) | ||
102 | |||
103 | # Fetch the data for that commit. | ||
104 | commit = data["object"]["sha"] | ||
105 | url = ( | ||
106 | f"https://raw.githubusercontent.com/git/git/{commit}/" | ||
107 | "contrib/hooks/pre-auto-gc-battery" | ||
108 | ) | ||
109 | with urllib.request.urlopen(url) as fp: | ||
110 | data = fp.read() | ||
111 | |||
112 | # Inject header into the hook. | ||
113 | lines = data.split(b"\n") | ||
114 | lines = ( | ||
115 | lines[:1] | ||
116 | + [ | ||
117 | b"# DO NOT EDIT THIS FILE", | ||
118 | ( | ||
119 | b"# All updates should be sent upstream: " | ||
120 | b"https://github.com/git/git/" | ||
121 | ), | ||
122 | f"# This is synced from commit: {commit}".encode("utf-8"), | ||
123 | b"# DO NOT EDIT THIS FILE", | ||
124 | ] | ||
125 | + lines[1:] | ||
126 | ) | ||
127 | data = b"\n".join(lines) | ||
128 | |||
129 | # Update the hook. | ||
130 | hook.write_bytes(data) | ||
131 | hook.chmod(0o755) | ||
132 | |||
133 | |||
134 | def main(argv: Optional[List[str]] = None) -> Optional[int]: | ||
135 | parser = argparse.ArgumentParser(description=__doc__) | ||
136 | parser.parse_args(argv) | ||
137 | |||
138 | update_hook_commit_msg() | ||
139 | update_hook_pre_auto_gc() | ||
140 | |||
141 | |||
142 | if __name__ == "__main__": | ||
143 | sys.exit(main(sys.argv[1:])) | ||