##// END OF EJS Templates
clonebundles: advertise clone bundles feature to clients...
Gregory Szorc -
r26691:23c0da28 default
parent child Browse files
Show More
@@ -1,98 +1,140 b''
1 # This software may be used and distributed according to the terms of the
1 # This software may be used and distributed according to the terms of the
2 # GNU General Public License version 2 or any later version.
2 # GNU General Public License version 2 or any later version.
3
3
4 """server side extension to advertise pre-generated bundles to seed clones.
4 """server side extension to advertise pre-generated bundles to seed clones.
5
5
6 The extension essentially serves the content of a .hg/clonebundles.manifest
6 The extension essentially serves the content of a .hg/clonebundles.manifest
7 file to clients that request it.
7 file to clients that request it.
8
8
9 The clonebundles.manifest file contains a list of URLs and attributes. URLs
9 The clonebundles.manifest file contains a list of URLs and attributes. URLs
10 hold pre-generated bundles that a client fetches and applies. After applying
10 hold pre-generated bundles that a client fetches and applies. After applying
11 the pre-generated bundle, the client will connect back to the original server
11 the pre-generated bundle, the client will connect back to the original server
12 and pull data not in the pre-generated bundle.
12 and pull data not in the pre-generated bundle.
13
13
14 Manifest File Format:
14 Manifest File Format:
15
15
16 The manifest file contains a newline (\n) delimited list of entries.
16 The manifest file contains a newline (\n) delimited list of entries.
17
17
18 Each line in this file defines an available bundle. Lines have the format:
18 Each line in this file defines an available bundle. Lines have the format:
19
19
20 <URL> [<key>=<value]
20 <URL> [<key>=<value]
21
21
22 That is, a URL followed by extra metadata describing it. Metadata keys and
22 That is, a URL followed by extra metadata describing it. Metadata keys and
23 values should be URL encoded.
23 values should be URL encoded.
24
24
25 This metadata is optional. It is up to server operators to populate this
25 This metadata is optional. It is up to server operators to populate this
26 metadata.
26 metadata.
27
27
28 Keys in UPPERCASE are reserved for use by Mercurial. All non-uppercase keys
28 Keys in UPPERCASE are reserved for use by Mercurial. All non-uppercase keys
29 can be used by site installations.
29 can be used by site installations.
30
30
31 The server operator is responsible for generating the bundle manifest file.
31 The server operator is responsible for generating the bundle manifest file.
32
32
33 Metadata Attributes:
33 Metadata Attributes:
34
34
35 BUNDLESPEC
35 BUNDLESPEC
36 A "bundle specification" string that describes the type of the bundle.
36 A "bundle specification" string that describes the type of the bundle.
37
37
38 These are string values that are accepted by the "--type" argument of
38 These are string values that are accepted by the "--type" argument of
39 `hg bundle`.
39 `hg bundle`.
40
40
41 The values are parsed in strict mode, which means they must be of the
41 The values are parsed in strict mode, which means they must be of the
42 "<compression>-<type>" form. See
42 "<compression>-<type>" form. See
43 mercurial.exchange.parsebundlespec() for more details.
43 mercurial.exchange.parsebundlespec() for more details.
44
44
45 Clients will automatically filter out specifications that are unknown or
45 Clients will automatically filter out specifications that are unknown or
46 unsupported so they won't attempt to download something that likely won't
46 unsupported so they won't attempt to download something that likely won't
47 apply.
47 apply.
48
48
49 The actual value doesn't impact client behavior beyond filtering:
49 The actual value doesn't impact client behavior beyond filtering:
50 clients will still sniff the bundle type from the header of downloaded
50 clients will still sniff the bundle type from the header of downloaded
51 files.
51 files.
52
52
53 REQUIRESNI
53 REQUIRESNI
54 Whether Server Name Indication (SNI) is required to connect to the URL.
54 Whether Server Name Indication (SNI) is required to connect to the URL.
55 SNI allows servers to use multiple certificates on the same IP. It is
55 SNI allows servers to use multiple certificates on the same IP. It is
56 somewhat common in CDNs and other hosting providers. Older Python
56 somewhat common in CDNs and other hosting providers. Older Python
57 versions do not support SNI. Defining this attribute enables clients
57 versions do not support SNI. Defining this attribute enables clients
58 with older Python versions to filter this entry.
58 with older Python versions to filter this entry.
59
59
60 If this is defined, it is important to advertise a non-SNI fallback
60 If this is defined, it is important to advertise a non-SNI fallback
61 URL or clients running old Python releases may not be able to clone
61 URL or clients running old Python releases may not be able to clone
62 with the clonebundles facility.
62 with the clonebundles facility.
63
63
64 Value should be "true".
64 Value should be "true".
65 """
65 """
66
66
67 from mercurial.i18n import _
68 from mercurial.node import nullid
67 from mercurial import (
69 from mercurial import (
70 exchange,
68 extensions,
71 extensions,
69 wireproto,
72 wireproto,
70 )
73 )
71
74
72 testedwith = 'internal'
75 testedwith = 'internal'
73
76
74 def capabilities(orig, repo, proto):
77 def capabilities(orig, repo, proto):
75 caps = orig(repo, proto)
78 caps = orig(repo, proto)
76
79
77 # Only advertise if a manifest exists. This does add some I/O to requests.
80 # Only advertise if a manifest exists. This does add some I/O to requests.
78 # But this should be cheaper than a wasted network round trip due to
81 # But this should be cheaper than a wasted network round trip due to
79 # missing file.
82 # missing file.
80 if repo.opener.exists('clonebundles.manifest'):
83 if repo.opener.exists('clonebundles.manifest'):
81 caps.append('clonebundles')
84 caps.append('clonebundles')
82
85
83 return caps
86 return caps
84
87
85 @wireproto.wireprotocommand('clonebundles', '')
88 @wireproto.wireprotocommand('clonebundles', '')
86 def bundles(repo, proto):
89 def bundles(repo, proto):
87 """Server command for returning info for available bundles to seed clones.
90 """Server command for returning info for available bundles to seed clones.
88
91
89 Clients will parse this response and determine what bundle to fetch.
92 Clients will parse this response and determine what bundle to fetch.
90
93
91 Other extensions may wrap this command to filter or dynamically emit
94 Other extensions may wrap this command to filter or dynamically emit
92 data depending on the request. e.g. you could advertise URLs for
95 data depending on the request. e.g. you could advertise URLs for
93 the closest data center given the client's IP address.
96 the closest data center given the client's IP address.
94 """
97 """
95 return repo.opener.tryread('clonebundles.manifest')
98 return repo.opener.tryread('clonebundles.manifest')
96
99
100 @exchange.getbundle2partsgenerator('clonebundlesadvertise', 0)
101 def advertiseclonebundlespart(bundler, repo, source, bundlecaps=None,
102 b2caps=None, heads=None, common=None,
103 cbattempted=None, **kwargs):
104 """Inserts an output part to advertise clone bundles availability."""
105 # Allow server operators to disable this behavior.
106 # # experimental config: ui.clonebundleadvertise
107 if not repo.ui.configbool('ui', 'clonebundleadvertise', True):
108 return
109
110 # Only advertise if a manifest is present.
111 if not repo.opener.exists('clonebundles.manifest'):
112 return
113
114 # And when changegroup data is requested.
115 if not kwargs.get('cg', True):
116 return
117
118 # And when the client supports clone bundles.
119 if cbattempted is None:
120 return
121
122 # And when the client didn't attempt a clone bundle as part of this pull.
123 if cbattempted:
124 return
125
126 # And when a full clone is requested.
127 # Note: client should not send "cbattempted" for regular pulls. This check
128 # is defense in depth.
129 if common and common != [nullid]:
130 return
131
132 msg = _('this server supports the experimental "clone bundles" feature '
133 'that should enable faster and more reliable cloning\n'
134 'help test it by setting the "experimental.clonebundles" config '
135 'flag to "true"')
136
137 bundler.newpart('output', data=msg)
138
97 def extsetup(ui):
139 def extsetup(ui):
98 extensions.wrapfunction(wireproto, '_capabilities', capabilities)
140 extensions.wrapfunction(wireproto, '_capabilities', capabilities)
@@ -1,357 +1,368 b''
1 Set up a server
1 Set up a server
2
2
3 $ hg init server
3 $ hg init server
4 $ cd server
4 $ cd server
5 $ cat >> .hg/hgrc << EOF
5 $ cat >> .hg/hgrc << EOF
6 > [extensions]
6 > [extensions]
7 > clonebundles =
7 > clonebundles =
8 > EOF
8 > EOF
9
9
10 $ touch foo
10 $ touch foo
11 $ hg -q commit -A -m 'add foo'
11 $ hg -q commit -A -m 'add foo'
12 $ touch bar
12 $ touch bar
13 $ hg -q commit -A -m 'add bar'
13 $ hg -q commit -A -m 'add bar'
14
14
15 $ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
15 $ hg serve -d -p $HGPORT --pid-file hg.pid --accesslog access.log
16 $ cat hg.pid >> $DAEMON_PIDS
16 $ cat hg.pid >> $DAEMON_PIDS
17 $ cd ..
17 $ cd ..
18
18
19 Feature disabled by default
19 Feature disabled by default
20 (client should not request manifest)
20 (client should not request manifest)
21
21
22 $ hg clone -U http://localhost:$HGPORT feature-disabled
22 $ hg clone -U http://localhost:$HGPORT feature-disabled
23 requesting all changes
23 requesting all changes
24 adding changesets
24 adding changesets
25 adding manifests
25 adding manifests
26 adding file changes
26 adding file changes
27 added 2 changesets with 2 changes to 2 files
27 added 2 changesets with 2 changes to 2 files
28
28
29 $ cat server/access.log
29 $ cat server/access.log
30 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
30 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
31 * - - [*] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
31 * - - [*] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
32 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=phase%2Cbookmarks (glob)
32 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=phase%2Cbookmarks (glob)
33 * - - [*] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases (glob)
33 * - - [*] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases (glob)
34
34
35 $ cat >> $HGRCPATH << EOF
35 $ cat >> $HGRCPATH << EOF
36 > [experimental]
36 > [experimental]
37 > clonebundles = true
37 > clonebundles = true
38 > EOF
38 > EOF
39
39
40 Missing manifest should not result in server lookup
40 Missing manifest should not result in server lookup
41
41
42 $ hg --verbose clone -U http://localhost:$HGPORT no-manifest
42 $ hg --verbose clone -U http://localhost:$HGPORT no-manifest
43 requesting all changes
43 requesting all changes
44 adding changesets
44 adding changesets
45 adding manifests
45 adding manifests
46 adding file changes
46 adding file changes
47 added 2 changesets with 2 changes to 2 files
47 added 2 changesets with 2 changes to 2 files
48
48
49 $ tail -4 server/access.log
49 $ tail -4 server/access.log
50 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
50 * - - [*] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
51 * - - [*] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
51 * - - [*] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D (glob)
52 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=phase%2Cbookmarks (glob)
52 * - - [*] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=aaff8d2ffbbf07a46dd1f05d8ae7877e3f56e2a2&listkeys=phase%2Cbookmarks (glob)
53 * - - [*] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases (glob)
53 * - - [*] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases (glob)
54
54
55 Empty manifest file results in retrieval
55 Empty manifest file results in retrieval
56 (the extension only checks if the manifest file exists)
56 (the extension only checks if the manifest file exists)
57
57
58 $ touch server/.hg/clonebundles.manifest
58 $ touch server/.hg/clonebundles.manifest
59 $ hg --verbose clone -U http://localhost:$HGPORT empty-manifest
59 $ hg --verbose clone -U http://localhost:$HGPORT empty-manifest
60 no clone bundles available on remote; falling back to regular clone
60 no clone bundles available on remote; falling back to regular clone
61 requesting all changes
61 requesting all changes
62 adding changesets
62 adding changesets
63 adding manifests
63 adding manifests
64 adding file changes
64 adding file changes
65 added 2 changesets with 2 changes to 2 files
65 added 2 changesets with 2 changes to 2 files
66
66
67 Server advertises presence of feature to client requesting full clone
68
69 $ hg --config experimental.clonebundles=false clone -U http://localhost:$HGPORT advertise-on-clone
70 requesting all changes
71 remote: this server supports the experimental "clone bundles" feature that should enable faster and more reliable cloning
72 remote: help test it by setting the "experimental.clonebundles" config flag to "true"
73 adding changesets
74 adding manifests
75 adding file changes
76 added 2 changesets with 2 changes to 2 files
77
67 Manifest file with invalid URL aborts
78 Manifest file with invalid URL aborts
68
79
69 $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
80 $ echo 'http://does.not.exist/bundle.hg' > server/.hg/clonebundles.manifest
70 $ hg clone http://localhost:$HGPORT 404-url
81 $ hg clone http://localhost:$HGPORT 404-url
71 applying clone bundle from http://does.not.exist/bundle.hg
82 applying clone bundle from http://does.not.exist/bundle.hg
72 error fetching bundle: [Errno -2] Name or service not known
83 error fetching bundle: [Errno -2] Name or service not known
73 abort: error applying bundle
84 abort: error applying bundle
74 (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
85 (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
75 [255]
86 [255]
76
87
77 Server is not running aborts
88 Server is not running aborts
78
89
79 $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
90 $ echo "http://localhost:$HGPORT1/bundle.hg" > server/.hg/clonebundles.manifest
80 $ hg clone http://localhost:$HGPORT server-not-runner
91 $ hg clone http://localhost:$HGPORT server-not-runner
81 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
92 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
82 error fetching bundle: [Errno 111] Connection refused
93 error fetching bundle: [Errno 111] Connection refused
83 abort: error applying bundle
94 abort: error applying bundle
84 (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
95 (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
85 [255]
96 [255]
86
97
87 Server returns 404
98 Server returns 404
88
99
89 $ python $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
100 $ python $TESTDIR/dumbhttp.py -p $HGPORT1 --pid http.pid
90 $ cat http.pid >> $DAEMON_PIDS
101 $ cat http.pid >> $DAEMON_PIDS
91 $ hg clone http://localhost:$HGPORT running-404
102 $ hg clone http://localhost:$HGPORT running-404
92 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
103 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
93 HTTP error fetching bundle: HTTP Error 404: File not found
104 HTTP error fetching bundle: HTTP Error 404: File not found
94 abort: error applying bundle
105 abort: error applying bundle
95 (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
106 (if this error persists, consider contacting the server operator or disable clone bundles via "--config experimental.clonebundles=false")
96 [255]
107 [255]
97
108
98 We can override failure to fall back to regular clone
109 We can override failure to fall back to regular clone
99
110
100 $ hg --config ui.clonebundlefallback=true clone -U http://localhost:$HGPORT 404-fallback
111 $ hg --config ui.clonebundlefallback=true clone -U http://localhost:$HGPORT 404-fallback
101 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
112 applying clone bundle from http://localhost:$HGPORT1/bundle.hg
102 HTTP error fetching bundle: HTTP Error 404: File not found
113 HTTP error fetching bundle: HTTP Error 404: File not found
103 falling back to normal clone
114 falling back to normal clone
104 requesting all changes
115 requesting all changes
105 adding changesets
116 adding changesets
106 adding manifests
117 adding manifests
107 adding file changes
118 adding file changes
108 added 2 changesets with 2 changes to 2 files
119 added 2 changesets with 2 changes to 2 files
109
120
110 Bundle with partial content works
121 Bundle with partial content works
111
122
112 $ hg -R server bundle --type gzip-v1 --base null -r 53245c60e682 partial.hg
123 $ hg -R server bundle --type gzip-v1 --base null -r 53245c60e682 partial.hg
113 1 changesets found
124 1 changesets found
114
125
115 We verify exact bundle content as an extra check against accidental future
126 We verify exact bundle content as an extra check against accidental future
116 changes. If this output changes, we could break old clients.
127 changes. If this output changes, we could break old clients.
117
128
118 $ f --size --hexdump partial.hg
129 $ f --size --hexdump partial.hg
119 partial.hg: size=208
130 partial.hg: size=208
120 0000: 48 47 31 30 47 5a 78 9c 63 60 60 98 17 ac 12 93 |HG10GZx.c``.....|
131 0000: 48 47 31 30 47 5a 78 9c 63 60 60 98 17 ac 12 93 |HG10GZx.c``.....|
121 0010: f0 ac a9 23 45 70 cb bf 0d 5f 59 4e 4a 7f 79 21 |...#Ep..._YNJ.y!|
132 0010: f0 ac a9 23 45 70 cb bf 0d 5f 59 4e 4a 7f 79 21 |...#Ep..._YNJ.y!|
122 0020: 9b cc 40 24 20 a0 d7 ce 2c d1 38 25 cd 24 25 d5 |..@$ ...,.8%.$%.|
133 0020: 9b cc 40 24 20 a0 d7 ce 2c d1 38 25 cd 24 25 d5 |..@$ ...,.8%.$%.|
123 0030: d8 c2 22 cd 38 d9 24 cd 22 d5 c8 22 cd 24 cd 32 |..".8.$."..".$.2|
134 0030: d8 c2 22 cd 38 d9 24 cd 22 d5 c8 22 cd 24 cd 32 |..".8.$."..".$.2|
124 0040: d1 c2 d0 c4 c8 d2 32 d1 38 39 29 c9 34 cd d4 80 |......2.89).4...|
135 0040: d1 c2 d0 c4 c8 d2 32 d1 38 39 29 c9 34 cd d4 80 |......2.89).4...|
125 0050: ab 24 b5 b8 84 cb 40 c1 80 2b 2d 3f 9f 8b 2b 31 |.$....@..+-?..+1|
136 0050: ab 24 b5 b8 84 cb 40 c1 80 2b 2d 3f 9f 8b 2b 31 |.$....@..+-?..+1|
126 0060: 25 45 01 c8 80 9a d2 9b 65 fb e5 9e 45 bf 8d 7f |%E......e...E...|
137 0060: 25 45 01 c8 80 9a d2 9b 65 fb e5 9e 45 bf 8d 7f |%E......e...E...|
127 0070: 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 92 0b 75 |....+D4g.......u|
138 0070: 9f c6 97 9f 2b 44 34 67 d9 ec 8e 0f a0 92 0b 75 |....+D4g.......u|
128 0080: 41 d6 24 59 18 a4 a4 9a a6 18 1a 5b 98 9b 5a 98 |A.$Y.......[..Z.|
139 0080: 41 d6 24 59 18 a4 a4 9a a6 18 1a 5b 98 9b 5a 98 |A.$Y.......[..Z.|
129 0090: 9a 18 26 9b a6 19 98 1a 99 99 26 a6 18 9a 98 24 |..&.......&....$|
140 0090: 9a 18 26 9b a6 19 98 1a 99 99 26 a6 18 9a 98 24 |..&.......&....$|
130 00a0: 26 59 a6 25 5a 98 a5 18 a6 24 71 41 35 b1 43 dc |&Y.%Z....$qA5.C.|
141 00a0: 26 59 a6 25 5a 98 a5 18 a6 24 71 41 35 b1 43 dc |&Y.%Z....$qA5.C.|
131 00b0: 96 b0 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a |.....E..V....R..|
142 00b0: 96 b0 83 f7 e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a |.....E..V....R..|
132 00c0: 78 ed fc d5 76 f1 36 95 dc 05 07 00 ad 39 5e d3 |x...v.6......9^.|
143 00c0: 78 ed fc d5 76 f1 36 95 dc 05 07 00 ad 39 5e d3 |x...v.6......9^.|
133
144
134 $ echo "http://localhost:$HGPORT1/partial.hg" > server/.hg/clonebundles.manifest
145 $ echo "http://localhost:$HGPORT1/partial.hg" > server/.hg/clonebundles.manifest
135 $ hg clone -U http://localhost:$HGPORT partial-bundle
146 $ hg clone -U http://localhost:$HGPORT partial-bundle
136 applying clone bundle from http://localhost:$HGPORT1/partial.hg
147 applying clone bundle from http://localhost:$HGPORT1/partial.hg
137 adding changesets
148 adding changesets
138 adding manifests
149 adding manifests
139 adding file changes
150 adding file changes
140 added 1 changesets with 1 changes to 1 files
151 added 1 changesets with 1 changes to 1 files
141 finished applying clone bundle
152 finished applying clone bundle
142 searching for changes
153 searching for changes
143 adding changesets
154 adding changesets
144 adding manifests
155 adding manifests
145 adding file changes
156 adding file changes
146 added 1 changesets with 1 changes to 1 files
157 added 1 changesets with 1 changes to 1 files
147
158
148 Bundle with full content works
159 Bundle with full content works
149
160
150 $ hg -R server bundle --type gzip-v2 --base null -r tip full.hg
161 $ hg -R server bundle --type gzip-v2 --base null -r tip full.hg
151 2 changesets found
162 2 changesets found
152
163
153 Again, we perform an extra check against bundle content changes. If this content
164 Again, we perform an extra check against bundle content changes. If this content
154 changes, clone bundles produced by new Mercurial versions may not be readable
165 changes, clone bundles produced by new Mercurial versions may not be readable
155 by old clients.
166 by old clients.
156
167
157 $ f --size --hexdump full.hg
168 $ f --size --hexdump full.hg
158 full.hg: size=408
169 full.hg: size=408
159 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
170 0000: 48 47 32 30 00 00 00 0e 43 6f 6d 70 72 65 73 73 |HG20....Compress|
160 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 90 e5 76 f6 70 |ion=GZx.c``..v.p|
171 0010: 69 6f 6e 3d 47 5a 78 9c 63 60 60 90 e5 76 f6 70 |ion=GZx.c``..v.p|
161 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 06 76 a6 b2 |.swu....`..F.v..|
172 0020: f4 73 77 75 0f f2 0f 0d 60 00 02 46 06 76 a6 b2 |.swu....`..F.v..|
162 0030: d4 a2 e2 cc fc 3c 03 23 06 06 e6 7d 40 b1 4d c1 |.....<.#...}@.M.|
173 0030: d4 a2 e2 cc fc 3c 03 23 06 06 e6 7d 40 b1 4d c1 |.....<.#...}@.M.|
163 0040: 2a 31 09 cf 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 |*1...:R.........|
174 0040: 2a 31 09 cf 9a 3a 52 04 b7 fc db f0 95 e5 a4 f4 |*1...:R.........|
164 0050: 97 17 b2 c9 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 |...........%....|
175 0050: 97 17 b2 c9 0c 14 00 02 e6 d9 99 25 1a a7 a4 99 |...........%....|
165 0060: a4 a4 1a 5b 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 |...[X..'..Y..Y..|
176 0060: a4 a4 1a 5b 58 a4 19 27 9b a4 59 a4 1a 59 a4 99 |...[X..'..Y..Y..|
166 0070: a4 59 26 5a 18 9a 18 59 5a 26 1a 27 27 25 99 a6 |.Y&Z...YZ&.''%..|
177 0070: a4 59 26 5a 18 9a 18 59 5a 26 1a 27 27 25 99 a6 |.Y&Z...YZ&.''%..|
167 0080: 99 1a 70 95 a4 16 97 70 19 28 18 70 a5 e5 e7 73 |..p....p.(.p...s|
178 0080: 99 1a 70 95 a4 16 97 70 19 28 18 70 a5 e5 e7 73 |..p....p.(.p...s|
168 0090: 71 25 a6 a4 28 00 19 40 13 0e ac fa df ab ff 7b |q%..(..@.......{|
179 0090: 71 25 a6 a4 28 00 19 40 13 0e ac fa df ab ff 7b |q%..(..@.......{|
169 00a0: 3f fb 92 dc 8b 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 |?.....b......=ZD|
180 00a0: 3f fb 92 dc 8b 1f 62 bb 9e b7 d7 d9 87 3d 5a 44 |?.....b......=ZD|
170 00b0: ac 2f b0 a9 c3 66 1e 54 b9 26 08 a7 1a 1b 1a a7 |./...f.T.&......|
181 00b0: ac 2f b0 a9 c3 66 1e 54 b9 26 08 a7 1a 1b 1a a7 |./...f.T.&......|
171 00c0: 25 1b 9a 1b 99 19 9a 5a 18 9b a6 18 19 00 dd 67 |%......Z.......g|
182 00c0: 25 1b 9a 1b 99 19 9a 5a 18 9b a6 18 19 00 dd 67 |%......Z.......g|
172 00d0: 61 61 98 06 f4 80 49 4a 8a 65 52 92 41 9a 81 81 |aa....IJ.eR.A...|
183 00d0: 61 61 98 06 f4 80 49 4a 8a 65 52 92 41 9a 81 81 |aa....IJ.eR.A...|
173 00e0: a5 11 17 50 31 30 58 19 cc 80 98 25 29 b1 08 c4 |...P10X....%)...|
184 00e0: a5 11 17 50 31 30 58 19 cc 80 98 25 29 b1 08 c4 |...P10X....%)...|
174 00f0: 37 07 79 19 88 d9 41 ee 07 8a 41 cd 5d 98 65 fb |7.y...A...A.].e.|
185 00f0: 37 07 79 19 88 d9 41 ee 07 8a 41 cd 5d 98 65 fb |7.y...A...A.].e.|
175 0100: e5 9e 45 bf 8d 7f 9f c6 97 9f 2b 44 34 67 d9 ec |..E.......+D4g..|
186 0100: e5 9e 45 bf 8d 7f 9f c6 97 9f 2b 44 34 67 d9 ec |..E.......+D4g..|
176 0110: 8e 0f a0 61 a8 eb 82 82 2e c9 c2 20 25 d5 34 c5 |...a....... %.4.|
187 0110: 8e 0f a0 61 a8 eb 82 82 2e c9 c2 20 25 d5 34 c5 |...a....... %.4.|
177 0120: d0 d8 c2 dc d4 c2 d4 c4 30 d9 34 cd c0 d4 c8 cc |........0.4.....|
188 0120: d0 d8 c2 dc d4 c2 d4 c4 30 d9 34 cd c0 d4 c8 cc |........0.4.....|
178 0130: 34 31 c5 d0 c4 24 31 c9 32 2d d1 c2 2c c5 30 25 |41...$1.2-..,.0%|
189 0130: 34 31 c5 d0 c4 24 31 c9 32 2d d1 c2 2c c5 30 25 |41...$1.2-..,.0%|
179 0140: 09 e4 ee 85 8f 85 ff 88 ab 89 36 c7 2a c4 47 34 |..........6.*.G4|
190 0140: 09 e4 ee 85 8f 85 ff 88 ab 89 36 c7 2a c4 47 34 |..........6.*.G4|
180 0150: fe f8 ec 7b 73 37 3f c3 24 62 1d 8d 4d 1d 9e 40 |...{s7?.$b..M..@|
191 0150: fe f8 ec 7b 73 37 3f c3 24 62 1d 8d 4d 1d 9e 40 |...{s7?.$b..M..@|
181 0160: 06 3b 10 14 36 a4 38 10 04 d8 21 01 5a b2 83 f7 |.;..6.8...!.Z...|
192 0160: 06 3b 10 14 36 a4 38 10 04 d8 21 01 5a b2 83 f7 |.;..6.8...!.Z...|
182 0170: e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a 78 ed fc d5 |.E..V....R..x...|
193 0170: e9 45 8b d2 56 c7 a3 1f 82 52 d7 8a 78 ed fc d5 |.E..V....R..x...|
183 0180: 76 f1 36 25 81 49 c0 ad 30 c0 0e 49 8f 54 b7 9e |v.6%.I..0..I.T..|
194 0180: 76 f1 36 25 81 49 c0 ad 30 c0 0e 49 8f 54 b7 9e |v.6%.I..0..I.T..|
184 0190: d4 1c 09 00 bb 8d f0 bd |........|
195 0190: d4 1c 09 00 bb 8d f0 bd |........|
185
196
186 $ echo "http://localhost:$HGPORT1/full.hg" > server/.hg/clonebundles.manifest
197 $ echo "http://localhost:$HGPORT1/full.hg" > server/.hg/clonebundles.manifest
187 $ hg clone -U http://localhost:$HGPORT full-bundle
198 $ hg clone -U http://localhost:$HGPORT full-bundle
188 applying clone bundle from http://localhost:$HGPORT1/full.hg
199 applying clone bundle from http://localhost:$HGPORT1/full.hg
189 adding changesets
200 adding changesets
190 adding manifests
201 adding manifests
191 adding file changes
202 adding file changes
192 added 2 changesets with 2 changes to 2 files
203 added 2 changesets with 2 changes to 2 files
193 finished applying clone bundle
204 finished applying clone bundle
194 searching for changes
205 searching for changes
195 no changes found
206 no changes found
196
207
197 Entry with unknown BUNDLESPEC is filtered and not used
208 Entry with unknown BUNDLESPEC is filtered and not used
198
209
199 $ cat > server/.hg/clonebundles.manifest << EOF
210 $ cat > server/.hg/clonebundles.manifest << EOF
200 > http://bad.entry1 BUNDLESPEC=UNKNOWN
211 > http://bad.entry1 BUNDLESPEC=UNKNOWN
201 > http://bad.entry2 BUNDLESPEC=xz-v1
212 > http://bad.entry2 BUNDLESPEC=xz-v1
202 > http://bad.entry3 BUNDLESPEC=none-v100
213 > http://bad.entry3 BUNDLESPEC=none-v100
203 > http://localhost:$HGPORT1/full.hg BUNDLESPEC=gzip-v2
214 > http://localhost:$HGPORT1/full.hg BUNDLESPEC=gzip-v2
204 > EOF
215 > EOF
205
216
206 $ hg clone -U http://localhost:$HGPORT filter-unknown-type
217 $ hg clone -U http://localhost:$HGPORT filter-unknown-type
207 applying clone bundle from http://localhost:$HGPORT1/full.hg
218 applying clone bundle from http://localhost:$HGPORT1/full.hg
208 adding changesets
219 adding changesets
209 adding manifests
220 adding manifests
210 adding file changes
221 adding file changes
211 added 2 changesets with 2 changes to 2 files
222 added 2 changesets with 2 changes to 2 files
212 finished applying clone bundle
223 finished applying clone bundle
213 searching for changes
224 searching for changes
214 no changes found
225 no changes found
215
226
216 Automatic fallback when all entries are filtered
227 Automatic fallback when all entries are filtered
217
228
218 $ cat > server/.hg/clonebundles.manifest << EOF
229 $ cat > server/.hg/clonebundles.manifest << EOF
219 > http://bad.entry BUNDLESPEC=UNKNOWN
230 > http://bad.entry BUNDLESPEC=UNKNOWN
220 > EOF
231 > EOF
221
232
222 $ hg clone -U http://localhost:$HGPORT filter-all
233 $ hg clone -U http://localhost:$HGPORT filter-all
223 no compatible clone bundles available on server; falling back to regular clone
234 no compatible clone bundles available on server; falling back to regular clone
224 (you may want to report this to the server operator)
235 (you may want to report this to the server operator)
225 requesting all changes
236 requesting all changes
226 adding changesets
237 adding changesets
227 adding manifests
238 adding manifests
228 adding file changes
239 adding file changes
229 added 2 changesets with 2 changes to 2 files
240 added 2 changesets with 2 changes to 2 files
230
241
231 URLs requiring SNI are filtered in Python <2.7.9
242 URLs requiring SNI are filtered in Python <2.7.9
232
243
233 $ cp full.hg sni.hg
244 $ cp full.hg sni.hg
234 $ cat > server/.hg/clonebundles.manifest << EOF
245 $ cat > server/.hg/clonebundles.manifest << EOF
235 > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true
246 > http://localhost:$HGPORT1/sni.hg REQUIRESNI=true
236 > http://localhost:$HGPORT1/full.hg
247 > http://localhost:$HGPORT1/full.hg
237 > EOF
248 > EOF
238
249
239 #if sslcontext
250 #if sslcontext
240 Python 2.7.9+ support SNI
251 Python 2.7.9+ support SNI
241
252
242 $ hg clone -U http://localhost:$HGPORT sni-supported
253 $ hg clone -U http://localhost:$HGPORT sni-supported
243 applying clone bundle from http://localhost:$HGPORT1/sni.hg
254 applying clone bundle from http://localhost:$HGPORT1/sni.hg
244 adding changesets
255 adding changesets
245 adding manifests
256 adding manifests
246 adding file changes
257 adding file changes
247 added 2 changesets with 2 changes to 2 files
258 added 2 changesets with 2 changes to 2 files
248 finished applying clone bundle
259 finished applying clone bundle
249 searching for changes
260 searching for changes
250 no changes found
261 no changes found
251 #else
262 #else
252 Python <2.7.9 will filter SNI URLs
263 Python <2.7.9 will filter SNI URLs
253
264
254 $ hg clone -U http://localhost:$HGPORT sni-unsupported
265 $ hg clone -U http://localhost:$HGPORT sni-unsupported
255 applying clone bundle from http://localhost:$HGPORT1/full.hg
266 applying clone bundle from http://localhost:$HGPORT1/full.hg
256 adding changesets
267 adding changesets
257 adding manifests
268 adding manifests
258 adding file changes
269 adding file changes
259 added 2 changesets with 2 changes to 2 files
270 added 2 changesets with 2 changes to 2 files
260 finished applying clone bundle
271 finished applying clone bundle
261 searching for changes
272 searching for changes
262 no changes found
273 no changes found
263 #endif
274 #endif
264
275
265 Set up manifest for testing preferences
276 Set up manifest for testing preferences
266 (Remember, the TYPE does not have to match reality - the URL is
277 (Remember, the TYPE does not have to match reality - the URL is
267 important)
278 important)
268
279
269 $ cp full.hg gz-a.hg
280 $ cp full.hg gz-a.hg
270 $ cp full.hg gz-b.hg
281 $ cp full.hg gz-b.hg
271 $ cp full.hg bz2-a.hg
282 $ cp full.hg bz2-a.hg
272 $ cp full.hg bz2-b.hg
283 $ cp full.hg bz2-b.hg
273 $ cat > server/.hg/clonebundles.manifest << EOF
284 $ cat > server/.hg/clonebundles.manifest << EOF
274 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 extra=a
285 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2 extra=a
275 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2 extra=a
286 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2 extra=a
276 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
287 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
277 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
288 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
278 > EOF
289 > EOF
279
290
280 Preferring an undefined attribute will take first entry
291 Preferring an undefined attribute will take first entry
281
292
282 $ hg --config experimental.clonebundleprefers=foo=bar clone -U http://localhost:$HGPORT prefer-foo
293 $ hg --config experimental.clonebundleprefers=foo=bar clone -U http://localhost:$HGPORT prefer-foo
283 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
294 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
284 adding changesets
295 adding changesets
285 adding manifests
296 adding manifests
286 adding file changes
297 adding file changes
287 added 2 changesets with 2 changes to 2 files
298 added 2 changesets with 2 changes to 2 files
288 finished applying clone bundle
299 finished applying clone bundle
289 searching for changes
300 searching for changes
290 no changes found
301 no changes found
291
302
292 Preferring bz2 type will download first entry of that type
303 Preferring bz2 type will download first entry of that type
293
304
294 $ hg --config experimental.clonebundleprefers=COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-bz
305 $ hg --config experimental.clonebundleprefers=COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-bz
295 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
306 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
296 adding changesets
307 adding changesets
297 adding manifests
308 adding manifests
298 adding file changes
309 adding file changes
299 added 2 changesets with 2 changes to 2 files
310 added 2 changesets with 2 changes to 2 files
300 finished applying clone bundle
311 finished applying clone bundle
301 searching for changes
312 searching for changes
302 no changes found
313 no changes found
303
314
304 Preferring multiple values of an option works
315 Preferring multiple values of an option works
305
316
306 $ hg --config experimental.clonebundleprefers=COMPRESSION=unknown,COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-multiple-bz
317 $ hg --config experimental.clonebundleprefers=COMPRESSION=unknown,COMPRESSION=bzip2 clone -U http://localhost:$HGPORT prefer-multiple-bz
307 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
318 applying clone bundle from http://localhost:$HGPORT1/bz2-a.hg
308 adding changesets
319 adding changesets
309 adding manifests
320 adding manifests
310 adding file changes
321 adding file changes
311 added 2 changesets with 2 changes to 2 files
322 added 2 changesets with 2 changes to 2 files
312 finished applying clone bundle
323 finished applying clone bundle
313 searching for changes
324 searching for changes
314 no changes found
325 no changes found
315
326
316 Sorting multiple values should get us back to original first entry
327 Sorting multiple values should get us back to original first entry
317
328
318 $ hg --config experimental.clonebundleprefers=BUNDLESPEC=unknown,BUNDLESPEC=gzip-v2,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-multiple-gz
329 $ hg --config experimental.clonebundleprefers=BUNDLESPEC=unknown,BUNDLESPEC=gzip-v2,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-multiple-gz
319 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
330 applying clone bundle from http://localhost:$HGPORT1/gz-a.hg
320 adding changesets
331 adding changesets
321 adding manifests
332 adding manifests
322 adding file changes
333 adding file changes
323 added 2 changesets with 2 changes to 2 files
334 added 2 changesets with 2 changes to 2 files
324 finished applying clone bundle
335 finished applying clone bundle
325 searching for changes
336 searching for changes
326 no changes found
337 no changes found
327
338
328 Preferring multiple attributes has correct order
339 Preferring multiple attributes has correct order
329
340
330 $ hg --config experimental.clonebundleprefers=extra=b,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-separate-attributes
341 $ hg --config experimental.clonebundleprefers=extra=b,BUNDLESPEC=bzip2-v2 clone -U http://localhost:$HGPORT prefer-separate-attributes
331 applying clone bundle from http://localhost:$HGPORT1/bz2-b.hg
342 applying clone bundle from http://localhost:$HGPORT1/bz2-b.hg
332 adding changesets
343 adding changesets
333 adding manifests
344 adding manifests
334 adding file changes
345 adding file changes
335 added 2 changesets with 2 changes to 2 files
346 added 2 changesets with 2 changes to 2 files
336 finished applying clone bundle
347 finished applying clone bundle
337 searching for changes
348 searching for changes
338 no changes found
349 no changes found
339
350
340 Test where attribute is missing from some entries
351 Test where attribute is missing from some entries
341
352
342 $ cat > server/.hg/clonebundles.manifest << EOF
353 $ cat > server/.hg/clonebundles.manifest << EOF
343 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
354 > http://localhost:$HGPORT1/gz-a.hg BUNDLESPEC=gzip-v2
344 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2
355 > http://localhost:$HGPORT1/bz2-a.hg BUNDLESPEC=bzip2-v2
345 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
356 > http://localhost:$HGPORT1/gz-b.hg BUNDLESPEC=gzip-v2 extra=b
346 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
357 > http://localhost:$HGPORT1/bz2-b.hg BUNDLESPEC=bzip2-v2 extra=b
347 > EOF
358 > EOF
348
359
349 $ hg --config experimental.clonebundleprefers=extra=b clone -U http://localhost:$HGPORT prefer-partially-defined-attribute
360 $ hg --config experimental.clonebundleprefers=extra=b clone -U http://localhost:$HGPORT prefer-partially-defined-attribute
350 applying clone bundle from http://localhost:$HGPORT1/gz-b.hg
361 applying clone bundle from http://localhost:$HGPORT1/gz-b.hg
351 adding changesets
362 adding changesets
352 adding manifests
363 adding manifests
353 adding file changes
364 adding file changes
354 added 2 changesets with 2 changes to 2 files
365 added 2 changesets with 2 changes to 2 files
355 finished applying clone bundle
366 finished applying clone bundle
356 searching for changes
367 searching for changes
357 no changes found
368 no changes found
General Comments 0
You need to be logged in to leave comments. Login now