| #!/usr/bin/env python3 |
| # Copyright 2016 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 script to quickly update the bundled cpplint.py script.""" |
| |
| import argparse |
| import json |
| from pathlib import Path |
| import re |
| import sys |
| import urllib.request |
| |
| |
| # Since this is manually run by repohooks developers, we can safely require more |
| # recent versions of Python. |
| assert sys.version_info >= (3, 9), f"Python 3.9+ required; found {sys.version}" |
| |
| |
| THIS_FILE = Path(__file__).resolve() |
| SCRIPT_NAME = THIS_FILE.name |
| THIS_DIR = THIS_FILE.parent |
| CPPLINT_PY = THIS_DIR / "cpplint.py" |
| |
| |
| # The cpplint project. |
| GITHUB_URL = "https://github.com/cpplint/cpplint/raw" |
| |
| |
| def find_latest_tag() -> str: |
| """Figure out the latest tag/release and return its commit.""" |
| url = "https://api.github.com/repos/cpplint/cpplint/tags" |
| with urllib.request.urlopen(url, timeout=60) as fp: |
| data = fp.read() |
| |
| # This will have the format: |
| # [ |
| # {"name": "0.0.7", "commit": {"sha": "<sha1>", ...}, ...}, |
| # {"name": "0.0.6", "commit": {"sha": "<sha1>", ...}, ...}, |
| # ... |
| # ] |
| resp = json.loads(data) |
| # Filter out random named tags. |
| tags = [x for x in resp if re.match(r"^[0-9.]+$", x["name"])] |
| tags = sorted( |
| tags, |
| key=lambda x: tuple(int(v) for v in x["name"].split(".")), |
| reverse=True, |
| ) |
| latest = tags[0] |
| print(f"{SCRIPT_NAME}: found latest tag {latest['name']}") |
| return latest["commit"]["sha"] |
| |
| |
| def download(commit: str) -> str: |
| """Download latest cpplint version.""" |
| url = f"{GITHUB_URL}/{commit}/cpplint.py" |
| with urllib.request.urlopen(url, timeout=60) as fp: |
| return fp.read() |
| |
| |
| def munge_content(data: str) -> str: |
| """Make changes to |data| for local script usage.""" |
| lines = data.splitlines() |
| if lines[0].endswith(b"python"): |
| lines[0] += b"3" |
| lines.insert(1, b"# pylint: skip-file") |
| return b"\n".join(lines).rstrip() + b"\n" |
| |
| |
| def update_script(data: str) -> None: |
| """Update the cpplint script.""" |
| CPPLINT_PY.write_bytes(data) |
| CPPLINT_PY.chmod(0o755) |
| |
| |
| def get_parser() -> argparse.ArgumentParser: |
| """Return a command line parser.""" |
| parser = argparse.ArgumentParser(description=__doc__) |
| parser.add_argument( |
| "--rev", |
| help="What git commit or ref to fetch (default: latest)", |
| ) |
| return parser |
| |
| |
| def main(argv: list[str]) -> int: |
| parser = get_parser() |
| opts = parser.parse_args(argv) |
| |
| ret = 0 |
| |
| commit = opts.rev |
| if not commit: |
| commit = find_latest_tag() |
| data = download(commit) |
| data = munge_content(data) |
| update_script(data) |
| |
| return ret |
| |
| |
| if __name__ == "__main__": |
| sys.exit(main(sys.argv[1:])) |