| #!/usr/bin/env vpython3 |
| # Copyright 2026 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """Extracts host, project, change, and patchset from a Gerrit CL URL.""" |
| |
| import argparse |
| import json |
| import re |
| import sys |
| import urllib.parse |
| |
| |
| def parse_gerrit_url(url: str) -> dict[str, str | int]: |
| """Parses a Gerrit CL URL into host, project, change, and patchset. |
| |
| Args: |
| url: Absolute Gerrit CL URL string. |
| |
| Returns: |
| Dictionary containing host, project, change (int), and patchset (int). |
| """ |
| parsed = urllib.parse.urlparse(url) |
| host = parsed.netloc |
| path = parsed.path |
| if not host or not path: |
| raise ValueError(f'Invalid Gerrit URL: {url}') |
| |
| match = re.match(r'^/c/(.+?)/\+/(\d+)(?:/(\d+))?', path) |
| if not match: |
| raise ValueError(f'Could not extract CL details from path: {path}') |
| |
| project = match.group(1) |
| change = int(match.group(2)) |
| patchset = int(match.group(3)) if match.group(3) else 1 |
| |
| return { |
| 'host': host, |
| 'project': project, |
| 'change': change, |
| 'patchset': patchset, |
| } |
| |
| |
| def main() -> None: |
| """Parses CLI arguments and prints Gerrit CL details as JSON.""" |
| parser = argparse.ArgumentParser(description=__doc__) |
| parser.add_argument('url', help='Gerrit CL URL') |
| args = parser.parse_args() |
| |
| try: |
| details = parse_gerrit_url(args.url) |
| print(json.dumps(details, indent=2)) |
| except ValueError as e: |
| print(str(e), file=sys.stderr) |
| sys.exit(1) |
| |
| |
| if __name__ == '__main__': |
| main() |