Show More
@@ -193,5 +193,8 b' def unbundle(repo, req):' | |||||
193 |
|
193 | |||
194 | def stream_out(repo, req): |
|
194 | def stream_out(repo, req): | |
195 | req.respond(HTTP_OK, HGTYPE) |
|
195 | req.respond(HTTP_OK, HGTYPE) | |
196 | streamclone.stream_out(repo, req, untrusted=True) |
|
196 | try: | |
197 | return [] |
|
197 | for chunk in streamclone.stream_out(repo, untrusted=True): | |
|
198 | yield chunk | |||
|
199 | except streamclone.StreamException, inst: | |||
|
200 | yield str(inst) |
@@ -204,4 +204,10 b' class sshserver(object):' | |||||
204 | os.unlink(tempname) |
|
204 | os.unlink(tempname) | |
205 |
|
205 | |||
206 | def do_stream_out(self): |
|
206 | def do_stream_out(self): | |
207 | streamclone.stream_out(self.repo, self.fout) |
|
207 | try: | |
|
208 | for chunk in streamclone.stream_out(self.repo): | |||
|
209 | self.fout.write(chunk) | |||
|
210 | self.fout.flush() | |||
|
211 | except streamclone.StreamException, inst: | |||
|
212 | self.fout.write(str(inst)) | |||
|
213 | self.fout.flush() |
@@ -7,6 +7,13 b'' | |||||
7 |
|
7 | |||
8 | import util, lock |
|
8 | import util, lock | |
9 |
|
9 | |||
|
10 | class StreamException(Exception): | |||
|
11 | def __init__(self, code): | |||
|
12 | Exception.__init__(self) | |||
|
13 | self.code = code | |||
|
14 | def __str__(self): | |||
|
15 | return '%i\n' % self.code | |||
|
16 | ||||
10 | # if server supports streaming clone, it advertises "stream" |
|
17 | # if server supports streaming clone, it advertises "stream" | |
11 | # capability with value that is version+flags of repo it is serving. |
|
18 | # capability with value that is version+flags of repo it is serving. | |
12 | # client only streams if it can read that repo format. |
|
19 | # client only streams if it can read that repo format. | |
@@ -23,13 +30,12 b' import util, lock' | |||||
23 | # |
|
30 | # | |
24 | # server writes out raw file data. |
|
31 | # server writes out raw file data. | |
25 |
|
32 | |||
26 |
def stream_out(repo, |
|
33 | def stream_out(repo, untrusted=False): | |
27 | '''stream out all metadata files in repository. |
|
34 | '''stream out all metadata files in repository. | |
28 | writes to file-like object, must support write() and optional flush().''' |
|
35 | writes to file-like object, must support write() and optional flush().''' | |
29 |
|
36 | |||
30 | if not repo.ui.configbool('server', 'uncompressed', untrusted=untrusted): |
|
37 | if not repo.ui.configbool('server', 'uncompressed', untrusted=untrusted): | |
31 | fileobj.write('1\n') |
|
38 | raise StreamException(1) | |
32 | return |
|
|||
33 |
|
39 | |||
34 | entries = [] |
|
40 | entries = [] | |
35 | total_bytes = 0 |
|
41 | total_bytes = 0 | |
@@ -45,18 +51,14 b' def stream_out(repo, fileobj, untrusted=' | |||||
45 | finally: |
|
51 | finally: | |
46 | del l |
|
52 | del l | |
47 | except (lock.LockHeld, lock.LockUnavailable), inst: |
|
53 | except (lock.LockHeld, lock.LockUnavailable), inst: | |
48 | repo.ui.warn('locking the repository failed: %s\n' % (inst,)) |
|
54 | raise StreamException(2) | |
49 | fileobj.write('2\n') |
|
|||
50 | return |
|
|||
51 |
|
55 | |||
52 | fileobj.write('0\n') |
|
56 | yield '0\n' | |
53 | repo.ui.debug('%d files, %d bytes to transfer\n' % |
|
57 | repo.ui.debug('%d files, %d bytes to transfer\n' % | |
54 | (len(entries), total_bytes)) |
|
58 | (len(entries), total_bytes)) | |
55 |
|
|
59 | yield '%d %d\n' % (len(entries), total_bytes) | |
56 | for name, size in entries: |
|
60 | for name, size in entries: | |
57 | repo.ui.debug('sending %s (%d bytes)\n' % (name, size)) |
|
61 | repo.ui.debug('sending %s (%d bytes)\n' % (name, size)) | |
58 |
|
|
62 | yield '%s\0%d\n' % (name, size) | |
59 | for chunk in util.filechunkiter(repo.sopener(name), limit=size): |
|
63 | for chunk in util.filechunkiter(repo.sopener(name), limit=size): | |
60 |
|
|
64 | yield chunk | |
61 | flush = getattr(fileobj, 'flush', None) |
|
|||
62 | if flush: flush() |
|
General Comments 0
You need to be logged in to leave comments.
Login now