4 from subprocess import Popen, PIPE
6 class ClientError(Exception):
10 def __init__(self, remote, create=False):
12 self._indexes_synced = 0
13 rs = remote.split(':', 1)
15 (host, dir) = ('NONE', remote)
16 argv = ['bup', 'server']
19 argv = ['ssh', host, '--', 'bup', 'server']
20 (self.host, self.dir) = (host, dir)
21 self.cachedir = git.repo('index-cache/%s'
22 % re.sub(r'[^@:\w]', '_',
23 "%s:%s" % (host, dir)))
24 self.p = p = Popen(argv, stdin=PIPE, stdout=PIPE)
25 self.conn = conn = Conn(p.stdout, p.stdin)
27 dir = re.sub(r'[\r\n]', ' ', dir)
29 conn.write('init-dir %s\n' % dir)
31 conn.write('set-dir %s\n' % dir)
38 if self.conn and not self._busy:
39 self.conn.write('quit\n')
42 while self.p.stdout.read(65536):
48 raise ClientError('server tunnel returned exit code %d' % rv)
54 raise ClientError('already busy with command %r' % self._busy)
59 def sync_indexes(self):
62 conn.write('list-indexes\n')
63 packdir = git.repo('objects/pack')
67 for line in linereader(conn):
71 assert(line.find('/') < 0)
72 if (not os.path.exists(os.path.join(self.cachedir, line)) and
73 not os.path.exists(os.path.join(packdir, line))):
77 for f in os.listdir(self.cachedir):
78 if f.endswith('.idx') and not f in all:
79 log('pruning old index: %r\n' % f)
80 os.unlink(os.path.join(self.cachedir, f))
82 # FIXME this should be pipelined: request multiple indexes at a time, or
83 # we waste lots of network turnarounds.
84 for name in needed.keys():
85 log('requesting %r\n' % name)
86 conn.write('send-index %s\n' % name)
87 n = struct.unpack('!I', conn.read(4))[0]
89 log(' expect %d bytes\n' % n)
90 fn = os.path.join(self.cachedir, name)
91 f = open(fn + '.tmp', 'w')
92 for b in chunkyreader(conn, n):
96 os.rename(fn + '.tmp', fn)
98 self._indexes_synced = 1
100 def new_packwriter(self):
101 assert(self._indexes_synced)
103 self._busy = 'receive-objects'
104 self.conn.write('receive-objects\n')
105 objcache = git.MultiPackIndex(self.cachedir)
106 return git.PackWriter_Remote(self.conn, objcache = objcache,
107 onclose = self._not_busy)