From 7ae29f930fe73adada5174a2ce74266411809ac7 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Mon, 18 Jan 2010 12:25:17 -0500 Subject: [PATCH] Added VCS._u_find_id_from_manifest for faster id->path calculation --- libbe/storage/base.py | 10 +++++++--- libbe/storage/vcs/base.py | 29 ++++++++++++++++++++++++++++- libbe/storage/vcs/bzr.py | 11 ++++++----- libbe/storage/vcs/hg.py | 20 +++----------------- 4 files changed, 44 insertions(+), 26 deletions(-) diff --git a/libbe/storage/base.py b/libbe/storage/base.py index 84ec1d4..10649a8 100644 --- a/libbe/storage/base.py +++ b/libbe/storage/base.py @@ -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 diff --git a/libbe/storage/vcs/base.py b/libbe/storage/vcs/base.py index 716283a..fa64b4e 100644 --- a/libbe/storage/vcs/base.py +++ b/libbe/storage/vcs/base.py @@ -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. diff --git a/libbe/storage/vcs/bzr.py b/libbe/storage/vcs/bzr.py index 285ecf1..e1cd2e5 100644 --- a/libbe/storage/vcs/bzr.py +++ b/libbe/storage/vcs/bzr.py @@ -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() diff --git a/libbe/storage/vcs/hg.py b/libbe/storage/vcs/hg.py index 824f687..5295a57 100644 --- a/libbe/storage/vcs/hg.py +++ b/libbe/storage/vcs/hg.py @@ -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) -- 2.26.2