Show More
@@ -1,69 +1,63 b'' | |||
|
1 | 1 | # streamclone.py - streaming clone server support for mercurial |
|
2 | 2 | # |
|
3 | 3 | # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
|
4 | 4 | # |
|
5 | 5 | # This software may be used and distributed according to the terms of the |
|
6 | 6 | # GNU General Public License version 2 or any later version. |
|
7 | 7 | |
|
8 | 8 | import util, error |
|
9 | ||
|
10 | 9 | from mercurial import store |
|
11 | 10 | |
|
12 | class StreamException(Exception): | |
|
13 | def __init__(self, code): | |
|
14 | Exception.__init__(self) | |
|
15 | self.code = code | |
|
16 | def __str__(self): | |
|
17 | return '%i\n' % self.code | |
|
18 | ||
|
19 | 11 | # if server supports streaming clone, it advertises "stream" |
|
20 | 12 | # capability with value that is version+flags of repo it is serving. |
|
21 | 13 | # client only streams if it can read that repo format. |
|
22 | 14 | |
|
23 | 15 | # stream file format is simple. |
|
24 | 16 | # |
|
25 | 17 | # server writes out line that says how many files, how many total |
|
26 | 18 | # bytes. separator is ascii space, byte counts are strings. |
|
27 | 19 | # |
|
28 | 20 | # then for each file: |
|
29 | 21 | # |
|
30 | 22 | # server writes out line that says filename, how many bytes in |
|
31 | 23 | # file. separator is ascii nul, byte count is string. |
|
32 | 24 | # |
|
33 | 25 | # server writes out raw file data. |
|
34 | 26 | |
|
35 | 27 | def allowed(ui): |
|
36 | 28 | return ui.configbool('server', 'uncompressed', True, untrusted=True) |
|
37 | 29 | |
|
38 | 30 | def stream_out(repo): |
|
39 | 31 | '''stream out all metadata files in repository. |
|
40 | 32 | writes to file-like object, must support write() and optional flush().''' |
|
41 | 33 | |
|
42 | 34 | if not allowed(repo.ui): |
|
43 | raise StreamException(1) | |
|
35 | yield '1\n' # error: 1 | |
|
36 | return | |
|
44 | 37 | |
|
45 | 38 | entries = [] |
|
46 | 39 | total_bytes = 0 |
|
47 | 40 | try: |
|
48 | 41 | # get consistent snapshot of repo, lock during scan |
|
49 | 42 | lock = repo.lock() |
|
50 | 43 | try: |
|
51 | 44 | repo.ui.debug('scanning\n') |
|
52 | 45 | for name, ename, size in repo.store.walk(): |
|
53 | 46 | entries.append((name, size)) |
|
54 | 47 | total_bytes += size |
|
55 | 48 | finally: |
|
56 | 49 | lock.release() |
|
57 | 50 | except error.LockError: |
|
58 | raise StreamException(2) | |
|
51 | yield '2\n' # error: 2 | |
|
52 | return | |
|
59 | 53 | |
|
60 | yield '0\n' | |
|
54 | yield '0\n' # success | |
|
61 | 55 | repo.ui.debug('%d files, %d bytes to transfer\n' % |
|
62 | 56 | (len(entries), total_bytes)) |
|
63 | 57 | yield '%d %d\n' % (len(entries), total_bytes) |
|
64 | 58 | for name, size in entries: |
|
65 | 59 | repo.ui.debug('sending %s (%d bytes)\n' % (name, size)) |
|
66 | 60 | # partially encode name over the wire for backwards compat |
|
67 | 61 | yield '%s\0%d\n' % (store.encodedir(name), size) |
|
68 | 62 | for chunk in util.filechunkiter(repo.sopener(name), limit=size): |
|
69 | 63 | yield chunk |
General Comments 0
You need to be logged in to leave comments.
Login now