]> git.michaelhowe.org Git - packages/b/bup.git/commitdiff
git.py: recover more elegantly if a MIDX file has the wrong version.
authorAvery Pennarun <apenwarr@gmail.com>
Thu, 2 Sep 2010 21:26:25 +0000 (14:26 -0700)
committerAvery Pennarun <apenwarr@gmail.com>
Thu, 2 Sep 2010 21:26:25 +0000 (14:26 -0700)
Previously we'd throw an assertion for any too-new-format MIDX file, which
isn't so good.  Let's recover more politely (and just ignore the file in
question) if that happens.

Noticed by Zoran Zaric who was testing my midx3 branch.

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

index f27e7605459b32c4858b9f617eec3743e4e89345..391ba9475973ec331bce42ff26e4216531b3b7e2 100644 (file)
@@ -6,6 +6,8 @@ import os, zlib, time, subprocess, struct, stat, re, tempfile
 import heapq
 from bup.helpers import *
 
+MIDX_VERSION = 2
+
 verbose = 0
 ignore_midx = 0
 home_repodir = os.path.expanduser('~/.bup')
@@ -207,24 +209,39 @@ class PackMidx:
     """
     def __init__(self, filename):
         self.name = filename
+        self.force_keep = False
         assert(filename.endswith('.midx'))
         self.map = mmap_read(open(filename))
-        if str(self.map[0:8]) == 'MIDX\0\0\0\1':
-            log('Warning: ignoring old-style midx %r\n' % filename)
-            self.bits = 0
-            self.entries = 1
-            self.fanout = buffer('\0\0\0\0')
-            self.shalist = buffer('\0'*20)
-            self.idxnames = []
-        else:
-            assert(str(self.map[0:8]) == 'MIDX\0\0\0\2')
-            self.bits = struct.unpack('!I', self.map[8:12])[0]
-            self.entries = 2**self.bits
-            self.fanout = buffer(self.map, 12, self.entries*4)
-            shaofs = 12 + self.entries*4
-            nsha = self._fanget(self.entries-1)
-            self.shalist = buffer(self.map, shaofs, nsha*20)
-            self.idxnames = str(self.map[shaofs + 20*nsha:]).split('\0')
+        if str(self.map[0:4]) != 'MIDX':
+            log('Warning: skipping: invalid MIDX header in %r\n' % filename)
+            self.force_keep = True
+            return self._init_failed()
+        ver = struct.unpack('!I', self.map[4:8])[0]
+        if ver < MIDX_VERSION:
+            log('Warning: ignoring old-style (v%d) midx %r\n' 
+                % (ver, filename))
+            self.force_keep = False  # old stuff is boring  
+            return self._init_failed()
+        if ver > MIDX_VERSION:
+            log('Warning: ignoring too-new (v%d) midx %r\n'
+                % (ver, filename))
+            self.force_keep = True  # new stuff is exciting
+            return self._init_failed()
+
+        self.bits = struct.unpack('!I', self.map[8:12])[0]
+        self.entries = 2**self.bits
+        self.fanout = buffer(self.map, 12, self.entries*4)
+        shaofs = 12 + self.entries*4
+        nsha = self._fanget(self.entries-1)
+        self.shalist = buffer(self.map, shaofs, nsha*20)
+        self.idxnames = str(self.map[shaofs + 20*nsha:]).split('\0')
+
+    def _init_failed(self):
+        self.bits = 0
+        self.entries = 1
+        self.fanout = buffer('\0\0\0\0')
+        self.shalist = buffer('\0'*20)
+        self.idxnames = []
 
     def _fanget(self, i):
         start = i*4
@@ -347,7 +364,7 @@ class PackIdxList:
                                 d[os.path.join(self.dir, name)] = ix
                             any += 1
                             break
-                    if not any:
+                    if not any and not ix.force_keep:
                         log('midx: removing redundant: %s\n'
                             % os.path.basename(ix.name))
                         unlink(ix.name)