]> arthur.barton.de Git - bup.git/commitdiff
vfs: include unique repo id in resolution cache key
authorRob Browning <rlb@defaultvalue.org>
Fri, 6 Jul 2018 17:01:55 +0000 (12:01 -0500)
committerRob Browning <rlb@defaultvalue.org>
Sat, 18 Aug 2018 20:12:16 +0000 (15:12 -0500)
...since resolve() currently requires a full parent path and the root
refs are only applicable to a particular repository.

Use differing integers to identify repositories that may be
independent (with respect to refs, tags, etc.), and use (typically
small) integers rather than the repo path/address so that they'll be
short if we want to embed them directly in cache keys later.

Use realpath() for local repositories in order to detect when the same
repository is reachable by multiple paths.  (Something similar could
eventually be done for remotes.)

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Tested-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/repo.py
lib/bup/vfs.py

index 97547d539e481b776e915b05a2efe1d5e9929802..cc8a3fd2e7161043b2bb158b0c2d25b55081a28a 100644 (file)
@@ -1,15 +1,29 @@
 
 from __future__ import absolute_import
+from os.path import realpath
 from functools import partial
 
 from bup import client, git
 
 
+_next_repo_id = 0
+_repo_ids = {}
+
+def _repo_id(key):
+    global _next_repo_id, _repo_ids
+    repo_id = _repo_ids.get(key)
+    if repo_id:
+        return repo_id
+    next_id = _next_repo_id = _next_repo_id + 1
+    _repo_ids[key] = next_id
+    return next_id
+
 class LocalRepo:
     def __init__(self, repo_dir=None):
-        self.repo_dir = repo_dir or git.repo()
+        self.repo_dir = realpath(repo_dir or git.repo())
         self._cp = git.cp(self.repo_dir)
         self.rev_list = partial(git.rev_list, repo_dir=self.repo_dir)
+        self._id = _repo_id(self.repo_dir)
 
     def close(self):
         pass
@@ -23,6 +37,12 @@ class LocalRepo:
     def __exit__(self, type, value, traceback):
         self.close()
 
+    def id(self):
+        """Return an identifier that differs from any other repository that
+        doesn't share the same repository-specific information
+        (e.g. refs, tags, etc.)."""
+        return self._id
+
     def cat(self, ref):
         """If ref does not exist, yield (None, None, None).  Otherwise yield
         (oidx, type, size), and then all of the data associated with
@@ -52,6 +72,7 @@ class RemoteRepo:
         self.address = address
         self.client = client.Client(address)
         self.rev_list = self.client.rev_list
+        self._id = _repo_id(self.address)
 
     def close(self):
         if self.client:
@@ -67,6 +88,12 @@ class RemoteRepo:
     def __exit__(self, type, value, traceback):
         self.close()
 
+    def id(self):
+        """Return an identifier that differs from any other repository that
+        doesn't share the same repository-specific information
+        (e.g. refs, tags, etc.)."""
+        return self._id
+
     def cat(self, ref):
         """If ref does not exist, yield (None, None, None).  Otherwise yield
         (oidx, type, size), and then all of the data associated with
index 7ad33e42625d7002c2e2c620b1773aa52dec6f58..e0aeb6ff9c0236790785224486b989299ce77216 100644 (file)
@@ -253,7 +253,7 @@ def clear_cache():
 def is_valid_cache_key(x):
     """Return logically true if x looks like it could be a valid cache key
     (with respect to structure).  Current valid cache entries:
-      (path, parent, want_meta, dref) -> resolution
+      (repo-id, path, parent, want_meta, dref) -> resolution
       commit_oid -> commit
       commit_oid + ':r' -> rev-list
          i.e. rev-list -> {'.', commit, '2012...', next_commit, ...}
@@ -261,7 +261,7 @@ def is_valid_cache_key(x):
     # Suspect we may eventually add "(container_oid, name) -> ...", and others.
     x_t = type(x)
     if x_t is tuple:
-        return len(x) == 4
+        return len(x) == 5
     if x_t is bytes:
         if len(x) == 20:
             return True
@@ -759,7 +759,7 @@ def contents(repo, item, names=None, want_meta=True):
         yield x
 
 def _resolve_path(repo, path, parent=None, want_meta=True, deref=False):
-    cache_key = (tuple(path), parent, not not want_meta, not not deref)
+    cache_key = (repo.id(), tuple(path), parent, bool(want_meta), bool(deref))
     resolution = cache_get(cache_key)
     if resolution:
         return resolution