Source

thg-qt-mq / mani-buildentry-fileset.diff

# HG changeset patch
# Parent 5ed8ae4d9369a707362be287f7f86fd79ed748af
manifest: use fileset query to build tree of files

TODO: speed test
TODO: test case for subrepos and largefiles
TODO: auditor
TODO: test with mercurial stable branch
TODO: test the case added + removed at once

diff --git a/tortoisehg/hgqt/manifestmodel.py b/tortoisehg/hgqt/manifestmodel.py
--- a/tortoisehg/hgqt/manifestmodel.py
+++ b/tortoisehg/hgqt/manifestmodel.py
@@ -13,7 +13,7 @@ import os, itertools
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 
-from mercurial import util
+from mercurial import util, match as matchmod
 from mercurial.subrepo import hgsubrepo
 from tortoisehg.util import hglib
 from tortoisehg.hgqt import qtlib, status, visdiff
@@ -225,33 +225,34 @@ class ManifestModel(QAbstractItemModel):
     def _buildrootentry(self):
         """Rebuild the tree of files and directories"""
 
-        def pathinstatus(path, status, uncleanpaths):
-            """Test path is included by the status filter"""
-            if util.any(c in self._statusfilter and path in e
-                        for c, e in status.iteritems()):
-                return True
-            if 'C' in self._statusfilter and path not in uncleanpaths:
-                return True
-            return False
-
-        def getctxtreeinfo(ctx):
-            """
-            Get the context information that is relevant to populating the tree
-            """
-            status = dict(zip(('M', 'A', 'R'),
-                      (set(a) for a in self._repo.status(ctx.parents()[0],
-                                                             ctx)[:3])))
-            uncleanpaths = status['M'] | status['A'] | status['R']
-            files = itertools.chain(ctx.manifest(), status['R'])
-            return status, uncleanpaths, files
-
         def addfilestotree(treeroot, ctx):
             """Add files to the tree according to their state"""
-            status, uncleanpaths, files = getctxtreeinfo(ctx)
+            filesetmap = {'M': 'modified()', 'A': 'added()', 'C': 'clean()'}
+
+            files = []
+
+            statusfileset = ' or '.join(v for k, v in filesetmap.iteritems()
+                                        if k in self._statusfilter)
+            if statusfileset:
+                # XXX matchmod.match() auditor?
+                m = matchmod.match(self._repo.root, self._repo.root,
+                                   ['set:%s' % statusfileset], ctx=ctx)
+                files.extend(ctx.walk(m))
+
+            # XXX matchmod.match() auditor?
+            statusmatchers = [(k, matchmod.match(self._repo.root,
+                                                 self._repo.root,
+                                                 ['set:%s' % v], ctx=ctx))
+                              for k, v in filesetmap.iteritems()
+                              if k in self._statusfilter]
+
+            # removed files are not member of ctx
+            if 'R' in self._statusfilter:
+                removedfiles = self._repo.status(ctx.parents()[0], ctx)[2]
+                files.extend(removedfiles)
+                statusmatchers.append(('R', lambda n: n in removedfiles))
+
             for path in files:
-                if not pathinstatus(path, status, uncleanpaths):
-                    continue
-
                 origpath = path
                 path = self._repo.removeStandin(path)
                 
@@ -261,12 +262,9 @@ class ManifestModel(QAbstractItemModel):
                         e.addchild(p)
                     e = e[p]
 
-                for st, filesofst in status.iteritems():
-                    if origpath in filesofst:
-                        e.setstatus(st)
-                        break
-                else:
-                    e.setstatus('C')
+                for k, m in statusmatchers:
+                    if m(origpath):
+                        e.setstatus(k)
 
         # Add subrepos to the tree
         def addrepocontentstotree(roote, ctx, toproot=''):