Add templates to calculate aurora and nightly dates
authorGregory Szorc <gps@mozilla.com>
Thu, 07 Nov 2013 22:53:58 -0800
changeset 62 c679e3ef7e09724cd71544c96c9a108536206269
parent 61 0acb68c2180069f70c4f98faa0fd7bd9023ffaf9
child 63 a10db377c453387b2460da08748d9b460cb5f6f5
push id43
push usergszorc@mozilla.com
push dateFri, 08 Nov 2013 06:54:07 +0000
Add templates to calculate aurora and nightly dates
__init__.py
--- a/__init__.py
+++ b/__init__.py
@@ -140,16 +140,40 @@ Templates
 This extension provides keywords that can used with templates.
 
 bug
    The bug primarily associated with a changeset.
 
 bugs
    All the bugs associated with a changeset.
 
+firstrelease
+   The version number of the first release channel release a changeset
+   was present in.
+
+firstbeta
+   The version number of the first beta channel release a changeset was
+   present in.
+
+auroradate
+   The date of the first Aurora a changeset was likely present in.
+
+   This value may not be accurate. The value is currently obtained by
+   querying the pushlog data to see when a changeset was pushed to this
+   channel. The date of the next Aurora is then calculated from that
+   (essentially looking for the next early morning Pacific time day).
+   Aurora releases are not always consistent. A more robust method of
+   calculation involves grabbing information from release engineering
+   servers.
+
+nightlydate
+   The date of the first Nightly a changeset was likely present in.
+
+   See auroradate for accuracy information.
+
 Config Options
 ==============
 
 This extension consults the following config options.
 
 mozext.headless
    Indicates that this extension is running in *headless* mode. *headless*
    mode is intended for server operation, not local development.
@@ -180,16 +204,17 @@ mozext.reject_pushes_with_repo_names
 mozext.refs_as_bookmarks
    If enabled, this boolean flag will cause remote keys to be added to
    the local repository's bookmarks during push and pull operations. This
    is most useful on servers, as remote keys/refs are typically only
    created dynamically at run-time via a mechanism independent of
    bookmarks.
 """
 
+import calendar
 import datetime
 import errno
 import os
 import shutil
 import sys
 
 from operator import methodcaller
 
@@ -722,23 +747,91 @@ def _compute_first_version(repo, ctx, wh
 
 
 def template_firstrelease(repo, ctx, **args):
     """:firstrelease: String. The version of the first release channel
     release with this changeset.
     """
     return _compute_first_version(repo, ctx, 'release', args['cache'])
 
+
 def template_firstbeta(repo, ctx, **args):
     """:firstbeta: String. The version of the first beta release with this
     changeset.
     """
     return _compute_first_version(repo, ctx, 'beta', args['cache'])
 
 
+def _calculate_next_daily_release(repo, ctx, tree):
+    pushes = repo.changetracker.pushes_for_changeset(ctx.node())
+    pushes = [p for p in pushes if p[0] == tree]
+
+    if not pushes:
+        return None
+
+    push = pushes[0]
+    when = push[2]
+
+    dt = datetime.datetime.utcfromtimestamp(when)
+
+    # Daily builds kick off at 3 AM in Mountain View. This is -7 hours
+    # from UTC during daylight savings and -8 during regular.
+    # Mercurial nor core Python have timezone info built-in, so we
+    # hack this calculation together here. This calculation is wrong
+    # for date before 2007, when the DST start/end days changed. It
+    # may not always be correct in the future. We should use a real
+    # timezone database.
+    dst_start = None
+    dst_end = None
+
+    c = calendar.Calendar(calendar.SUNDAY)
+    sunday_count = 0
+    for day in c.itermonthdates(dt.year, 3):
+        if day.month != 3:
+            continue
+
+        if day.weekday() == 6:
+            sunday_count += 1
+            if sunday_count == 2:
+                dst_start = day
+                break
+
+    for day in c.itermonthdates(dt.year, 11):
+        if day.month != 11:
+            if day.weekday() == 6:
+                dst_end = day
+                break
+
+    dst_start = datetime.datetime(dst_start.year, dst_start.month,
+        dst_start.day, 2)
+    dst_end = datetime.datetime(dst_end.year, dst_end.month,
+        dst_end.day, 2)
+
+    is_dst = dt >= dst_start and dt <= dst_end
+    utc_offset = 11 if is_dst else 10
+
+    if dt.hour > 3 + utc_offset:
+        dt += datetime.timedelta(days=1)
+
+    return dt.date().isoformat()
+
+
+def template_auroradate(repo, ctx, **args):
+    """:auroradate: String. The date of the first Aurora this
+    changeset was likely first active in as a YYYY-MM-DD value.
+    """
+    return _calculate_next_daily_release(repo, ctx, 'aurora')
+
+
+def template_nightlydate(repo, ctx, **args):
+    """:nightlydate: Date information. The date of the first Nightly this
+    changeset was likely first active in as a YYYY-MM-DD value.
+    """
+    return _calculate_next_daily_release(repo, ctx, 'central')
+
 
 def extsetup(ui):
     global bz_available
     try:
         extensions.find('bzexport')
         bz_available = True
     except KeyError:
         pass
@@ -748,16 +841,18 @@ def extsetup(ui):
     revset.symbols['bug'] = revset_bug
     revset.symbols['me'] = revset_me
     revset.symbols['tree'] = revset_tree
 
     templatekw.keywords['bug'] = template_bug
     templatekw.keywords['bugs'] = template_bugs
     templatekw.keywords['firstrelease'] = template_firstrelease
     templatekw.keywords['firstbeta'] = template_firstbeta
+    templatekw.keywords['auroradate'] = template_auroradate
+    templatekw.keywords['nightlydate'] = template_nightlydate
 
 
 def reposetup(ui, repo):
     """Custom repository implementation.
 
     Our custom repository class tracks remote tree references so users can
     reference specific revisions on remotes.
     """