]> git.michaelhowe.org Git - packages/b/bup.git/commitdiff
vfs: resolve absolute symlinks inside their particular backup set.
authorAvery Pennarun <apenwarr@gmail.com>
Mon, 26 Jul 2010 04:50:59 +0000 (00:50 -0400)
committerAvery Pennarun <apenwarr@gmail.com>
Mon, 26 Jul 2010 04:50:59 +0000 (00:50 -0400)
Let's say you back up a file "/etc/motd" that's a symlink to
"/var/run/motd".  The file inside the backup repo is actually
/whatever/latest/etc/motd, so the symlink should *actually* point to
/whatever/latest/var/run/motd.  Let's resolve it that way automatically in
Symlink.dereference().

Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
lib/bup/vfs.py

index 596a8b6910335f84a7cc72a33f7c78422b2ae91d..e02c9ad03f04d3008cc95bb3b10e28d127554ee2 100644 (file)
@@ -184,11 +184,20 @@ class Node:
         return ret
 
     def top(self):
+        """ Return the very top node of the tree. """
         if self.parent:
             return self.parent.top()
         else:
             return self
 
+    def fs_top(self):
+        """ Return the top node of the particular backup set, or the root
+            level if this node isn't inside a backup set. """
+        if self.parent and not isinstance(self.parent, CommitList):
+            return self.parent.fs_top()
+        else:
+            return self
+
     def _lresolve(self, parts):
         #log('_lresolve %r in %r\n' % (parts, self.name))
         if not parts:
@@ -207,12 +216,15 @@ class Node:
 
     # walk into a given sub-path of this node.  If the last element is
     # a symlink, leave it as a symlink, don't resolve it.  (like lstat())
-    def lresolve(self, path):
+    def lresolve(self, path, stay_inside_fs=False):
         start = self
         if not path:
             return start
         if path.startswith('/'):
-            start = self.top()
+            if stay_inside_fs:
+                start = self.fs_top()
+            else:
+                start = self.top()
             path = path[1:]
         parts = re.split(r'/+', path or '.')
         if not parts[-1]:
@@ -295,7 +307,8 @@ class Symlink(File):
                                   % self.fullname())
         _symrefs += 1
         try:
-            return self.parent.lresolve(self.readlink())
+            return self.parent.lresolve(self.readlink(),
+                                        stay_inside_fs=True)
         except NoSuchFile:
             raise NoSuchFile("%s: broken symlink to %r"
                              % (self.fullname(), self.readlink()))