tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

fetch_github_release.py (3181B)


      1 # Copyright 2023 The Chromium Authors
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import argparse
      6 import hashlib
      7 import json
      8 import os
      9 import pathlib
     10 import re
     11 import sys
     12 from typing import Dict, List
     13 import urllib.request
     14 
     15 import scripthash
     16 
     17 
     18 def _fetch_json(url):
     19    return json.load(urllib.request.urlopen(url))
     20 
     21 
     22 def _find_valid_urls(release, artifact_regex):
     23    urls = [x['browser_download_url'] for x in release['assets']]
     24    if artifact_regex:
     25        urls = [x for x in urls if re.search(artifact_regex, x)]
     26    return urls
     27 
     28 
     29 def _latest(api_url, install_scripts=None, artifact_regex=None):
     30    # Make the version change every time this file changes.
     31    file_hash = scripthash.compute(extra_paths=install_scripts)
     32 
     33    releases: List[Dict] = _fetch_json(f'{api_url}/releases')
     34    for release in releases:
     35        tag_name = release['tag_name']
     36        urls = _find_valid_urls(release, artifact_regex)
     37        if len(urls) == 1:
     38            print('{}.{}'.format(tag_name, file_hash))
     39            return
     40        print(f'Bad urls={urls} for tag_name={tag_name}, skipping.',
     41              file=sys.stderr)
     42 
     43 
     44 def _get_url(api_url,
     45             artifact_filename=None,
     46             artifact_extension=None,
     47             artifact_regex=None):
     48    # Split off our md5 hash.
     49    version = os.environ['_3PP_VERSION'].rsplit('.', 1)[0]
     50    json_dict = _fetch_json(f'{api_url}/releases/tags/{version}')
     51    urls = _find_valid_urls(json_dict, artifact_regex)
     52 
     53    if len(urls) != 1:
     54        raise Exception('len(urls) != 1, urls: \n' + '\n'.join(urls))
     55 
     56    partial_manifest = {
     57        'url': urls,
     58        'ext': artifact_extension or '',
     59    }
     60    if artifact_filename:
     61        partial_manifest['name'] = [artifact_filename]
     62 
     63    print(json.dumps(partial_manifest))
     64 
     65 
     66 def main(*,
     67         project,
     68         artifact_filename=None,
     69         artifact_extension=None,
     70         artifact_regex=None,
     71         install_scripts=None):
     72    """The fetch.py script for a 3pp module.
     73 
     74    Args:
     75      project: GitHub username for the repo. e.g. "google/protobuf".
     76      artifact_filename: The name for the downloaded file. Required when not
     77          setting "unpack_archive: true" in 3pp.pb.
     78      artifact_extension: File extension of file being downloaded. Required when
     79          setting "unpack_archive: true" in 3pp.pb.
     80      artifact_regex: A regex to use to identify the desired artifact from the
     81          list of artifacts on the release.
     82      install_scripts: List of script to add to the md5 of the version. The main
     83          module and this module are always included.
     84    """
     85    parser = argparse.ArgumentParser()
     86    parser.add_argument('action', choices=('latest', 'get_url'))
     87    args = parser.parse_args()
     88 
     89    api_url = f'https://api.github.com/repos/{project}'
     90    if args.action == 'latest':
     91        _latest(api_url,
     92                install_scripts=install_scripts,
     93                artifact_regex=artifact_regex)
     94    else:
     95        _get_url(api_url,
     96                 artifact_filename=artifact_filename,
     97                 artifact_extension=artifact_extension,
     98                 artifact_regex=artifact_regex)