]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/client.py
Fix memory leak in *stat calls in _helpers.c
[bup.git] / lib / bup / client.py
index cad6e28b75145c338ab5102f0a1f4800a3ab1c18..19d52cb968e25145d194a7359ce01a1bb9ce654a 100644 (file)
@@ -2,11 +2,12 @@
 from __future__ import absolute_import
 import errno, os, re, struct, sys, time, zlib
 
-from bup import git, ssh
+from bup import git, ssh, vfs
 from bup.compat import range
 from bup.helpers import (Conn, atomically_replaced_file, chunkyreader, debug1,
                          debug2, linereader, lines_until_sentinel,
                          mkdirp, progress, qprogress)
+from bup.vint import read_bvec, read_vuint, write_bvec
 
 
 bwlimit = None
@@ -392,6 +393,13 @@ class Client:
         self._not_busy()
 
     def rev_list(self, refs, count=None, parse=None, format=None):
+        """See git.rev_list for the general semantics, but note that with the
+        current interface, the parse function must be able to handle
+        (consume) any blank lines produced by the format because the
+        first one received that it doesn't consume will be interpreted
+        as a terminator for the entire rev-list result.
+
+        """
         self._require_command('rev-list')
         assert (count is None) or (isinstance(count, Integral))
         if format:
@@ -415,26 +423,48 @@ class Client:
             conn.write('\n')
         conn.write('\n')
         if not format:
-            for _ in range(len(refs)):
-                line = conn.readline()
-                if not line:
-                    raise ClientError('unexpected EOF')
+            for line in lines_until_sentinel(conn, '\n', ClientError):
                 line = line.strip()
                 assert len(line) == 40
                 yield line
         else:
-            for _ in range(len(refs)):
-                line = conn.readline()
-                if not line:
-                    raise ClientError('unexpected EOF')
+            for line in lines_until_sentinel(conn, '\n', ClientError):
                 if not line.startswith('commit '):
                     raise ClientError('unexpected line ' + repr(line))
-                yield line[7:].strip(), parse(conn)
+                cmt_oidx = line[7:].strip()
+                assert len(cmt_oidx) == 40
+                yield cmt_oidx, parse(conn)
+        # FIXME: confusing
+        not_ok = self.check_ok()
+        if not_ok:
+            raise not_ok
+        self._not_busy()
+
+    def resolve(self, path, parent=None, want_meta=True, follow=False):
+        self._require_command('resolve')
+        self.check_busy()
+        self._busy = 'resolve'
+        conn = self.conn
+        conn.write('resolve %d\n' % ((1 if want_meta else 0)
+                                     | (2 if follow else 0)
+                                     | (4 if parent else 0)))
+        if parent:
+            vfs.write_resolution(conn, parent)
+        write_bvec(conn, path)
+        success = ord(conn.read(1))
+        assert success in (0, 1)
+        if success:
+            result = vfs.read_resolution(conn)
+        else:
+            result = vfs.read_ioerror(conn)
         # FIXME: confusing
         not_ok = self.check_ok()
         if not_ok:
             raise not_ok
         self._not_busy()
+        if isinstance(result, vfs.IOError):
+            raise result
+        return result
 
 
 class PackWriter_Remote(git.PackWriter):