| # Copyright 2023 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| """3pp fetch.py shared logic for libs.""" |
| |
| import argparse |
| import dataclasses |
| import json |
| import os |
| import re |
| import typing |
| import urllib.request |
| |
| |
| @dataclasses.dataclass |
| class Spec: |
| repo_url: str |
| group_name: str |
| module_name: str |
| file_ext: str |
| patch_version: str = '' |
| version_override: typing.Optional[str] = None |
| version_filter: typing.Optional[str] = None |
| |
| |
| def do_latest(spec): |
| if spec.version_override is not None: |
| print(spec.version_override + f'.{spec.patch_version}') |
| return |
| maven_metadata_url = '{}/{}/{}/maven-metadata.xml'.format( |
| spec.repo_url, spec.group_name, spec.module_name) |
| metadata = urllib.request.urlopen(maven_metadata_url).read().decode( |
| 'utf-8') |
| # Do not parse xml with the python included parser since it is susceptible |
| # to maliciously crafted xmls. Only use regular expression parsing to be |
| # safe. RE should be enough to handle what we need to extract. |
| versions = re.findall('<version>([^<]+)</version>', metadata) |
| if m := re.search('<latest>([^<]+)</latest>', metadata): |
| versions.append(m.group(1)) |
| |
| # If no latest info was found just hope the versions are sorted and the |
| # last one is the latest (as is commonly the case). |
| if spec.version_filter is not None: |
| versions = [v for v in versions if spec.version_filter in v] |
| latest = versions[-1] |
| print(latest + f'.{spec.patch_version}') |
| |
| |
| def get_download_url(version, spec): |
| # Remove the patch version when getting the download url |
| version_no_patch, patch = version.rsplit('.', 1) |
| if patch.startswith('cr'): |
| version = version_no_patch |
| file_url = '{0}/{1}/{2}/{3}/{2}-{3}.{4}'.format(spec.repo_url, |
| spec.group_name, |
| spec.module_name, version, |
| spec.file_ext) |
| file_name = file_url.rsplit('/', 1)[-1] |
| |
| partial_manifest = { |
| 'url': [file_url], |
| 'name': [file_name], |
| 'ext': '.' + spec.file_ext, |
| } |
| print(json.dumps(partial_manifest)) |
| |
| |
| def main(spec): |
| ap = argparse.ArgumentParser() |
| sub = ap.add_subparsers(required=True) |
| |
| latest = sub.add_parser('latest') |
| latest.set_defaults(func=lambda _opts: do_latest(spec)) |
| |
| download = sub.add_parser('get_url') |
| download.set_defaults( |
| func=lambda _opts: get_download_url(os.environ['_3PP_VERSION'], spec)) |
| |
| opts = ap.parse_args() |
| opts.func(opts) |