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