]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/index.py
Merge branch 'maint'
[bup.git] / lib / bup / index.py
index 623b2d6c71e5ed83f6469fba4a9448eb2a3dfe85..348b73d8ea45a1ce16ff973161a8edd19cd4fcc2 100644 (file)
@@ -4,7 +4,12 @@ from bup.helpers import *
 EMPTY_SHA = '\0'*20
 FAKE_SHA = '\x01'*20
 INDEX_HDR = 'BUPI\0\0\0\2'
+
+# FIXME: guess I should have used 64-bit integers to store the mtime/ctime.
+# NTFS mtime=0 corresponds to the year 1600, which can't be stored in a 32-bit
+# time_t.  Next time we update the bupindex format, keep that in mind.
 INDEX_SIG = '!IIIIIQII20sHII'
+
 ENTLEN = struct.calcsize(INDEX_SIG)
 FOOTER_SIG = '!Q'
 FOOTLEN = struct.calcsize(FOOTER_SIG)
@@ -77,11 +82,15 @@ class Entry:
                    self.flags, self.children_ofs, self.children_n))
 
     def packed(self):
-        return struct.pack(INDEX_SIG,
+        try:
+            return struct.pack(INDEX_SIG,
                            self.dev, self.ctime, self.mtime, 
                            self.uid, self.gid, self.size, self.mode,
                            self.gitmode, self.sha, self.flags,
                            self.children_ofs, self.children_n)
+        except DeprecationWarning, e:
+            log('pack error: %s (%r)\n' % (e, self))
+            raise
 
     def from_stat(self, st, tstart):
         old = (self.dev, self.ctime, self.mtime,
@@ -99,6 +108,23 @@ class Entry:
         if int(st.st_ctime) >= tstart or old != new \
               or self.sha == EMPTY_SHA or not self.gitmode:
             self.invalidate()
+        self._fixup()
+        
+    def _fixup(self):
+        if self.uid < 0:
+            self.uid += 0x100000000
+        if self.gid < 0:
+            self.gid += 0x100000000
+        assert(self.uid >= 0)
+        assert(self.gid >= 0)
+        if self.mtime < -0x80000000:  # can happen in NTFS on 64-bit linux
+            self.mtime = 0
+        if self.ctime < -0x80000000:
+            self.ctime = 0
+        if self.mtime > 0x7fffffff:
+            self.mtime = 0x7fffffff
+        if self.ctime > 0x7fffffff:
+            self.ctime = 0x7fffffff
 
     def is_valid(self):
         f = IX_HASHVALID|IX_EXISTS
@@ -151,6 +177,7 @@ class NewEntry(Entry):
          self.flags, self.children_ofs, self.children_n
          ) = (dev, int(ctime), int(mtime), uid, gid,
               size, mode, gitmode, sha, flags, children_ofs, children_n)
+        self._fixup()
 
 
 class BlankNewEntry(NewEntry):
@@ -404,11 +431,14 @@ def reduce_paths(paths):
     xpaths = []
     for p in paths:
         rp = realpath(p)
-        st = os.lstat(rp)
-        if stat.S_ISDIR(st.st_mode):
-            rp = slashappend(rp)
-            p = slashappend(p)
-        xpaths.append((rp, p))
+        try:
+            st = os.lstat(rp)
+            if stat.S_ISDIR(st.st_mode):
+                rp = slashappend(rp)
+                p = slashappend(p)
+            xpaths.append((rp, p))
+        except OSError, e:
+            add_error('reduce_paths: %s' % e)
     xpaths.sort()
 
     paths = []