]> arthur.barton.de Git - bup.git/blobdiff - lib/bup/client.py
If you specified the port number on the command line, convert it to an int.
[bup.git] / lib / bup / client.py
index f75fab6064cba76761d15c1b03c5620e42355b90..f06d54965979d0c92ca36044af24a5c62c9668e3 100644 (file)
@@ -65,6 +65,7 @@ class Client:
         if is_reverse:
             self.pout = os.fdopen(3, 'rb')
             self.pin = os.fdopen(4, 'wb')
+            self.conn = Conn(self.pout, self.pin)
         else:
             if self.protocol in ('ssh', 'file'):
                 try:
@@ -72,14 +73,14 @@ class Client:
                     self.p = ssh.connect(self.host, self.port, 'server')
                     self.pout = self.p.stdout
                     self.pin = self.p.stdin
+                    self.conn = Conn(self.pout, self.pin)
                 except OSError, e:
                     raise ClientError, 'connect: %s' % e, sys.exc_info()[2]
             elif self.protocol == 'bup':
                 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-                self.sock.connect((self.host, self.port or 1982))
-                self.pout = self.sock.makefile('rb')
-                self.pin = self.sock.makefile('wb')
-        self.conn = Conn(self.pout, self.pin)
+                self.sock.connect((self.host, atoi(self.port) or 1982))
+                self.sockw = self.sock.makefile('wb')
+                self.conn = DemuxConn(self.sock.fileno(), self.sockw)
         if self.dir:
             self.dir = re.sub(r'[\r\n]', ' ', self.dir)
             if create:
@@ -101,10 +102,14 @@ class Client:
     def close(self):
         if self.conn and not self._busy:
             self.conn.write('quit\n')
-        if self.pin and self.pout:
+        if self.pin:
             self.pin.close()
-            while self.pout.read(65536):
-                pass
+        if self.sock and self.sockw:
+            self.sockw.close()
+            self.sock.shutdown(socket.SHUT_WR)
+        if self.conn:
+            self.conn.close()
+        if self.pout:
             self.pout.close()
         if self.sock:
             self.sock.close()
@@ -170,6 +175,8 @@ class Client:
         debug1('client: server requested load of: %s\n' % needed)
         for idx in needed:
             self.sync_index(idx)
+        git.auto_midx(self.cachedir)
+
 
     def sync_index(self, name):
         #debug1('requesting %r\n' % name)
@@ -190,27 +197,38 @@ class Client:
         self.check_ok()
         f.close()
         os.rename(fn + '.tmp', fn)
-        git.auto_midx(self.cachedir)
 
     def _make_objcache(self):
-        ob = self._busy
-        self._busy = None
-        #self.sync_indexes()
-        self._busy = ob
         return git.PackIdxList(self.cachedir)
 
-    def _suggest_pack(self, indexname):
-        debug1('client: received index suggestion: %s\n' % indexname)
+    def _suggest_packs(self):
         ob = self._busy
         if ob:
             assert(ob == 'receive-objects-v2')
-            self.conn.write('\xff\xff\xff\xff')  # suspend receive-objects
+            self.conn.write('\xff\xff\xff\xff')  # suspend receive-objects-v2
+        suggested = []
+        for line in linereader(self.conn):
+            if not line:
+                break
+            debug2('%s\n' % line)
+            if line.startswith('index '):
+                idx = line[6:]
+                debug1('client: received index suggestion: %s\n' % idx)
+                suggested.append(idx)
+            else:
+                assert(line.endswith('.idx'))
+                debug1('client: completed writing pack, idx: %s\n' % line)
+                suggested.append(line)
+        self.check_ok()
+        if ob:
             self._busy = None
-            self.conn.drain_and_check_ok()
-        self.sync_index(indexname)
+        for idx in suggested:
+            self.sync_index(idx)
+        git.auto_midx(self.cachedir)
         if ob:
             self._busy = ob
-            self.conn.write('receive-objects-v2\n')
+            self.conn.write('%s\n' % ob)
+        return idx
 
     def new_packwriter(self):
         self.check_busy()
@@ -219,7 +237,7 @@ class Client:
             self.conn.write('receive-objects-v2\n')
         return PackWriter_Remote(self.conn,
                                  objcache_maker = self._make_objcache,
-                                 suggest_pack = self._suggest_pack,
+                                 suggest_packs = self._suggest_packs,
                                  onopen = _set_busy,
                                  onclose = self._not_busy,
                                  ensure_busy = self.ensure_busy)
@@ -257,13 +275,13 @@ class Client:
 
 
 class PackWriter_Remote(git.PackWriter):
-    def __init__(self, conn, objcache_maker, suggest_pack,
+    def __init__(self, conn, objcache_maker, suggest_packs,
                  onopen, onclose,
                  ensure_busy):
         git.PackWriter.__init__(self, objcache_maker)
         self.file = conn
         self.filename = 'remote socket'
-        self.suggest_pack = suggest_pack
+        self.suggest_packs = suggest_packs
         self.onopen = onopen
         self.onclose = onclose
         self.ensure_busy = ensure_busy
@@ -273,29 +291,16 @@ class PackWriter_Remote(git.PackWriter):
 
     def _open(self):
         if not self._packopen:
-            self._make_objcache()
-            if self.onopen:
-                self.onopen()
+            self.onopen()
             self._packopen = True
 
     def _end(self):
         if self._packopen and self.file:
             self.file.write('\0\0\0\0')
             self._packopen = False
-            while True:
-                line = self.file.readline().strip()
-                if line.startswith('index '):
-                    pass
-                else:
-                    break
-            id = line
-            self.file.check_ok()
+            self.onclose() # Unbusy
             self.objcache = None
-            if self.onclose:
-                self.onclose()
-            if id and self.suggest_pack:
-                self.suggest_pack(id)
-            return id
+            return self.suggest_packs() # Returns last idx received
 
     def close(self):
         id = self._end()
@@ -309,8 +314,7 @@ class PackWriter_Remote(git.PackWriter):
         assert(self.file)
         if not self._packopen:
             self._open()
-        if self.ensure_busy:
-            self.ensure_busy()
+        self.ensure_busy()
         data = ''.join(datalist)
         assert(data)
         assert(sha)
@@ -319,17 +323,16 @@ class PackWriter_Remote(git.PackWriter):
                           sha,
                           struct.pack('!I', crc),
                           data))
-        (self._bwcount, self._bwtime) = \
-            _raw_write_bwlimit(self.file, outbuf, self._bwcount, self._bwtime)
-        self.outbytes += len(data) - 20 - 4 # Don't count sha1+crc
+        try:
+            (self._bwcount, self._bwtime) = _raw_write_bwlimit(
+                    self.file, outbuf, self._bwcount, self._bwtime)
+        except IOError, e:
+            raise ClientError, e, sys.exc_info()[2]
+        self.outbytes += len(data)
         self.count += 1
 
         if self.file.has_input():
-            line = self.file.readline().strip()
-            assert(line.startswith('index '))
-            idxname = line[6:]
-            if self.suggest_pack:
-                self.suggest_pack(idxname)
-                self.objcache.refresh()
+            self.suggest_packs()
+            self.objcache.refresh()
 
         return sha, crc