tor-browser

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

hg.py (4304B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 
      6 import logging
      7 import subprocess
      8 
      9 import requests
     10 from mozbuild.util import memoize
     11 from redo import retry
     12 
     13 logger = logging.getLogger(__name__)
     14 
     15 PUSHLOG_CHANGESET_TMPL = (
     16    "{repository}/json-pushes?version=2&changeset={revision}&tipsonly=1"
     17 )
     18 PUSHLOG_PUSHES_TMPL = (
     19    "{repository}/json-pushes/?version=2&startID={push_id_start}&endID={push_id_end}"
     20 )
     21 
     22 
     23 def _query_pushlog(url):
     24    response = retry(
     25        requests.get,
     26        attempts=5,
     27        sleeptime=10,
     28        args=(url,),
     29        kwargs={"timeout": 60, "headers": {"User-Agent": "TaskCluster"}},
     30    )
     31 
     32    return response.json()["pushes"]
     33 
     34 
     35 def find_hg_revision_push_info(repository, revision):
     36    """Given the parameters for this action and a revision, find the
     37    pushlog_id of the revision."""
     38    url = PUSHLOG_CHANGESET_TMPL.format(repository=repository, revision=revision)
     39 
     40    pushes = _query_pushlog(url)
     41 
     42    if len(pushes) != 1:
     43        raise RuntimeError(
     44            f"Found {len(pushes)} pushlog_ids, expected 1, for {repository} revision {revision}: {pushes}"
     45        )
     46 
     47    pushid = list(pushes.keys())[0]
     48    return {
     49        "pushdate": pushes[pushid]["date"],
     50        "pushid": pushid,
     51        "user": pushes[pushid]["user"],
     52    }
     53 
     54 
     55 @memoize
     56 def get_push_data(repository, project, push_id_start, push_id_end):
     57    url = PUSHLOG_PUSHES_TMPL.format(
     58        repository=repository,
     59        push_id_start=push_id_start - 1,
     60        push_id_end=push_id_end,
     61    )
     62 
     63    try:
     64        pushes = _query_pushlog(url)
     65 
     66        return {
     67            push_id: pushes[str(push_id)]
     68            for push_id in range(push_id_start, push_id_end + 1)
     69        }
     70 
     71    # In the event of request times out, requests will raise a TimeoutError.
     72    except requests.exceptions.Timeout:
     73        logger.warning("json-pushes timeout")
     74 
     75    # In the event of a network problem (e.g. DNS failure, refused connection, etc),
     76    # requests will raise a ConnectionError.
     77    except requests.exceptions.ConnectionError:
     78        logger.warning("json-pushes connection error")
     79 
     80    # In the event of the rare invalid HTTP response(e.g 404, 401),
     81    # requests will raise an HTTPError exception
     82    except requests.exceptions.HTTPError:
     83        logger.warning("Bad Http response")
     84 
     85    # When we get invalid JSON (i.e. 500 error), it results in a ValueError (bug 1313426)
     86    except ValueError as error:
     87        logger.warning(f"Invalid JSON, possible server error: {error}")
     88 
     89    # We just print the error out as a debug message if we failed to catch the exception above
     90    except requests.exceptions.RequestException as error:
     91        logger.warning(error)
     92 
     93    return None
     94 
     95 
     96 @memoize
     97 def get_json_pushchangedfiles(repository, revision):
     98    url = "{}/json-pushchangedfiles/{}".format(repository.rstrip("/"), revision)
     99    logger.debug("Querying version control for metadata: %s", url)
    100 
    101    def get_pushchangedfiles():
    102        response = requests.get(url, timeout=60)
    103        response.raise_for_status()
    104        return response.json()
    105 
    106    return retry(get_pushchangedfiles, attempts=10, sleeptime=10)
    107 
    108 
    109 def get_hg_revision_branch(root, revision):
    110    """Given the parameters for a revision, find the hg_branch (aka
    111    relbranch) of the revision."""
    112    return get_hg_revision_info(root, revision, "branch")
    113 
    114 
    115 def get_hg_revision_info(root, revision, info):
    116    return subprocess.check_output(
    117        [
    118            "hg",
    119            "identify",
    120            "-T",
    121            f"{{{info}}}",
    122            "--rev",
    123            revision,
    124        ],
    125        cwd=root,
    126        universal_newlines=True,
    127    )
    128 
    129 
    130 # For these functions, we assume that run-task has correctly checked out the
    131 # revision indicated by GECKO_HEAD_REF, so all that remains is to see what the
    132 # current revision is.  Mercurial refers to that as `.`.
    133 def get_hg_commit_message(root, rev="."):
    134    return subprocess.check_output(
    135        ["hg", "log", "-r", rev, "-T", "{desc}"], cwd=root, universal_newlines=True
    136    )
    137 
    138 
    139 def calculate_head_rev(root):
    140    return subprocess.check_output(
    141        ["hg", "log", "-r", ".", "-T", "{node}"], cwd=root, universal_newlines=True
    142    )