Added VCS._u_find_id_from_manifest for faster id->path calculation
authorW. Trevor King <wking@drexel.edu>
Mon, 18 Jan 2010 17:25:17 +0000 (12:25 -0500)
committerW. Trevor King <wking@drexel.edu>
Mon, 18 Jan 2010 17:25:17 +0000 (12:25 -0500)
libbe/storage/base.py
libbe/storage/vcs/base.py
libbe/storage/vcs/bzr.py
libbe/storage/vcs/hg.py

index 84ec1d42a6e03b46a1d8ddd0dea1d13a94d2bd92..10649a8ef00667c90045b07d1c64227a84b208f4 100644 (file)
@@ -53,11 +53,15 @@ class InvalidStorageVersion(ConnectionError):
 
 class InvalidID (KeyError):
     def __init__(self, id=None, revision=None, msg=None):
-        if msg == None and id != None:
-            msg = id
-        KeyError.__init__(self, msg)
+        KeyError.__init__(self, id)
+        self.msg = msg
         self.id = id
         self.revision = revision
+    def __str__(self):
+        if self.msg == None:
+            return '%s in revision %s' % (self.id, self.revision)
+        return self.msg
+
 
 class InvalidRevision (KeyError):
     pass
index 716283af7ed70ae6989df39ea43605054837b4c3..fa64b4ea1f1b960580044e925fa78fbe8538c22e 100644 (file)
@@ -756,7 +756,7 @@ os.listdir(self.get_path("bugs")):
             path = id_to_path(id)
         ancestors = []
         while True:
-            if path == self.repo:
+            if not path.startswith(self.repo + os.path.sep):
                 break
             path = os.path.dirname(path)
             try:
@@ -926,6 +926,33 @@ os.listdir(self.get_path("bugs")):
             return None
         return ret
 
+    def _u_find_id_from_manifest(self, id, manifest, revision=None):
+        """
+        Search for the relative path to id using manifest, a list of all files.
+        
+        Returns None if the id is not found.
+        """
+        be_dir = self._cached_path_id._spacer_dirs[0]
+        be_dir_sep = self._cached_path_id._spacer_dirs[0] + os.path.sep
+        files = [f for f in manifest if f.startswith(be_dir_sep)]
+        for file in files:
+            if not file.startswith(be_dir+os.path.sep):
+                continue
+            parts = file.split(os.path.sep)
+            dir = parts.pop(0) # don't add the first spacer dir
+            for part in parts[:-1]:
+                dir = os.path.join(dir, part)
+                if not dir in files:
+                    files.append(dir)
+        for file in files:
+            try:
+                p_id = self._u_path_to_id(file)
+                if p_id == id:
+                    return file
+            except (SpacerCollision, InvalidPath):
+                pass
+        raise InvalidID(id, revision=revision)
+
     def _u_find_id(self, id, revision):
         """
         Search for the relative path to id as of revision.
index 285ecf18cc988863b681398380dd1bbee9448070..e1cd2e57dfe0f490a3b34394ee03d5852d2d0e3d 100644 (file)
@@ -134,7 +134,9 @@ class Bzr(base.VCS):
         return cmd.outf.getvalue()        
 
     def _vcs_path(self, id, revision):
-        return self._u_find_id(id, revision)
+        manifest = self._vcs_listdir(
+            self.repo, revision=revision, recursive=True)
+        return self._u_find_id_from_manifest(id, manifest, revision=revision)
 
     def _vcs_isdir(self, path, revision):
         try:
@@ -145,13 +147,13 @@ class Bzr(base.VCS):
             raise
         return True
 
-    def _vcs_listdir(self, path, revision):
+    def _vcs_listdir(self, path, revision, recursive=False):
         path = os.path.join(self.repo, path)
         revision = self._parse_revision_string(revision)
         cmd = bzrlib.builtins.cmd_ls()
         cmd.outf = StringIO.StringIO()
         try:
-            cmd.run(revision=revision, path=path)
+            cmd.run(revision=revision, path=path, recursive=recursive)
         except bzrlib.errors.BzrCommandError, e:
             if 'not present in revision' in str(e):
                 raise base.InvalidPath(path, root=self.repo, revision=revision)
@@ -252,8 +254,7 @@ class Bzr(base.VCS):
         new = []
         modified = []
         removed = []
-        lines = diff_text.splitlines()
-        for i,line in enumerate(lines):
+        for line in diff_text.splitlines():
             if not line.startswith('=== '):
                 continue
             fields = line.split()
index 824f6877c45e7c7b316182602849f2cc50d9b9c2..5295a5702bc0190e4cec990ae40dc9f09f77a85c 100644 (file)
@@ -112,23 +112,9 @@ class Hg(base.VCS):
             return self._u_invoke_client('cat', '-r', revision, path)
 
     def _vcs_path(self, id, revision):
-        output = self._u_invoke_client('manifest', '--rev', revision)
-        be_dir = self._cached_path_id._spacer_dirs[0]
-        be_dir_sep = self._cached_path_id._spacer_dirs[0] + os.path.sep
-        files = [f for f in output.splitlines() if f.startswith(be_dir_sep)]
-        for file in files:
-            if not file.startswith(be_dir+os.path.sep):
-                continue
-            parts = file.split(os.path.sep)
-            dir = parts.pop(0) # don't add the first spacer dir
-            for part in parts[:-1]:
-                dir = os.path.join(dir, part)
-                if not dir in files:
-                    files.append(dir)
-        for file in files:
-            if self._u_path_to_id(file) == id:
-                return file
-        raise base.InvalidId(id, revision=revision)
+        manifest = self._u_invoke_client(
+            'manifest', '--rev', revision).splitlines()
+        return self._u_find_id_from_manifest(id, manifest, revision=revision)
 
     def _vcs_isdir(self, path, revision):
         output = self._u_invoke_client('manifest', '--rev', revision)