from __future__ import absolute_import
from binascii import hexlify, unhexlify
-import errno, os, re, struct, sys, time, zlib
+import os, re, struct, time, zlib
import socket
from bup import git, ssh, vfs
-from bup.compat import environ, range, reraise
+from bup.compat import environ, pending_raise, range, reraise
from bup.helpers import (Conn, atomically_replaced_file, chunkyreader, debug1,
debug2, linereader, lines_until_sentinel,
- mkdirp, progress, qprogress, DemuxConn, atoi)
+ mkdirp, nullcontext_if_not, progress, qprogress, DemuxConn)
from bup.io import path_msg
-from bup.vint import read_bvec, read_vuint, write_bvec
+from bup.vint import write_bvec
bwlimit = None
reraise(ClientError('connect: %s' % e))
elif self.protocol == b'bup':
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.connect((self.host, atoi(self.port) or 1982))
+ self.sock.connect((self.host,
+ 1982 if self.port is None else int(self.port)))
self.sockw = self.sock.makefile('wb')
self.conn = DemuxConn(self.sock.fileno(), self.sockw)
self._available_commands = self._get_available_commands()
self.check_ok()
self.sync_indexes()
- def __del__(self):
- try:
+ def __enter__(self):
+ return self
+
+ def __exit__(self, type, value, traceback):
+ with pending_raise(value, rethrow=False):
self.close()
- except IOError as e:
- if e.errno == errno.EPIPE:
- pass
- else:
- raise
def close(self):
if self.conn and not self._busy:
return self.conn.check_ok()
except Exception as e:
reraise(ClientError(e))
+ # reraise doesn't return
+ return None
def check_busy(self):
if self._busy:
raise ClientError('already busy with command %r' % self._busy)
-
+
def ensure_busy(self):
if not self._busy:
raise ClientError('expected to be busy, but not busy?!')
-
+
def _not_busy(self):
self._busy = None
raise not_ok
self._not_busy()
- def rev_list(self, refs, count=None, parse=None, format=None):
+ def rev_list(self, refs, 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
"""
self._require_command(b'rev-list')
- assert (count is None) or (isinstance(count, Integral))
if format:
assert b'\n' not in format
assert parse
self._busy = b'rev-list'
conn = self.conn
conn.write(b'rev-list\n')
- if count is not None:
- conn.write(b'%d' % count)
conn.write(b'\n')
if format:
conn.write(format)
return result
+# FIXME: disentangle this (stop inheriting) from PackWriter
class PackWriter_Remote(git.PackWriter):
+
def __init__(self, conn, objcache_maker, suggest_packs,
onopen, onclose,
ensure_busy,
self._bwcount = 0
self._bwtime = time.time()
+ # __enter__ and __exit__ are inherited
+
def _open(self):
if not self._packopen:
self.onopen()
self._packopen = True
def _end(self, run_midx=True):
+ # Called by other PackWriter methods like breakpoint().
+ # Must not close the connection (self.file)
assert(run_midx) # We don't support this via remote yet
- if self._packopen and self.file:
+ self.objcache, objcache = None, self.objcache
+ with nullcontext_if_not(objcache):
+ if not (self._packopen and self.file):
+ return None
self.file.write(b'\0\0\0\0')
self._packopen = False
self.onclose() # Unbusy
- self.objcache = None
+ if objcache is not None:
+ objcache.close()
return self.suggest_packs() # Returns last idx received
def close(self):
+ # Called by inherited __exit__
id = self._end()
self.file = None
return id