tor-browser

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

revlist.py (4367B)


      1 import argparse
      2 import os
      3 import time
      4 from typing import Any, Iterator, Tuple
      5 
      6 from tools.wpt.testfiles import get_git_cmd
      7 
      8 here = os.path.dirname(__file__)
      9 wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir))
     10 
     11 
     12 def calculate_cutoff_date(until: int, epoch: int, offset: int) -> int:
     13    return (((until - offset) // epoch) * epoch) + offset
     14 
     15 
     16 def parse_epoch(string: str) -> int:
     17    UNIT_DICT = {"h": 3600, "d": 86400, "w": 604800}
     18    base = string[:-1]
     19    unit = string[-1:]
     20    if base.isdigit() and unit in UNIT_DICT:
     21        return int(base) * UNIT_DICT[unit]
     22    raise argparse.ArgumentTypeError('must be digits followed by h/d/w')
     23 
     24 
     25 def get_tagged_revisions(pattern: str) -> Iterator[Tuple[str, str, int]]:
     26    '''
     27    Iterates the tagged revisions as (tag name, commit sha, committer date) tuples.
     28    '''
     29    git = get_git_cmd(wpt_root)
     30    args = [
     31        pattern,
     32        '--sort=-committerdate',
     33        '--format=%(refname:lstrip=2) %(objectname) %(committerdate:raw)',
     34        '--count=100000'
     35    ]
     36    ref_list = git("for-each-ref", *args)  # type: ignore
     37    for line in ref_list.splitlines():
     38        if not line:
     39            continue
     40        tag, commit, date, _ = line.split(" ")
     41        date = int(date)
     42        yield tag, commit, date
     43 
     44 
     45 def get_epoch_revisions(epoch: int, until: int, max_count: int) -> Iterator[str]:
     46    # Set an offset to start to count the weekly epoch from
     47    # Monday 00:00:00. This is particularly important for the weekly epoch
     48    # because fix the start of the epoch to Monday. This offset is calculated
     49    # from Thursday, 1 January 1970 0:00:00 to Monday, 5 January 1970 0:00:00
     50    epoch_offset = 345600
     51    count = 0
     52 
     53    # Iterates the tagged revisions in descending order finding the more
     54    # recent commit still older than a "cutoff_date" value.
     55    # When a commit is found "cutoff_date" is set to a new value multiplier of
     56    # "epoch" but still below of the date of the current commit found.
     57    # This needed to deal with intervals where no candidates were found
     58    # for the current "epoch" and the next candidate found is yet below
     59    # the lower values of the interval (it is the case of J and I for the
     60    # interval between Wed and Tue, in the example). The algorithm fix
     61    # the next "cutoff_date" value based on the date value of the current one
     62    # skipping the intermediate values.
     63    # The loop ends once we reached the required number of revisions to return
     64    # or the are no more tagged revisions or the cutoff_date reach zero.
     65    #
     66    #   Fri   Sat   Sun   Mon   Tue   Wed   Thu   Fri   Sat
     67    #    |     |     |     |     |     |     |     |     |
     68    # -A---B-C---DEF---G---H--IJ----------K-----L-M----N--O--
     69    #                                                       ^
     70    #                                                      now
     71    # Expected result: N,M,K,J,H,G,F,C,A
     72 
     73    cutoff_date = calculate_cutoff_date(until, epoch, epoch_offset)
     74    for _, commit, date in get_tagged_revisions("refs/tags/merge_pr_*"):
     75        if count >= max_count:
     76            return
     77        if date < cutoff_date:
     78            yield commit
     79            count += 1
     80            cutoff_date = calculate_cutoff_date(date, epoch, epoch_offset)
     81 
     82 
     83 def get_parser() -> argparse.ArgumentParser:
     84    parser = argparse.ArgumentParser()
     85    parser.add_argument("--epoch",
     86                        default="1d",
     87                        type=parse_epoch,
     88                        help="regular interval of time selected to get the "
     89                             "tagged revisions. Valid values are digits "
     90                             "followed by h/d/w (e.x. 9h, 9d, 9w ...) where "
     91                             "the mimimun selectable interval is one hour "
     92                             "(1h)")
     93    parser.add_argument("--max-count",
     94                        default=1,
     95                        type=int,
     96                        help="maximum number of revisions to be returned by "
     97                             "the command")
     98    return parser
     99 
    100 
    101 def run_rev_list(**kwargs: Any) -> None:
    102    # "epoch_threshold" is a safety margin. After this time it is fine to
    103    # assume that any tags are created and pushed.
    104    epoch_threshold = 600
    105    until = int(time.time()) - epoch_threshold
    106    for line in get_epoch_revisions(kwargs["epoch"], until, kwargs["max_count"]):
    107        print(line)