Show More
@@ -1,70 +1,70 b'' | |||||
1 | # streamclone.py - streaming clone server support for mercurial |
|
1 | # streamclone.py - streaming clone server support for mercurial | |
2 | # |
|
2 | # | |
3 | # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> |
|
3 | # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | import util, error |
|
8 | import util, error | |
9 | from i18n import _ |
|
9 | from i18n import _ | |
10 |
|
10 | |||
11 | from mercurial import store |
|
11 | from mercurial import store | |
12 |
|
12 | |||
13 | class StreamException(Exception): |
|
13 | class StreamException(Exception): | |
14 | def __init__(self, code): |
|
14 | def __init__(self, code): | |
15 | Exception.__init__(self) |
|
15 | Exception.__init__(self) | |
16 | self.code = code |
|
16 | self.code = code | |
17 | def __str__(self): |
|
17 | def __str__(self): | |
18 | return '%i\n' % self.code |
|
18 | return '%i\n' % self.code | |
19 |
|
19 | |||
20 | # if server supports streaming clone, it advertises "stream" |
|
20 | # if server supports streaming clone, it advertises "stream" | |
21 | # capability with value that is version+flags of repo it is serving. |
|
21 | # capability with value that is version+flags of repo it is serving. | |
22 | # client only streams if it can read that repo format. |
|
22 | # client only streams if it can read that repo format. | |
23 |
|
23 | |||
24 | # stream file format is simple. |
|
24 | # stream file format is simple. | |
25 | # |
|
25 | # | |
26 | # server writes out line that says how many files, how many total |
|
26 | # server writes out line that says how many files, how many total | |
27 | # bytes. separator is ascii space, byte counts are strings. |
|
27 | # bytes. separator is ascii space, byte counts are strings. | |
28 | # |
|
28 | # | |
29 | # then for each file: |
|
29 | # then for each file: | |
30 | # |
|
30 | # | |
31 | # server writes out line that says filename, how many bytes in |
|
31 | # server writes out line that says filename, how many bytes in | |
32 | # file. separator is ascii nul, byte count is string. |
|
32 | # file. separator is ascii nul, byte count is string. | |
33 | # |
|
33 | # | |
34 | # server writes out raw file data. |
|
34 | # server writes out raw file data. | |
35 |
|
35 | |||
36 | def allowed(ui): |
|
36 | def allowed(ui): | |
37 | return ui.configbool('server', 'uncompressed', untrusted=True) |
|
37 | return ui.configbool('server', 'uncompressed', True, untrusted=True) | |
38 |
|
38 | |||
39 | def stream_out(repo): |
|
39 | def stream_out(repo): | |
40 | '''stream out all metadata files in repository. |
|
40 | '''stream out all metadata files in repository. | |
41 | writes to file-like object, must support write() and optional flush().''' |
|
41 | writes to file-like object, must support write() and optional flush().''' | |
42 |
|
42 | |||
43 | if not allowed(repo.ui): |
|
43 | if not allowed(repo.ui): | |
44 | raise StreamException(1) |
|
44 | raise StreamException(1) | |
45 |
|
45 | |||
46 | entries = [] |
|
46 | entries = [] | |
47 | total_bytes = 0 |
|
47 | total_bytes = 0 | |
48 | try: |
|
48 | try: | |
49 | # get consistent snapshot of repo, lock during scan |
|
49 | # get consistent snapshot of repo, lock during scan | |
50 | lock = repo.lock() |
|
50 | lock = repo.lock() | |
51 | try: |
|
51 | try: | |
52 | repo.ui.debug('scanning\n') |
|
52 | repo.ui.debug('scanning\n') | |
53 | for name, ename, size in repo.store.walk(): |
|
53 | for name, ename, size in repo.store.walk(): | |
54 | entries.append((name, size)) |
|
54 | entries.append((name, size)) | |
55 | total_bytes += size |
|
55 | total_bytes += size | |
56 | finally: |
|
56 | finally: | |
57 | lock.release() |
|
57 | lock.release() | |
58 | except error.LockError: |
|
58 | except error.LockError: | |
59 | raise StreamException(2) |
|
59 | raise StreamException(2) | |
60 |
|
60 | |||
61 | yield '0\n' |
|
61 | yield '0\n' | |
62 | repo.ui.debug('%d files, %d bytes to transfer\n' % |
|
62 | repo.ui.debug('%d files, %d bytes to transfer\n' % | |
63 | (len(entries), total_bytes)) |
|
63 | (len(entries), total_bytes)) | |
64 | yield '%d %d\n' % (len(entries), total_bytes) |
|
64 | yield '%d %d\n' % (len(entries), total_bytes) | |
65 | for name, size in entries: |
|
65 | for name, size in entries: | |
66 | repo.ui.debug('sending %s (%d bytes)\n' % (name, size)) |
|
66 | repo.ui.debug('sending %s (%d bytes)\n' % (name, size)) | |
67 | # partially encode name over the wire for backwards compat |
|
67 | # partially encode name over the wire for backwards compat | |
68 | yield '%s\0%d\n' % (store.encodedir(name), size) |
|
68 | yield '%s\0%d\n' % (store.encodedir(name), size) | |
69 | for chunk in util.filechunkiter(repo.sopener(name), limit=size): |
|
69 | for chunk in util.filechunkiter(repo.sopener(name), limit=size): | |
70 | yield chunk |
|
70 | yield chunk |
@@ -1,64 +1,64 b'' | |||||
1 | #!/bin/sh |
|
1 | #!/bin/sh | |
2 | # An attempt at more fully testing the hgweb web interface. |
|
2 | # An attempt at more fully testing the hgweb web interface. | |
3 | # The following things are tested elsewhere and are therefore omitted: |
|
3 | # The following things are tested elsewhere and are therefore omitted: | |
4 | # - archive, tested in test-archive |
|
4 | # - archive, tested in test-archive | |
5 | # - unbundle, tested in test-push-http |
|
5 | # - unbundle, tested in test-push-http | |
6 | # - changegroupsubset, tested in test-pull |
|
6 | # - changegroupsubset, tested in test-pull | |
7 |
|
7 | |||
8 | echo % Set up the repo |
|
8 | echo % Set up the repo | |
9 | hg init test |
|
9 | hg init test | |
10 | cd test |
|
10 | cd test | |
11 | mkdir da |
|
11 | mkdir da | |
12 | echo foo > da/foo |
|
12 | echo foo > da/foo | |
13 | echo foo > foo |
|
13 | echo foo > foo | |
14 | hg ci -Ambase |
|
14 | hg ci -Ambase | |
15 | hg tag 1.0 |
|
15 | hg tag 1.0 | |
16 | echo another > foo |
|
16 | echo another > foo | |
17 | hg branch stable |
|
17 | hg branch stable | |
18 | hg ci -Ambranch |
|
18 | hg ci -Ambranch | |
19 | hg serve -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log |
|
19 | hg serve --config server.uncompressed=False -n test -p $HGPORT -d --pid-file=hg.pid -E errors.log | |
20 | cat hg.pid >> $DAEMON_PIDS |
|
20 | cat hg.pid >> $DAEMON_PIDS | |
21 |
|
21 | |||
22 | echo % Logs and changes |
|
22 | echo % Logs and changes | |
23 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom' | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//" |
|
23 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/?style=atom' | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//" | |
24 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom' | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//" |
|
24 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/?style=atom' | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//" | |
25 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom' | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//" |
|
25 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log/1/foo/?style=atom' | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//" | |
26 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/' |
|
26 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/shortlog/' | |
27 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/' |
|
27 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/0/' | |
28 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw' |
|
28 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/rev/1/?style=raw' | |
29 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base' |
|
29 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/log?rev=base' | |
30 |
|
30 | |||
31 | echo % File-related |
|
31 | echo % File-related | |
32 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw' |
|
32 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo/?style=raw' | |
33 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw' |
|
33 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/annotate/1/foo/?style=raw' | |
34 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw' |
|
34 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/?style=raw' | |
35 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo' |
|
35 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/file/1/foo' | |
36 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw' |
|
36 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/filediff/1/foo/?style=raw' | |
37 |
|
37 | |||
38 | echo % Overviews |
|
38 | echo % Overviews | |
39 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags' |
|
39 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-tags' | |
40 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches' |
|
40 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/raw-branches' | |
41 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb' |
|
41 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/summary/?style=gitweb' | |
42 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb' |
|
42 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/graph/?style=gitweb' | |
43 |
|
43 | |||
44 | echo % capabilities |
|
44 | echo % capabilities | |
45 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities' |
|
45 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities' | |
46 | echo % heads |
|
46 | echo % heads | |
47 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads' |
|
47 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=heads' | |
48 | echo % lookup |
|
48 | echo % lookup | |
49 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=lookup&node=1' |
|
49 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=lookup&node=1' | |
50 | echo % branches |
|
50 | echo % branches | |
51 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches' |
|
51 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=branches' | |
52 | echo % changegroup |
|
52 | echo % changegroup | |
53 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup' \ |
|
53 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=changegroup' \ | |
54 | | $TESTDIR/printrepr.py |
|
54 | | $TESTDIR/printrepr.py | |
55 | echo % stream_out |
|
55 | echo % stream_out | |
56 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out' |
|
56 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=stream_out' | |
57 | echo % failing unbundle, requires POST request |
|
57 | echo % failing unbundle, requires POST request | |
58 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle' |
|
58 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=unbundle' | |
59 |
|
59 | |||
60 | echo % Static files |
|
60 | echo % Static files | |
61 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css' |
|
61 | "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '/static/style.css' | |
62 |
|
62 | |||
63 | echo % ERRORS ENCOUNTERED |
|
63 | echo % ERRORS ENCOUNTERED | |
64 | cat errors.log |
|
64 | cat errors.log |
@@ -1,43 +1,43 b'' | |||||
1 | #!/bin/sh |
|
1 | #!/bin/sh | |
2 |
|
2 | |||
3 | cp "$TESTDIR"/printenv.py . |
|
3 | cp "$TESTDIR"/printenv.py . | |
4 |
|
4 | |||
5 | hg init test |
|
5 | hg init test | |
6 | cd test |
|
6 | cd test | |
7 | echo foo>foo |
|
7 | echo foo>foo | |
8 | mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg |
|
8 | mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg | |
9 | echo foo>foo.d/foo |
|
9 | echo foo>foo.d/foo | |
10 | echo bar>foo.d/bAr.hg.d/BaR |
|
10 | echo bar>foo.d/bAr.hg.d/BaR | |
11 | echo bar>foo.d/baR.d.hg/bAR |
|
11 | echo bar>foo.d/baR.d.hg/bAR | |
12 |
|
12 | |||
13 | hg commit -A -m 1 |
|
13 | hg commit -A -m 1 | |
14 |
hg |
|
14 | hg serve -p $HGPORT -d --pid-file=../hg1.pid | |
15 | hg serve -p $HGPORT1 -d --pid-file=../hg2.pid |
|
15 | hg --config server.uncompressed=False serve -p $HGPORT1 -d --pid-file=../hg2.pid | |
16 | # Test server address cannot be reused |
|
16 | # Test server address cannot be reused | |
17 | hg serve -p $HGPORT1 2>&1 | sed -e "s/abort: cannot start server at ':$HGPORT1':.*/abort: cannot start server at ':\$HGPORT1':/" |
|
17 | hg serve -p $HGPORT1 2>&1 | sed -e "s/abort: cannot start server at ':$HGPORT1':.*/abort: cannot start server at ':\$HGPORT1':/" | |
18 | cd .. |
|
18 | cd .. | |
19 | cat hg1.pid hg2.pid >> $DAEMON_PIDS |
|
19 | cat hg1.pid hg2.pid >> $DAEMON_PIDS | |
20 |
|
20 | |||
21 | echo % clone via stream |
|
21 | echo % clone via stream | |
22 | hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1 | \ |
|
22 | hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1 | \ | |
23 | sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/' |
|
23 | sed -e 's/[0-9][0-9.]*/XXX/g' -e 's/[KM]\(B\/sec\)/X\1/' | |
24 | hg verify -R copy |
|
24 | hg verify -R copy | |
25 |
|
25 | |||
26 | echo % try to clone via stream, should use pull instead |
|
26 | echo % try to clone via stream, should use pull instead | |
27 | hg clone --uncompressed http://localhost:$HGPORT1/ copy2 |
|
27 | hg clone --uncompressed http://localhost:$HGPORT1/ copy2 | |
28 |
|
28 | |||
29 | echo % clone via pull |
|
29 | echo % clone via pull | |
30 | hg clone http://localhost:$HGPORT1/ copy-pull |
|
30 | hg clone http://localhost:$HGPORT1/ copy-pull | |
31 | hg verify -R copy-pull |
|
31 | hg verify -R copy-pull | |
32 |
|
32 | |||
33 | cd test |
|
33 | cd test | |
34 | echo bar > bar |
|
34 | echo bar > bar | |
35 | hg commit -A -d '1 0' -m 2 |
|
35 | hg commit -A -d '1 0' -m 2 | |
36 | cd .. |
|
36 | cd .. | |
37 |
|
37 | |||
38 | echo % pull |
|
38 | echo % pull | |
39 | cd copy-pull |
|
39 | cd copy-pull | |
40 | echo '[hooks]' >> .hg/hgrc |
|
40 | echo '[hooks]' >> .hg/hgrc | |
41 | echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc |
|
41 | echo 'changegroup = python ../printenv.py changegroup' >> .hg/hgrc | |
42 | hg pull | sed -e "s,:$HGPORT1/,:\$HGPORT1/," |
|
42 | hg pull | sed -e "s,:$HGPORT1/,:\$HGPORT1/," | |
43 | cd .. |
|
43 | cd .. |
General Comments 0
You need to be logged in to leave comments.
Login now