]> arthur.barton.de Git - bup.git/commitdiff
Merge branch 'master' into meta
authorAvery Pennarun <apenwarr@gmail.com>
Tue, 31 May 2011 04:31:50 +0000 (00:31 -0400)
committerAvery Pennarun <apenwarr@gmail.com>
Tue, 31 May 2011 04:31:50 +0000 (00:31 -0400)
* master:
  Improve formatting of error and warning messages.

1  2 
lib/bup/git.py
lib/bup/index.py

diff --combined lib/bup/git.py
index 5edfe1c3185d6a143902aac79a2726520b1afc8f,a86f80e5b151571cb432126abaf8f23a47bef04d..5cb282922c392169dffc6bb9083ae441be606256
@@@ -4,7 -4,7 +4,7 @@@ interact with the Git data structures
  """
  import os, sys, zlib, time, subprocess, struct, stat, re, tempfile, glob
  from bup.helpers import *
 -from bup import _helpers, path, midx, bloom
 +from bup import _helpers, path, midx, bloom, xstat
  
  max_pack_size = 1000*1000*1000  # larger packs will slow down pruning
  max_pack_objects = 200*1000  # cache memory usage is about 83 bytes per object
@@@ -413,7 -413,7 +413,7 @@@ class PackIdxList
                          else:
                              midxl.append(mx)
                  midxl.sort(key=lambda ix:
 -                           (-len(ix), -os.stat(ix.name).st_mtime))
 +                           (-len(ix), -xstat.stat(ix.name).st_mtime))
                  for ix in midxl:
                      any_needed = False
                      for sub in ix.idxnames:
@@@ -821,7 -821,7 +821,7 @@@ def init_repo(path=None)
      if parent and not os.path.exists(parent):
          raise GitError('parent directory "%s" does not exist\n' % parent)
      if os.path.exists(d) and not os.path.isdir(os.path.join(d, '.')):
-         raise GitError('"%d" exists but is not a directory\n' % d)
+         raise GitError('"%s" exists but is not a directory\n' % d)
      p = subprocess.Popen(['git', '--bare', 'init'], stdout=sys.stderr,
                           preexec_fn = _gitenv)
      _git_wait('git init', p)
@@@ -961,7 -961,7 +961,7 @@@ class CatPipe
          assert(self.p)
          assert(self.p.poll() == None)
          if self.inprogress:
-             log('_fast_get: opening %r while %r is open'
+             log('_fast_get: opening %r while %r is open\n'
                  % (id, self.inprogress))
          assert(not self.inprogress)
          assert(id.find('\n') < 0)
diff --combined lib/bup/index.py
index 3fde0f968a0d8d4f052ce9c94eec1f3da569738c,8d2471e3eeac9138346cb2086ce4ef9d01be6a73..4efc03be1dea32bc29b4cd378ac0460d0ef6cae0
@@@ -1,13 -1,14 +1,13 @@@
  import os, stat, struct, tempfile
 +from bup import xstat
  from bup.helpers import *
  
  EMPTY_SHA = '\0'*20
  FAKE_SHA = '\x01'*20
 -INDEX_HDR = 'BUPI\0\0\0\2'
 +INDEX_HDR = 'BUPI\0\0\0\3'
  
 -# 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'
 +# Use 64-bit integers for mtime/ctime to handle NTFS zero (Y1600) and Y2038.
 +INDEX_SIG = '!QQQqqIIQII20sHII'
  
  ENTLEN = struct.calcsize(INDEX_SIG)
  FOOTER_SIG = '!Q'
@@@ -41,11 -42,11 +41,11 @@@ class Level
          return (ofs,n)
  
  
 -def _golevel(level, f, ename, newentry):
 +def _golevel(level, f, ename, newentry, tmax):
      # close nodes back up the tree
      assert(level)
      while ename[:len(level.ename)] != level.ename:
 -        n = BlankNewEntry(level.ename[-1])
 +        n = BlankNewEntry(level.ename[-1], tmax)
          n.flags |= IX_EXISTS
          (n.children_ofs,n.children_n) = level.write(f)
          level.parent.list.append(n)
@@@ -57,7 -58,7 +57,7 @@@
  
      # are we in precisely the right place?
      assert(ename == level.ename)
 -    n = newentry or BlankNewEntry(ename and level.ename[-1] or None)
 +    n = newentry or BlankNewEntry(ename and level.ename[-1] or None, tmax)
      (n.children_ofs,n.children_n) = level.write(f)
      if level.parent:
          level.parent.list.append(n)
  
  
  class Entry:
 -    def __init__(self, basename, name):
 +    def __init__(self, basename, name, tmax):
          self.basename = str(basename)
          self.name = str(name)
 +        self.tmax = tmax
          self.children_ofs = 0
          self.children_n = 0
  
      def __repr__(self):
          return ("(%s,0x%04x,%d,%d,%d,%d,%d,%s/%s,0x%04x,0x%08x/%d)" 
 -                % (self.name, self.dev,
 +                % (self.name, self.dev, self.ino, self.nlink,
                     self.ctime, self.mtime, self.uid, self.gid,
                     self.size, oct(self.mode), oct(self.gitmode),
                     self.flags, self.children_ofs, self.children_n))
@@@ -84,8 -84,7 +84,8 @@@
      def packed(self):
          try:
              return struct.pack(INDEX_SIG,
 -                           self.dev, self.ctime, self.mtime, 
 +                           self.dev, self.ino, self.nlink,
 +                           self.ctime, self.mtime, 
                             self.uid, self.gid, self.size, self.mode,
                             self.gitmode, self.sha, self.flags,
                             self.children_ofs, self.children_n)
              raise
  
      def from_stat(self, st, tstart):
 -        old = (self.dev, self.ctime, self.mtime,
 +        old = (self.dev, self.ino, self.nlink, self.ctime, self.mtime,
                 self.uid, self.gid, self.size, self.flags & IX_EXISTS)
 -        new = (st.st_dev,
 -               int(st.st_ctime.approx_secs()),
 -               int(st.st_mtime.approx_secs()),
 +        new = (st.st_dev, st.st_ino, st.st_nlink,
 +               xstat.fstime_floor_secs(st.st_ctime),
 +               xstat.fstime_floor_secs(st.st_mtime),
                 st.st_uid, st.st_gid, st.st_size, IX_EXISTS)
          self.dev = st.st_dev
 -        self.ctime = int(st.st_ctime.approx_secs())
 -        self.mtime = int(st.st_mtime.approx_secs())
 +        self.ino = st.st_ino
 +        self.nlink = st.st_nlink
 +        self.ctime = xstat.fstime_floor_secs(st.st_ctime)
 +        self.mtime = xstat.fstime_floor_secs(st.st_mtime)
          self.uid = st.st_uid
          self.gid = st.st_gid
          self.size = st.st_size
          self.mode = st.st_mode
          self.flags |= IX_EXISTS
 -        if int(st.st_ctime.approx_secs()) >= tstart or old != new \
 +        if xstat.fstime_floor_secs(st.st_ctime) >= tstart or old != new \
                or self.sha == EMPTY_SHA or not self.gitmode:
              self.invalidate()
          self._fixup()
              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
 +        self.mtime = self._fixup_time(self.mtime)
 +        self.ctime = self._fixup_time(self.ctime)
 +
 +    def _fixup_time(self, t):
 +        if self.tmax != None and t > self.tmax:
 +            return self.tmax
 +        else:
 +            return t
  
      def is_valid(self):
          f = IX_HASHVALID|IX_EXISTS
  
  
  class NewEntry(Entry):
 -    def __init__(self, basename, name, dev, ctime, mtime, uid, gid,
 -                 size, mode, gitmode, sha, flags, children_ofs, children_n):
 -        Entry.__init__(self, basename, name)
 -        (self.dev, self.ctime, self.mtime, self.uid, self.gid,
 -         self.size, self.mode, self.gitmode, self.sha,
 +    def __init__(self, basename, name, tmax, dev, ino, nlink, ctime, mtime,
 +                 uid, gid, size, mode, gitmode, sha, flags,
 +                 children_ofs, children_n):
 +        Entry.__init__(self, basename, name, tmax)
 +        (self.dev, self.ino, self.nlink, self.ctime, self.mtime,
 +         self.uid, self.gid, self.size, self.mode, self.gitmode, self.sha,
           self.flags, self.children_ofs, self.children_n
 -         ) = (dev, int(ctime), int(mtime), uid, gid,
 +         ) = (dev, ino, nlink, int(ctime), int(mtime), uid, gid,
                size, mode, gitmode, sha, flags, children_ofs, children_n)
          self._fixup()
  
  
  class BlankNewEntry(NewEntry):
 -    def __init__(self, basename):
 -        NewEntry.__init__(self, basename, basename,
 -                          0, 0, 0, 0, 0, 0, 0,
 +    def __init__(self, basename, tmax):
 +        NewEntry.__init__(self, basename, basename, tmax,
 +                          0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, EMPTY_SHA, 0, 0, 0)
  
  
  class ExistingEntry(Entry):
      def __init__(self, parent, basename, name, m, ofs):
 -        Entry.__init__(self, basename, name)
 +        Entry.__init__(self, basename, name, None)
          self.parent = parent
          self._m = m
          self._ofs = ofs
 -        (self.dev, self.ctime, self.mtime, self.uid, self.gid,
 -         self.size, self.mode, self.gitmode, self.sha,
 +        (self.dev, self.ino, self.nlink, self.ctime, self.mtime,
 +         self.uid, self.gid, self.size, self.mode, self.gitmode, self.sha,
           self.flags, self.children_ofs, self.children_n
           ) = struct.unpack(INDEX_SIG, str(buffer(m, ofs, ENTLEN)))
  
@@@ -275,7 -271,7 +275,7 @@@ class Reader
          if f:
              b = f.read(len(INDEX_HDR))
              if b != INDEX_HDR:
-                 log('warning: %s: header: expected %r, got %r'
+                 log('warning: %s: header: expected %r, got %r\n'
                                   % (filename, INDEX_HDR, b))
              else:
                  st = os.fstat(f.fileno())
@@@ -351,14 -347,13 +351,14 @@@ def pathsplit(p)
  
  
  class Writer:
 -    def __init__(self, filename):
 +    def __init__(self, filename, tmax):
          self.rootlevel = self.level = Level([], None)
          self.f = None
          self.count = 0
          self.lastfile = None
          self.filename = None
          self.filename = filename = realpath(filename)
 +        self.tmax = tmax
          (dir,name) = os.path.split(filename)
          (ffd,self.tmpname) = tempfile.mkstemp('.tmp', filename, dir)
          self.f = os.fdopen(ffd, 'wb', 65536)
  
      def flush(self):
          if self.level:
 -            self.level = _golevel(self.level, self.f, [], None)
 +            self.level = _golevel(self.level, self.f, [], None, self.tmax)
              self.count = self.rootlevel.count
              if self.count:
                  self.count += 1
              raise Error('%r must come before %r' 
                               % (''.join(e.name), ''.join(self.lastfile)))
              self.lastfile = e.name
 -        self.level = _golevel(self.level, self.f, ename, entry)
 +        self.level = _golevel(self.level, self.f, ename, entry, self.tmax)
  
      def add(self, name, st, hashgen = None):
          endswith = name.endswith('/')
          if st:
              isdir = stat.S_ISDIR(st.st_mode)
              assert(isdir == endswith)
 -            e = NewEntry(basename, name, st.st_dev,
 -                         int(st.st_ctime.approx_secs()),
 -                         int(st.st_mtime.approx_secs()),
 +            e = NewEntry(basename, name, self.tmax,
 +                         st.st_dev, st.st_ino, st.st_nlink,
 +                         xstat.fstime_floor_secs(st.st_ctime),
 +                         xstat.fstime_floor_secs(st.st_mtime),
                           st.st_uid, st.st_gid,
                           st.st_size, st.st_mode, gitmode, sha, flags,
                           0, 0)
          else:
              assert(endswith)
 -            e = BlankNewEntry(basename)
 +            e = BlankNewEntry(basename, tmax)
              e.gitmode = gitmode
              e.sha = sha
              e.flags = flags