# # # patch "tracvc/mtn/automate.py" # from [1cabae2a601a4a744d60267eb278beb687b542dc] # to [b4c10bd231d383b3bc39f65273ac9116d39549d7] # # patch "tracvc/mtn/backend.py" # from [16a92a8ac8deb5ddbd48780da32781d005ffd5b1] # to [b563ac13448f4daa3148bef9fc12cbb39e5eb699] # ============================================================ --- tracvc/mtn/automate.py 1cabae2a601a4a744d60267eb278beb687b542dc +++ tracvc/mtn/automate.py b4c10bd231d383b3bc39f65273ac9116d39549d7 @@ -234,18 +234,6 @@ class MTN: certs[name].append(value) return certs - def dates(self, rev): - """ - Return a sorted list of commit datetimes for this rev. The - datetimes are converted to floats for use by Trac. - """ - dates = [] - for date in self.certs(rev)['date']: - dt = time.strptime(date + " UTC","%Y-%m-%dT%H:%M:%S %Z") - dates.append(calendar.timegm(dt)) - dates.sort() - return dates - def file(self, id): """Returns the file contents for a given file id.""" status, result = self.automate.command("get_file", id) ============================================================ --- tracvc/mtn/backend.py 16a92a8ac8deb5ddbd48780da32781d005ffd5b1 +++ tracvc/mtn/backend.py b563ac13448f4daa3148bef9fc12cbb39e5eb699 @@ -31,6 +31,9 @@ from trac.config import Option from trac.util import shorten_line, escape from trac.core import * from trac.config import Option +from trac import __version__ as trac_version +from pkg_resources import parse_version +from time import strptime from automate import MTN import util @@ -107,6 +110,40 @@ class MonotoneConnector(Component): % (str(e), formatter.href.changeset(rev), label) +# Datetime handling changed somewhere between 0.10 and 0.11. We try to +# support both variants for a while. +if parse_version(trac_version) < parse_version("0.11dev"): + + def parse_date(s): + """ + Convert a monotone date string into a unix timestamp. + """ + from calendar import timegm + return timegm(strptime(s + " UTC","%Y-%m-%dT%H:%M:%S %Z")) + +else: + + def parse_date(s): + """ + Convert a monotone date string into a datetime object. + """ + from datetime import datetime + from trac.util.datefmt import utc + date = datetime(*strptime(s, "%Y-%m-%dT%H:%M:%S")[:6]) + return date.replace(tzinfo=utc) + + +def dates(certvals): + """ + Parse the raw dates and return a sorted list. + """ + result = [] + for s in certvals: + result.append(parse_date(s)) + result.sort() + return result + + class MonotoneRepository(Repository): def __init__(self, path, log, binary, cachespec): @@ -128,7 +165,7 @@ class MonotoneRepository(Repository): seen = set() while nodes: current = nodes.pop(0) - time = self.mtn.dates(current)[0] + time = self.get_dates(current)[0] if time < start: continue # assume none of the parents is younger elif time < stop: @@ -149,14 +186,14 @@ class MonotoneRepository(Repository): # hierarchies, so it makes no sense to ask for the latest # version of a path. rev = self.normalize_rev(rev) or self.get_youngest_rev() - return MonotoneNode(self.mtn, rev , path) + return MonotoneNode(self.mtn, rev, path) def get_oldest_rev(self): """ Return the oldest revision stored in the repository. Here: Return the oldest root. """ - roots = dict([(self.mtn.dates(rev)[0], rev) for rev in self.mtn.roots()]) + roots = dict([(self.get_dates(rev)[0], rev) for rev in self.mtn.roots()]) dates = roots.keys() dates.sort() return roots[dates[0]] @@ -166,7 +203,7 @@ class MonotoneRepository(Repository): Return the youngest revision in the repository. Here: Return the youngest leave. """ - leaves = dict([(self.mtn.dates(rev)[-1], rev) for rev in self.mtn.leaves()]) + leaves = dict([(self.get_dates(rev)[-1], rev) for rev in self.mtn.leaves()]) dates = leaves.keys() dates.sort() return leaves[dates[-1]] @@ -195,7 +232,7 @@ class MonotoneRepository(Repository): Return True if rev1 is older than rev2, i.e. if rev1 comes before rev2 in the revision sequence. """ - return self.mtn.dates(rev1)[0] < self.mtn.dates(rev2)[-1] + return self.get_dates(rev1)[0] < self.get_dates(rev2)[-1] def get_path_history(self, path, rev=None, limit=None): """ @@ -218,7 +255,6 @@ class MonotoneRepository(Repository): Return a canonical representation of a revision in the repos. 'None' is a valid revision value and represents the youngest revision. It should simply be passed through. - """ if rev != None: if isinstance(rev, unicode): @@ -275,7 +311,14 @@ class MonotoneRepository(Repository): return result + def get_dates(self, rev): + """ + Parse the date certs and return a sorted list of trac + compatible dates for rev. + """ + return dates(self.mtn.certs(rev).get('date', [])) + class MonotoneNode(Node): def __init__(self, mtn, rev, path, manifest = None): @@ -361,7 +404,7 @@ class MonotoneNode(Node): def get_last_modified(self): # fixme: might be to pessimistic - return self.mtn.dates(self.rev)[-1] + return dates(self.mtn.certs(rev).get('date', []))[-1] class MonotoneChangeset(Changeset): @@ -373,7 +416,7 @@ class MonotoneChangeset(Changeset): self.messages = self.certs.get('changelog', ['-']) self.authors = self.certs.get('author', ['-']) - self.dates = mtn.dates(rev) + self.dates = dates(self.certs.get('date', [])) self.branches = self.certs.get('branch', []) self.tags = self.certs.get('tag', [])