crashclouseau/pushlog.py (99 lines of code) (raw):

# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. from dateutil.relativedelta import relativedelta from libmozdata.hgmozilla import Mercurial, Revision from libmozdata import utils as lmdutils import re import requests from . import buildhub, hgauthors, models, utils BACKOUT_PAT = re.compile( r"^(?:(?:back(?:ed|ing|s)?(?:[ _]*out[_]?))|(?:revert(?:ing|s)?)) (?:(?:cset|changeset|revision|rev|of)s?)?", re.I | re.DOTALL, ) BUG_PAT = re.compile(r"^bug[ \t]*([0-9]+)", re.I) def is_backed_out(desc): """Check the patch description to know if we've a backout or not""" return BACKOUT_PAT.match(desc) is not None def get_bug(desc): """Get a bug number from the patch description""" m = BUG_PAT.search(desc) if m: return int(m.group(1)) return -1 def collect(data, file_filter): """Collect the data we need in the pushlog got from hg.mozilla.org""" res = [] for push in data["pushes"].values(): pushdate = lmdutils.get_date_from_timestamp(push["date"]) for chgset in push["changesets"]: files = [f for f in chgset["files"] if file_filter(f)] desc = chgset["desc"] author = chgset["author"] res.append( { "date": pushdate, "node": utils.short_rev(chgset["node"]), "backedout": is_backed_out(desc), "files": files, "merge": len(chgset["parents"]) > 1, "bug": get_bug(desc), "author": hgauthors.analyze_author(author), } ) return res def pushlog( startdate, enddate, channel="nightly", file_filter=utils.is_interesting_file ): """Get the pushlog from hg.mozilla.org""" # Get the pushes where startdate <= pushdate <= enddate # pushlog uses strict inequality, it's why we add +/- 1 second fmt = "%Y-%m-%d %H:%M:%S" startdate -= relativedelta(seconds=1) startdate = startdate.strftime(fmt) enddate += relativedelta(seconds=1) enddate = enddate.strftime(fmt) url = "{}/json-pushes".format(Mercurial.get_repo_url(channel)) r = requests.get( url, params={"startdate": startdate, "enddate": enddate, "version": 2, "full": 1}, ) return collect(r.json(), file_filter) def pushlog_for_revs( startrev, endrev, channel="nightly", file_filter=utils.is_interesting_file ): """Get the pushlog from startrev to endrev""" # startrev is not include in the pushlog url = "{}/json-pushes".format(Mercurial.get_repo_url(channel)) r = requests.get( url, params={"fromchange": startrev, "tochange": endrev, "version": 2, "full": 1}, ) return collect(r.json(), file_filter) def pushlog_for_revs_url(startrev, endrev, channel): """Get the pushlog url from startrev to endrev""" return "{}/pushloghtml?fromchange={}&tochange={}".format( Mercurial.get_repo_url(channel), startrev, endrev ) def pushlog_for_buildid( buildid, channel, product, file_filter=utils.is_interesting_file ): """Get the pushlog for a buildid/channel/product""" data = buildhub.get_two_last(buildid, channel, product) if data: startrev = data[0]["revision"] endrev = data[1]["revision"] return pushlog_for_revs( startrev, endrev, channel=channel, file_filter=file_filter ) return None def pushlog_for_buildid_url(buildid, channel, product): """Get the pushlog url for a buildid/channel/product""" data = models.Build.get_two_last(utils.get_build_date(buildid), channel, product) if len(data) != 2: data = buildhub.get_two_last(buildid, channel, product) if data: startrev = data[0]["revision"] endrev = data[1]["revision"] return pushlog_for_revs_url(startrev, endrev, channel) return None def pushlog_for_pushdate_url(pushdate, channel, product): """Get the pushlog url for the build containing pushdate""" data = buildhub.get_enclosing_builds(pushdate, channel, product) if data: startrev = data[0]["revision"] if data[1] is None: endrev = "tip" else: endrev = data[1]["revision"] return pushlog_for_revs_url(startrev, endrev, channel) return None def pushlog_for_rev_url(revision, channel, product): """Get the pushlog url for the build containing revision""" data = Revision.get_revision(channel=channel, node=revision) pushdate = lmdutils.get_date_from_timestamp(data["pushdate"][0]) return pushlog_for_pushdate_url(pushdate, channel, product)