# # # patch "setup.py" # from [06fc7bdc71ab6ffccbb8f4a994047861c8e5b42f] # to [af9c163d61a82f0cf49700cc590af692ca9d5fc6] # # patch "tracvc/mtn/automate.py" # from [9e84da952a42a8bf13b2ed01859b5a332b9e1600] # to [03b65e719913b77116bd86fc7e2845b2afb39b8b] # # patch "tracvc/mtn/backend.py" # from [eed6094031a922ee107ed025bcf50f174cdd8958] # to [15d7b0d4adfc2ff8e9f70890c07b6acf8b7d15c6] # ============================================================ --- setup.py 06fc7bdc71ab6ffccbb8f4a994047861c8e5b42f +++ setup.py af9c163d61a82f0cf49700cc590af692ca9d5fc6 @@ -5,7 +5,7 @@ setup( name = 'TracMonotone', keywords = 'trac monotone scm plugin mtn', - version = '0.1', + version = '0.0.1', author = 'Thomas Moschny', author_email = 'address@hidden', packages = ['tracvc', 'tracvc.mtn'], ============================================================ --- tracvc/mtn/automate.py 9e84da952a42a8bf13b2ed01859b5a332b9e1600 +++ tracvc/mtn/automate.py 03b65e719913b77116bd86fc7e2845b2afb39b8b @@ -91,8 +91,9 @@ class MTN: - def __init__(self, db, binary = MT_BINARY): + def __init__(self, db, log, binary = MT_BINARY): self.automate = Automate(db, binary) + self.log = log self.manifest_cache = {} self.certs_cache = {} self.roots_cache = [] @@ -134,6 +135,13 @@ self.roots_cache = roots return roots + def select(self, selector): + """Returns a list of revisions selected by the selector.""" + #self.log.debug('select: %s', selector) + status, result = self.automate.command("select", selector) + if status == 0: return result.splitlines() + else: return [] + def manifest(self, rev): """ Returns a processed manifest for rev. @@ -142,10 +150,7 @@ with kind being 'file' or 'dir', and attrs being a dictionary attr_name -> attr_value. """ - - #print "MANIFEST of %s" % rev - if self.manifest_cache.has_key(rev): - # print "cached" + if rev in self.manifest_cache: return self.manifest_cache[rev] status, result = self.automate.command("get_manifest_of", rev) manifest = {} @@ -170,7 +175,7 @@ in a list. """ #print "asking for cert for rev", revb - if self.certs_cache.has_key(rev): + if rev in self.certs_cache: return self.certs_cache[rev] status, result = self.automate.command("certs", rev) certs = {} @@ -179,7 +184,7 @@ cert = basic_io.get_hash_from_stanza(stanza) name = unicode(cert['name'], 'utf-8', 'replace') value = unicode(cert['value'], 'utf-8', 'replace') - if not certs.has_key(name): + if not name in certs: certs[name] = [value] else: certs[name].append(value) @@ -231,7 +236,7 @@ changeset.append((newpath, None, 'move', oldpath, oldrev)) elif entry.has_key('patch'): path = '/' + entry['patch'] - if renames.has_key(path): + if path in renames: (oldpath, oldrev_for_path) = renames[path] changeset.append((path, 'file', 'edit', oldpath, oldrev_for_path)) else: ============================================================ --- tracvc/mtn/backend.py eed6094031a922ee107ed025bcf50f174cdd8958 +++ tracvc/mtn/backend.py 15d7b0d4adfc2ff8e9f70890c07b6acf8b7d15c6 @@ -28,7 +28,9 @@ from trac.core import * from cStringIO import StringIO from automate import MTN +import re +REV = re.compile('^[0-9a-f]{40}$') class MonotoneConnector(Component): @@ -46,7 +48,7 @@ """Return a monotone repository.""" # note: we don't use type or authname, therefore we can always # return the same Repository object for the same database path - if not self.repos.has_key(path): + if not path in self.repos: self.repos[path] = MonotoneRepository(path, self.log) return self.repos[path] @@ -57,12 +59,18 @@ def get_link_resolvers(self): """Add the cset namespace.""" - yield('cset', self._format_cset) + yield('cset', self._format_link) + yield('chgset', self._format_link) + yield('branch', self._format_link) # returns head of the branch + yield('revtag', self._format_link) - def _format_cset(self, formatter, ns, rev, label): + def _format_link(self, formatter, ns, rev, label): """Format a changeset link.""" # fixme: add support for selectors repos = self.env.get_repository() + if ns == 'branch': rev = "h:/b:" + rev + elif ns == 'revtag': rev = "t:" + rev + rev = repos.normalize_rev(rev) try: changeset = repos.get_changeset(rev) return '%s' \ @@ -77,7 +85,7 @@ class MonotoneRepository(Repository): def __init__(self, db_path, log): - self.mtn = MTN(db_path) + self.mtn = MTN(db_path, log) Repository.__init__(self, 'mtn:%s' % db_path, None, log) def get_changeset(self, rev): @@ -175,7 +183,9 @@ Return a canonical representation of a revision in the repos. 'None' is a valid revision value and represents the youngest revision. """ - return rev or self.get_youngest_rev() + if REV.match(rev): return rev + revs = self.mtn.select(rev) + return revs and revs[0] or self.get_youngest_rev() def short_rev(self, rev): """ @@ -200,7 +210,7 @@ def __init__(self, mtn, rev, path): self.mtn = mtn self.manifest = self.mtn.manifest(rev) - if not self.manifest.has_key(path): + if not path in self.manifest: raise NoSuchNode(path, rev) kind = self.manifest[path][0] # 'file' or 'dir' Node.__init__(self, path, rev, kind) @@ -274,15 +284,19 @@ class MonotoneChangeset(Changeset): def __init__(self, mtn, rev): - certs = mtn.certs(rev) + self.certs = mtn.certs(rev) # always pick the first - self.messages = certs['changelog'] + self.messages = self.certs.get('changelog', ['-']) + self.authors = self.certs.get('author', ['-']) + self.dates = mtn.dates(rev) + self.branches = self.certs.get('branch', []) + self.tags = self.certs.get('tag', []) + message = self.messages[0] - self.dates = mtn.dates(rev) + author = self.authors[0] date = self.dates[0] - self.authors = certs['author'] - author = self.authors[0] + Changeset.__init__(self, rev, message, author, date) self.mtn = mtn @@ -313,7 +327,9 @@ yield('Parent', '[cset:%s]' % parent, True, 'changeset') for child in self.mtn.children(self.rev): yield('Child', '[cset:%s]' % child, True, 'changeset') - for branch in self.mtn.certs(self.rev)['branch']: - yield('Branch', branch, False, '') + for branch in self.branches: + yield('Branch', '[branch:%s]' % branch, True, 'changeset') + for tag in self.tags: + yield('Tag', '[revtag:%s]' % tag, True, 'changeset') for message in self.messages[1:]: yield('+Message', message, True, 'message')