changeset 13:62e59cafa3de 1.0

Merge #10851 fix from 0.12 and bump version to 1.0.0.2
author Christian Boos <cboos@edgewall.org>
date Mon, 17 Sep 2012 12:09:52 +0200
parents c77621b0f6bb (diff) 45f04cd0ada8 (current diff)
children 32fd17a943f7
files setup.py tracext/hg/backend.py
diffstat 6 files changed, 228 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/README	Mon Sep 17 11:54:00 2012 +0200
+++ b/README	Mon Sep 17 12:09:52 2012 +0200
@@ -8,16 +8,16 @@
 
 === Trac ===
 
-This plugin for Trac 0.12 doesn't yet work with Trac ''trunk'',
-but requires the ''multirepos'' branch (to be integrated in trunk 
-shortly):
+This plugin works with Trac 1.0.x.
+
+You can also use the trunk version (1.1.x):
 {{{
-svn co http://svn.edgewall.com/repos/trac/sandbox/multirepos
+svn co http://svn.edgewall.org/repos/trac/trunk
 }}}
 
 and install from there:
 {{{
-$ cd multirepos
+$ cd trunk
 $ python setup.py egg_info
 $ python setup.py install
 }}}
--- a/setup.py	Mon Sep 17 11:54:00 2012 +0200
+++ b/setup.py	Mon Sep 17 12:09:52 2012 +0200
@@ -36,16 +36,16 @@
 TracMercurial = 'http://trac.edgewall.org/wiki/TracMercurial'
 
 setup(name='TracMercurial',
-      install_requires='Trac >=0.12dev-r9125',
-      description='Mercurial plugin for Trac multirepos branch',
+      install_requires='Trac >=1.0dev',
+      description='Mercurial plugin for Trac (1.0 branch)',
       keywords='trac scm plugin mercurial hg',
-      version='0.12.0.30',
+      version='1.0.0.2',
       url=TracMercurial,
       license='GPL',
       author='Christian Boos',
       author_email='cboos@edgewall.org',
       long_description="""
-      This plugin for Trac 0.12 provides support for the Mercurial SCM.
+      This plugin for Trac 1.0 provides support for the Mercurial SCM.
 
       See %s for more details.
       """ % TracMercurial,
--- a/tracext/hg/backend.py	Mon Sep 17 11:54:00 2012 +0200
+++ b/tracext/hg/backend.py	Mon Sep 17 12:09:52 2012 +0200
@@ -15,6 +15,7 @@
 
 from bisect import bisect
 from datetime import datetime
+from heapq import heappop, heappush
 import os
 import time
 import posixpath
@@ -177,7 +178,8 @@
 
     def match_property(self, name, mode):
         return (name.startswith('hg-') and
-                name[3:] in ('Parents', 'Children', 'Tags', 'Branch') and
+                name[3:] in ('Parents', 'Children', 'Tags', 'Branch',
+                             'Bookmarks') and
                 mode == 'revprop') and 4 or 0
     
     def render_property(self, name, mode, context, props):
@@ -725,6 +727,9 @@
         for c in ctx.children():
             return c.hex() # always follow first child
    
+    def parent_revs(self, rev):
+        return [p.hex() for p in self.changectx(rev).parents()]
+
     def rev_older_than(self, rev1, rev2):
         # FIXME use == and ancestors?
         return self.short_rev(rev1) < self.short_rev(rev2)
@@ -884,8 +889,8 @@
             if not dirctx:
                 # we need to find the most recent change for a file below dir
                 str_dir = str_path + '/'
-                dirctxs = self.find_dirctx(changectx.rev(), [str_dir,],
-                                           {str_dir: str_entries})
+                dirctxs = self._find_dirctx(changectx.rev(), [str_dir,],
+                                            {str_dir: str_entries})
                 dirctx = dirctxs.values()[0]
 
         if not kind:
@@ -906,13 +911,13 @@
         self.created_rev = created_rev
         self.data = None
 
-    def find_dirctx(self, max_rev, str_dirnames, str_entries):
+    def _find_dirctx(self, max_rev, str_dirnames, str_entries):
         """Find most recent modification for each given directory path.
         
         :param max_rev: find no revision more recent than this one
         :param str_dirnames: directory paths to consider 
-                             (as `str` ending with '/')
-        :param str_entries: optionally maps directories to their file content
+                             (list of `str` ending with '/')
+        :param str_entries: maps each directory to the files it contains
 
         :return: a `dict` with `str_dirnames` as keys, `changectx` as values
 
@@ -929,46 +934,66 @@
            each directory; this is much faster but can still be slow
            if some folders are only modified in the distant past
            
-        It is possible to combine both approach, and this can yield
-        excellent results in some cases (e.g. browsing the Linux repos
-        @ 118733 takes several minutes with the first approach, 11s
-        with the second, but only 1.2s with the hybrid approach)
+        It is possible to combine both approaches, and this can
+        produce excellent results in some cases, for example browsing
+        the root of the Hg mirror of the Linux repository (at revision
+        118733) takes several minutes with the first approach, 11s
+        with the second, but only 1.2s with the hybrid approach.
 
         Note that the specialized scan of the changelog we do below is
-        more efficient than the general cmdutil.walkchangerevs here.
+        more efficient than the general cmdutil.walkchangerevs.
         """
         str_dirctxs = {}
         repo = self.repos.repo
         max_ctx = repo[max_rev]
-        for r in xrange(max_rev, -1, -1):
+        orevs = [-max_rev]
+        revs = set(orevs)
+        while orevs:
+            r = -heappop(orevs)
             ctx = repo[r]
+            for p in ctx.parents():
+                if p and p.rev() not in revs:
+                    revs.add(p.rev())
+                    heappush(orevs, -p.rev())
             # lookup changes to str_dirnames in current cset
             for str_file in ctx.files():
                 for str_dir in str_dirnames[:]:
                     if str_file.startswith(str_dir):
+                        # rev for str_dir was found using first strategy
                         str_dirctxs[str_dir] = ctx
                         str_dirnames.remove(str_dir)
-                        if not str_dirnames: # if nothing left to find
+                        if not str_dirnames: # nothing left to find
                             return str_dirctxs
-            # in parallel, try the filelog strategy (the 463, 2, 40
+
+            # In parallel, try the filelog strategy (the 463, 2, 40
             # values below look a bit like magic numbers; actually
             # they were selected by testing the plugin on the Linux
             # and NetBeans repositories)
-            if r % 463 == 0:
-                k = max(2, 40 / len(str_dirnames))
+
+            # only use the filelog strategy every `n` revs
+            n = 463
+
+            # k, the number of files to examine per directory,
+            # will be comprised between `min_files` and `max_files`
+            min_files = 2
+            max_files = 40 # (will be the max if there's only one dir left)
+
+            if r % n == 0:
+                k = max(min_files, max_files / len(str_dirnames))
                 for str_dir in str_dirnames[:]:
                     str_files = str_entries[str_dir]
                     dr = str_dirctxs.get(str_dir, 0)
                     for f in str_files[:k]:
-                        try:
-                            dr = max(dr, max_ctx.filectx(f).linkrev())
-                        except LookupError:
-                            pass # that file was not on this revision `r`
+                        dr = max(dr, max_ctx.filectx(f).linkrev())
                     str_files = str_files[k:]
                     if str_files:
+                        # not all files for str_dir seen yet,
+                        # store max rev found so far
                         str_entries[str_dir] = str_files
                         str_dirctxs[str_dir] = dr
                     else:
+                        # all files for str_dir were examined,
+                        # rev found using filelog strategy
                         str_dirctxs[str_dir] = repo[dr]
                         str_dirnames.remove(str_dir)
                         if not str_dirnames:
@@ -1032,14 +1057,13 @@
 
         # pre-computing the changectx for the last change in each sub-directory
         if str_dirnames:
-            dirctxs = self.find_dirctx(self.created_rev, str_dirnames, 
-                                       str_entries)
+            dirctxs = self._find_dirctx(self.created_rev, str_dirnames, 
+                                        str_entries)
         else:
             dirctxs = {}
 
         for str_entry in str_entries:
-            yield self.subnode(str_entry.rstrip('/'),
-                               dirctxs.get(str_entry, None))
+            yield self.subnode(str_entry.rstrip('/'), dirctxs.get(str_entry))
 
     def get_history(self, limit=None):
         repo = self.repos.repo
@@ -1047,7 +1071,7 @@
         if self.str_path:
             pats.append('path:' + self.str_path)
         opts = {'rev': ['%s:0' % self.changectx.hex()]}
-        if self.isfile:
+        if self.isfile and self.repos.version_info < (2, 1, 1):
             opts['follow'] = True
         if arity(cmdutil.walkchangerevs) == 4:
             return self._get_history_1_4(repo, pats, opts, limit)
@@ -1171,7 +1195,8 @@
         Changeset.__init__(self, repos, ctx.hex(), desc, user, time)
 
     hg_properties = [
-        N_("Parents:"), N_("Children:"), N_("Branch:"), N_("Tags:")
+        N_("Parents:"), N_("Children:"), N_("Branch:"), N_("Tags:"),
+        N_("Bookmarks:")
     ]
 
     def get_properties(self):
@@ -1186,10 +1211,12 @@
                                          [c.hex() for c in children])
         if self.branch:
             properties['hg-Branch'] = (self.repos, [self.branch])
-        tags = self.ctx.tags()
+        tags = self.get_tags()
         if len(tags):
-            properties['hg-Tags'] = (self.repos, 
-                                     [self.repos.to_u(t) for t in tags])
+            properties['hg-Tags'] = (self.repos, tags) 
+        bookmarks = self.ctx.bookmarks()
+        if len(bookmarks):
+            properties['hg-Bookmarks'] = (self.repos, bookmarks) 
         for k, v in self.ctx.extra().iteritems():
             if k != 'branch':
                 properties['hg-' + k] = (self.repos, v)
@@ -1241,5 +1268,9 @@
 
     def get_branches(self):
         """Yield branch names to which this changeset belong."""
-        return self.branch and [(self.branch, 
-                                 len(self.ctx.children()) == 0)] or []
+        if self.branch:
+            yield (self.branch, len(self.ctx.children()) == 0)
+
+    def get_tags(self):
+        """Yield tag names to which this changeset belong."""
+        return [self.repos.to_u(t) for t in self.ctx.tags()]
--- a/tracext/hg/hooks.py	Mon Sep 17 11:54:00 2012 +0200
+++ b/tracext/hg/hooks.py	Mon Sep 17 12:09:52 2012 +0200
@@ -106,7 +106,7 @@
         try:
             revs_per_call = int(ui.config('trac', 'revs_per_call'))
         except (TypeError, ValueError):
-            revs_per_call = os.name == 'nt' and 160 or 1000
+            revs_per_call = 160 if os.name == 'nt' else 1000
 
         trac_admin = expand_path(trac_admin)
         for i in xrange(0, len(revs), revs_per_call):
--- a/tracext/hg/locale/fr/LC_MESSAGES/tracmercurial.po	Mon Sep 17 11:54:00 2012 +0200
+++ b/tracext/hg/locale/fr/LC_MESSAGES/tracmercurial.po	Mon Sep 17 12:09:52 2012 +0200
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: TracMercurial 0.12.0.4\n"
 "Report-Msgid-Bugs-To: cboos@edgewall.org\n"
-"POT-Creation-Date: 2008-11-13 12:33+0100\n"
+"POT-Creation-Date: 2012-06-11 23:08+0200\n"
 "PO-Revision-Date: 2009-11-19 16:22+0100\n"
 "Last-Translator: Christian Boos <cboos@edgewall.org>\n"
 "Language-Team: fr_FR <LL@li.org>\n"
@@ -16,19 +16,19 @@
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
+"Generated-By: Babel 0.9.6dev-r0\n"
 
-#: tracext/hg/backend.py:99
+#: tracext/hg/backend.py:183
 msgid ":"
-msgstr ""
+msgstr " :"
 
-#: tracext/hg/backend.py:114
+#: tracext/hg/backend.py:205
 msgid "Diff against this parent (show the changes merged from the other parents)"
 msgstr ""
 "Différences vis-à-vis de ce parent (montre les changements apportés par "
 "l'autre parent)"
 
-#: tracext/hg/backend.py:124
+#: tracext/hg/backend.py:215
 #, python-format
 msgid ""
 "Note: this is a %(merge)s changeset, the changes displayed below "
@@ -37,7 +37,7 @@
 "Note: ceci est un changeset de type %(merge)s, les modifications ci-"
 "dessous correspondent au merge lui-même."
 
-#: tracext/hg/backend.py:132
+#: tracext/hg/backend.py:223
 #, python-format
 msgid ""
 "Use the %(diff)s links above to see all the changes relative to each "
@@ -46,37 +46,46 @@
 "Utilisez les liens %(diff)s ci-dessus pour voir les modifications "
 "relatives à chaque parent."
 
-#: tracext/hg/backend.py:155
+#: tracext/hg/backend.py:248
 msgid "no such changeset"
-msgstr "pas de révisio"
+msgstr "pas de révision"
+
+#: tracext/hg/backend.py:249
+msgid "Transplant:"
+msgstr "Transplant :"
 
-#: tracext/hg/backend.py:156
-msgid "Transplant:"
-msgstr ""
+#: tracext/hg/backend.py:264
+msgid "Changeset in source repository"
+msgstr "Modification dans le dépôt d'origine"
 
-#: tracext/hg/backend.py:173
+#: tracext/hg/backend.py:266
+msgid "Convert:"
+msgstr "Conversion :"
+
+#: tracext/hg/backend.py:291
 msgid "(binary, size greater than 100 bytes)"
 msgstr "(binaire, taille supérieure à 100 octets)"
 
-#: tracext/hg/backend.py:285
+#: tracext/hg/backend.py:452
 #, python-format
 msgid "Repository '%(repo)s' not found"
-msgstr "Dépôt '%(repo)s' non trouvé"
+msgstr "Dépôt « %(repo)s »' non trouvé"
 
-#: tracext/hg/backend.py:344
+#: tracext/hg/backend.py:518
 #, python-format
-msgid "%(path)s does not appear to contain a Mercurial repository."
-msgstr "%(path)s ne semble pas contenir un dépôt Mercurial"
+msgid "Repository path '%(path)s' does not exist."
+msgstr "Chemin du dépôt « %(path)s » inexistant."
 
-#: tracext/hg/backend.py:566
-msgid "The Base for Diff is invalid"
+#: tracext/hg/backend.py:526
+#, python-format
+msgid ""
+"'%(path)s' does not appear to contain a repository (Mercurial %(version)s"
+" says %(error)s)"
 msgstr ""
+"%(path)s ne semble pas contenir un dépôt Mercurial (Mercurial %(version)s"
+" reporte l'erreur suivante : %(error)s)"
 
-#: tracext/hg/backend.py:571
-msgid "The Target for Diff is invalid"
-msgstr ""
-
-#: tracext/hg/backend.py:575
+#: tracext/hg/backend.py:755
 #, python-format
 msgid ""
 "Diff mismatch: Base is a %(okind)s (%(opath)s in revision %(orev)s) and "
@@ -86,24 +95,28 @@
 "révision %(orev)s) et Destination est un %(nkind)s (%(npath)s dans la "
 "révision %(nrev)s)."
 
-#: tracext/hg/backend.py:719
+#: tracext/hg/backend.py:1017
 #, python-format
 msgid "Can't read from directory %(path)s"
 msgstr "Lecture du répertoire %(path)s impossible"
 
-#: tracext/hg/backend.py:892
+#: tracext/hg/backend.py:1195
 msgid "Parents:"
 msgstr "Ascendants :"
 
-#: tracext/hg/backend.py:892
+#: tracext/hg/backend.py:1195
 msgid "Children:"
 msgstr "Descendants :"
 
-#: tracext/hg/backend.py:892
+#: tracext/hg/backend.py:1195
 msgid "Branch:"
 msgstr "Branche :"
 
-#: tracext/hg/backend.py:892
+#: tracext/hg/backend.py:1195
 msgid "Tags:"
 msgstr "Tags :"
 
+#: tracext/hg/backend.py:1196
+msgid "Bookmarks:"
+msgstr "Signets :"
+
--- a/tracext/hg/locale/messages.pot	Mon Sep 17 11:54:00 2012 +0200
+++ b/tracext/hg/locale/messages.pot	Mon Sep 17 12:09:52 2012 +0200
@@ -1,102 +1,113 @@
-# Translations template for TracMercurial.
-# Copyright (C) 2009 ORGANIZATION
-# This file is distributed under the same license as the TracMercurial
-# project.
-# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: TracMercurial 0.12.0.9\n"
-"Report-Msgid-Bugs-To: cboos@edgewall.org\n"
-"POT-Creation-Date: 2009-11-19 16:21+0100\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
-"Language-Team: LANGUAGE <LL@li.org>\n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.4\n"
-
-#: tracext/hg/backend.py:99
-msgid ":"
-msgstr ""
-
-#: tracext/hg/backend.py:114
-msgid ""
-"Diff against this parent (show the changes merged from the other "
-"parents)"
-msgstr ""
-
-#: tracext/hg/backend.py:124
-#, python-format
-msgid ""
-"Note: this is a %(merge)s changeset, the changes displayed below "
-"correspond to the merge itself."
-msgstr ""
-
-#: tracext/hg/backend.py:132
-#, python-format
-msgid ""
-"Use the %(diff)s links above to see all the changes relative to each "
-"parent."
-msgstr ""
-
-#: tracext/hg/backend.py:155
-msgid "no such changeset"
-msgstr ""
-
-#: tracext/hg/backend.py:156
-msgid "Transplant:"
-msgstr ""
-
-#: tracext/hg/backend.py:173
-msgid "(binary, size greater than 100 bytes)"
-msgstr ""
-
-#: tracext/hg/backend.py:285
-#, python-format
-msgid "Repository '%(repo)s' not found"
-msgstr ""
-
-#: tracext/hg/backend.py:344
-#, python-format
-msgid "%(path)s does not appear to contain a Mercurial repository."
-msgstr ""
-
-#: tracext/hg/backend.py:566
-msgid "The Base for Diff is invalid"
-msgstr ""
-
-#: tracext/hg/backend.py:571
-msgid "The Target for Diff is invalid"
-msgstr ""
-
-#: tracext/hg/backend.py:575
-#, python-format
-msgid ""
-"Diff mismatch: Base is a %(okind)s (%(opath)s in revision %(orev)s) "
-"and Target is a %(nkind)s (%(npath)s in revision %(nrev)s)."
-msgstr ""
-
-#: tracext/hg/backend.py:719
-#, python-format
-msgid "Can't read from directory %(path)s"
-msgstr ""
-
-#: tracext/hg/backend.py:892
-msgid "Parents:"
-msgstr ""
-
-#: tracext/hg/backend.py:892
-msgid "Children:"
-msgstr ""
-
-#: tracext/hg/backend.py:892
-msgid "Branch:"
-msgstr ""
-
-#: tracext/hg/backend.py:892
-msgid "Tags:"
-msgstr ""
-
+# Translations template for TracMercurial.
+# Copyright (C) 2012 ORGANIZATION
+# This file is distributed under the same license as the TracMercurial
+# project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: TracMercurial 0.13.0.5\n"
+"Report-Msgid-Bugs-To: cboos@edgewall.org\n"
+"POT-Creation-Date: 2012-06-11 23:08+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6dev-r0\n"
+
+#: tracext/hg/backend.py:183
+msgid ":"
+msgstr ""
+
+#: tracext/hg/backend.py:205
+msgid ""
+"Diff against this parent (show the changes merged from the other "
+"parents)"
+msgstr ""
+
+#: tracext/hg/backend.py:215
+#, python-format
+msgid ""
+"Note: this is a %(merge)s changeset, the changes displayed below "
+"correspond to the merge itself."
+msgstr ""
+
+#: tracext/hg/backend.py:223
+#, python-format
+msgid ""
+"Use the %(diff)s links above to see all the changes relative to each "
+"parent."
+msgstr ""
+
+#: tracext/hg/backend.py:248
+msgid "no such changeset"
+msgstr ""
+
+#: tracext/hg/backend.py:249
+msgid "Transplant:"
+msgstr ""
+
+#: tracext/hg/backend.py:264
+msgid "Changeset in source repository"
+msgstr ""
+
+#: tracext/hg/backend.py:266
+msgid "Convert:"
+msgstr ""
+
+#: tracext/hg/backend.py:291
+msgid "(binary, size greater than 100 bytes)"
+msgstr ""
+
+#: tracext/hg/backend.py:452
+#, python-format
+msgid "Repository '%(repo)s' not found"
+msgstr ""
+
+#: tracext/hg/backend.py:518
+#, python-format
+msgid "Repository path '%(path)s' does not exist."
+msgstr ""
+
+#: tracext/hg/backend.py:526
+#, python-format
+msgid ""
+"'%(path)s' does not appear to contain a repository (Mercurial "
+"%(version)s says %(error)s)"
+msgstr ""
+
+#: tracext/hg/backend.py:755
+#, python-format
+msgid ""
+"Diff mismatch: Base is a %(okind)s (%(opath)s in revision %(orev)s) "
+"and Target is a %(nkind)s (%(npath)s in revision %(nrev)s)."
+msgstr ""
+
+#: tracext/hg/backend.py:1017
+#, python-format
+msgid "Can't read from directory %(path)s"
+msgstr ""
+
+#: tracext/hg/backend.py:1195
+msgid "Parents:"
+msgstr ""
+
+#: tracext/hg/backend.py:1195
+msgid "Children:"
+msgstr ""
+
+#: tracext/hg/backend.py:1195
+msgid "Branch:"
+msgstr ""
+
+#: tracext/hg/backend.py:1195
+msgid "Tags:"
+msgstr ""
+
+#: tracext/hg/backend.py:1196
+msgid "Bookmarks:"
+msgstr ""
+