##// END OF EJS Templates
wireprotov2: let clients drive delta behavior...
Gregory Szorc -
r39677:aa7e3123 default
parent child Browse files
Show More
@@ -1,394 +1,396
1 # exchangev2.py - repository exchange for wire protocol version 2
1 # exchangev2.py - repository exchange for wire protocol version 2
2 #
2 #
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2018 Gregory Szorc <gregory.szorc@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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import collections
10 import collections
11 import weakref
11 import weakref
12
12
13 from .i18n import _
13 from .i18n import _
14 from .node import (
14 from .node import (
15 nullid,
15 nullid,
16 short,
16 short,
17 )
17 )
18 from . import (
18 from . import (
19 bookmarks,
19 bookmarks,
20 error,
20 error,
21 mdiff,
21 mdiff,
22 phases,
22 phases,
23 pycompat,
23 pycompat,
24 setdiscovery,
24 setdiscovery,
25 )
25 )
26
26
27 def pull(pullop):
27 def pull(pullop):
28 """Pull using wire protocol version 2."""
28 """Pull using wire protocol version 2."""
29 repo = pullop.repo
29 repo = pullop.repo
30 remote = pullop.remote
30 remote = pullop.remote
31 tr = pullop.trmanager.transaction()
31 tr = pullop.trmanager.transaction()
32
32
33 # Figure out what needs to be fetched.
33 # Figure out what needs to be fetched.
34 common, fetch, remoteheads = _pullchangesetdiscovery(
34 common, fetch, remoteheads = _pullchangesetdiscovery(
35 repo, remote, pullop.heads, abortwhenunrelated=pullop.force)
35 repo, remote, pullop.heads, abortwhenunrelated=pullop.force)
36
36
37 # And fetch the data.
37 # And fetch the data.
38 pullheads = pullop.heads or remoteheads
38 pullheads = pullop.heads or remoteheads
39 csetres = _fetchchangesets(repo, tr, remote, common, fetch, pullheads)
39 csetres = _fetchchangesets(repo, tr, remote, common, fetch, pullheads)
40
40
41 # New revisions are written to the changelog. But all other updates
41 # New revisions are written to the changelog. But all other updates
42 # are deferred. Do those now.
42 # are deferred. Do those now.
43
43
44 # Ensure all new changesets are draft by default. If the repo is
44 # Ensure all new changesets are draft by default. If the repo is
45 # publishing, the phase will be adjusted by the loop below.
45 # publishing, the phase will be adjusted by the loop below.
46 if csetres['added']:
46 if csetres['added']:
47 phases.registernew(repo, tr, phases.draft, csetres['added'])
47 phases.registernew(repo, tr, phases.draft, csetres['added'])
48
48
49 # And adjust the phase of all changesets accordingly.
49 # And adjust the phase of all changesets accordingly.
50 for phase in phases.phasenames:
50 for phase in phases.phasenames:
51 if phase == b'secret' or not csetres['nodesbyphase'][phase]:
51 if phase == b'secret' or not csetres['nodesbyphase'][phase]:
52 continue
52 continue
53
53
54 phases.advanceboundary(repo, tr, phases.phasenames.index(phase),
54 phases.advanceboundary(repo, tr, phases.phasenames.index(phase),
55 csetres['nodesbyphase'][phase])
55 csetres['nodesbyphase'][phase])
56
56
57 # Write bookmark updates.
57 # Write bookmark updates.
58 bookmarks.updatefromremote(repo.ui, repo, csetres['bookmarks'],
58 bookmarks.updatefromremote(repo.ui, repo, csetres['bookmarks'],
59 remote.url(), pullop.gettransaction,
59 remote.url(), pullop.gettransaction,
60 explicit=pullop.explicitbookmarks)
60 explicit=pullop.explicitbookmarks)
61
61
62 manres = _fetchmanifests(repo, tr, remote, csetres['manifestnodes'])
62 manres = _fetchmanifests(repo, tr, remote, csetres['manifestnodes'])
63
63
64 # Find all file nodes referenced by added manifests and fetch those
64 # Find all file nodes referenced by added manifests and fetch those
65 # revisions.
65 # revisions.
66 fnodes = _derivefilesfrommanifests(repo, manres['added'])
66 fnodes = _derivefilesfrommanifests(repo, manres['added'])
67 _fetchfiles(repo, tr, remote, fnodes, manres['linkrevs'])
67 _fetchfiles(repo, tr, remote, fnodes, manres['linkrevs'])
68
68
69 def _pullchangesetdiscovery(repo, remote, heads, abortwhenunrelated=True):
69 def _pullchangesetdiscovery(repo, remote, heads, abortwhenunrelated=True):
70 """Determine which changesets need to be pulled."""
70 """Determine which changesets need to be pulled."""
71
71
72 if heads:
72 if heads:
73 knownnode = repo.changelog.hasnode
73 knownnode = repo.changelog.hasnode
74 if all(knownnode(head) for head in heads):
74 if all(knownnode(head) for head in heads):
75 return heads, False, heads
75 return heads, False, heads
76
76
77 # TODO wire protocol version 2 is capable of more efficient discovery
77 # TODO wire protocol version 2 is capable of more efficient discovery
78 # than setdiscovery. Consider implementing something better.
78 # than setdiscovery. Consider implementing something better.
79 common, fetch, remoteheads = setdiscovery.findcommonheads(
79 common, fetch, remoteheads = setdiscovery.findcommonheads(
80 repo.ui, repo, remote, abortwhenunrelated=abortwhenunrelated)
80 repo.ui, repo, remote, abortwhenunrelated=abortwhenunrelated)
81
81
82 common = set(common)
82 common = set(common)
83 remoteheads = set(remoteheads)
83 remoteheads = set(remoteheads)
84
84
85 # If a remote head is filtered locally, put it back in the common set.
85 # If a remote head is filtered locally, put it back in the common set.
86 # See the comment in exchange._pulldiscoverychangegroup() for more.
86 # See the comment in exchange._pulldiscoverychangegroup() for more.
87
87
88 if fetch and remoteheads:
88 if fetch and remoteheads:
89 nodemap = repo.unfiltered().changelog.nodemap
89 nodemap = repo.unfiltered().changelog.nodemap
90
90
91 common |= {head for head in remoteheads if head in nodemap}
91 common |= {head for head in remoteheads if head in nodemap}
92
92
93 if set(remoteheads).issubset(common):
93 if set(remoteheads).issubset(common):
94 fetch = []
94 fetch = []
95
95
96 common.discard(nullid)
96 common.discard(nullid)
97
97
98 return common, fetch, remoteheads
98 return common, fetch, remoteheads
99
99
100 def _fetchchangesets(repo, tr, remote, common, fetch, remoteheads):
100 def _fetchchangesets(repo, tr, remote, common, fetch, remoteheads):
101 # TODO consider adding a step here where we obtain the DAG shape first
101 # TODO consider adding a step here where we obtain the DAG shape first
102 # (or ask the server to slice changesets into chunks for us) so that
102 # (or ask the server to slice changesets into chunks for us) so that
103 # we can perform multiple fetches in batches. This will facilitate
103 # we can perform multiple fetches in batches. This will facilitate
104 # resuming interrupted clones, higher server-side cache hit rates due
104 # resuming interrupted clones, higher server-side cache hit rates due
105 # to smaller segments, etc.
105 # to smaller segments, etc.
106 with remote.commandexecutor() as e:
106 with remote.commandexecutor() as e:
107 objs = e.callcommand(b'changesetdata', {
107 objs = e.callcommand(b'changesetdata', {
108 b'noderange': [sorted(common), sorted(remoteheads)],
108 b'noderange': [sorted(common), sorted(remoteheads)],
109 b'fields': {b'bookmarks', b'parents', b'phase', b'revision'},
109 b'fields': {b'bookmarks', b'parents', b'phase', b'revision'},
110 }).result()
110 }).result()
111
111
112 # The context manager waits on all response data when exiting. So
112 # The context manager waits on all response data when exiting. So
113 # we need to remain in the context manager in order to stream data.
113 # we need to remain in the context manager in order to stream data.
114 return _processchangesetdata(repo, tr, objs)
114 return _processchangesetdata(repo, tr, objs)
115
115
116 def _processchangesetdata(repo, tr, objs):
116 def _processchangesetdata(repo, tr, objs):
117 repo.hook('prechangegroup', throw=True,
117 repo.hook('prechangegroup', throw=True,
118 **pycompat.strkwargs(tr.hookargs))
118 **pycompat.strkwargs(tr.hookargs))
119
119
120 urepo = repo.unfiltered()
120 urepo = repo.unfiltered()
121 cl = urepo.changelog
121 cl = urepo.changelog
122
122
123 cl.delayupdate(tr)
123 cl.delayupdate(tr)
124
124
125 # The first emitted object is a header describing the data that
125 # The first emitted object is a header describing the data that
126 # follows.
126 # follows.
127 meta = next(objs)
127 meta = next(objs)
128
128
129 progress = repo.ui.makeprogress(_('changesets'),
129 progress = repo.ui.makeprogress(_('changesets'),
130 unit=_('chunks'),
130 unit=_('chunks'),
131 total=meta.get(b'totalitems'))
131 total=meta.get(b'totalitems'))
132
132
133 manifestnodes = {}
133 manifestnodes = {}
134
134
135 def linkrev(node):
135 def linkrev(node):
136 repo.ui.debug('add changeset %s\n' % short(node))
136 repo.ui.debug('add changeset %s\n' % short(node))
137 # Linkrev for changelog is always self.
137 # Linkrev for changelog is always self.
138 return len(cl)
138 return len(cl)
139
139
140 def onchangeset(cl, node):
140 def onchangeset(cl, node):
141 progress.increment()
141 progress.increment()
142
142
143 revision = cl.changelogrevision(node)
143 revision = cl.changelogrevision(node)
144
144
145 # We need to preserve the mapping of changelog revision to node
145 # We need to preserve the mapping of changelog revision to node
146 # so we can set the linkrev accordingly when manifests are added.
146 # so we can set the linkrev accordingly when manifests are added.
147 manifestnodes[cl.rev(node)] = revision.manifest
147 manifestnodes[cl.rev(node)] = revision.manifest
148
148
149 nodesbyphase = {phase: set() for phase in phases.phasenames}
149 nodesbyphase = {phase: set() for phase in phases.phasenames}
150 remotebookmarks = {}
150 remotebookmarks = {}
151
151
152 # addgroup() expects a 7-tuple describing revisions. This normalizes
152 # addgroup() expects a 7-tuple describing revisions. This normalizes
153 # the wire data to that format.
153 # the wire data to that format.
154 #
154 #
155 # This loop also aggregates non-revision metadata, such as phase
155 # This loop also aggregates non-revision metadata, such as phase
156 # data.
156 # data.
157 def iterrevisions():
157 def iterrevisions():
158 for cset in objs:
158 for cset in objs:
159 node = cset[b'node']
159 node = cset[b'node']
160
160
161 if b'phase' in cset:
161 if b'phase' in cset:
162 nodesbyphase[cset[b'phase']].add(node)
162 nodesbyphase[cset[b'phase']].add(node)
163
163
164 for mark in cset.get(b'bookmarks', []):
164 for mark in cset.get(b'bookmarks', []):
165 remotebookmarks[mark] = node
165 remotebookmarks[mark] = node
166
166
167 # TODO add mechanism for extensions to examine records so they
167 # TODO add mechanism for extensions to examine records so they
168 # can siphon off custom data fields.
168 # can siphon off custom data fields.
169
169
170 # Some entries might only be metadata only updates.
170 # Some entries might only be metadata only updates.
171 if b'revisionsize' not in cset:
171 if b'revisionsize' not in cset:
172 continue
172 continue
173
173
174 data = next(objs)
174 data = next(objs)
175
175
176 yield (
176 yield (
177 node,
177 node,
178 cset[b'parents'][0],
178 cset[b'parents'][0],
179 cset[b'parents'][1],
179 cset[b'parents'][1],
180 # Linknode is always itself for changesets.
180 # Linknode is always itself for changesets.
181 cset[b'node'],
181 cset[b'node'],
182 # We always send full revisions. So delta base is not set.
182 # We always send full revisions. So delta base is not set.
183 nullid,
183 nullid,
184 mdiff.trivialdiffheader(len(data)) + data,
184 mdiff.trivialdiffheader(len(data)) + data,
185 # Flags not yet supported.
185 # Flags not yet supported.
186 0,
186 0,
187 )
187 )
188
188
189 added = cl.addgroup(iterrevisions(), linkrev, weakref.proxy(tr),
189 added = cl.addgroup(iterrevisions(), linkrev, weakref.proxy(tr),
190 addrevisioncb=onchangeset)
190 addrevisioncb=onchangeset)
191
191
192 progress.complete()
192 progress.complete()
193
193
194 return {
194 return {
195 'added': added,
195 'added': added,
196 'nodesbyphase': nodesbyphase,
196 'nodesbyphase': nodesbyphase,
197 'bookmarks': remotebookmarks,
197 'bookmarks': remotebookmarks,
198 'manifestnodes': manifestnodes,
198 'manifestnodes': manifestnodes,
199 }
199 }
200
200
201 def _fetchmanifests(repo, tr, remote, manifestnodes):
201 def _fetchmanifests(repo, tr, remote, manifestnodes):
202 rootmanifest = repo.manifestlog.getstorage(b'')
202 rootmanifest = repo.manifestlog.getstorage(b'')
203
203
204 # Some manifests can be shared between changesets. Filter out revisions
204 # Some manifests can be shared between changesets. Filter out revisions
205 # we already know about.
205 # we already know about.
206 fetchnodes = []
206 fetchnodes = []
207 linkrevs = {}
207 linkrevs = {}
208 seen = set()
208 seen = set()
209
209
210 for clrev, node in sorted(manifestnodes.iteritems()):
210 for clrev, node in sorted(manifestnodes.iteritems()):
211 if node in seen:
211 if node in seen:
212 continue
212 continue
213
213
214 try:
214 try:
215 rootmanifest.rev(node)
215 rootmanifest.rev(node)
216 except error.LookupError:
216 except error.LookupError:
217 fetchnodes.append(node)
217 fetchnodes.append(node)
218 linkrevs[node] = clrev
218 linkrevs[node] = clrev
219
219
220 seen.add(node)
220 seen.add(node)
221
221
222 # TODO handle tree manifests
222 # TODO handle tree manifests
223
223
224 # addgroup() expects 7-tuple describing revisions. This normalizes
224 # addgroup() expects 7-tuple describing revisions. This normalizes
225 # the wire data to that format.
225 # the wire data to that format.
226 def iterrevisions(objs, progress):
226 def iterrevisions(objs, progress):
227 for manifest in objs:
227 for manifest in objs:
228 node = manifest[b'node']
228 node = manifest[b'node']
229
229
230 if b'deltasize' in manifest:
230 if b'deltasize' in manifest:
231 basenode = manifest[b'deltabasenode']
231 basenode = manifest[b'deltabasenode']
232 delta = next(objs)
232 delta = next(objs)
233 elif b'revisionsize' in manifest:
233 elif b'revisionsize' in manifest:
234 basenode = nullid
234 basenode = nullid
235 revision = next(objs)
235 revision = next(objs)
236 delta = mdiff.trivialdiffheader(len(revision)) + revision
236 delta = mdiff.trivialdiffheader(len(revision)) + revision
237 else:
237 else:
238 continue
238 continue
239
239
240 yield (
240 yield (
241 node,
241 node,
242 manifest[b'parents'][0],
242 manifest[b'parents'][0],
243 manifest[b'parents'][1],
243 manifest[b'parents'][1],
244 # The value passed in is passed to the lookup function passed
244 # The value passed in is passed to the lookup function passed
245 # to addgroup(). We already have a map of manifest node to
245 # to addgroup(). We already have a map of manifest node to
246 # changelog revision number. So we just pass in the
246 # changelog revision number. So we just pass in the
247 # manifest node here and use linkrevs.__getitem__ as the
247 # manifest node here and use linkrevs.__getitem__ as the
248 # resolution function.
248 # resolution function.
249 node,
249 node,
250 basenode,
250 basenode,
251 delta,
251 delta,
252 # Flags not yet supported.
252 # Flags not yet supported.
253 0
253 0
254 )
254 )
255
255
256 progress.increment()
256 progress.increment()
257
257
258 progress = repo.ui.makeprogress(_('manifests'), unit=_('chunks'),
258 progress = repo.ui.makeprogress(_('manifests'), unit=_('chunks'),
259 total=len(fetchnodes))
259 total=len(fetchnodes))
260
260
261 # Fetch manifests 10,000 per command.
261 # Fetch manifests 10,000 per command.
262 # TODO have server advertise preferences?
262 # TODO have server advertise preferences?
263 # TODO make size configurable on client?
263 # TODO make size configurable on client?
264 batchsize = 10000
264 batchsize = 10000
265
265
266 # We send commands 1 at a time to the remote. This is not the most
266 # We send commands 1 at a time to the remote. This is not the most
267 # efficient because we incur a round trip at the end of each batch.
267 # efficient because we incur a round trip at the end of each batch.
268 # However, the existing frame-based reactor keeps consuming server
268 # However, the existing frame-based reactor keeps consuming server
269 # data in the background. And this results in response data buffering
269 # data in the background. And this results in response data buffering
270 # in memory. This can consume gigabytes of memory.
270 # in memory. This can consume gigabytes of memory.
271 # TODO send multiple commands in a request once background buffering
271 # TODO send multiple commands in a request once background buffering
272 # issues are resolved.
272 # issues are resolved.
273
273
274 added = []
274 added = []
275
275
276 for i in pycompat.xrange(0, len(fetchnodes), batchsize):
276 for i in pycompat.xrange(0, len(fetchnodes), batchsize):
277 batch = [node for node in fetchnodes[i:i + batchsize]]
277 batch = [node for node in fetchnodes[i:i + batchsize]]
278 if not batch:
278 if not batch:
279 continue
279 continue
280
280
281 with remote.commandexecutor() as e:
281 with remote.commandexecutor() as e:
282 objs = e.callcommand(b'manifestdata', {
282 objs = e.callcommand(b'manifestdata', {
283 b'tree': b'',
283 b'tree': b'',
284 b'nodes': batch,
284 b'nodes': batch,
285 b'fields': {b'parents', b'revision'},
285 b'fields': {b'parents', b'revision'},
286 b'haveparents': True,
286 }).result()
287 }).result()
287
288
288 # Chomp off header object.
289 # Chomp off header object.
289 next(objs)
290 next(objs)
290
291
291 added.extend(rootmanifest.addgroup(
292 added.extend(rootmanifest.addgroup(
292 iterrevisions(objs, progress),
293 iterrevisions(objs, progress),
293 linkrevs.__getitem__,
294 linkrevs.__getitem__,
294 weakref.proxy(tr)))
295 weakref.proxy(tr)))
295
296
296 progress.complete()
297 progress.complete()
297
298
298 return {
299 return {
299 'added': added,
300 'added': added,
300 'linkrevs': linkrevs,
301 'linkrevs': linkrevs,
301 }
302 }
302
303
303 def _derivefilesfrommanifests(repo, manifestnodes):
304 def _derivefilesfrommanifests(repo, manifestnodes):
304 """Determine what file nodes are relevant given a set of manifest nodes.
305 """Determine what file nodes are relevant given a set of manifest nodes.
305
306
306 Returns a dict mapping file paths to dicts of file node to first manifest
307 Returns a dict mapping file paths to dicts of file node to first manifest
307 node.
308 node.
308 """
309 """
309 ml = repo.manifestlog
310 ml = repo.manifestlog
310 fnodes = collections.defaultdict(dict)
311 fnodes = collections.defaultdict(dict)
311
312
312 for manifestnode in manifestnodes:
313 for manifestnode in manifestnodes:
313 m = ml.get(b'', manifestnode)
314 m = ml.get(b'', manifestnode)
314
315
315 # TODO this will pull in unwanted nodes because it takes the storage
316 # TODO this will pull in unwanted nodes because it takes the storage
316 # delta into consideration. What we really want is something that takes
317 # delta into consideration. What we really want is something that takes
317 # the delta between the manifest's parents. And ideally we would
318 # the delta between the manifest's parents. And ideally we would
318 # ignore file nodes that are known locally. For now, ignore both
319 # ignore file nodes that are known locally. For now, ignore both
319 # these limitations. This will result in incremental fetches requesting
320 # these limitations. This will result in incremental fetches requesting
320 # data we already have. So this is far from ideal.
321 # data we already have. So this is far from ideal.
321 md = m.readfast()
322 md = m.readfast()
322
323
323 for path, fnode in md.items():
324 for path, fnode in md.items():
324 fnodes[path].setdefault(fnode, manifestnode)
325 fnodes[path].setdefault(fnode, manifestnode)
325
326
326 return fnodes
327 return fnodes
327
328
328 def _fetchfiles(repo, tr, remote, fnodes, linkrevs):
329 def _fetchfiles(repo, tr, remote, fnodes, linkrevs):
329 def iterrevisions(objs, progress):
330 def iterrevisions(objs, progress):
330 for filerevision in objs:
331 for filerevision in objs:
331 node = filerevision[b'node']
332 node = filerevision[b'node']
332
333
333 if b'deltasize' in filerevision:
334 if b'deltasize' in filerevision:
334 basenode = filerevision[b'deltabasenode']
335 basenode = filerevision[b'deltabasenode']
335 delta = next(objs)
336 delta = next(objs)
336 elif b'revisionsize' in filerevision:
337 elif b'revisionsize' in filerevision:
337 basenode = nullid
338 basenode = nullid
338 revision = next(objs)
339 revision = next(objs)
339 delta = mdiff.trivialdiffheader(len(revision)) + revision
340 delta = mdiff.trivialdiffheader(len(revision)) + revision
340 else:
341 else:
341 continue
342 continue
342
343
343 yield (
344 yield (
344 node,
345 node,
345 filerevision[b'parents'][0],
346 filerevision[b'parents'][0],
346 filerevision[b'parents'][1],
347 filerevision[b'parents'][1],
347 node,
348 node,
348 basenode,
349 basenode,
349 delta,
350 delta,
350 # Flags not yet supported.
351 # Flags not yet supported.
351 0,
352 0,
352 )
353 )
353
354
354 progress.increment()
355 progress.increment()
355
356
356 progress = repo.ui.makeprogress(
357 progress = repo.ui.makeprogress(
357 _('files'), unit=_('chunks'),
358 _('files'), unit=_('chunks'),
358 total=sum(len(v) for v in fnodes.itervalues()))
359 total=sum(len(v) for v in fnodes.itervalues()))
359
360
360 # TODO make batch size configurable
361 # TODO make batch size configurable
361 batchsize = 10000
362 batchsize = 10000
362 fnodeslist = [x for x in sorted(fnodes.items())]
363 fnodeslist = [x for x in sorted(fnodes.items())]
363
364
364 for i in pycompat.xrange(0, len(fnodeslist), batchsize):
365 for i in pycompat.xrange(0, len(fnodeslist), batchsize):
365 batch = [x for x in fnodeslist[i:i + batchsize]]
366 batch = [x for x in fnodeslist[i:i + batchsize]]
366 if not batch:
367 if not batch:
367 continue
368 continue
368
369
369 with remote.commandexecutor() as e:
370 with remote.commandexecutor() as e:
370 fs = []
371 fs = []
371 locallinkrevs = {}
372 locallinkrevs = {}
372
373
373 for path, nodes in batch:
374 for path, nodes in batch:
374 fs.append((path, e.callcommand(b'filedata', {
375 fs.append((path, e.callcommand(b'filedata', {
375 b'path': path,
376 b'path': path,
376 b'nodes': sorted(nodes),
377 b'nodes': sorted(nodes),
377 b'fields': {b'parents', b'revision'}
378 b'fields': {b'parents', b'revision'},
379 b'haveparents': True,
378 })))
380 })))
379
381
380 locallinkrevs[path] = {
382 locallinkrevs[path] = {
381 node: linkrevs[manifestnode]
383 node: linkrevs[manifestnode]
382 for node, manifestnode in nodes.iteritems()}
384 for node, manifestnode in nodes.iteritems()}
383
385
384 for path, f in fs:
386 for path, f in fs:
385 objs = f.result()
387 objs = f.result()
386
388
387 # Chomp off header objects.
389 # Chomp off header objects.
388 next(objs)
390 next(objs)
389
391
390 store = repo.file(path)
392 store = repo.file(path)
391 store.addgroup(
393 store.addgroup(
392 iterrevisions(objs, progress),
394 iterrevisions(objs, progress),
393 locallinkrevs[path].__getitem__,
395 locallinkrevs[path].__getitem__,
394 weakref.proxy(tr))
396 weakref.proxy(tr))
@@ -1,425 +1,440
1 **Experimental and under active development**
1 **Experimental and under active development**
2
2
3 This section documents the wire protocol commands exposed to transports
3 This section documents the wire protocol commands exposed to transports
4 using the frame-based protocol. The set of commands exposed through
4 using the frame-based protocol. The set of commands exposed through
5 these transports is distinct from the set of commands exposed to legacy
5 these transports is distinct from the set of commands exposed to legacy
6 transports.
6 transports.
7
7
8 The frame-based protocol uses CBOR to encode command execution requests.
8 The frame-based protocol uses CBOR to encode command execution requests.
9 All command arguments must be mapped to a specific or set of CBOR data
9 All command arguments must be mapped to a specific or set of CBOR data
10 types.
10 types.
11
11
12 The response to many commands is also CBOR. There is no common response
12 The response to many commands is also CBOR. There is no common response
13 format: each command defines its own response format.
13 format: each command defines its own response format.
14
14
15 TODOs
15 TODOs
16 =====
16 =====
17
17
18 * Add "node namespace" support to each command. In order to support
18 * Add "node namespace" support to each command. In order to support
19 SHA-1 hash transition, we want servers to be able to expose different
19 SHA-1 hash transition, we want servers to be able to expose different
20 "node namespaces" for the same data. Every command operating on nodes
20 "node namespaces" for the same data. Every command operating on nodes
21 should specify which "node namespace" it is operating on and responses
21 should specify which "node namespace" it is operating on and responses
22 should encode the "node namespace" accordingly.
22 should encode the "node namespace" accordingly.
23
23
24 Commands
24 Commands
25 ========
25 ========
26
26
27 The sections below detail all commands available to wire protocol version
27 The sections below detail all commands available to wire protocol version
28 2.
28 2.
29
29
30 branchmap
30 branchmap
31 ---------
31 ---------
32
32
33 Obtain heads in named branches.
33 Obtain heads in named branches.
34
34
35 Receives no arguments.
35 Receives no arguments.
36
36
37 The response is a map with bytestring keys defining the branch name.
37 The response is a map with bytestring keys defining the branch name.
38 Values are arrays of bytestring defining raw changeset nodes.
38 Values are arrays of bytestring defining raw changeset nodes.
39
39
40 capabilities
40 capabilities
41 ------------
41 ------------
42
42
43 Obtain the server's capabilities.
43 Obtain the server's capabilities.
44
44
45 Receives no arguments.
45 Receives no arguments.
46
46
47 This command is typically called only as part of the handshake during
47 This command is typically called only as part of the handshake during
48 initial connection establishment.
48 initial connection establishment.
49
49
50 The response is a map with bytestring keys defining server information.
50 The response is a map with bytestring keys defining server information.
51
51
52 The defined keys are:
52 The defined keys are:
53
53
54 commands
54 commands
55 A map defining available wire protocol commands on this server.
55 A map defining available wire protocol commands on this server.
56
56
57 Keys in the map are the names of commands that can be invoked. Values
57 Keys in the map are the names of commands that can be invoked. Values
58 are maps defining information about that command. The bytestring keys
58 are maps defining information about that command. The bytestring keys
59 are:
59 are:
60
60
61 args
61 args
62 A map of argument names and their expected types.
62 A map of argument names and their expected types.
63
63
64 Types are defined as a representative value for the expected type.
64 Types are defined as a representative value for the expected type.
65 e.g. an argument expecting a boolean type will have its value
65 e.g. an argument expecting a boolean type will have its value
66 set to true. An integer type will have its value set to 42. The
66 set to true. An integer type will have its value set to 42. The
67 actual values are arbitrary and may not have meaning.
67 actual values are arbitrary and may not have meaning.
68 permissions
68 permissions
69 An array of permissions required to execute this command.
69 An array of permissions required to execute this command.
70
70
71 compression
71 compression
72 An array of maps defining available compression format support.
72 An array of maps defining available compression format support.
73
73
74 The array is sorted from most preferred to least preferred.
74 The array is sorted from most preferred to least preferred.
75
75
76 Each entry has the following bytestring keys:
76 Each entry has the following bytestring keys:
77
77
78 name
78 name
79 Name of the compression engine. e.g. ``zstd`` or ``zlib``.
79 Name of the compression engine. e.g. ``zstd`` or ``zlib``.
80
80
81 framingmediatypes
81 framingmediatypes
82 An array of bytestrings defining the supported framing protocol
82 An array of bytestrings defining the supported framing protocol
83 media types. Servers will not accept media types not in this list.
83 media types. Servers will not accept media types not in this list.
84
84
85 rawrepoformats
85 rawrepoformats
86 An array of storage formats the repository is using. This set of
86 An array of storage formats the repository is using. This set of
87 requirements can be used to determine whether a client can read a
87 requirements can be used to determine whether a client can read a
88 *raw* copy of file data available.
88 *raw* copy of file data available.
89
89
90 changesetdata
90 changesetdata
91 -------------
91 -------------
92
92
93 Obtain various data related to changesets.
93 Obtain various data related to changesets.
94
94
95 The command accepts the following arguments:
95 The command accepts the following arguments:
96
96
97 noderange
97 noderange
98 (array of arrays of bytestrings) An array of 2 elements, each being an
98 (array of arrays of bytestrings) An array of 2 elements, each being an
99 array of node bytestrings. The first array denotes the changelog revisions
99 array of node bytestrings. The first array denotes the changelog revisions
100 that are already known to the client. The second array denotes the changelog
100 that are already known to the client. The second array denotes the changelog
101 revision DAG heads to fetch. The argument essentially defines a DAG range
101 revision DAG heads to fetch. The argument essentially defines a DAG range
102 bounded by root and head nodes to fetch.
102 bounded by root and head nodes to fetch.
103
103
104 The roots array may be empty. The heads array must be defined.
104 The roots array may be empty. The heads array must be defined.
105
105
106 nodes
106 nodes
107 (array of bytestrings) Changelog revisions to request explicitly.
107 (array of bytestrings) Changelog revisions to request explicitly.
108
108
109 fields
109 fields
110 (set of bytestring) Which data associated with changelog revisions to
110 (set of bytestring) Which data associated with changelog revisions to
111 fetch. The following values are recognized:
111 fetch. The following values are recognized:
112
112
113 bookmarks
113 bookmarks
114 Bookmarks associated with a revision.
114 Bookmarks associated with a revision.
115
115
116 parents
116 parents
117 Parent revisions.
117 Parent revisions.
118
118
119 phase
119 phase
120 The phase state of a revision.
120 The phase state of a revision.
121
121
122 revision
122 revision
123 The raw, revision data for the changelog entry. The hash of this data
123 The raw, revision data for the changelog entry. The hash of this data
124 will match the revision's node value.
124 will match the revision's node value.
125
125
126 The server resolves the set of revisions relevant to the request by taking
126 The server resolves the set of revisions relevant to the request by taking
127 the union of the ``noderange`` and ``nodes`` arguments. At least one of these
127 the union of the ``noderange`` and ``nodes`` arguments. At least one of these
128 arguments must be defined.
128 arguments must be defined.
129
129
130 The response bytestream starts with a CBOR map describing the data that follows.
130 The response bytestream starts with a CBOR map describing the data that follows.
131 This map has the following bytestring keys:
131 This map has the following bytestring keys:
132
132
133 totalitems
133 totalitems
134 (unsigned integer) Total number of changelog revisions whose data is being
134 (unsigned integer) Total number of changelog revisions whose data is being
135 transferred. This maps to the set of revisions in the requested node
135 transferred. This maps to the set of revisions in the requested node
136 range, not the total number of records that follow (see below for why).
136 range, not the total number of records that follow (see below for why).
137
137
138 Following the map header is a series of 0 or more CBOR values. If values
138 Following the map header is a series of 0 or more CBOR values. If values
139 are present, the first value will always be a map describing a single changeset
139 are present, the first value will always be a map describing a single changeset
140 revision. If revision data is requested, the raw revision data (encoded as
140 revision. If revision data is requested, the raw revision data (encoded as
141 a CBOR bytestring) will follow the map describing it. Otherwise, another CBOR
141 a CBOR bytestring) will follow the map describing it. Otherwise, another CBOR
142 map describing the next changeset revision will occur.
142 map describing the next changeset revision will occur.
143
143
144 Each map has the following bytestring keys:
144 Each map has the following bytestring keys:
145
145
146 node
146 node
147 (bytestring) The node value for this revision. This is the SHA-1 hash of
147 (bytestring) The node value for this revision. This is the SHA-1 hash of
148 the raw revision data.
148 the raw revision data.
149
149
150 bookmarks (optional)
150 bookmarks (optional)
151 (array of bytestrings) Bookmarks attached to this revision. Only present
151 (array of bytestrings) Bookmarks attached to this revision. Only present
152 if ``bookmarks`` data is being requested and the revision has bookmarks
152 if ``bookmarks`` data is being requested and the revision has bookmarks
153 attached.
153 attached.
154
154
155 parents (optional)
155 parents (optional)
156 (array of bytestrings) The nodes representing the parent revisions of this
156 (array of bytestrings) The nodes representing the parent revisions of this
157 revision. Only present if ``parents`` data is being requested.
157 revision. Only present if ``parents`` data is being requested.
158
158
159 phase (optional)
159 phase (optional)
160 (bytestring) The phase that a revision is in. Recognized values are
160 (bytestring) The phase that a revision is in. Recognized values are
161 ``secret``, ``draft``, and ``public``. Only present if ``phase`` data
161 ``secret``, ``draft``, and ``public``. Only present if ``phase`` data
162 is being requested.
162 is being requested.
163
163
164 revisionsize (optional)
164 revisionsize (optional)
165 (unsigned integer) Indicates the size of raw revision data that follows this
165 (unsigned integer) Indicates the size of raw revision data that follows this
166 map. The following data contains a serialized form of the changeset data,
166 map. The following data contains a serialized form of the changeset data,
167 including the author, date, commit message, set of changed files, manifest
167 including the author, date, commit message, set of changed files, manifest
168 node, and other metadata.
168 node, and other metadata.
169
169
170 Only present if ``revision`` data was requested and the data follows this
170 Only present if ``revision`` data was requested and the data follows this
171 map.
171 map.
172
172
173 If nodes are requested via ``noderange``, they will be emitted in DAG order,
173 If nodes are requested via ``noderange``, they will be emitted in DAG order,
174 parents always before children.
174 parents always before children.
175
175
176 If nodes are requested via ``nodes``, they will be emitted in requested order.
176 If nodes are requested via ``nodes``, they will be emitted in requested order.
177
177
178 Nodes from ``nodes`` are emitted before nodes from ``noderange``.
178 Nodes from ``nodes`` are emitted before nodes from ``noderange``.
179
179
180 The set of changeset revisions emitted may not match the exact set of
180 The set of changeset revisions emitted may not match the exact set of
181 changesets requested. Furthermore, the set of keys present on each
181 changesets requested. Furthermore, the set of keys present on each
182 map may vary. This is to facilitate emitting changeset updates as well
182 map may vary. This is to facilitate emitting changeset updates as well
183 as new revisions.
183 as new revisions.
184
184
185 For example, if the request wants ``phase`` and ``revision`` data,
185 For example, if the request wants ``phase`` and ``revision`` data,
186 the response may contain entries for each changeset in the common nodes
186 the response may contain entries for each changeset in the common nodes
187 set with the ``phase`` key and without the ``revision`` key in order
187 set with the ``phase`` key and without the ``revision`` key in order
188 to reflect a phase-only update.
188 to reflect a phase-only update.
189
189
190 TODO support different revision selection mechanisms (e.g. non-public, specific
190 TODO support different revision selection mechanisms (e.g. non-public, specific
191 revisions)
191 revisions)
192 TODO support different hash "namespaces" for revisions (e.g. sha-1 versus other)
192 TODO support different hash "namespaces" for revisions (e.g. sha-1 versus other)
193 TODO support emitting obsolescence data
193 TODO support emitting obsolescence data
194 TODO support filtering based on relevant paths (narrow clone)
194 TODO support filtering based on relevant paths (narrow clone)
195 TODO support depth limiting
195 TODO support depth limiting
196 TODO support hgtagsfnodes cache / tags data
196 TODO support hgtagsfnodes cache / tags data
197 TODO support branch heads cache
197 TODO support branch heads cache
198
198
199 filedata
199 filedata
200 --------
200 --------
201
201
202 Obtain various data related to an individual tracked file.
202 Obtain various data related to an individual tracked file.
203
203
204 The command accepts the following arguments:
204 The command accepts the following arguments:
205
205
206 fields
206 fields
207 (set of bytestring) Which data associated with a file to fetch.
207 (set of bytestring) Which data associated with a file to fetch.
208 The following values are recognized:
208 The following values are recognized:
209
209
210 parents
210 parents
211 Parent nodes for the revision.
211 Parent nodes for the revision.
212
212
213 revision
213 revision
214 The raw revision data for a file.
214 The raw revision data for a file.
215
215
216 haveparents
217 (bool) Whether the client has the parent revisions of all requested
218 nodes. If set, the server may emit revision data as deltas against
219 any parent revision. If not set, the server MUST only emit deltas for
220 revisions previously emitted by this command.
221
222 False is assumed in the absence of any value.
223
216 nodes
224 nodes
217 (array of bytestrings) File nodes whose data to retrieve.
225 (array of bytestrings) File nodes whose data to retrieve.
218
226
219 path
227 path
220 (bytestring) Path of the tracked file whose data to retrieve.
228 (bytestring) Path of the tracked file whose data to retrieve.
221
229
222 TODO allow specifying revisions via alternate means (such as from
230 TODO allow specifying revisions via alternate means (such as from
223 changeset revisions or ranges)
231 changeset revisions or ranges)
224
232
225 The response bytestream starts with a CBOR map describing the data that
233 The response bytestream starts with a CBOR map describing the data that
226 follows. It has the following bytestream keys:
234 follows. It has the following bytestream keys:
227
235
228 totalitems
236 totalitems
229 (unsigned integer) Total number of file revisions whose data is
237 (unsigned integer) Total number of file revisions whose data is
230 being returned.
238 being returned.
231
239
232 Following the header map is a series of 0 or more CBOR values. The first
240 Following the header map is a series of 0 or more CBOR values. The first
233 value is always a map describing a file revision. If this map has the
241 value is always a map describing a file revision. If this map has the
234 ``deltasize`` or ``revisionsize`` keys, a bytestring containing the delta
242 ``deltasize`` or ``revisionsize`` keys, a bytestring containing the delta
235 or revision, respectively, will immediately follow the map. Otherwise
243 or revision, respectively, will immediately follow the map. Otherwise
236 the next value will be a map describing the next file revision.
244 the next value will be a map describing the next file revision.
237
245
238 Each map has the following bytestring keys:
246 Each map has the following bytestring keys:
239
247
240 node
248 node
241 (bytestring) The node of the file revision whose data is represented.
249 (bytestring) The node of the file revision whose data is represented.
242
250
243 deltabasenode
251 deltabasenode
244 (bytestring) Node of the file revision the following delta is against.
252 (bytestring) Node of the file revision the following delta is against.
245
253
246 Only present if the ``revision`` field is requested and delta data
254 Only present if the ``revision`` field is requested and delta data
247 follows this map.
255 follows this map.
248
256
249 deltasize
257 deltasize
250 (unsigned integer) The size of the delta data that follows this map.
258 (unsigned integer) The size of the delta data that follows this map.
251
259
252 Only present if the ``revision`` field is requested and delta data
260 Only present if the ``revision`` field is requested and delta data
253 follows this map.
261 follows this map.
254
262
255 parents
263 parents
256 (array of bytestring) The nodes of the parents of this file revision.
264 (array of bytestring) The nodes of the parents of this file revision.
257
265
258 Only present if the ``parents`` field is requested.
266 Only present if the ``parents`` field is requested.
259
267
260 revisionsize
268 revisionsize
261 (unsigned integer) The size of the fulltext revision data that follows
269 (unsigned integer) The size of the fulltext revision data that follows
262 this map.
270 this map.
263
271
264 Only present if the ``revision`` field is requested and fulltext revision
272 Only present if the ``revision`` field is requested and fulltext revision
265 data follows this map.
273 data follows this map.
266
274
267 When ``revision`` data is requested, the server chooses to emit either fulltext
275 When ``revision`` data is requested, the server chooses to emit either fulltext
268 revision data or a delta. What the server decides can be inferred by looking
276 revision data or a delta. What the server decides can be inferred by looking
269 for the presence of the ``deltasize`` or ``revisionsize`` keys in the map.
277 for the presence of the ``deltasize`` or ``revisionsize`` keys in the map.
270 Servers MUST NOT define both keys.
278 Servers MUST NOT define both keys.
271
279
272 heads
280 heads
273 -----
281 -----
274
282
275 Obtain DAG heads in the repository.
283 Obtain DAG heads in the repository.
276
284
277 The command accepts the following arguments:
285 The command accepts the following arguments:
278
286
279 publiconly (optional)
287 publiconly (optional)
280 (boolean) If set, operate on the DAG for public phase changesets only.
288 (boolean) If set, operate on the DAG for public phase changesets only.
281 Non-public (i.e. draft) phase DAG heads will not be returned.
289 Non-public (i.e. draft) phase DAG heads will not be returned.
282
290
283 The response is a CBOR array of bytestrings defining changeset nodes
291 The response is a CBOR array of bytestrings defining changeset nodes
284 of DAG heads. The array can be empty if the repository is empty or no
292 of DAG heads. The array can be empty if the repository is empty or no
285 changesets satisfied the request.
293 changesets satisfied the request.
286
294
287 TODO consider exposing phase of heads in response
295 TODO consider exposing phase of heads in response
288
296
289 known
297 known
290 -----
298 -----
291
299
292 Determine whether a series of changeset nodes is known to the server.
300 Determine whether a series of changeset nodes is known to the server.
293
301
294 The command accepts the following arguments:
302 The command accepts the following arguments:
295
303
296 nodes
304 nodes
297 (array of bytestrings) List of changeset nodes whose presence to
305 (array of bytestrings) List of changeset nodes whose presence to
298 query.
306 query.
299
307
300 The response is a bytestring where each byte contains a 0 or 1 for the
308 The response is a bytestring where each byte contains a 0 or 1 for the
301 corresponding requested node at the same index.
309 corresponding requested node at the same index.
302
310
303 TODO use a bit array for even more compact response
311 TODO use a bit array for even more compact response
304
312
305 listkeys
313 listkeys
306 --------
314 --------
307
315
308 List values in a specified ``pushkey`` namespace.
316 List values in a specified ``pushkey`` namespace.
309
317
310 The command receives the following arguments:
318 The command receives the following arguments:
311
319
312 namespace
320 namespace
313 (bytestring) Pushkey namespace to query.
321 (bytestring) Pushkey namespace to query.
314
322
315 The response is a map with bytestring keys and values.
323 The response is a map with bytestring keys and values.
316
324
317 TODO consider using binary to represent nodes in certain pushkey namespaces.
325 TODO consider using binary to represent nodes in certain pushkey namespaces.
318
326
319 lookup
327 lookup
320 ------
328 ------
321
329
322 Try to resolve a value to a changeset revision.
330 Try to resolve a value to a changeset revision.
323
331
324 Unlike ``known`` which operates on changeset nodes, lookup operates on
332 Unlike ``known`` which operates on changeset nodes, lookup operates on
325 node fragments and other names that a user may use.
333 node fragments and other names that a user may use.
326
334
327 The command receives the following arguments:
335 The command receives the following arguments:
328
336
329 key
337 key
330 (bytestring) Value to try to resolve.
338 (bytestring) Value to try to resolve.
331
339
332 On success, returns a bytestring containing the resolved node.
340 On success, returns a bytestring containing the resolved node.
333
341
334 manifestdata
342 manifestdata
335 ------------
343 ------------
336
344
337 Obtain various data related to manifests (which are lists of files in
345 Obtain various data related to manifests (which are lists of files in
338 a revision).
346 a revision).
339
347
340 The command accepts the following arguments:
348 The command accepts the following arguments:
341
349
342 fields
350 fields
343 (set of bytestring) Which data associated with manifests to fetch.
351 (set of bytestring) Which data associated with manifests to fetch.
344 The following values are recognized:
352 The following values are recognized:
345
353
346 parents
354 parents
347 Parent nodes for the manifest.
355 Parent nodes for the manifest.
348
356
349 revision
357 revision
350 The raw revision data for the manifest.
358 The raw revision data for the manifest.
351
359
360 haveparents
361 (bool) Whether the client has the parent revisions of all requested
362 nodes. If set, the server may emit revision data as deltas against
363 any parent revision. If not set, the server MUST only emit deltas for
364 revisions previously emitted by this command.
365
366 False is assumed in the absence of any value.
367
352 nodes
368 nodes
353 (array of bytestring) Manifest nodes whose data to retrieve.
369 (array of bytestring) Manifest nodes whose data to retrieve.
354
370
355 tree
371 tree
356 (bytestring) Path to manifest to retrieve. The empty bytestring represents
372 (bytestring) Path to manifest to retrieve. The empty bytestring represents
357 the root manifest. All other values represent directories/trees within
373 the root manifest. All other values represent directories/trees within
358 the repository.
374 the repository.
359
375
360 TODO allow specifying revisions via alternate means (such as from changeset
376 TODO allow specifying revisions via alternate means (such as from changeset
361 revisions or ranges)
377 revisions or ranges)
362 TODO consider recursive expansion of manifests (with path filtering for
378 TODO consider recursive expansion of manifests (with path filtering for
363 narrow use cases)
379 narrow use cases)
364 TODO more control over whether to emit fulltexts or deltas
365
380
366 The response bytestream starts with a CBOR map describing the data that
381 The response bytestream starts with a CBOR map describing the data that
367 follows. It has the following bytestring keys:
382 follows. It has the following bytestring keys:
368
383
369 totalitems
384 totalitems
370 (unsigned integer) Total number of manifest revisions whose data is
385 (unsigned integer) Total number of manifest revisions whose data is
371 being returned.
386 being returned.
372
387
373 Following the header map is a series of 0 or more CBOR values. The first
388 Following the header map is a series of 0 or more CBOR values. The first
374 value is always a map describing a manifest revision. If this map has the
389 value is always a map describing a manifest revision. If this map has the
375 ``deltasize`` or ``revisionsize`` keys, a bytestring containing the delta
390 ``deltasize`` or ``revisionsize`` keys, a bytestring containing the delta
376 or revision, respectively, will immediately follow the map. Otherwise
391 or revision, respectively, will immediately follow the map. Otherwise
377 the next value will be a map describing the next manifest revision.
392 the next value will be a map describing the next manifest revision.
378
393
379 Each map has the following bytestring keys:
394 Each map has the following bytestring keys:
380
395
381 node
396 node
382 (bytestring) The node of the manifest revision whose data is represented.
397 (bytestring) The node of the manifest revision whose data is represented.
383
398
384 deltabasenode
399 deltabasenode
385 (bytestring) The node that the delta representation of this revision is
400 (bytestring) The node that the delta representation of this revision is
386 computed against. Only present if the ``revision`` field is requested and
401 computed against. Only present if the ``revision`` field is requested and
387 a delta is being emitted.
402 a delta is being emitted.
388
403
389 deltasize
404 deltasize
390 (unsigned integer) The size of the delta data that follows this map.
405 (unsigned integer) The size of the delta data that follows this map.
391 Only present if the ``revision`` field is requested and a delta is
406 Only present if the ``revision`` field is requested and a delta is
392 being emitted.
407 being emitted.
393
408
394 parents
409 parents
395 (array of bytestring) The nodes of the parents of this manifest revision.
410 (array of bytestring) The nodes of the parents of this manifest revision.
396 Only present if the ``parents`` field is requested.
411 Only present if the ``parents`` field is requested.
397
412
398 revisionsize
413 revisionsize
399 (unsigned integer) The size of the fulltext revision data that follows
414 (unsigned integer) The size of the fulltext revision data that follows
400 this map. Only present if the ``revision`` field is requested and a fulltext
415 this map. Only present if the ``revision`` field is requested and a fulltext
401 revision is being emitted.
416 revision is being emitted.
402
417
403 When ``revision`` data is requested, the server chooses to emit either fulltext
418 When ``revision`` data is requested, the server chooses to emit either fulltext
404 revision data or a delta. What the server decides can be inferred by looking
419 revision data or a delta. What the server decides can be inferred by looking
405 for the presence of the ``deltasize`` or ``revisionsize`` keys in the map.
420 for the presence of the ``deltasize`` or ``revisionsize`` keys in the map.
406 Servers MUST NOT define both keys.
421 Servers MUST NOT define both keys.
407
422
408 pushkey
423 pushkey
409 -------
424 -------
410
425
411 Set a value using the ``pushkey`` protocol.
426 Set a value using the ``pushkey`` protocol.
412
427
413 The command receives the following arguments:
428 The command receives the following arguments:
414
429
415 namespace
430 namespace
416 (bytestring) Pushkey namespace to operate on.
431 (bytestring) Pushkey namespace to operate on.
417 key
432 key
418 (bytestring) The pushkey key to set.
433 (bytestring) The pushkey key to set.
419 old
434 old
420 (bytestring) Old value for this key.
435 (bytestring) Old value for this key.
421 new
436 new
422 (bytestring) New value for this key.
437 (bytestring) New value for this key.
423
438
424 TODO consider using binary to represent nodes is certain pushkey namespaces.
439 TODO consider using binary to represent nodes is certain pushkey namespaces.
425 TODO better define response type and meaning.
440 TODO better define response type and meaning.
@@ -1,898 +1,921
1 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
1 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
2 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
2 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 #
3 #
4 # This software may be used and distributed according to the terms of the
4 # This software may be used and distributed according to the terms of the
5 # GNU General Public License version 2 or any later version.
5 # GNU General Public License version 2 or any later version.
6
6
7 from __future__ import absolute_import
7 from __future__ import absolute_import
8
8
9 import contextlib
9 import contextlib
10
10
11 from .i18n import _
11 from .i18n import _
12 from .node import (
12 from .node import (
13 hex,
13 hex,
14 nullid,
14 nullid,
15 nullrev,
15 nullrev,
16 )
16 )
17 from . import (
17 from . import (
18 changegroup,
18 changegroup,
19 dagop,
19 dagop,
20 discovery,
20 discovery,
21 encoding,
21 encoding,
22 error,
22 error,
23 pycompat,
23 pycompat,
24 streamclone,
24 streamclone,
25 util,
25 util,
26 wireprotoframing,
26 wireprotoframing,
27 wireprototypes,
27 wireprototypes,
28 )
28 )
29 from .utils import (
29 from .utils import (
30 interfaceutil,
30 interfaceutil,
31 )
31 )
32
32
33 FRAMINGTYPE = b'application/mercurial-exp-framing-0005'
33 FRAMINGTYPE = b'application/mercurial-exp-framing-0005'
34
34
35 HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2
35 HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2
36
36
37 COMMANDS = wireprototypes.commanddict()
37 COMMANDS = wireprototypes.commanddict()
38
38
39 def handlehttpv2request(rctx, req, res, checkperm, urlparts):
39 def handlehttpv2request(rctx, req, res, checkperm, urlparts):
40 from .hgweb import common as hgwebcommon
40 from .hgweb import common as hgwebcommon
41
41
42 # URL space looks like: <permissions>/<command>, where <permission> can
42 # URL space looks like: <permissions>/<command>, where <permission> can
43 # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
43 # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
44
44
45 # Root URL does nothing meaningful... yet.
45 # Root URL does nothing meaningful... yet.
46 if not urlparts:
46 if not urlparts:
47 res.status = b'200 OK'
47 res.status = b'200 OK'
48 res.headers[b'Content-Type'] = b'text/plain'
48 res.headers[b'Content-Type'] = b'text/plain'
49 res.setbodybytes(_('HTTP version 2 API handler'))
49 res.setbodybytes(_('HTTP version 2 API handler'))
50 return
50 return
51
51
52 if len(urlparts) == 1:
52 if len(urlparts) == 1:
53 res.status = b'404 Not Found'
53 res.status = b'404 Not Found'
54 res.headers[b'Content-Type'] = b'text/plain'
54 res.headers[b'Content-Type'] = b'text/plain'
55 res.setbodybytes(_('do not know how to process %s\n') %
55 res.setbodybytes(_('do not know how to process %s\n') %
56 req.dispatchpath)
56 req.dispatchpath)
57 return
57 return
58
58
59 permission, command = urlparts[0:2]
59 permission, command = urlparts[0:2]
60
60
61 if permission not in (b'ro', b'rw'):
61 if permission not in (b'ro', b'rw'):
62 res.status = b'404 Not Found'
62 res.status = b'404 Not Found'
63 res.headers[b'Content-Type'] = b'text/plain'
63 res.headers[b'Content-Type'] = b'text/plain'
64 res.setbodybytes(_('unknown permission: %s') % permission)
64 res.setbodybytes(_('unknown permission: %s') % permission)
65 return
65 return
66
66
67 if req.method != 'POST':
67 if req.method != 'POST':
68 res.status = b'405 Method Not Allowed'
68 res.status = b'405 Method Not Allowed'
69 res.headers[b'Allow'] = b'POST'
69 res.headers[b'Allow'] = b'POST'
70 res.setbodybytes(_('commands require POST requests'))
70 res.setbodybytes(_('commands require POST requests'))
71 return
71 return
72
72
73 # At some point we'll want to use our own API instead of recycling the
73 # At some point we'll want to use our own API instead of recycling the
74 # behavior of version 1 of the wire protocol...
74 # behavior of version 1 of the wire protocol...
75 # TODO return reasonable responses - not responses that overload the
75 # TODO return reasonable responses - not responses that overload the
76 # HTTP status line message for error reporting.
76 # HTTP status line message for error reporting.
77 try:
77 try:
78 checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
78 checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
79 except hgwebcommon.ErrorResponse as e:
79 except hgwebcommon.ErrorResponse as e:
80 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
80 res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
81 for k, v in e.headers:
81 for k, v in e.headers:
82 res.headers[k] = v
82 res.headers[k] = v
83 res.setbodybytes('permission denied')
83 res.setbodybytes('permission denied')
84 return
84 return
85
85
86 # We have a special endpoint to reflect the request back at the client.
86 # We have a special endpoint to reflect the request back at the client.
87 if command == b'debugreflect':
87 if command == b'debugreflect':
88 _processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res)
88 _processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res)
89 return
89 return
90
90
91 # Extra commands that we handle that aren't really wire protocol
91 # Extra commands that we handle that aren't really wire protocol
92 # commands. Think extra hard before making this hackery available to
92 # commands. Think extra hard before making this hackery available to
93 # extension.
93 # extension.
94 extracommands = {'multirequest'}
94 extracommands = {'multirequest'}
95
95
96 if command not in COMMANDS and command not in extracommands:
96 if command not in COMMANDS and command not in extracommands:
97 res.status = b'404 Not Found'
97 res.status = b'404 Not Found'
98 res.headers[b'Content-Type'] = b'text/plain'
98 res.headers[b'Content-Type'] = b'text/plain'
99 res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
99 res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
100 return
100 return
101
101
102 repo = rctx.repo
102 repo = rctx.repo
103 ui = repo.ui
103 ui = repo.ui
104
104
105 proto = httpv2protocolhandler(req, ui)
105 proto = httpv2protocolhandler(req, ui)
106
106
107 if (not COMMANDS.commandavailable(command, proto)
107 if (not COMMANDS.commandavailable(command, proto)
108 and command not in extracommands):
108 and command not in extracommands):
109 res.status = b'404 Not Found'
109 res.status = b'404 Not Found'
110 res.headers[b'Content-Type'] = b'text/plain'
110 res.headers[b'Content-Type'] = b'text/plain'
111 res.setbodybytes(_('invalid wire protocol command: %s') % command)
111 res.setbodybytes(_('invalid wire protocol command: %s') % command)
112 return
112 return
113
113
114 # TODO consider cases where proxies may add additional Accept headers.
114 # TODO consider cases where proxies may add additional Accept headers.
115 if req.headers.get(b'Accept') != FRAMINGTYPE:
115 if req.headers.get(b'Accept') != FRAMINGTYPE:
116 res.status = b'406 Not Acceptable'
116 res.status = b'406 Not Acceptable'
117 res.headers[b'Content-Type'] = b'text/plain'
117 res.headers[b'Content-Type'] = b'text/plain'
118 res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
118 res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
119 % FRAMINGTYPE)
119 % FRAMINGTYPE)
120 return
120 return
121
121
122 if req.headers.get(b'Content-Type') != FRAMINGTYPE:
122 if req.headers.get(b'Content-Type') != FRAMINGTYPE:
123 res.status = b'415 Unsupported Media Type'
123 res.status = b'415 Unsupported Media Type'
124 # TODO we should send a response with appropriate media type,
124 # TODO we should send a response with appropriate media type,
125 # since client does Accept it.
125 # since client does Accept it.
126 res.headers[b'Content-Type'] = b'text/plain'
126 res.headers[b'Content-Type'] = b'text/plain'
127 res.setbodybytes(_('client MUST send Content-Type header with '
127 res.setbodybytes(_('client MUST send Content-Type header with '
128 'value: %s\n') % FRAMINGTYPE)
128 'value: %s\n') % FRAMINGTYPE)
129 return
129 return
130
130
131 _processhttpv2request(ui, repo, req, res, permission, command, proto)
131 _processhttpv2request(ui, repo, req, res, permission, command, proto)
132
132
133 def _processhttpv2reflectrequest(ui, repo, req, res):
133 def _processhttpv2reflectrequest(ui, repo, req, res):
134 """Reads unified frame protocol request and dumps out state to client.
134 """Reads unified frame protocol request and dumps out state to client.
135
135
136 This special endpoint can be used to help debug the wire protocol.
136 This special endpoint can be used to help debug the wire protocol.
137
137
138 Instead of routing the request through the normal dispatch mechanism,
138 Instead of routing the request through the normal dispatch mechanism,
139 we instead read all frames, decode them, and feed them into our state
139 we instead read all frames, decode them, and feed them into our state
140 tracker. We then dump the log of all that activity back out to the
140 tracker. We then dump the log of all that activity back out to the
141 client.
141 client.
142 """
142 """
143 import json
143 import json
144
144
145 # Reflection APIs have a history of being abused, accidentally disclosing
145 # Reflection APIs have a history of being abused, accidentally disclosing
146 # sensitive data, etc. So we have a config knob.
146 # sensitive data, etc. So we have a config knob.
147 if not ui.configbool('experimental', 'web.api.debugreflect'):
147 if not ui.configbool('experimental', 'web.api.debugreflect'):
148 res.status = b'404 Not Found'
148 res.status = b'404 Not Found'
149 res.headers[b'Content-Type'] = b'text/plain'
149 res.headers[b'Content-Type'] = b'text/plain'
150 res.setbodybytes(_('debugreflect service not available'))
150 res.setbodybytes(_('debugreflect service not available'))
151 return
151 return
152
152
153 # We assume we have a unified framing protocol request body.
153 # We assume we have a unified framing protocol request body.
154
154
155 reactor = wireprotoframing.serverreactor()
155 reactor = wireprotoframing.serverreactor()
156 states = []
156 states = []
157
157
158 while True:
158 while True:
159 frame = wireprotoframing.readframe(req.bodyfh)
159 frame = wireprotoframing.readframe(req.bodyfh)
160
160
161 if not frame:
161 if not frame:
162 states.append(b'received: <no frame>')
162 states.append(b'received: <no frame>')
163 break
163 break
164
164
165 states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
165 states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
166 frame.requestid,
166 frame.requestid,
167 frame.payload))
167 frame.payload))
168
168
169 action, meta = reactor.onframerecv(frame)
169 action, meta = reactor.onframerecv(frame)
170 states.append(json.dumps((action, meta), sort_keys=True,
170 states.append(json.dumps((action, meta), sort_keys=True,
171 separators=(', ', ': ')))
171 separators=(', ', ': ')))
172
172
173 action, meta = reactor.oninputeof()
173 action, meta = reactor.oninputeof()
174 meta['action'] = action
174 meta['action'] = action
175 states.append(json.dumps(meta, sort_keys=True, separators=(', ',': ')))
175 states.append(json.dumps(meta, sort_keys=True, separators=(', ',': ')))
176
176
177 res.status = b'200 OK'
177 res.status = b'200 OK'
178 res.headers[b'Content-Type'] = b'text/plain'
178 res.headers[b'Content-Type'] = b'text/plain'
179 res.setbodybytes(b'\n'.join(states))
179 res.setbodybytes(b'\n'.join(states))
180
180
181 def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
181 def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
182 """Post-validation handler for HTTPv2 requests.
182 """Post-validation handler for HTTPv2 requests.
183
183
184 Called when the HTTP request contains unified frame-based protocol
184 Called when the HTTP request contains unified frame-based protocol
185 frames for evaluation.
185 frames for evaluation.
186 """
186 """
187 # TODO Some HTTP clients are full duplex and can receive data before
187 # TODO Some HTTP clients are full duplex and can receive data before
188 # the entire request is transmitted. Figure out a way to indicate support
188 # the entire request is transmitted. Figure out a way to indicate support
189 # for that so we can opt into full duplex mode.
189 # for that so we can opt into full duplex mode.
190 reactor = wireprotoframing.serverreactor(deferoutput=True)
190 reactor = wireprotoframing.serverreactor(deferoutput=True)
191 seencommand = False
191 seencommand = False
192
192
193 outstream = reactor.makeoutputstream()
193 outstream = reactor.makeoutputstream()
194
194
195 while True:
195 while True:
196 frame = wireprotoframing.readframe(req.bodyfh)
196 frame = wireprotoframing.readframe(req.bodyfh)
197 if not frame:
197 if not frame:
198 break
198 break
199
199
200 action, meta = reactor.onframerecv(frame)
200 action, meta = reactor.onframerecv(frame)
201
201
202 if action == 'wantframe':
202 if action == 'wantframe':
203 # Need more data before we can do anything.
203 # Need more data before we can do anything.
204 continue
204 continue
205 elif action == 'runcommand':
205 elif action == 'runcommand':
206 sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
206 sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
207 reqcommand, reactor, outstream,
207 reqcommand, reactor, outstream,
208 meta, issubsequent=seencommand)
208 meta, issubsequent=seencommand)
209
209
210 if sentoutput:
210 if sentoutput:
211 return
211 return
212
212
213 seencommand = True
213 seencommand = True
214
214
215 elif action == 'error':
215 elif action == 'error':
216 # TODO define proper error mechanism.
216 # TODO define proper error mechanism.
217 res.status = b'200 OK'
217 res.status = b'200 OK'
218 res.headers[b'Content-Type'] = b'text/plain'
218 res.headers[b'Content-Type'] = b'text/plain'
219 res.setbodybytes(meta['message'] + b'\n')
219 res.setbodybytes(meta['message'] + b'\n')
220 return
220 return
221 else:
221 else:
222 raise error.ProgrammingError(
222 raise error.ProgrammingError(
223 'unhandled action from frame processor: %s' % action)
223 'unhandled action from frame processor: %s' % action)
224
224
225 action, meta = reactor.oninputeof()
225 action, meta = reactor.oninputeof()
226 if action == 'sendframes':
226 if action == 'sendframes':
227 # We assume we haven't started sending the response yet. If we're
227 # We assume we haven't started sending the response yet. If we're
228 # wrong, the response type will raise an exception.
228 # wrong, the response type will raise an exception.
229 res.status = b'200 OK'
229 res.status = b'200 OK'
230 res.headers[b'Content-Type'] = FRAMINGTYPE
230 res.headers[b'Content-Type'] = FRAMINGTYPE
231 res.setbodygen(meta['framegen'])
231 res.setbodygen(meta['framegen'])
232 elif action == 'noop':
232 elif action == 'noop':
233 pass
233 pass
234 else:
234 else:
235 raise error.ProgrammingError('unhandled action from frame processor: %s'
235 raise error.ProgrammingError('unhandled action from frame processor: %s'
236 % action)
236 % action)
237
237
238 def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
238 def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
239 outstream, command, issubsequent):
239 outstream, command, issubsequent):
240 """Dispatch a wire protocol command made from HTTPv2 requests.
240 """Dispatch a wire protocol command made from HTTPv2 requests.
241
241
242 The authenticated permission (``authedperm``) along with the original
242 The authenticated permission (``authedperm``) along with the original
243 command from the URL (``reqcommand``) are passed in.
243 command from the URL (``reqcommand``) are passed in.
244 """
244 """
245 # We already validated that the session has permissions to perform the
245 # We already validated that the session has permissions to perform the
246 # actions in ``authedperm``. In the unified frame protocol, the canonical
246 # actions in ``authedperm``. In the unified frame protocol, the canonical
247 # command to run is expressed in a frame. However, the URL also requested
247 # command to run is expressed in a frame. However, the URL also requested
248 # to run a specific command. We need to be careful that the command we
248 # to run a specific command. We need to be careful that the command we
249 # run doesn't have permissions requirements greater than what was granted
249 # run doesn't have permissions requirements greater than what was granted
250 # by ``authedperm``.
250 # by ``authedperm``.
251 #
251 #
252 # Our rule for this is we only allow one command per HTTP request and
252 # Our rule for this is we only allow one command per HTTP request and
253 # that command must match the command in the URL. However, we make
253 # that command must match the command in the URL. However, we make
254 # an exception for the ``multirequest`` URL. This URL is allowed to
254 # an exception for the ``multirequest`` URL. This URL is allowed to
255 # execute multiple commands. We double check permissions of each command
255 # execute multiple commands. We double check permissions of each command
256 # as it is invoked to ensure there is no privilege escalation.
256 # as it is invoked to ensure there is no privilege escalation.
257 # TODO consider allowing multiple commands to regular command URLs
257 # TODO consider allowing multiple commands to regular command URLs
258 # iff each command is the same.
258 # iff each command is the same.
259
259
260 proto = httpv2protocolhandler(req, ui, args=command['args'])
260 proto = httpv2protocolhandler(req, ui, args=command['args'])
261
261
262 if reqcommand == b'multirequest':
262 if reqcommand == b'multirequest':
263 if not COMMANDS.commandavailable(command['command'], proto):
263 if not COMMANDS.commandavailable(command['command'], proto):
264 # TODO proper error mechanism
264 # TODO proper error mechanism
265 res.status = b'200 OK'
265 res.status = b'200 OK'
266 res.headers[b'Content-Type'] = b'text/plain'
266 res.headers[b'Content-Type'] = b'text/plain'
267 res.setbodybytes(_('wire protocol command not available: %s') %
267 res.setbodybytes(_('wire protocol command not available: %s') %
268 command['command'])
268 command['command'])
269 return True
269 return True
270
270
271 # TODO don't use assert here, since it may be elided by -O.
271 # TODO don't use assert here, since it may be elided by -O.
272 assert authedperm in (b'ro', b'rw')
272 assert authedperm in (b'ro', b'rw')
273 wirecommand = COMMANDS[command['command']]
273 wirecommand = COMMANDS[command['command']]
274 assert wirecommand.permission in ('push', 'pull')
274 assert wirecommand.permission in ('push', 'pull')
275
275
276 if authedperm == b'ro' and wirecommand.permission != 'pull':
276 if authedperm == b'ro' and wirecommand.permission != 'pull':
277 # TODO proper error mechanism
277 # TODO proper error mechanism
278 res.status = b'403 Forbidden'
278 res.status = b'403 Forbidden'
279 res.headers[b'Content-Type'] = b'text/plain'
279 res.headers[b'Content-Type'] = b'text/plain'
280 res.setbodybytes(_('insufficient permissions to execute '
280 res.setbodybytes(_('insufficient permissions to execute '
281 'command: %s') % command['command'])
281 'command: %s') % command['command'])
282 return True
282 return True
283
283
284 # TODO should we also call checkperm() here? Maybe not if we're going
284 # TODO should we also call checkperm() here? Maybe not if we're going
285 # to overhaul that API. The granted scope from the URL check should
285 # to overhaul that API. The granted scope from the URL check should
286 # be good enough.
286 # be good enough.
287
287
288 else:
288 else:
289 # Don't allow multiple commands outside of ``multirequest`` URL.
289 # Don't allow multiple commands outside of ``multirequest`` URL.
290 if issubsequent:
290 if issubsequent:
291 # TODO proper error mechanism
291 # TODO proper error mechanism
292 res.status = b'200 OK'
292 res.status = b'200 OK'
293 res.headers[b'Content-Type'] = b'text/plain'
293 res.headers[b'Content-Type'] = b'text/plain'
294 res.setbodybytes(_('multiple commands cannot be issued to this '
294 res.setbodybytes(_('multiple commands cannot be issued to this '
295 'URL'))
295 'URL'))
296 return True
296 return True
297
297
298 if reqcommand != command['command']:
298 if reqcommand != command['command']:
299 # TODO define proper error mechanism
299 # TODO define proper error mechanism
300 res.status = b'200 OK'
300 res.status = b'200 OK'
301 res.headers[b'Content-Type'] = b'text/plain'
301 res.headers[b'Content-Type'] = b'text/plain'
302 res.setbodybytes(_('command in frame must match command in URL'))
302 res.setbodybytes(_('command in frame must match command in URL'))
303 return True
303 return True
304
304
305 res.status = b'200 OK'
305 res.status = b'200 OK'
306 res.headers[b'Content-Type'] = FRAMINGTYPE
306 res.headers[b'Content-Type'] = FRAMINGTYPE
307
307
308 try:
308 try:
309 objs = dispatch(repo, proto, command['command'])
309 objs = dispatch(repo, proto, command['command'])
310
310
311 action, meta = reactor.oncommandresponsereadyobjects(
311 action, meta = reactor.oncommandresponsereadyobjects(
312 outstream, command['requestid'], objs)
312 outstream, command['requestid'], objs)
313
313
314 except Exception as e:
314 except Exception as e:
315 action, meta = reactor.onservererror(
315 action, meta = reactor.onservererror(
316 outstream, command['requestid'],
316 outstream, command['requestid'],
317 _('exception when invoking command: %s') % e)
317 _('exception when invoking command: %s') % e)
318
318
319 if action == 'sendframes':
319 if action == 'sendframes':
320 res.setbodygen(meta['framegen'])
320 res.setbodygen(meta['framegen'])
321 return True
321 return True
322 elif action == 'noop':
322 elif action == 'noop':
323 return False
323 return False
324 else:
324 else:
325 raise error.ProgrammingError('unhandled event from reactor: %s' %
325 raise error.ProgrammingError('unhandled event from reactor: %s' %
326 action)
326 action)
327
327
328 def getdispatchrepo(repo, proto, command):
328 def getdispatchrepo(repo, proto, command):
329 return repo.filtered('served')
329 return repo.filtered('served')
330
330
331 def dispatch(repo, proto, command):
331 def dispatch(repo, proto, command):
332 repo = getdispatchrepo(repo, proto, command)
332 repo = getdispatchrepo(repo, proto, command)
333
333
334 func, spec = COMMANDS[command]
334 func, spec = COMMANDS[command]
335 args = proto.getargs(spec)
335 args = proto.getargs(spec)
336
336
337 return func(repo, proto, **args)
337 return func(repo, proto, **args)
338
338
339 @interfaceutil.implementer(wireprototypes.baseprotocolhandler)
339 @interfaceutil.implementer(wireprototypes.baseprotocolhandler)
340 class httpv2protocolhandler(object):
340 class httpv2protocolhandler(object):
341 def __init__(self, req, ui, args=None):
341 def __init__(self, req, ui, args=None):
342 self._req = req
342 self._req = req
343 self._ui = ui
343 self._ui = ui
344 self._args = args
344 self._args = args
345
345
346 @property
346 @property
347 def name(self):
347 def name(self):
348 return HTTP_WIREPROTO_V2
348 return HTTP_WIREPROTO_V2
349
349
350 def getargs(self, args):
350 def getargs(self, args):
351 data = {}
351 data = {}
352 for k, typ in args.items():
352 for k, typ in args.items():
353 if k == '*':
353 if k == '*':
354 raise NotImplementedError('do not support * args')
354 raise NotImplementedError('do not support * args')
355 elif k in self._args:
355 elif k in self._args:
356 # TODO consider validating value types.
356 # TODO consider validating value types.
357 data[k] = self._args[k]
357 data[k] = self._args[k]
358
358
359 return data
359 return data
360
360
361 def getprotocaps(self):
361 def getprotocaps(self):
362 # Protocol capabilities are currently not implemented for HTTP V2.
362 # Protocol capabilities are currently not implemented for HTTP V2.
363 return set()
363 return set()
364
364
365 def getpayload(self):
365 def getpayload(self):
366 raise NotImplementedError
366 raise NotImplementedError
367
367
368 @contextlib.contextmanager
368 @contextlib.contextmanager
369 def mayberedirectstdio(self):
369 def mayberedirectstdio(self):
370 raise NotImplementedError
370 raise NotImplementedError
371
371
372 def client(self):
372 def client(self):
373 raise NotImplementedError
373 raise NotImplementedError
374
374
375 def addcapabilities(self, repo, caps):
375 def addcapabilities(self, repo, caps):
376 return caps
376 return caps
377
377
378 def checkperm(self, perm):
378 def checkperm(self, perm):
379 raise NotImplementedError
379 raise NotImplementedError
380
380
381 def httpv2apidescriptor(req, repo):
381 def httpv2apidescriptor(req, repo):
382 proto = httpv2protocolhandler(req, repo.ui)
382 proto = httpv2protocolhandler(req, repo.ui)
383
383
384 return _capabilitiesv2(repo, proto)
384 return _capabilitiesv2(repo, proto)
385
385
386 def _capabilitiesv2(repo, proto):
386 def _capabilitiesv2(repo, proto):
387 """Obtain the set of capabilities for version 2 transports.
387 """Obtain the set of capabilities for version 2 transports.
388
388
389 These capabilities are distinct from the capabilities for version 1
389 These capabilities are distinct from the capabilities for version 1
390 transports.
390 transports.
391 """
391 """
392 compression = []
392 compression = []
393 for engine in wireprototypes.supportedcompengines(repo.ui, util.SERVERROLE):
393 for engine in wireprototypes.supportedcompengines(repo.ui, util.SERVERROLE):
394 compression.append({
394 compression.append({
395 b'name': engine.wireprotosupport().name,
395 b'name': engine.wireprotosupport().name,
396 })
396 })
397
397
398 caps = {
398 caps = {
399 'commands': {},
399 'commands': {},
400 'compression': compression,
400 'compression': compression,
401 'framingmediatypes': [FRAMINGTYPE],
401 'framingmediatypes': [FRAMINGTYPE],
402 }
402 }
403
403
404 # TODO expose available changesetdata fields.
404 # TODO expose available changesetdata fields.
405
405
406 for command, entry in COMMANDS.items():
406 for command, entry in COMMANDS.items():
407 caps['commands'][command] = {
407 caps['commands'][command] = {
408 'args': entry.args,
408 'args': entry.args,
409 'permissions': [entry.permission],
409 'permissions': [entry.permission],
410 }
410 }
411
411
412 if streamclone.allowservergeneration(repo):
412 if streamclone.allowservergeneration(repo):
413 caps['rawrepoformats'] = sorted(repo.requirements &
413 caps['rawrepoformats'] = sorted(repo.requirements &
414 repo.supportedformats)
414 repo.supportedformats)
415
415
416 return proto.addcapabilities(repo, caps)
416 return proto.addcapabilities(repo, caps)
417
417
418 def builddeltarequests(store, nodes):
418 def builddeltarequests(store, nodes, haveparents):
419 """Build a series of revision delta requests against a backend store.
419 """Build a series of revision delta requests against a backend store.
420
420
421 Returns a list of revision numbers in the order they should be sent
421 Returns a list of revision numbers in the order they should be sent
422 and a list of ``irevisiondeltarequest`` instances to be made against
422 and a list of ``irevisiondeltarequest`` instances to be made against
423 the backend store.
423 the backend store.
424 """
424 """
425 # We sort and send nodes in DAG order because this is optimal for
425 # We sort and send nodes in DAG order because this is optimal for
426 # storage emission.
426 # storage emission.
427 # TODO we may want a better storage API here - one where we can throw
427 # TODO we may want a better storage API here - one where we can throw
428 # a list of nodes and delta preconditions over a figurative wall and
428 # a list of nodes and delta preconditions over a figurative wall and
429 # have the storage backend figure it out for us.
429 # have the storage backend figure it out for us.
430 revs = dagop.linearize({store.rev(n) for n in nodes}, store.parentrevs)
430 revs = dagop.linearize({store.rev(n) for n in nodes}, store.parentrevs)
431
431
432 requests = []
432 requests = []
433 seenrevs = set()
433
434
434 for rev in revs:
435 for rev in revs:
435 node = store.node(rev)
436 node = store.node(rev)
436 parents = store.parents(node)
437 parentnodes = store.parents(node)
437 deltaparent = store.node(store.deltaparent(rev))
438 parentrevs = [store.rev(n) for n in parentnodes]
439 deltabaserev = store.deltaparent(rev)
440 deltabasenode = store.node(deltabaserev)
438
441
439 # There is a delta in storage. That means we can send the delta
442 # The choice of whether to send a fulltext revision or a delta and
440 # efficiently.
443 # what delta to send is governed by a few factors.
441 #
444 #
442 # But, the delta may be against a revision the receiver doesn't
445 # To send a delta, we need to ensure the receiver is capable of
443 # have (e.g. shallow clone or when the delta isn't against a parent
446 # decoding it. And that requires the receiver to have the base
444 # revision). For now, we ignore the problem of shallow clone. As
447 # revision the delta is against.
445 # long as a delta exists against a parent, we send it.
448 #
446 # TODO allow arguments to control this behavior, as the receiver
449 # We can only guarantee the receiver has the base revision if
447 # may not have the base revision in some scenarios.
450 # a) we've already sent the revision as part of this group
448 if deltaparent != nullid and deltaparent in parents:
451 # b) the receiver has indicated they already have the revision.
449 basenode = deltaparent
452 # And the mechanism for "b" is the client indicating they have
453 # parent revisions. So this means we can only send the delta if
454 # it is sent before or it is against a delta and the receiver says
455 # they have a parent.
450
456
451 # Else there is no delta parent in storage or the delta that is
457 # We can send storage delta if it is against a revision we've sent
452 # # there isn't suitable. Let's use a delta against a parent
458 # in this group.
453 # revision, if possible.
459 if deltabaserev != nullrev and deltabaserev in seenrevs:
454 #
460 basenode = deltabasenode
455 # There is room to check if the delta parent is in the ancestry of
461
456 # this node. But there isn't an API on the manifest storage object
462 # We can send storage delta if it is against a parent revision and
457 # for that. So ignore this case for now.
463 # the receiver indicates they have the parents.
464 elif (deltabaserev != nullrev and deltabaserev in parentrevs
465 and haveparents):
466 basenode = deltabasenode
458
467
459 elif parents[0] != nullid:
468 # Otherwise the storage delta isn't appropriate. Fall back to
460 basenode = parents[0]
469 # using another delta, if possible.
461 elif parents[1] != nullid:
462 basenode = parents[1]
463
470
464 # No potential bases to delta against. Send a full revision.
471 # Use p1 if we've emitted it or receiver says they have it.
472 elif parentrevs[0] != nullrev and (
473 parentrevs[0] in seenrevs or haveparents):
474 basenode = parentnodes[0]
475
476 # Use p2 if we've emitted it or receiver says they have it.
477 elif parentrevs[1] != nullrev and (
478 parentrevs[1] in seenrevs or haveparents):
479 basenode = parentnodes[1]
480
481 # Nothing appropriate to delta against. Send the full revision.
465 else:
482 else:
466 basenode = nullid
483 basenode = nullid
467
484
468 requests.append(changegroup.revisiondeltarequest(
485 requests.append(changegroup.revisiondeltarequest(
469 node=node,
486 node=node,
470 p1node=parents[0],
487 p1node=parentnodes[0],
471 p2node=parents[1],
488 p2node=parentnodes[1],
472 # Receiver deals with linknode resolution.
489 # Receiver deals with linknode resolution.
473 linknode=nullid,
490 linknode=nullid,
474 basenode=basenode,
491 basenode=basenode,
475 ))
492 ))
476
493
494 seenrevs.add(rev)
495
477 return revs, requests
496 return revs, requests
478
497
479 def wireprotocommand(name, args=None, permission='push'):
498 def wireprotocommand(name, args=None, permission='push'):
480 """Decorator to declare a wire protocol command.
499 """Decorator to declare a wire protocol command.
481
500
482 ``name`` is the name of the wire protocol command being provided.
501 ``name`` is the name of the wire protocol command being provided.
483
502
484 ``args`` is a dict of argument names to example values.
503 ``args`` is a dict of argument names to example values.
485
504
486 ``permission`` defines the permission type needed to run this command.
505 ``permission`` defines the permission type needed to run this command.
487 Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
506 Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
488 respectively. Default is to assume command requires ``push`` permissions
507 respectively. Default is to assume command requires ``push`` permissions
489 because otherwise commands not declaring their permissions could modify
508 because otherwise commands not declaring their permissions could modify
490 a repository that is supposed to be read-only.
509 a repository that is supposed to be read-only.
491
510
492 Wire protocol commands are generators of objects to be serialized and
511 Wire protocol commands are generators of objects to be serialized and
493 sent to the client.
512 sent to the client.
494
513
495 If a command raises an uncaught exception, this will be translated into
514 If a command raises an uncaught exception, this will be translated into
496 a command error.
515 a command error.
497 """
516 """
498 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
517 transports = {k for k, v in wireprototypes.TRANSPORTS.items()
499 if v['version'] == 2}
518 if v['version'] == 2}
500
519
501 if permission not in ('push', 'pull'):
520 if permission not in ('push', 'pull'):
502 raise error.ProgrammingError('invalid wire protocol permission; '
521 raise error.ProgrammingError('invalid wire protocol permission; '
503 'got %s; expected "push" or "pull"' %
522 'got %s; expected "push" or "pull"' %
504 permission)
523 permission)
505
524
506 if args is None:
525 if args is None:
507 args = {}
526 args = {}
508
527
509 if not isinstance(args, dict):
528 if not isinstance(args, dict):
510 raise error.ProgrammingError('arguments for version 2 commands '
529 raise error.ProgrammingError('arguments for version 2 commands '
511 'must be declared as dicts')
530 'must be declared as dicts')
512
531
513 def register(func):
532 def register(func):
514 if name in COMMANDS:
533 if name in COMMANDS:
515 raise error.ProgrammingError('%s command already registered '
534 raise error.ProgrammingError('%s command already registered '
516 'for version 2' % name)
535 'for version 2' % name)
517
536
518 COMMANDS[name] = wireprototypes.commandentry(
537 COMMANDS[name] = wireprototypes.commandentry(
519 func, args=args, transports=transports, permission=permission)
538 func, args=args, transports=transports, permission=permission)
520
539
521 return func
540 return func
522
541
523 return register
542 return register
524
543
525 @wireprotocommand('branchmap', permission='pull')
544 @wireprotocommand('branchmap', permission='pull')
526 def branchmapv2(repo, proto):
545 def branchmapv2(repo, proto):
527 yield {encoding.fromlocal(k): v
546 yield {encoding.fromlocal(k): v
528 for k, v in repo.branchmap().iteritems()}
547 for k, v in repo.branchmap().iteritems()}
529
548
530 @wireprotocommand('capabilities', permission='pull')
549 @wireprotocommand('capabilities', permission='pull')
531 def capabilitiesv2(repo, proto):
550 def capabilitiesv2(repo, proto):
532 yield _capabilitiesv2(repo, proto)
551 yield _capabilitiesv2(repo, proto)
533
552
534 @wireprotocommand('changesetdata',
553 @wireprotocommand('changesetdata',
535 args={
554 args={
536 'noderange': [[b'0123456...'], [b'abcdef...']],
555 'noderange': [[b'0123456...'], [b'abcdef...']],
537 'nodes': [b'0123456...'],
556 'nodes': [b'0123456...'],
538 'fields': {b'parents', b'revision'},
557 'fields': {b'parents', b'revision'},
539 },
558 },
540 permission='pull')
559 permission='pull')
541 def changesetdata(repo, proto, noderange=None, nodes=None, fields=None):
560 def changesetdata(repo, proto, noderange=None, nodes=None, fields=None):
542 fields = fields or set()
561 fields = fields or set()
543
562
544 # TODO look for unknown fields and abort when they can't be serviced.
563 # TODO look for unknown fields and abort when they can't be serviced.
545
564
546 if noderange is None and nodes is None:
565 if noderange is None and nodes is None:
547 raise error.WireprotoCommandError(
566 raise error.WireprotoCommandError(
548 'noderange or nodes must be defined')
567 'noderange or nodes must be defined')
549
568
550 if noderange is not None:
569 if noderange is not None:
551 if len(noderange) != 2:
570 if len(noderange) != 2:
552 raise error.WireprotoCommandError(
571 raise error.WireprotoCommandError(
553 'noderange must consist of 2 elements')
572 'noderange must consist of 2 elements')
554
573
555 if not noderange[1]:
574 if not noderange[1]:
556 raise error.WireprotoCommandError(
575 raise error.WireprotoCommandError(
557 'heads in noderange request cannot be empty')
576 'heads in noderange request cannot be empty')
558
577
559 cl = repo.changelog
578 cl = repo.changelog
560 hasnode = cl.hasnode
579 hasnode = cl.hasnode
561
580
562 seen = set()
581 seen = set()
563 outgoing = []
582 outgoing = []
564
583
565 if nodes is not None:
584 if nodes is not None:
566 outgoing.extend(n for n in nodes if hasnode(n))
585 outgoing.extend(n for n in nodes if hasnode(n))
567 seen |= set(outgoing)
586 seen |= set(outgoing)
568
587
569 if noderange is not None:
588 if noderange is not None:
570 if noderange[0]:
589 if noderange[0]:
571 common = [n for n in noderange[0] if hasnode(n)]
590 common = [n for n in noderange[0] if hasnode(n)]
572 else:
591 else:
573 common = [nullid]
592 common = [nullid]
574
593
575 for n in discovery.outgoing(repo, common, noderange[1]).missing:
594 for n in discovery.outgoing(repo, common, noderange[1]).missing:
576 if n not in seen:
595 if n not in seen:
577 outgoing.append(n)
596 outgoing.append(n)
578 # Don't need to add to seen here because this is the final
597 # Don't need to add to seen here because this is the final
579 # source of nodes and there should be no duplicates in this
598 # source of nodes and there should be no duplicates in this
580 # list.
599 # list.
581
600
582 seen.clear()
601 seen.clear()
583 publishing = repo.publishing()
602 publishing = repo.publishing()
584
603
585 if outgoing:
604 if outgoing:
586 repo.hook('preoutgoing', throw=True, source='serve')
605 repo.hook('preoutgoing', throw=True, source='serve')
587
606
588 yield {
607 yield {
589 b'totalitems': len(outgoing),
608 b'totalitems': len(outgoing),
590 }
609 }
591
610
592 # The phases of nodes already transferred to the client may have changed
611 # The phases of nodes already transferred to the client may have changed
593 # since the client last requested data. We send phase-only records
612 # since the client last requested data. We send phase-only records
594 # for these revisions, if requested.
613 # for these revisions, if requested.
595 if b'phase' in fields and noderange is not None:
614 if b'phase' in fields and noderange is not None:
596 # TODO skip nodes whose phase will be reflected by a node in the
615 # TODO skip nodes whose phase will be reflected by a node in the
597 # outgoing set. This is purely an optimization to reduce data
616 # outgoing set. This is purely an optimization to reduce data
598 # size.
617 # size.
599 for node in noderange[0]:
618 for node in noderange[0]:
600 yield {
619 yield {
601 b'node': node,
620 b'node': node,
602 b'phase': b'public' if publishing else repo[node].phasestr()
621 b'phase': b'public' if publishing else repo[node].phasestr()
603 }
622 }
604
623
605 nodebookmarks = {}
624 nodebookmarks = {}
606 for mark, node in repo._bookmarks.items():
625 for mark, node in repo._bookmarks.items():
607 nodebookmarks.setdefault(node, set()).add(mark)
626 nodebookmarks.setdefault(node, set()).add(mark)
608
627
609 # It is already topologically sorted by revision number.
628 # It is already topologically sorted by revision number.
610 for node in outgoing:
629 for node in outgoing:
611 d = {
630 d = {
612 b'node': node,
631 b'node': node,
613 }
632 }
614
633
615 if b'parents' in fields:
634 if b'parents' in fields:
616 d[b'parents'] = cl.parents(node)
635 d[b'parents'] = cl.parents(node)
617
636
618 if b'phase' in fields:
637 if b'phase' in fields:
619 if publishing:
638 if publishing:
620 d[b'phase'] = b'public'
639 d[b'phase'] = b'public'
621 else:
640 else:
622 ctx = repo[node]
641 ctx = repo[node]
623 d[b'phase'] = ctx.phasestr()
642 d[b'phase'] = ctx.phasestr()
624
643
625 if b'bookmarks' in fields and node in nodebookmarks:
644 if b'bookmarks' in fields and node in nodebookmarks:
626 d[b'bookmarks'] = sorted(nodebookmarks[node])
645 d[b'bookmarks'] = sorted(nodebookmarks[node])
627 del nodebookmarks[node]
646 del nodebookmarks[node]
628
647
629 revisiondata = None
648 revisiondata = None
630
649
631 if b'revision' in fields:
650 if b'revision' in fields:
632 revisiondata = cl.revision(node, raw=True)
651 revisiondata = cl.revision(node, raw=True)
633 d[b'revisionsize'] = len(revisiondata)
652 d[b'revisionsize'] = len(revisiondata)
634
653
635 # TODO make it possible for extensions to wrap a function or register
654 # TODO make it possible for extensions to wrap a function or register
636 # a handler to service custom fields.
655 # a handler to service custom fields.
637
656
638 yield d
657 yield d
639
658
640 if revisiondata is not None:
659 if revisiondata is not None:
641 yield revisiondata
660 yield revisiondata
642
661
643 # If requested, send bookmarks from nodes that didn't have revision
662 # If requested, send bookmarks from nodes that didn't have revision
644 # data sent so receiver is aware of any bookmark updates.
663 # data sent so receiver is aware of any bookmark updates.
645 if b'bookmarks' in fields:
664 if b'bookmarks' in fields:
646 for node, marks in sorted(nodebookmarks.iteritems()):
665 for node, marks in sorted(nodebookmarks.iteritems()):
647 yield {
666 yield {
648 b'node': node,
667 b'node': node,
649 b'bookmarks': sorted(marks),
668 b'bookmarks': sorted(marks),
650 }
669 }
651
670
652 class FileAccessError(Exception):
671 class FileAccessError(Exception):
653 """Represents an error accessing a specific file."""
672 """Represents an error accessing a specific file."""
654
673
655 def __init__(self, path, msg, args):
674 def __init__(self, path, msg, args):
656 self.path = path
675 self.path = path
657 self.msg = msg
676 self.msg = msg
658 self.args = args
677 self.args = args
659
678
660 def getfilestore(repo, proto, path):
679 def getfilestore(repo, proto, path):
661 """Obtain a file storage object for use with wire protocol.
680 """Obtain a file storage object for use with wire protocol.
662
681
663 Exists as a standalone function so extensions can monkeypatch to add
682 Exists as a standalone function so extensions can monkeypatch to add
664 access control.
683 access control.
665 """
684 """
666 # This seems to work even if the file doesn't exist. So catch
685 # This seems to work even if the file doesn't exist. So catch
667 # "empty" files and return an error.
686 # "empty" files and return an error.
668 fl = repo.file(path)
687 fl = repo.file(path)
669
688
670 if not len(fl):
689 if not len(fl):
671 raise FileAccessError(path, 'unknown file: %s', (path,))
690 raise FileAccessError(path, 'unknown file: %s', (path,))
672
691
673 return fl
692 return fl
674
693
675 @wireprotocommand('filedata',
694 @wireprotocommand('filedata',
676 args={
695 args={
696 'haveparents': True,
677 'nodes': [b'0123456...'],
697 'nodes': [b'0123456...'],
678 'fields': [b'parents', b'revision'],
698 'fields': [b'parents', b'revision'],
679 'path': b'foo.txt',
699 'path': b'foo.txt',
680 },
700 },
681 permission='pull')
701 permission='pull')
682 def filedata(repo, proto, nodes=None, fields=None, path=None):
702 def filedata(repo, proto, haveparents=False, nodes=None, fields=None,
703 path=None):
683 fields = fields or set()
704 fields = fields or set()
684
705
685 if nodes is None:
706 if nodes is None:
686 raise error.WireprotoCommandError('nodes argument must be defined')
707 raise error.WireprotoCommandError('nodes argument must be defined')
687
708
688 if path is None:
709 if path is None:
689 raise error.WireprotoCommandError('path argument must be defined')
710 raise error.WireprotoCommandError('path argument must be defined')
690
711
691 try:
712 try:
692 # Extensions may wish to access the protocol handler.
713 # Extensions may wish to access the protocol handler.
693 store = getfilestore(repo, proto, path)
714 store = getfilestore(repo, proto, path)
694 except FileAccessError as e:
715 except FileAccessError as e:
695 raise error.WireprotoCommandError(e.msg, e.args)
716 raise error.WireprotoCommandError(e.msg, e.args)
696
717
697 # Validate requested nodes.
718 # Validate requested nodes.
698 for node in nodes:
719 for node in nodes:
699 try:
720 try:
700 store.rev(node)
721 store.rev(node)
701 except error.LookupError:
722 except error.LookupError:
702 raise error.WireprotoCommandError('unknown file node: %s',
723 raise error.WireprotoCommandError('unknown file node: %s',
703 (hex(node),))
724 (hex(node),))
704
725
705 revs, requests = builddeltarequests(store, nodes)
726 revs, requests = builddeltarequests(store, nodes, haveparents)
706
727
707 yield {
728 yield {
708 b'totalitems': len(revs),
729 b'totalitems': len(revs),
709 }
730 }
710
731
711 if b'revision' in fields:
732 if b'revision' in fields:
712 deltas = store.emitrevisiondeltas(requests)
733 deltas = store.emitrevisiondeltas(requests)
713 else:
734 else:
714 deltas = None
735 deltas = None
715
736
716 for rev in revs:
737 for rev in revs:
717 node = store.node(rev)
738 node = store.node(rev)
718
739
719 if deltas is not None:
740 if deltas is not None:
720 delta = next(deltas)
741 delta = next(deltas)
721 else:
742 else:
722 delta = None
743 delta = None
723
744
724 d = {
745 d = {
725 b'node': node,
746 b'node': node,
726 }
747 }
727
748
728 if b'parents' in fields:
749 if b'parents' in fields:
729 d[b'parents'] = store.parents(node)
750 d[b'parents'] = store.parents(node)
730
751
731 if b'revision' in fields:
752 if b'revision' in fields:
732 assert delta is not None
753 assert delta is not None
733 assert delta.flags == 0
754 assert delta.flags == 0
734 assert d[b'node'] == delta.node
755 assert d[b'node'] == delta.node
735
756
736 if delta.revision is not None:
757 if delta.revision is not None:
737 revisiondata = delta.revision
758 revisiondata = delta.revision
738 d[b'revisionsize'] = len(revisiondata)
759 d[b'revisionsize'] = len(revisiondata)
739 else:
760 else:
740 d[b'deltabasenode'] = delta.basenode
761 d[b'deltabasenode'] = delta.basenode
741 revisiondata = delta.delta
762 revisiondata = delta.delta
742 d[b'deltasize'] = len(revisiondata)
763 d[b'deltasize'] = len(revisiondata)
743 else:
764 else:
744 revisiondata = None
765 revisiondata = None
745
766
746 yield d
767 yield d
747
768
748 if revisiondata is not None:
769 if revisiondata is not None:
749 yield revisiondata
770 yield revisiondata
750
771
751 if deltas is not None:
772 if deltas is not None:
752 try:
773 try:
753 next(deltas)
774 next(deltas)
754 raise error.ProgrammingError('should not have more deltas')
775 raise error.ProgrammingError('should not have more deltas')
755 except GeneratorExit:
776 except GeneratorExit:
756 pass
777 pass
757
778
758 @wireprotocommand('heads',
779 @wireprotocommand('heads',
759 args={
780 args={
760 'publiconly': False,
781 'publiconly': False,
761 },
782 },
762 permission='pull')
783 permission='pull')
763 def headsv2(repo, proto, publiconly=False):
784 def headsv2(repo, proto, publiconly=False):
764 if publiconly:
785 if publiconly:
765 repo = repo.filtered('immutable')
786 repo = repo.filtered('immutable')
766
787
767 yield repo.heads()
788 yield repo.heads()
768
789
769 @wireprotocommand('known',
790 @wireprotocommand('known',
770 args={
791 args={
771 'nodes': [b'deadbeef'],
792 'nodes': [b'deadbeef'],
772 },
793 },
773 permission='pull')
794 permission='pull')
774 def knownv2(repo, proto, nodes=None):
795 def knownv2(repo, proto, nodes=None):
775 nodes = nodes or []
796 nodes = nodes or []
776 result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
797 result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
777 yield result
798 yield result
778
799
779 @wireprotocommand('listkeys',
800 @wireprotocommand('listkeys',
780 args={
801 args={
781 'namespace': b'ns',
802 'namespace': b'ns',
782 },
803 },
783 permission='pull')
804 permission='pull')
784 def listkeysv2(repo, proto, namespace=None):
805 def listkeysv2(repo, proto, namespace=None):
785 keys = repo.listkeys(encoding.tolocal(namespace))
806 keys = repo.listkeys(encoding.tolocal(namespace))
786 keys = {encoding.fromlocal(k): encoding.fromlocal(v)
807 keys = {encoding.fromlocal(k): encoding.fromlocal(v)
787 for k, v in keys.iteritems()}
808 for k, v in keys.iteritems()}
788
809
789 yield keys
810 yield keys
790
811
791 @wireprotocommand('lookup',
812 @wireprotocommand('lookup',
792 args={
813 args={
793 'key': b'foo',
814 'key': b'foo',
794 },
815 },
795 permission='pull')
816 permission='pull')
796 def lookupv2(repo, proto, key):
817 def lookupv2(repo, proto, key):
797 key = encoding.tolocal(key)
818 key = encoding.tolocal(key)
798
819
799 # TODO handle exception.
820 # TODO handle exception.
800 node = repo.lookup(key)
821 node = repo.lookup(key)
801
822
802 yield node
823 yield node
803
824
804 @wireprotocommand('manifestdata',
825 @wireprotocommand('manifestdata',
805 args={
826 args={
806 'nodes': [b'0123456...'],
827 'nodes': [b'0123456...'],
828 'haveparents': True,
807 'fields': [b'parents', b'revision'],
829 'fields': [b'parents', b'revision'],
808 'tree': b'',
830 'tree': b'',
809 },
831 },
810 permission='pull')
832 permission='pull')
811 def manifestdata(repo, proto, nodes=None, fields=None, tree=None):
833 def manifestdata(repo, proto, haveparents=False, nodes=None, fields=None,
834 tree=None):
812 fields = fields or set()
835 fields = fields or set()
813
836
814 if nodes is None:
837 if nodes is None:
815 raise error.WireprotoCommandError(
838 raise error.WireprotoCommandError(
816 'nodes argument must be defined')
839 'nodes argument must be defined')
817
840
818 if tree is None:
841 if tree is None:
819 raise error.WireprotoCommandError(
842 raise error.WireprotoCommandError(
820 'tree argument must be defined')
843 'tree argument must be defined')
821
844
822 store = repo.manifestlog.getstorage(tree)
845 store = repo.manifestlog.getstorage(tree)
823
846
824 # Validate the node is known and abort on unknown revisions.
847 # Validate the node is known and abort on unknown revisions.
825 for node in nodes:
848 for node in nodes:
826 try:
849 try:
827 store.rev(node)
850 store.rev(node)
828 except error.LookupError:
851 except error.LookupError:
829 raise error.WireprotoCommandError(
852 raise error.WireprotoCommandError(
830 'unknown node: %s', (node,))
853 'unknown node: %s', (node,))
831
854
832 revs, requests = builddeltarequests(store, nodes)
855 revs, requests = builddeltarequests(store, nodes, haveparents)
833
856
834 yield {
857 yield {
835 b'totalitems': len(revs),
858 b'totalitems': len(revs),
836 }
859 }
837
860
838 if b'revision' in fields:
861 if b'revision' in fields:
839 deltas = store.emitrevisiondeltas(requests)
862 deltas = store.emitrevisiondeltas(requests)
840 else:
863 else:
841 deltas = None
864 deltas = None
842
865
843 for rev in revs:
866 for rev in revs:
844 node = store.node(rev)
867 node = store.node(rev)
845
868
846 if deltas is not None:
869 if deltas is not None:
847 delta = next(deltas)
870 delta = next(deltas)
848 else:
871 else:
849 delta = None
872 delta = None
850
873
851 d = {
874 d = {
852 b'node': node,
875 b'node': node,
853 }
876 }
854
877
855 if b'parents' in fields:
878 if b'parents' in fields:
856 d[b'parents'] = store.parents(node)
879 d[b'parents'] = store.parents(node)
857
880
858 if b'revision' in fields:
881 if b'revision' in fields:
859 assert delta is not None
882 assert delta is not None
860 assert delta.flags == 0
883 assert delta.flags == 0
861 assert d[b'node'] == delta.node
884 assert d[b'node'] == delta.node
862
885
863 if delta.revision is not None:
886 if delta.revision is not None:
864 revisiondata = delta.revision
887 revisiondata = delta.revision
865 d[b'revisionsize'] = len(revisiondata)
888 d[b'revisionsize'] = len(revisiondata)
866 else:
889 else:
867 d[b'deltabasenode'] = delta.basenode
890 d[b'deltabasenode'] = delta.basenode
868 revisiondata = delta.delta
891 revisiondata = delta.delta
869 d[b'deltasize'] = len(revisiondata)
892 d[b'deltasize'] = len(revisiondata)
870 else:
893 else:
871 revisiondata = None
894 revisiondata = None
872
895
873 yield d
896 yield d
874
897
875 if revisiondata is not None:
898 if revisiondata is not None:
876 yield revisiondata
899 yield revisiondata
877
900
878 if deltas is not None:
901 if deltas is not None:
879 try:
902 try:
880 next(deltas)
903 next(deltas)
881 raise error.ProgrammingError('should not have more deltas')
904 raise error.ProgrammingError('should not have more deltas')
882 except GeneratorExit:
905 except GeneratorExit:
883 pass
906 pass
884
907
885 @wireprotocommand('pushkey',
908 @wireprotocommand('pushkey',
886 args={
909 args={
887 'namespace': b'ns',
910 'namespace': b'ns',
888 'key': b'key',
911 'key': b'key',
889 'old': b'old',
912 'old': b'old',
890 'new': b'new',
913 'new': b'new',
891 },
914 },
892 permission='push')
915 permission='push')
893 def pushkeyv2(repo, proto, namespace, key, old, new):
916 def pushkeyv2(repo, proto, namespace, key, old, new):
894 # TODO handle ui output redirection
917 # TODO handle ui output redirection
895 yield repo.pushkey(encoding.tolocal(namespace),
918 yield repo.pushkey(encoding.tolocal(namespace),
896 encoding.tolocal(key),
919 encoding.tolocal(key),
897 encoding.tolocal(old),
920 encoding.tolocal(old),
898 encoding.tolocal(new))
921 encoding.tolocal(new))
@@ -1,749 +1,749
1 #require no-chg
1 #require no-chg
2
2
3 $ . $TESTDIR/wireprotohelpers.sh
3 $ . $TESTDIR/wireprotohelpers.sh
4
4
5 $ cat >> $HGRCPATH << EOF
5 $ cat >> $HGRCPATH << EOF
6 > [web]
6 > [web]
7 > push_ssl = false
7 > push_ssl = false
8 > allow_push = *
8 > allow_push = *
9 > EOF
9 > EOF
10
10
11 $ hg init server
11 $ hg init server
12 $ cd server
12 $ cd server
13 $ touch a
13 $ touch a
14 $ hg -q commit -A -m initial
14 $ hg -q commit -A -m initial
15 $ cd ..
15 $ cd ..
16
16
17 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
17 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
18 $ cat hg.pid >> $DAEMON_PIDS
18 $ cat hg.pid >> $DAEMON_PIDS
19
19
20 compression formats are advertised in compression capability
20 compression formats are advertised in compression capability
21
21
22 #if zstd
22 #if zstd
23 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zstd,zlib$' > /dev/null
23 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zstd,zlib$' > /dev/null
24 #else
24 #else
25 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zlib$' > /dev/null
25 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zlib$' > /dev/null
26 #endif
26 #endif
27
27
28 $ killdaemons.py
28 $ killdaemons.py
29
29
30 server.compressionengines can replace engines list wholesale
30 server.compressionengines can replace engines list wholesale
31
31
32 $ hg serve --config server.compressionengines=none -R server -p $HGPORT -d --pid-file hg.pid
32 $ hg serve --config server.compressionengines=none -R server -p $HGPORT -d --pid-file hg.pid
33 $ cat hg.pid > $DAEMON_PIDS
33 $ cat hg.pid > $DAEMON_PIDS
34 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none$' > /dev/null
34 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none$' > /dev/null
35
35
36 $ killdaemons.py
36 $ killdaemons.py
37
37
38 Order of engines can also change
38 Order of engines can also change
39
39
40 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
40 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
41 $ cat hg.pid > $DAEMON_PIDS
41 $ cat hg.pid > $DAEMON_PIDS
42 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none,zlib$' > /dev/null
42 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none,zlib$' > /dev/null
43
43
44 $ killdaemons.py
44 $ killdaemons.py
45
45
46 Start a default server again
46 Start a default server again
47
47
48 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
48 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
49 $ cat hg.pid > $DAEMON_PIDS
49 $ cat hg.pid > $DAEMON_PIDS
50
50
51 Server should send application/mercurial-0.1 to clients if no Accept is used
51 Server should send application/mercurial-0.1 to clients if no Accept is used
52
52
53 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
53 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
54 200 Script output follows
54 200 Script output follows
55 content-type: application/mercurial-0.1
55 content-type: application/mercurial-0.1
56 date: $HTTP_DATE$
56 date: $HTTP_DATE$
57 server: testing stub value
57 server: testing stub value
58 transfer-encoding: chunked
58 transfer-encoding: chunked
59
59
60 Server should send application/mercurial-0.1 when client says it wants it
60 Server should send application/mercurial-0.1 when client says it wants it
61
61
62 $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
62 $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
63 200 Script output follows
63 200 Script output follows
64 content-type: application/mercurial-0.1
64 content-type: application/mercurial-0.1
65 date: $HTTP_DATE$
65 date: $HTTP_DATE$
66 server: testing stub value
66 server: testing stub value
67 transfer-encoding: chunked
67 transfer-encoding: chunked
68
68
69 Server should send application/mercurial-0.2 when client says it wants it
69 Server should send application/mercurial-0.2 when client says it wants it
70
70
71 $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
71 $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
72 200 Script output follows
72 200 Script output follows
73 content-type: application/mercurial-0.2
73 content-type: application/mercurial-0.2
74 date: $HTTP_DATE$
74 date: $HTTP_DATE$
75 server: testing stub value
75 server: testing stub value
76 transfer-encoding: chunked
76 transfer-encoding: chunked
77
77
78 $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
78 $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
79 200 Script output follows
79 200 Script output follows
80 content-type: application/mercurial-0.2
80 content-type: application/mercurial-0.2
81 date: $HTTP_DATE$
81 date: $HTTP_DATE$
82 server: testing stub value
82 server: testing stub value
83 transfer-encoding: chunked
83 transfer-encoding: chunked
84
84
85 Requesting a compression format that server doesn't support results will fall back to 0.1
85 Requesting a compression format that server doesn't support results will fall back to 0.1
86
86
87 $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
87 $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
88 200 Script output follows
88 200 Script output follows
89 content-type: application/mercurial-0.1
89 content-type: application/mercurial-0.1
90 date: $HTTP_DATE$
90 date: $HTTP_DATE$
91 server: testing stub value
91 server: testing stub value
92 transfer-encoding: chunked
92 transfer-encoding: chunked
93
93
94 #if zstd
94 #if zstd
95 zstd is used if available
95 zstd is used if available
96
96
97 $ get-with-headers.py --hgproto '0.2 comp=zstd' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
97 $ get-with-headers.py --hgproto '0.2 comp=zstd' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
98 $ f --size --hexdump --bytes 36 --sha1 resp
98 $ f --size --hexdump --bytes 36 --sha1 resp
99 resp: size=248, sha1=4d8d8f87fb82bd542ce52881fdc94f850748
99 resp: size=248, sha1=4d8d8f87fb82bd542ce52881fdc94f850748
100 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
100 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
101 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 73 74 64 |t follows...zstd|
101 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 73 74 64 |t follows...zstd|
102 0020: 28 b5 2f fd |(./.|
102 0020: 28 b5 2f fd |(./.|
103
103
104 #endif
104 #endif
105
105
106 application/mercurial-0.2 is not yet used on non-streaming responses
106 application/mercurial-0.2 is not yet used on non-streaming responses
107
107
108 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=heads' -
108 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=heads' -
109 200 Script output follows
109 200 Script output follows
110 content-length: 41
110 content-length: 41
111 content-type: application/mercurial-0.1
111 content-type: application/mercurial-0.1
112 date: $HTTP_DATE$
112 date: $HTTP_DATE$
113 server: testing stub value
113 server: testing stub value
114
114
115 e93700bd72895c5addab234c56d4024b487a362f
115 e93700bd72895c5addab234c56d4024b487a362f
116
116
117 Now test protocol preference usage
117 Now test protocol preference usage
118
118
119 $ killdaemons.py
119 $ killdaemons.py
120 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
120 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
121 $ cat hg.pid > $DAEMON_PIDS
121 $ cat hg.pid > $DAEMON_PIDS
122
122
123 No Accept will send 0.1+zlib, even though "none" is preferred b/c "none" isn't supported on 0.1
123 No Accept will send 0.1+zlib, even though "none" is preferred b/c "none" isn't supported on 0.1
124
124
125 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' Content-Type
125 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' Content-Type
126 200 Script output follows
126 200 Script output follows
127 content-type: application/mercurial-0.1
127 content-type: application/mercurial-0.1
128
128
129 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
129 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
130 $ f --size --hexdump --bytes 28 --sha1 resp
130 $ f --size --hexdump --bytes 28 --sha1 resp
131 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
131 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
132 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
132 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
133 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
133 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
134
134
135 Explicit 0.1 will send zlib because "none" isn't supported on 0.1
135 Explicit 0.1 will send zlib because "none" isn't supported on 0.1
136
136
137 $ get-with-headers.py --hgproto '0.1' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
137 $ get-with-headers.py --hgproto '0.1' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
138 $ f --size --hexdump --bytes 28 --sha1 resp
138 $ f --size --hexdump --bytes 28 --sha1 resp
139 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
139 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
140 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
140 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
141 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
141 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
142
142
143 0.2 with no compression will get "none" because that is server's preference
143 0.2 with no compression will get "none" because that is server's preference
144 (spec says ZL and UN are implicitly supported)
144 (spec says ZL and UN are implicitly supported)
145
145
146 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
146 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
147 $ f --size --hexdump --bytes 32 --sha1 resp
147 $ f --size --hexdump --bytes 32 --sha1 resp
148 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
148 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
149 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
149 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
150 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
150 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
151
151
152 Client receives server preference even if local order doesn't match
152 Client receives server preference even if local order doesn't match
153
153
154 $ get-with-headers.py --hgproto '0.2 comp=zlib,none' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
154 $ get-with-headers.py --hgproto '0.2 comp=zlib,none' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
155 $ f --size --hexdump --bytes 32 --sha1 resp
155 $ f --size --hexdump --bytes 32 --sha1 resp
156 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
156 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
157 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
157 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
158 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
158 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
159
159
160 Client receives only supported format even if not server preferred format
160 Client receives only supported format even if not server preferred format
161
161
162 $ get-with-headers.py --hgproto '0.2 comp=zlib' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
162 $ get-with-headers.py --hgproto '0.2 comp=zlib' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
163 $ f --size --hexdump --bytes 33 --sha1 resp
163 $ f --size --hexdump --bytes 33 --sha1 resp
164 resp: size=232, sha1=a1c727f0c9693ca15742a75c30419bc36
164 resp: size=232, sha1=a1c727f0c9693ca15742a75c30419bc36
165 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
165 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
166 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
166 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
167 0020: 78 |x|
167 0020: 78 |x|
168
168
169 $ killdaemons.py
169 $ killdaemons.py
170 $ cd ..
170 $ cd ..
171
171
172 Test listkeys for listing namespaces
172 Test listkeys for listing namespaces
173
173
174 $ hg init empty
174 $ hg init empty
175 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
175 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
176 $ cat hg.pid > $DAEMON_PIDS
176 $ cat hg.pid > $DAEMON_PIDS
177
177
178 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
178 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
179 > command listkeys
179 > command listkeys
180 > namespace namespaces
180 > namespace namespaces
181 > EOF
181 > EOF
182 s> GET /?cmd=capabilities HTTP/1.1\r\n
182 s> GET /?cmd=capabilities HTTP/1.1\r\n
183 s> Accept-Encoding: identity\r\n
183 s> Accept-Encoding: identity\r\n
184 s> accept: application/mercurial-0.1\r\n
184 s> accept: application/mercurial-0.1\r\n
185 s> host: $LOCALIP:$HGPORT\r\n (glob)
185 s> host: $LOCALIP:$HGPORT\r\n (glob)
186 s> user-agent: Mercurial debugwireproto\r\n
186 s> user-agent: Mercurial debugwireproto\r\n
187 s> \r\n
187 s> \r\n
188 s> makefile('rb', None)
188 s> makefile('rb', None)
189 s> HTTP/1.1 200 Script output follows\r\n
189 s> HTTP/1.1 200 Script output follows\r\n
190 s> Server: testing stub value\r\n
190 s> Server: testing stub value\r\n
191 s> Date: $HTTP_DATE$\r\n
191 s> Date: $HTTP_DATE$\r\n
192 s> Content-Type: application/mercurial-0.1\r\n
192 s> Content-Type: application/mercurial-0.1\r\n
193 s> Content-Length: *\r\n (glob)
193 s> Content-Length: *\r\n (glob)
194 s> \r\n
194 s> \r\n
195 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
195 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
196 sending listkeys command
196 sending listkeys command
197 s> GET /?cmd=listkeys HTTP/1.1\r\n
197 s> GET /?cmd=listkeys HTTP/1.1\r\n
198 s> Accept-Encoding: identity\r\n
198 s> Accept-Encoding: identity\r\n
199 s> vary: X-HgArg-1,X-HgProto-1\r\n
199 s> vary: X-HgArg-1,X-HgProto-1\r\n
200 s> x-hgarg-1: namespace=namespaces\r\n
200 s> x-hgarg-1: namespace=namespaces\r\n
201 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
201 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
202 s> accept: application/mercurial-0.1\r\n
202 s> accept: application/mercurial-0.1\r\n
203 s> host: $LOCALIP:$HGPORT\r\n (glob)
203 s> host: $LOCALIP:$HGPORT\r\n (glob)
204 s> user-agent: Mercurial debugwireproto\r\n
204 s> user-agent: Mercurial debugwireproto\r\n
205 s> \r\n
205 s> \r\n
206 s> makefile('rb', None)
206 s> makefile('rb', None)
207 s> HTTP/1.1 200 Script output follows\r\n
207 s> HTTP/1.1 200 Script output follows\r\n
208 s> Server: testing stub value\r\n
208 s> Server: testing stub value\r\n
209 s> Date: $HTTP_DATE$\r\n
209 s> Date: $HTTP_DATE$\r\n
210 s> Content-Type: application/mercurial-0.1\r\n
210 s> Content-Type: application/mercurial-0.1\r\n
211 s> Content-Length: 30\r\n
211 s> Content-Length: 30\r\n
212 s> \r\n
212 s> \r\n
213 s> bookmarks\t\n
213 s> bookmarks\t\n
214 s> namespaces\t\n
214 s> namespaces\t\n
215 s> phases\t
215 s> phases\t
216 response: {
216 response: {
217 b'bookmarks': b'',
217 b'bookmarks': b'',
218 b'namespaces': b'',
218 b'namespaces': b'',
219 b'phases': b''
219 b'phases': b''
220 }
220 }
221
221
222 Same thing, but with "httprequest" command
222 Same thing, but with "httprequest" command
223
223
224 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
224 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
225 > httprequest GET ?cmd=listkeys
225 > httprequest GET ?cmd=listkeys
226 > user-agent: test
226 > user-agent: test
227 > x-hgarg-1: namespace=namespaces
227 > x-hgarg-1: namespace=namespaces
228 > EOF
228 > EOF
229 using raw connection to peer
229 using raw connection to peer
230 s> GET /?cmd=listkeys HTTP/1.1\r\n
230 s> GET /?cmd=listkeys HTTP/1.1\r\n
231 s> Accept-Encoding: identity\r\n
231 s> Accept-Encoding: identity\r\n
232 s> user-agent: test\r\n
232 s> user-agent: test\r\n
233 s> x-hgarg-1: namespace=namespaces\r\n
233 s> x-hgarg-1: namespace=namespaces\r\n
234 s> host: $LOCALIP:$HGPORT\r\n (glob)
234 s> host: $LOCALIP:$HGPORT\r\n (glob)
235 s> \r\n
235 s> \r\n
236 s> makefile('rb', None)
236 s> makefile('rb', None)
237 s> HTTP/1.1 200 Script output follows\r\n
237 s> HTTP/1.1 200 Script output follows\r\n
238 s> Server: testing stub value\r\n
238 s> Server: testing stub value\r\n
239 s> Date: $HTTP_DATE$\r\n
239 s> Date: $HTTP_DATE$\r\n
240 s> Content-Type: application/mercurial-0.1\r\n
240 s> Content-Type: application/mercurial-0.1\r\n
241 s> Content-Length: 30\r\n
241 s> Content-Length: 30\r\n
242 s> \r\n
242 s> \r\n
243 s> bookmarks\t\n
243 s> bookmarks\t\n
244 s> namespaces\t\n
244 s> namespaces\t\n
245 s> phases\t
245 s> phases\t
246
246
247 Client with HTTPv2 enabled advertises that and gets old capabilities response from old server
247 Client with HTTPv2 enabled advertises that and gets old capabilities response from old server
248
248
249 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
249 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
250 > command heads
250 > command heads
251 > EOF
251 > EOF
252 s> GET /?cmd=capabilities HTTP/1.1\r\n
252 s> GET /?cmd=capabilities HTTP/1.1\r\n
253 s> Accept-Encoding: identity\r\n
253 s> Accept-Encoding: identity\r\n
254 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
254 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
255 s> x-hgproto-1: cbor\r\n
255 s> x-hgproto-1: cbor\r\n
256 s> x-hgupgrade-1: exp-http-v2-0001\r\n
256 s> x-hgupgrade-1: exp-http-v2-0001\r\n
257 s> accept: application/mercurial-0.1\r\n
257 s> accept: application/mercurial-0.1\r\n
258 s> host: $LOCALIP:$HGPORT\r\n (glob)
258 s> host: $LOCALIP:$HGPORT\r\n (glob)
259 s> user-agent: Mercurial debugwireproto\r\n
259 s> user-agent: Mercurial debugwireproto\r\n
260 s> \r\n
260 s> \r\n
261 s> makefile('rb', None)
261 s> makefile('rb', None)
262 s> HTTP/1.1 200 Script output follows\r\n
262 s> HTTP/1.1 200 Script output follows\r\n
263 s> Server: testing stub value\r\n
263 s> Server: testing stub value\r\n
264 s> Date: $HTTP_DATE$\r\n
264 s> Date: $HTTP_DATE$\r\n
265 s> Content-Type: application/mercurial-0.1\r\n
265 s> Content-Type: application/mercurial-0.1\r\n
266 s> Content-Length: *\r\n (glob)
266 s> Content-Length: *\r\n (glob)
267 s> \r\n
267 s> \r\n
268 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
268 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
269 sending heads command
269 sending heads command
270 s> GET /?cmd=heads HTTP/1.1\r\n
270 s> GET /?cmd=heads HTTP/1.1\r\n
271 s> Accept-Encoding: identity\r\n
271 s> Accept-Encoding: identity\r\n
272 s> vary: X-HgProto-1\r\n
272 s> vary: X-HgProto-1\r\n
273 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
273 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
274 s> accept: application/mercurial-0.1\r\n
274 s> accept: application/mercurial-0.1\r\n
275 s> host: $LOCALIP:$HGPORT\r\n (glob)
275 s> host: $LOCALIP:$HGPORT\r\n (glob)
276 s> user-agent: Mercurial debugwireproto\r\n
276 s> user-agent: Mercurial debugwireproto\r\n
277 s> \r\n
277 s> \r\n
278 s> makefile('rb', None)
278 s> makefile('rb', None)
279 s> HTTP/1.1 200 Script output follows\r\n
279 s> HTTP/1.1 200 Script output follows\r\n
280 s> Server: testing stub value\r\n
280 s> Server: testing stub value\r\n
281 s> Date: $HTTP_DATE$\r\n
281 s> Date: $HTTP_DATE$\r\n
282 s> Content-Type: application/mercurial-0.1\r\n
282 s> Content-Type: application/mercurial-0.1\r\n
283 s> Content-Length: 41\r\n
283 s> Content-Length: 41\r\n
284 s> \r\n
284 s> \r\n
285 s> 0000000000000000000000000000000000000000\n
285 s> 0000000000000000000000000000000000000000\n
286 response: [
286 response: [
287 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
287 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
288 ]
288 ]
289
289
290 $ killdaemons.py
290 $ killdaemons.py
291 $ enablehttpv2 empty
291 $ enablehttpv2 empty
292 $ hg --config server.compressionengines=zlib -R empty serve -p $HGPORT -d --pid-file hg.pid
292 $ hg --config server.compressionengines=zlib -R empty serve -p $HGPORT -d --pid-file hg.pid
293 $ cat hg.pid > $DAEMON_PIDS
293 $ cat hg.pid > $DAEMON_PIDS
294
294
295 Client with HTTPv2 enabled automatically upgrades if the server supports it
295 Client with HTTPv2 enabled automatically upgrades if the server supports it
296
296
297 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
297 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
298 > command heads
298 > command heads
299 > EOF
299 > EOF
300 s> GET /?cmd=capabilities HTTP/1.1\r\n
300 s> GET /?cmd=capabilities HTTP/1.1\r\n
301 s> Accept-Encoding: identity\r\n
301 s> Accept-Encoding: identity\r\n
302 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
302 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
303 s> x-hgproto-1: cbor\r\n
303 s> x-hgproto-1: cbor\r\n
304 s> x-hgupgrade-1: exp-http-v2-0001\r\n
304 s> x-hgupgrade-1: exp-http-v2-0001\r\n
305 s> accept: application/mercurial-0.1\r\n
305 s> accept: application/mercurial-0.1\r\n
306 s> host: $LOCALIP:$HGPORT\r\n (glob)
306 s> host: $LOCALIP:$HGPORT\r\n (glob)
307 s> user-agent: Mercurial debugwireproto\r\n
307 s> user-agent: Mercurial debugwireproto\r\n
308 s> \r\n
308 s> \r\n
309 s> makefile('rb', None)
309 s> makefile('rb', None)
310 s> HTTP/1.1 200 OK\r\n
310 s> HTTP/1.1 200 OK\r\n
311 s> Server: testing stub value\r\n
311 s> Server: testing stub value\r\n
312 s> Date: $HTTP_DATE$\r\n
312 s> Date: $HTTP_DATE$\r\n
313 s> Content-Type: application/mercurial-cbor\r\n
313 s> Content-Type: application/mercurial-cbor\r\n
314 s> Content-Length: *\r\n (glob)
314 s> Content-Length: *\r\n (glob)
315 s> \r\n
315 s> \r\n
316 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
316 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
317 sending heads command
317 sending heads command
318 s> POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
318 s> POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
319 s> Accept-Encoding: identity\r\n
319 s> Accept-Encoding: identity\r\n
320 s> accept: application/mercurial-exp-framing-0005\r\n
320 s> accept: application/mercurial-exp-framing-0005\r\n
321 s> content-type: application/mercurial-exp-framing-0005\r\n
321 s> content-type: application/mercurial-exp-framing-0005\r\n
322 s> content-length: 20\r\n
322 s> content-length: 20\r\n
323 s> host: $LOCALIP:$HGPORT\r\n (glob)
323 s> host: $LOCALIP:$HGPORT\r\n (glob)
324 s> user-agent: Mercurial debugwireproto\r\n
324 s> user-agent: Mercurial debugwireproto\r\n
325 s> \r\n
325 s> \r\n
326 s> \x0c\x00\x00\x01\x00\x01\x01\x11\xa1DnameEheads
326 s> \x0c\x00\x00\x01\x00\x01\x01\x11\xa1DnameEheads
327 s> makefile('rb', None)
327 s> makefile('rb', None)
328 s> HTTP/1.1 200 OK\r\n
328 s> HTTP/1.1 200 OK\r\n
329 s> Server: testing stub value\r\n
329 s> Server: testing stub value\r\n
330 s> Date: $HTTP_DATE$\r\n
330 s> Date: $HTTP_DATE$\r\n
331 s> Content-Type: application/mercurial-exp-framing-0005\r\n
331 s> Content-Type: application/mercurial-exp-framing-0005\r\n
332 s> Transfer-Encoding: chunked\r\n
332 s> Transfer-Encoding: chunked\r\n
333 s> \r\n
333 s> \r\n
334 s> 13\r\n
334 s> 13\r\n
335 s> \x0b\x00\x00\x01\x00\x02\x011
335 s> \x0b\x00\x00\x01\x00\x02\x011
336 s> \xa1FstatusBok
336 s> \xa1FstatusBok
337 s> \r\n
337 s> \r\n
338 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
338 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
339 s> 1e\r\n
339 s> 1e\r\n
340 s> \x16\x00\x00\x01\x00\x02\x001
340 s> \x16\x00\x00\x01\x00\x02\x001
341 s> \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
341 s> \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
342 s> \r\n
342 s> \r\n
343 received frame(size=22; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
343 received frame(size=22; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
344 s> 8\r\n
344 s> 8\r\n
345 s> \x00\x00\x00\x01\x00\x02\x002
345 s> \x00\x00\x00\x01\x00\x02\x002
346 s> \r\n
346 s> \r\n
347 s> 0\r\n
347 s> 0\r\n
348 s> \r\n
348 s> \r\n
349 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
349 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
350 response: [
350 response: [
351 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
351 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
352 ]
352 ]
353
353
354 $ killdaemons.py
354 $ killdaemons.py
355
355
356 HTTP client follows HTTP redirect on handshake to new repo
356 HTTP client follows HTTP redirect on handshake to new repo
357
357
358 $ cd $TESTTMP
358 $ cd $TESTTMP
359
359
360 $ hg init redirector
360 $ hg init redirector
361 $ hg init redirected
361 $ hg init redirected
362 $ cd redirected
362 $ cd redirected
363 $ touch foo
363 $ touch foo
364 $ hg -q commit -A -m initial
364 $ hg -q commit -A -m initial
365 $ cd ..
365 $ cd ..
366
366
367 $ cat > paths.conf << EOF
367 $ cat > paths.conf << EOF
368 > [paths]
368 > [paths]
369 > / = $TESTTMP/*
369 > / = $TESTTMP/*
370 > EOF
370 > EOF
371
371
372 $ cat > redirectext.py << EOF
372 $ cat > redirectext.py << EOF
373 > from mercurial import extensions, wireprotoserver
373 > from mercurial import extensions, wireprotoserver
374 > def wrappedcallhttp(orig, repo, req, res, proto, cmd):
374 > def wrappedcallhttp(orig, repo, req, res, proto, cmd):
375 > path = req.advertisedurl[len(req.advertisedbaseurl):]
375 > path = req.advertisedurl[len(req.advertisedbaseurl):]
376 > if not path.startswith(b'/redirector'):
376 > if not path.startswith(b'/redirector'):
377 > return orig(repo, req, res, proto, cmd)
377 > return orig(repo, req, res, proto, cmd)
378 > relpath = path[len(b'/redirector'):]
378 > relpath = path[len(b'/redirector'):]
379 > res.status = b'301 Redirect'
379 > res.status = b'301 Redirect'
380 > newurl = b'%s/redirected%s' % (req.baseurl, relpath)
380 > newurl = b'%s/redirected%s' % (req.baseurl, relpath)
381 > if not repo.ui.configbool('testing', 'redirectqs', True) and b'?' in newurl:
381 > if not repo.ui.configbool('testing', 'redirectqs', True) and b'?' in newurl:
382 > newurl = newurl[0:newurl.index(b'?')]
382 > newurl = newurl[0:newurl.index(b'?')]
383 > res.headers[b'Location'] = newurl
383 > res.headers[b'Location'] = newurl
384 > res.headers[b'Content-Type'] = b'text/plain'
384 > res.headers[b'Content-Type'] = b'text/plain'
385 > res.setbodybytes(b'redirected')
385 > res.setbodybytes(b'redirected')
386 > return True
386 > return True
387 >
387 >
388 > extensions.wrapfunction(wireprotoserver, '_callhttp', wrappedcallhttp)
388 > extensions.wrapfunction(wireprotoserver, '_callhttp', wrappedcallhttp)
389 > EOF
389 > EOF
390
390
391 $ hg --config extensions.redirect=$TESTTMP/redirectext.py \
391 $ hg --config extensions.redirect=$TESTTMP/redirectext.py \
392 > --config server.compressionengines=zlib \
392 > --config server.compressionengines=zlib \
393 > serve --web-conf paths.conf --pid-file hg.pid -p $HGPORT -d
393 > serve --web-conf paths.conf --pid-file hg.pid -p $HGPORT -d
394 $ cat hg.pid > $DAEMON_PIDS
394 $ cat hg.pid > $DAEMON_PIDS
395
395
396 Verify our HTTP 301 is served properly
396 Verify our HTTP 301 is served properly
397
397
398 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
398 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
399 > httprequest GET /redirector?cmd=capabilities
399 > httprequest GET /redirector?cmd=capabilities
400 > user-agent: test
400 > user-agent: test
401 > EOF
401 > EOF
402 using raw connection to peer
402 using raw connection to peer
403 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
403 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
404 s> Accept-Encoding: identity\r\n
404 s> Accept-Encoding: identity\r\n
405 s> user-agent: test\r\n
405 s> user-agent: test\r\n
406 s> host: $LOCALIP:$HGPORT\r\n (glob)
406 s> host: $LOCALIP:$HGPORT\r\n (glob)
407 s> \r\n
407 s> \r\n
408 s> makefile('rb', None)
408 s> makefile('rb', None)
409 s> HTTP/1.1 301 Redirect\r\n
409 s> HTTP/1.1 301 Redirect\r\n
410 s> Server: testing stub value\r\n
410 s> Server: testing stub value\r\n
411 s> Date: $HTTP_DATE$\r\n
411 s> Date: $HTTP_DATE$\r\n
412 s> Location: http://$LOCALIP:$HGPORT/redirected?cmd=capabilities\r\n (glob)
412 s> Location: http://$LOCALIP:$HGPORT/redirected?cmd=capabilities\r\n (glob)
413 s> Content-Type: text/plain\r\n
413 s> Content-Type: text/plain\r\n
414 s> Content-Length: 10\r\n
414 s> Content-Length: 10\r\n
415 s> \r\n
415 s> \r\n
416 s> redirected
416 s> redirected
417 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
417 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
418 s> Accept-Encoding: identity\r\n
418 s> Accept-Encoding: identity\r\n
419 s> user-agent: test\r\n
419 s> user-agent: test\r\n
420 s> host: $LOCALIP:$HGPORT\r\n (glob)
420 s> host: $LOCALIP:$HGPORT\r\n (glob)
421 s> \r\n
421 s> \r\n
422 s> makefile('rb', None)
422 s> makefile('rb', None)
423 s> HTTP/1.1 200 Script output follows\r\n
423 s> HTTP/1.1 200 Script output follows\r\n
424 s> Server: testing stub value\r\n
424 s> Server: testing stub value\r\n
425 s> Date: $HTTP_DATE$\r\n
425 s> Date: $HTTP_DATE$\r\n
426 s> Content-Type: application/mercurial-0.1\r\n
426 s> Content-Type: application/mercurial-0.1\r\n
427 s> Content-Length: 453\r\n
427 s> Content-Length: 453\r\n
428 s> \r\n
428 s> \r\n
429 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
429 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
430
430
431 Test with the HTTP peer
431 Test with the HTTP peer
432
432
433 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT/redirector << EOF
433 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT/redirector << EOF
434 > command heads
434 > command heads
435 > EOF
435 > EOF
436 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
436 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
437 s> Accept-Encoding: identity\r\n
437 s> Accept-Encoding: identity\r\n
438 s> accept: application/mercurial-0.1\r\n
438 s> accept: application/mercurial-0.1\r\n
439 s> host: $LOCALIP:$HGPORT\r\n (glob)
439 s> host: $LOCALIP:$HGPORT\r\n (glob)
440 s> user-agent: Mercurial debugwireproto\r\n
440 s> user-agent: Mercurial debugwireproto\r\n
441 s> \r\n
441 s> \r\n
442 s> makefile('rb', None)
442 s> makefile('rb', None)
443 s> HTTP/1.1 301 Redirect\r\n
443 s> HTTP/1.1 301 Redirect\r\n
444 s> Server: testing stub value\r\n
444 s> Server: testing stub value\r\n
445 s> Date: $HTTP_DATE$\r\n
445 s> Date: $HTTP_DATE$\r\n
446 s> Location: http://$LOCALIP:$HGPORT/redirected?cmd=capabilities\r\n (glob)
446 s> Location: http://$LOCALIP:$HGPORT/redirected?cmd=capabilities\r\n (glob)
447 s> Content-Type: text/plain\r\n
447 s> Content-Type: text/plain\r\n
448 s> Content-Length: 10\r\n
448 s> Content-Length: 10\r\n
449 s> \r\n
449 s> \r\n
450 s> redirected
450 s> redirected
451 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
451 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
452 s> Accept-Encoding: identity\r\n
452 s> Accept-Encoding: identity\r\n
453 s> accept: application/mercurial-0.1\r\n
453 s> accept: application/mercurial-0.1\r\n
454 s> host: $LOCALIP:$HGPORT\r\n (glob)
454 s> host: $LOCALIP:$HGPORT\r\n (glob)
455 s> user-agent: Mercurial debugwireproto\r\n
455 s> user-agent: Mercurial debugwireproto\r\n
456 s> \r\n
456 s> \r\n
457 s> makefile('rb', None)
457 s> makefile('rb', None)
458 s> HTTP/1.1 200 Script output follows\r\n
458 s> HTTP/1.1 200 Script output follows\r\n
459 s> Server: testing stub value\r\n
459 s> Server: testing stub value\r\n
460 s> Date: $HTTP_DATE$\r\n
460 s> Date: $HTTP_DATE$\r\n
461 s> Content-Type: application/mercurial-0.1\r\n
461 s> Content-Type: application/mercurial-0.1\r\n
462 s> Content-Length: 453\r\n
462 s> Content-Length: 453\r\n
463 s> \r\n
463 s> \r\n
464 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
464 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
465 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
465 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
466 sending heads command
466 sending heads command
467 s> GET /redirected?cmd=heads HTTP/1.1\r\n
467 s> GET /redirected?cmd=heads HTTP/1.1\r\n
468 s> Accept-Encoding: identity\r\n
468 s> Accept-Encoding: identity\r\n
469 s> vary: X-HgProto-1\r\n
469 s> vary: X-HgProto-1\r\n
470 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
470 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
471 s> accept: application/mercurial-0.1\r\n
471 s> accept: application/mercurial-0.1\r\n
472 s> host: $LOCALIP:$HGPORT\r\n (glob)
472 s> host: $LOCALIP:$HGPORT\r\n (glob)
473 s> user-agent: Mercurial debugwireproto\r\n
473 s> user-agent: Mercurial debugwireproto\r\n
474 s> \r\n
474 s> \r\n
475 s> makefile('rb', None)
475 s> makefile('rb', None)
476 s> HTTP/1.1 200 Script output follows\r\n
476 s> HTTP/1.1 200 Script output follows\r\n
477 s> Server: testing stub value\r\n
477 s> Server: testing stub value\r\n
478 s> Date: $HTTP_DATE$\r\n
478 s> Date: $HTTP_DATE$\r\n
479 s> Content-Type: application/mercurial-0.1\r\n
479 s> Content-Type: application/mercurial-0.1\r\n
480 s> Content-Length: 41\r\n
480 s> Content-Length: 41\r\n
481 s> \r\n
481 s> \r\n
482 s> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n
482 s> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n
483 response: [
483 response: [
484 b'\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL'
484 b'\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL'
485 ]
485 ]
486
486
487 $ killdaemons.py
487 $ killdaemons.py
488
488
489 Now test a variation where we strip the query string from the redirect URL.
489 Now test a variation where we strip the query string from the redirect URL.
490 (SCM Manager apparently did this and clients would recover from it)
490 (SCM Manager apparently did this and clients would recover from it)
491
491
492 $ hg --config extensions.redirect=$TESTTMP/redirectext.py \
492 $ hg --config extensions.redirect=$TESTTMP/redirectext.py \
493 > --config server.compressionengines=zlib \
493 > --config server.compressionengines=zlib \
494 > --config testing.redirectqs=false \
494 > --config testing.redirectqs=false \
495 > serve --web-conf paths.conf --pid-file hg.pid -p $HGPORT -d
495 > serve --web-conf paths.conf --pid-file hg.pid -p $HGPORT -d
496 $ cat hg.pid > $DAEMON_PIDS
496 $ cat hg.pid > $DAEMON_PIDS
497
497
498 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
498 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
499 > httprequest GET /redirector?cmd=capabilities
499 > httprequest GET /redirector?cmd=capabilities
500 > user-agent: test
500 > user-agent: test
501 > EOF
501 > EOF
502 using raw connection to peer
502 using raw connection to peer
503 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
503 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
504 s> Accept-Encoding: identity\r\n
504 s> Accept-Encoding: identity\r\n
505 s> user-agent: test\r\n
505 s> user-agent: test\r\n
506 s> host: $LOCALIP:$HGPORT\r\n (glob)
506 s> host: $LOCALIP:$HGPORT\r\n (glob)
507 s> \r\n
507 s> \r\n
508 s> makefile('rb', None)
508 s> makefile('rb', None)
509 s> HTTP/1.1 301 Redirect\r\n
509 s> HTTP/1.1 301 Redirect\r\n
510 s> Server: testing stub value\r\n
510 s> Server: testing stub value\r\n
511 s> Date: $HTTP_DATE$\r\n
511 s> Date: $HTTP_DATE$\r\n
512 s> Location: http://$LOCALIP:$HGPORT/redirected\r\n (glob)
512 s> Location: http://$LOCALIP:$HGPORT/redirected\r\n (glob)
513 s> Content-Type: text/plain\r\n
513 s> Content-Type: text/plain\r\n
514 s> Content-Length: 10\r\n
514 s> Content-Length: 10\r\n
515 s> \r\n
515 s> \r\n
516 s> redirected
516 s> redirected
517 s> GET /redirected HTTP/1.1\r\n
517 s> GET /redirected HTTP/1.1\r\n
518 s> Accept-Encoding: identity\r\n
518 s> Accept-Encoding: identity\r\n
519 s> user-agent: test\r\n
519 s> user-agent: test\r\n
520 s> host: $LOCALIP:$HGPORT\r\n (glob)
520 s> host: $LOCALIP:$HGPORT\r\n (glob)
521 s> \r\n
521 s> \r\n
522 s> makefile('rb', None)
522 s> makefile('rb', None)
523 s> HTTP/1.1 200 Script output follows\r\n
523 s> HTTP/1.1 200 Script output follows\r\n
524 s> Server: testing stub value\r\n
524 s> Server: testing stub value\r\n
525 s> Date: $HTTP_DATE$\r\n
525 s> Date: $HTTP_DATE$\r\n
526 s> ETag: W/"*"\r\n (glob)
526 s> ETag: W/"*"\r\n (glob)
527 s> Content-Type: text/html; charset=ascii\r\n
527 s> Content-Type: text/html; charset=ascii\r\n
528 s> Transfer-Encoding: chunked\r\n
528 s> Transfer-Encoding: chunked\r\n
529 s> \r\n
529 s> \r\n
530 s> 414\r\n
530 s> 414\r\n
531 s> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n
531 s> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n
532 s> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n
532 s> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n
533 s> <head>\n
533 s> <head>\n
534 s> <link rel="icon" href="/redirected/static/hgicon.png" type="image/png" />\n
534 s> <link rel="icon" href="/redirected/static/hgicon.png" type="image/png" />\n
535 s> <meta name="robots" content="index, nofollow" />\n
535 s> <meta name="robots" content="index, nofollow" />\n
536 s> <link rel="stylesheet" href="/redirected/static/style-paper.css" type="text/css" />\n
536 s> <link rel="stylesheet" href="/redirected/static/style-paper.css" type="text/css" />\n
537 s> <script type="text/javascript" src="/redirected/static/mercurial.js"></script>\n
537 s> <script type="text/javascript" src="/redirected/static/mercurial.js"></script>\n
538 s> \n
538 s> \n
539 s> <title>redirected: log</title>\n
539 s> <title>redirected: log</title>\n
540 s> <link rel="alternate" type="application/atom+xml"\n
540 s> <link rel="alternate" type="application/atom+xml"\n
541 s> href="/redirected/atom-log" title="Atom feed for redirected" />\n
541 s> href="/redirected/atom-log" title="Atom feed for redirected" />\n
542 s> <link rel="alternate" type="application/rss+xml"\n
542 s> <link rel="alternate" type="application/rss+xml"\n
543 s> href="/redirected/rss-log" title="RSS feed for redirected" />\n
543 s> href="/redirected/rss-log" title="RSS feed for redirected" />\n
544 s> </head>\n
544 s> </head>\n
545 s> <body>\n
545 s> <body>\n
546 s> \n
546 s> \n
547 s> <div class="container">\n
547 s> <div class="container">\n
548 s> <div class="menu">\n
548 s> <div class="menu">\n
549 s> <div class="logo">\n
549 s> <div class="logo">\n
550 s> <a href="https://mercurial-scm.org/">\n
550 s> <a href="https://mercurial-scm.org/">\n
551 s> <img src="/redirected/static/hglogo.png" alt="mercurial" /></a>\n
551 s> <img src="/redirected/static/hglogo.png" alt="mercurial" /></a>\n
552 s> </div>\n
552 s> </div>\n
553 s> <ul>\n
553 s> <ul>\n
554 s> <li class="active">log</li>\n
554 s> <li class="active">log</li>\n
555 s> <li><a href="/redirected/graph/tip">graph</a></li>\n
555 s> <li><a href="/redirected/graph/tip">graph</a></li>\n
556 s> <li><a href="/redirected/tags">tags</a></li>\n
556 s> <li><a href="/redirected/tags">tags</a></li>\n
557 s> <li><a href="
557 s> <li><a href="
558 s> \r\n
558 s> \r\n
559 s> 810\r\n
559 s> 810\r\n
560 s> /redirected/bookmarks">bookmarks</a></li>\n
560 s> /redirected/bookmarks">bookmarks</a></li>\n
561 s> <li><a href="/redirected/branches">branches</a></li>\n
561 s> <li><a href="/redirected/branches">branches</a></li>\n
562 s> </ul>\n
562 s> </ul>\n
563 s> <ul>\n
563 s> <ul>\n
564 s> <li><a href="/redirected/rev/tip">changeset</a></li>\n
564 s> <li><a href="/redirected/rev/tip">changeset</a></li>\n
565 s> <li><a href="/redirected/file/tip">browse</a></li>\n
565 s> <li><a href="/redirected/file/tip">browse</a></li>\n
566 s> </ul>\n
566 s> </ul>\n
567 s> <ul>\n
567 s> <ul>\n
568 s> \n
568 s> \n
569 s> </ul>\n
569 s> </ul>\n
570 s> <ul>\n
570 s> <ul>\n
571 s> <li><a href="/redirected/help">help</a></li>\n
571 s> <li><a href="/redirected/help">help</a></li>\n
572 s> </ul>\n
572 s> </ul>\n
573 s> <div class="atom-logo">\n
573 s> <div class="atom-logo">\n
574 s> <a href="/redirected/atom-log" title="subscribe to atom feed">\n
574 s> <a href="/redirected/atom-log" title="subscribe to atom feed">\n
575 s> <img class="atom-logo" src="/redirected/static/feed-icon-14x14.png" alt="atom feed" />\n
575 s> <img class="atom-logo" src="/redirected/static/feed-icon-14x14.png" alt="atom feed" />\n
576 s> </a>\n
576 s> </a>\n
577 s> </div>\n
577 s> </div>\n
578 s> </div>\n
578 s> </div>\n
579 s> \n
579 s> \n
580 s> <div class="main">\n
580 s> <div class="main">\n
581 s> <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/redirected">redirected</a> </h2>\n
581 s> <h2 class="breadcrumb"><a href="/">Mercurial</a> &gt; <a href="/redirected">redirected</a> </h2>\n
582 s> <h3>log</h3>\n
582 s> <h3>log</h3>\n
583 s> \n
583 s> \n
584 s> \n
584 s> \n
585 s> <form class="search" action="/redirected/log">\n
585 s> <form class="search" action="/redirected/log">\n
586 s> \n
586 s> \n
587 s> <p><input name="rev" id="search1" type="text" size="30" value="" /></p>\n
587 s> <p><input name="rev" id="search1" type="text" size="30" value="" /></p>\n
588 s> <div id="hint">Find changesets by keywords (author, files, the commit message), revision\n
588 s> <div id="hint">Find changesets by keywords (author, files, the commit message), revision\n
589 s> number or hash, or <a href="/redirected/help/revsets">revset expression</a>.</div>\n
589 s> number or hash, or <a href="/redirected/help/revsets">revset expression</a>.</div>\n
590 s> </form>\n
590 s> </form>\n
591 s> \n
591 s> \n
592 s> <div class="navigate">\n
592 s> <div class="navigate">\n
593 s> <a href="/redirected/shortlog/tip?revcount=30">less</a>\n
593 s> <a href="/redirected/shortlog/tip?revcount=30">less</a>\n
594 s> <a href="/redirected/shortlog/tip?revcount=120">more</a>\n
594 s> <a href="/redirected/shortlog/tip?revcount=120">more</a>\n
595 s> | rev 0: <a href="/redirected/shortlog/96ee1d7354c4">(0)</a> <a href="/redirected/shortlog/tip">tip</a> \n
595 s> | rev 0: <a href="/redirected/shortlog/96ee1d7354c4">(0)</a> <a href="/redirected/shortlog/tip">tip</a> \n
596 s> </div>\n
596 s> </div>\n
597 s> \n
597 s> \n
598 s> <table class="bigtable">\n
598 s> <table class="bigtable">\n
599 s> <thead>\n
599 s> <thead>\n
600 s> <tr>\n
600 s> <tr>\n
601 s> <th class="age">age</th>\n
601 s> <th class="age">age</th>\n
602 s> <th class="author">author</th>\n
602 s> <th class="author">author</th>\n
603 s> <th class="description">description</th>\n
603 s> <th class="description">description</th>\n
604 s> </tr>\n
604 s> </tr>\n
605 s> </thead>\n
605 s> </thead>\n
606 s> <tbody class="stripes2">\n
606 s> <tbody class="stripes2">\n
607 s> <tr>\n
607 s> <tr>\n
608 s> <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>\n
608 s> <td class="age">Thu, 01 Jan 1970 00:00:00 +0000</td>\n
609 s> <td class="author">test</td>\n
609 s> <td class="author">test</td>\n
610 s> <td class="description">\n
610 s> <td class="description">\n
611 s> <a href="/redirected/rev/96ee1d7354c4">initial</a>\n
611 s> <a href="/redirected/rev/96ee1d7354c4">initial</a>\n
612 s> <span class="phase">draft</span> <span class="branchhead">default</span> <span class="tag">tip</span> \n
612 s> <span class="phase">draft</span> <span class="branchhead">default</span> <span class="tag">tip</span> \n
613 s> </td>\n
613 s> </td>\n
614 s> </tr>\n
614 s> </tr>\n
615 s> \n
615 s> \n
616 s> </tbody>\n
616 s> </tbody>\n
617 s> </table>\n
617 s> </table>\n
618 s> \n
618 s> \n
619 s> <div class="navigate">\n
619 s> <div class="navigate">\n
620 s> <a href="/redirected/shortlog/tip?revcount=30">less</a>\n
620 s> <a href="/redirected/shortlog/tip?revcount=30">less</a>\n
621 s> <a href="/redirected/shortlog/tip?revcount=120">more</a>\n
621 s> <a href="/redirected/shortlog/tip?revcount=120">more</a>\n
622 s> | rev 0: <a href="/redirected/shortlog/96ee1d7354c4">(0)</a> <a href="/redirected/shortlog/tip">tip</a> \n
622 s> | rev 0: <a href="/redirected/shortlog/96ee1d7354c4">(0)</a> <a href="/redirected/shortlog/tip">tip</a> \n
623 s> </div>\n
623 s> </div>\n
624 s> \n
624 s> \n
625 s> <script type="text/javascript">\n
625 s> <script type="text/javascript">\n
626 s> ajaxScrollInit(\n
626 s> ajaxScrollInit(\n
627 s> \'/redirected/shortlog/%next%\',\n
627 s> \'/redirected/shortlog/%next%\',\n
628 s> \'\', <!-- NEXTHASH\n
628 s> \'\', <!-- NEXTHASH\n
629 s> function (htmlText) {
629 s> function (htmlText) {
630 s> \r\n
630 s> \r\n
631 s> 14a\r\n
631 s> 14a\r\n
632 s> \n
632 s> \n
633 s> var m = htmlText.match(/\'(\\w+)\', <!-- NEXTHASH/);\n
633 s> var m = htmlText.match(/\'(\\w+)\', <!-- NEXTHASH/);\n
634 s> return m ? m[1] : null;\n
634 s> return m ? m[1] : null;\n
635 s> },\n
635 s> },\n
636 s> \'.bigtable > tbody\',\n
636 s> \'.bigtable > tbody\',\n
637 s> \'<tr class="%class%">\\\n
637 s> \'<tr class="%class%">\\\n
638 s> <td colspan="3" style="text-align: center;">%text%</td>\\\n
638 s> <td colspan="3" style="text-align: center;">%text%</td>\\\n
639 s> </tr>\'\n
639 s> </tr>\'\n
640 s> );\n
640 s> );\n
641 s> </script>\n
641 s> </script>\n
642 s> \n
642 s> \n
643 s> </div>\n
643 s> </div>\n
644 s> </div>\n
644 s> </div>\n
645 s> \n
645 s> \n
646 s> \n
646 s> \n
647 s> \n
647 s> \n
648 s> </body>\n
648 s> </body>\n
649 s> </html>\n
649 s> </html>\n
650 s> \n
650 s> \n
651 s> \r\n
651 s> \r\n
652 s> 0\r\n
652 s> 0\r\n
653 s> \r\n
653 s> \r\n
654
654
655 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT/redirector << EOF
655 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT/redirector << EOF
656 > command heads
656 > command heads
657 > EOF
657 > EOF
658 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
658 s> GET /redirector?cmd=capabilities HTTP/1.1\r\n
659 s> Accept-Encoding: identity\r\n
659 s> Accept-Encoding: identity\r\n
660 s> accept: application/mercurial-0.1\r\n
660 s> accept: application/mercurial-0.1\r\n
661 s> host: $LOCALIP:$HGPORT\r\n (glob)
661 s> host: $LOCALIP:$HGPORT\r\n (glob)
662 s> user-agent: Mercurial debugwireproto\r\n
662 s> user-agent: Mercurial debugwireproto\r\n
663 s> \r\n
663 s> \r\n
664 s> makefile('rb', None)
664 s> makefile('rb', None)
665 s> HTTP/1.1 301 Redirect\r\n
665 s> HTTP/1.1 301 Redirect\r\n
666 s> Server: testing stub value\r\n
666 s> Server: testing stub value\r\n
667 s> Date: $HTTP_DATE$\r\n
667 s> Date: $HTTP_DATE$\r\n
668 s> Location: http://$LOCALIP:$HGPORT/redirected\r\n (glob)
668 s> Location: http://$LOCALIP:$HGPORT/redirected\r\n (glob)
669 s> Content-Type: text/plain\r\n
669 s> Content-Type: text/plain\r\n
670 s> Content-Length: 10\r\n
670 s> Content-Length: 10\r\n
671 s> \r\n
671 s> \r\n
672 s> redirected
672 s> redirected
673 s> GET /redirected HTTP/1.1\r\n
673 s> GET /redirected HTTP/1.1\r\n
674 s> Accept-Encoding: identity\r\n
674 s> Accept-Encoding: identity\r\n
675 s> accept: application/mercurial-0.1\r\n
675 s> accept: application/mercurial-0.1\r\n
676 s> host: $LOCALIP:$HGPORT\r\n (glob)
676 s> host: $LOCALIP:$HGPORT\r\n (glob)
677 s> user-agent: Mercurial debugwireproto\r\n
677 s> user-agent: Mercurial debugwireproto\r\n
678 s> \r\n
678 s> \r\n
679 s> makefile('rb', None)
679 s> makefile('rb', None)
680 s> HTTP/1.1 200 Script output follows\r\n
680 s> HTTP/1.1 200 Script output follows\r\n
681 s> Server: testing stub value\r\n
681 s> Server: testing stub value\r\n
682 s> Date: $HTTP_DATE$\r\n
682 s> Date: $HTTP_DATE$\r\n
683 s> ETag: W/"*"\r\n (glob)
683 s> ETag: W/"*"\r\n (glob)
684 s> Content-Type: text/html; charset=ascii\r\n
684 s> Content-Type: text/html; charset=ascii\r\n
685 s> Transfer-Encoding: chunked\r\n
685 s> Transfer-Encoding: chunked\r\n
686 s> \r\n
686 s> \r\n
687 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
687 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
688 s> 414\r\n
688 s> 414\r\n
689 s> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n
689 s> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n
690 s> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n
690 s> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">\n
691 s> <head>\n
691 s> <head>\n
692 s> <link rel="icon" href="/redirected/static/hgicon.png" type="image/png" />\n
692 s> <link rel="icon" href="/redirected/static/hgicon.png" type="image/png" />\n
693 s> <meta name="robots" content="index, nofollow" />\n
693 s> <meta name="robots" content="index, nofollow" />\n
694 s> <link rel="stylesheet" href="/redirected/static/style-paper.css" type="text/css" />\n
694 s> <link rel="stylesheet" href="/redirected/static/style-paper.css" type="text/css" />\n
695 s> <script type="text/javascript" src="/redirected/static/mercurial.js"></script>\n
695 s> <script type="text/javascript" src="/redirected/static/mercurial.js"></script>\n
696 s> \n
696 s> \n
697 s> <title>redirected: log</title>\n
697 s> <title>redirected: log</title>\n
698 s> <link rel="alternate" type="application/atom+xml"\n
698 s> <link rel="alternate" type="application/atom+xml"\n
699 s> href="/redirected/atom-log" title="Atom feed for redirected" />\n
699 s> href="/redirected/atom-log" title="Atom feed for redirected" />\n
700 s> <link rel="alternate" type="application/rss+xml"\n
700 s> <link rel="alternate" type="application/rss+xml"\n
701 s> href="/redirected/rss-log" title="RSS feed for redirected" />\n
701 s> href="/redirected/rss-log" title="RSS feed for redirected" />\n
702 s> </head>\n
702 s> </head>\n
703 s> <body>\n
703 s> <body>\n
704 s> \n
704 s> \n
705 s> <div class="container">\n
705 s> <div class="container">\n
706 s> <div class="menu">\n
706 s> <div class="menu">\n
707 s> <div class="logo">\n
707 s> <div class="logo">\n
708 s> <a href="https://mercurial-scm.org/">\n
708 s> <a href="https://mercurial-scm.org/">\n
709 s> <img src="/redirected/static/hglogo.png" alt="mercurial" /></a>\n
709 s> <img src="/redirected/static/hglogo.png" alt="mercurial" /></a>\n
710 s> </div>\n
710 s> </div>\n
711 s> <ul>\n
711 s> <ul>\n
712 s> <li class="active">log</li>\n
712 s> <li class="active">log</li>\n
713 s> <li><a href="/redirected/graph/tip">graph</a></li>\n
713 s> <li><a href="/redirected/graph/tip">graph</a></li>\n
714 s> <li><a href="/redirected/tags">tags</a
714 s> <li><a href="/redirected/tags">tags</a
715 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
715 s> GET /redirected?cmd=capabilities HTTP/1.1\r\n
716 s> Accept-Encoding: identity\r\n
716 s> Accept-Encoding: identity\r\n
717 s> accept: application/mercurial-0.1\r\n
717 s> accept: application/mercurial-0.1\r\n
718 s> host: $LOCALIP:$HGPORT\r\n (glob)
718 s> host: $LOCALIP:$HGPORT\r\n (glob)
719 s> user-agent: Mercurial debugwireproto\r\n
719 s> user-agent: Mercurial debugwireproto\r\n
720 s> \r\n
720 s> \r\n
721 s> makefile('rb', None)
721 s> makefile('rb', None)
722 s> HTTP/1.1 200 Script output follows\r\n
722 s> HTTP/1.1 200 Script output follows\r\n
723 s> Server: testing stub value\r\n
723 s> Server: testing stub value\r\n
724 s> Date: $HTTP_DATE$\r\n
724 s> Date: $HTTP_DATE$\r\n
725 s> Content-Type: application/mercurial-0.1\r\n
725 s> Content-Type: application/mercurial-0.1\r\n
726 s> Content-Length: 453\r\n
726 s> Content-Length: 453\r\n
727 s> \r\n
727 s> \r\n
728 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
728 real URL is http://$LOCALIP:$HGPORT/redirected (glob)
729 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
729 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
730 sending heads command
730 sending heads command
731 s> GET /redirected?cmd=heads HTTP/1.1\r\n
731 s> GET /redirected?cmd=heads HTTP/1.1\r\n
732 s> Accept-Encoding: identity\r\n
732 s> Accept-Encoding: identity\r\n
733 s> vary: X-HgProto-1\r\n
733 s> vary: X-HgProto-1\r\n
734 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
734 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
735 s> accept: application/mercurial-0.1\r\n
735 s> accept: application/mercurial-0.1\r\n
736 s> host: $LOCALIP:$HGPORT\r\n (glob)
736 s> host: $LOCALIP:$HGPORT\r\n (glob)
737 s> user-agent: Mercurial debugwireproto\r\n
737 s> user-agent: Mercurial debugwireproto\r\n
738 s> \r\n
738 s> \r\n
739 s> makefile('rb', None)
739 s> makefile('rb', None)
740 s> HTTP/1.1 200 Script output follows\r\n
740 s> HTTP/1.1 200 Script output follows\r\n
741 s> Server: testing stub value\r\n
741 s> Server: testing stub value\r\n
742 s> Date: $HTTP_DATE$\r\n
742 s> Date: $HTTP_DATE$\r\n
743 s> Content-Type: application/mercurial-0.1\r\n
743 s> Content-Type: application/mercurial-0.1\r\n
744 s> Content-Length: 41\r\n
744 s> Content-Length: 41\r\n
745 s> \r\n
745 s> \r\n
746 s> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n
746 s> 96ee1d7354c4ad7372047672c36a1f561e3a6a4c\n
747 response: [
747 response: [
748 b'\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL'
748 b'\x96\xee\x1dsT\xc4\xadsr\x04vr\xc3j\x1fV\x1e:jL'
749 ]
749 ]
@@ -1,532 +1,536
1 #require no-chg
1 #require no-chg
2
2
3 $ . $TESTDIR/wireprotohelpers.sh
3 $ . $TESTDIR/wireprotohelpers.sh
4
4
5 $ hg init server
5 $ hg init server
6
6
7 zstd isn't present in plain builds. Make tests easier by removing
7 zstd isn't present in plain builds. Make tests easier by removing
8 zstd from the equation.
8 zstd from the equation.
9
9
10 $ cat >> server/.hg/hgrc << EOF
10 $ cat >> server/.hg/hgrc << EOF
11 > [server]
11 > [server]
12 > compressionengines = zlib
12 > compressionengines = zlib
13 > EOF
13 > EOF
14
14
15 $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
15 $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
16 $ cat hg.pid > $DAEMON_PIDS
16 $ cat hg.pid > $DAEMON_PIDS
17
17
18 A normal capabilities request is serviced for version 1
18 A normal capabilities request is serviced for version 1
19
19
20 $ sendhttpraw << EOF
20 $ sendhttpraw << EOF
21 > httprequest GET ?cmd=capabilities
21 > httprequest GET ?cmd=capabilities
22 > user-agent: test
22 > user-agent: test
23 > EOF
23 > EOF
24 using raw connection to peer
24 using raw connection to peer
25 s> GET /?cmd=capabilities HTTP/1.1\r\n
25 s> GET /?cmd=capabilities HTTP/1.1\r\n
26 s> Accept-Encoding: identity\r\n
26 s> Accept-Encoding: identity\r\n
27 s> user-agent: test\r\n
27 s> user-agent: test\r\n
28 s> host: $LOCALIP:$HGPORT\r\n (glob)
28 s> host: $LOCALIP:$HGPORT\r\n (glob)
29 s> \r\n
29 s> \r\n
30 s> makefile('rb', None)
30 s> makefile('rb', None)
31 s> HTTP/1.1 200 Script output follows\r\n
31 s> HTTP/1.1 200 Script output follows\r\n
32 s> Server: testing stub value\r\n
32 s> Server: testing stub value\r\n
33 s> Date: $HTTP_DATE$\r\n
33 s> Date: $HTTP_DATE$\r\n
34 s> Content-Type: application/mercurial-0.1\r\n
34 s> Content-Type: application/mercurial-0.1\r\n
35 s> Content-Length: *\r\n (glob)
35 s> Content-Length: *\r\n (glob)
36 s> \r\n
36 s> \r\n
37 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
37 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
38
38
39 A proper request without the API server enabled returns the legacy response
39 A proper request without the API server enabled returns the legacy response
40
40
41 $ sendhttpraw << EOF
41 $ sendhttpraw << EOF
42 > httprequest GET ?cmd=capabilities
42 > httprequest GET ?cmd=capabilities
43 > user-agent: test
43 > user-agent: test
44 > x-hgupgrade-1: foo
44 > x-hgupgrade-1: foo
45 > x-hgproto-1: cbor
45 > x-hgproto-1: cbor
46 > EOF
46 > EOF
47 using raw connection to peer
47 using raw connection to peer
48 s> GET /?cmd=capabilities HTTP/1.1\r\n
48 s> GET /?cmd=capabilities HTTP/1.1\r\n
49 s> Accept-Encoding: identity\r\n
49 s> Accept-Encoding: identity\r\n
50 s> user-agent: test\r\n
50 s> user-agent: test\r\n
51 s> x-hgproto-1: cbor\r\n
51 s> x-hgproto-1: cbor\r\n
52 s> x-hgupgrade-1: foo\r\n
52 s> x-hgupgrade-1: foo\r\n
53 s> host: $LOCALIP:$HGPORT\r\n (glob)
53 s> host: $LOCALIP:$HGPORT\r\n (glob)
54 s> \r\n
54 s> \r\n
55 s> makefile('rb', None)
55 s> makefile('rb', None)
56 s> HTTP/1.1 200 Script output follows\r\n
56 s> HTTP/1.1 200 Script output follows\r\n
57 s> Server: testing stub value\r\n
57 s> Server: testing stub value\r\n
58 s> Date: $HTTP_DATE$\r\n
58 s> Date: $HTTP_DATE$\r\n
59 s> Content-Type: application/mercurial-0.1\r\n
59 s> Content-Type: application/mercurial-0.1\r\n
60 s> Content-Length: *\r\n (glob)
60 s> Content-Length: *\r\n (glob)
61 s> \r\n
61 s> \r\n
62 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
62 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
63
63
64 Restart with just API server enabled. This enables serving the new format.
64 Restart with just API server enabled. This enables serving the new format.
65
65
66 $ killdaemons.py
66 $ killdaemons.py
67 $ cat error.log
67 $ cat error.log
68
68
69 $ cat >> server/.hg/hgrc << EOF
69 $ cat >> server/.hg/hgrc << EOF
70 > [experimental]
70 > [experimental]
71 > web.apiserver = true
71 > web.apiserver = true
72 > EOF
72 > EOF
73
73
74 $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
74 $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
75 $ cat hg.pid > $DAEMON_PIDS
75 $ cat hg.pid > $DAEMON_PIDS
76
76
77 X-HgUpgrade-<N> without CBOR advertisement uses legacy response
77 X-HgUpgrade-<N> without CBOR advertisement uses legacy response
78
78
79 $ sendhttpraw << EOF
79 $ sendhttpraw << EOF
80 > httprequest GET ?cmd=capabilities
80 > httprequest GET ?cmd=capabilities
81 > user-agent: test
81 > user-agent: test
82 > x-hgupgrade-1: foo bar
82 > x-hgupgrade-1: foo bar
83 > EOF
83 > EOF
84 using raw connection to peer
84 using raw connection to peer
85 s> GET /?cmd=capabilities HTTP/1.1\r\n
85 s> GET /?cmd=capabilities HTTP/1.1\r\n
86 s> Accept-Encoding: identity\r\n
86 s> Accept-Encoding: identity\r\n
87 s> user-agent: test\r\n
87 s> user-agent: test\r\n
88 s> x-hgupgrade-1: foo bar\r\n
88 s> x-hgupgrade-1: foo bar\r\n
89 s> host: $LOCALIP:$HGPORT\r\n (glob)
89 s> host: $LOCALIP:$HGPORT\r\n (glob)
90 s> \r\n
90 s> \r\n
91 s> makefile('rb', None)
91 s> makefile('rb', None)
92 s> HTTP/1.1 200 Script output follows\r\n
92 s> HTTP/1.1 200 Script output follows\r\n
93 s> Server: testing stub value\r\n
93 s> Server: testing stub value\r\n
94 s> Date: $HTTP_DATE$\r\n
94 s> Date: $HTTP_DATE$\r\n
95 s> Content-Type: application/mercurial-0.1\r\n
95 s> Content-Type: application/mercurial-0.1\r\n
96 s> Content-Length: *\r\n (glob)
96 s> Content-Length: *\r\n (glob)
97 s> \r\n
97 s> \r\n
98 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
98 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
99
99
100 X-HgUpgrade-<N> without known serialization in X-HgProto-<N> uses legacy response
100 X-HgUpgrade-<N> without known serialization in X-HgProto-<N> uses legacy response
101
101
102 $ sendhttpraw << EOF
102 $ sendhttpraw << EOF
103 > httprequest GET ?cmd=capabilities
103 > httprequest GET ?cmd=capabilities
104 > user-agent: test
104 > user-agent: test
105 > x-hgupgrade-1: foo bar
105 > x-hgupgrade-1: foo bar
106 > x-hgproto-1: some value
106 > x-hgproto-1: some value
107 > EOF
107 > EOF
108 using raw connection to peer
108 using raw connection to peer
109 s> GET /?cmd=capabilities HTTP/1.1\r\n
109 s> GET /?cmd=capabilities HTTP/1.1\r\n
110 s> Accept-Encoding: identity\r\n
110 s> Accept-Encoding: identity\r\n
111 s> user-agent: test\r\n
111 s> user-agent: test\r\n
112 s> x-hgproto-1: some value\r\n
112 s> x-hgproto-1: some value\r\n
113 s> x-hgupgrade-1: foo bar\r\n
113 s> x-hgupgrade-1: foo bar\r\n
114 s> host: $LOCALIP:$HGPORT\r\n (glob)
114 s> host: $LOCALIP:$HGPORT\r\n (glob)
115 s> \r\n
115 s> \r\n
116 s> makefile('rb', None)
116 s> makefile('rb', None)
117 s> HTTP/1.1 200 Script output follows\r\n
117 s> HTTP/1.1 200 Script output follows\r\n
118 s> Server: testing stub value\r\n
118 s> Server: testing stub value\r\n
119 s> Date: $HTTP_DATE$\r\n
119 s> Date: $HTTP_DATE$\r\n
120 s> Content-Type: application/mercurial-0.1\r\n
120 s> Content-Type: application/mercurial-0.1\r\n
121 s> Content-Length: *\r\n (glob)
121 s> Content-Length: *\r\n (glob)
122 s> \r\n
122 s> \r\n
123 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
123 s> batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
124
124
125 X-HgUpgrade-<N> + X-HgProto-<N> headers trigger new response format
125 X-HgUpgrade-<N> + X-HgProto-<N> headers trigger new response format
126
126
127 $ sendhttpraw << EOF
127 $ sendhttpraw << EOF
128 > httprequest GET ?cmd=capabilities
128 > httprequest GET ?cmd=capabilities
129 > user-agent: test
129 > user-agent: test
130 > x-hgupgrade-1: foo bar
130 > x-hgupgrade-1: foo bar
131 > x-hgproto-1: cbor
131 > x-hgproto-1: cbor
132 > EOF
132 > EOF
133 using raw connection to peer
133 using raw connection to peer
134 s> GET /?cmd=capabilities HTTP/1.1\r\n
134 s> GET /?cmd=capabilities HTTP/1.1\r\n
135 s> Accept-Encoding: identity\r\n
135 s> Accept-Encoding: identity\r\n
136 s> user-agent: test\r\n
136 s> user-agent: test\r\n
137 s> x-hgproto-1: cbor\r\n
137 s> x-hgproto-1: cbor\r\n
138 s> x-hgupgrade-1: foo bar\r\n
138 s> x-hgupgrade-1: foo bar\r\n
139 s> host: $LOCALIP:$HGPORT\r\n (glob)
139 s> host: $LOCALIP:$HGPORT\r\n (glob)
140 s> \r\n
140 s> \r\n
141 s> makefile('rb', None)
141 s> makefile('rb', None)
142 s> HTTP/1.1 200 OK\r\n
142 s> HTTP/1.1 200 OK\r\n
143 s> Server: testing stub value\r\n
143 s> Server: testing stub value\r\n
144 s> Date: $HTTP_DATE$\r\n
144 s> Date: $HTTP_DATE$\r\n
145 s> Content-Type: application/mercurial-cbor\r\n
145 s> Content-Type: application/mercurial-cbor\r\n
146 s> Content-Length: *\r\n (glob)
146 s> Content-Length: *\r\n (glob)
147 s> \r\n
147 s> \r\n
148 s> \xa3GapibaseDapi/Dapis\xa0Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
148 s> \xa3GapibaseDapi/Dapis\xa0Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
149 cbor> {
149 cbor> {
150 b'apibase': b'api/',
150 b'apibase': b'api/',
151 b'apis': {},
151 b'apis': {},
152 b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'
152 b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'
153 }
153 }
154
154
155 Restart server to enable HTTPv2
155 Restart server to enable HTTPv2
156
156
157 $ killdaemons.py
157 $ killdaemons.py
158 $ enablehttpv2 server
158 $ enablehttpv2 server
159 $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
159 $ hg -R server serve -p $HGPORT -d --pid-file hg.pid -E error.log
160 $ cat hg.pid > $DAEMON_PIDS
160 $ cat hg.pid > $DAEMON_PIDS
161
161
162 Only requested API services are returned
162 Only requested API services are returned
163
163
164 $ sendhttpraw << EOF
164 $ sendhttpraw << EOF
165 > httprequest GET ?cmd=capabilities
165 > httprequest GET ?cmd=capabilities
166 > user-agent: test
166 > user-agent: test
167 > x-hgupgrade-1: foo bar
167 > x-hgupgrade-1: foo bar
168 > x-hgproto-1: cbor
168 > x-hgproto-1: cbor
169 > EOF
169 > EOF
170 using raw connection to peer
170 using raw connection to peer
171 s> GET /?cmd=capabilities HTTP/1.1\r\n
171 s> GET /?cmd=capabilities HTTP/1.1\r\n
172 s> Accept-Encoding: identity\r\n
172 s> Accept-Encoding: identity\r\n
173 s> user-agent: test\r\n
173 s> user-agent: test\r\n
174 s> x-hgproto-1: cbor\r\n
174 s> x-hgproto-1: cbor\r\n
175 s> x-hgupgrade-1: foo bar\r\n
175 s> x-hgupgrade-1: foo bar\r\n
176 s> host: $LOCALIP:$HGPORT\r\n (glob)
176 s> host: $LOCALIP:$HGPORT\r\n (glob)
177 s> \r\n
177 s> \r\n
178 s> makefile('rb', None)
178 s> makefile('rb', None)
179 s> HTTP/1.1 200 OK\r\n
179 s> HTTP/1.1 200 OK\r\n
180 s> Server: testing stub value\r\n
180 s> Server: testing stub value\r\n
181 s> Date: $HTTP_DATE$\r\n
181 s> Date: $HTTP_DATE$\r\n
182 s> Content-Type: application/mercurial-cbor\r\n
182 s> Content-Type: application/mercurial-cbor\r\n
183 s> Content-Length: *\r\n (glob)
183 s> Content-Length: *\r\n (glob)
184 s> \r\n
184 s> \r\n
185 s> \xa3GapibaseDapi/Dapis\xa0Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
185 s> \xa3GapibaseDapi/Dapis\xa0Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
186 cbor> {
186 cbor> {
187 b'apibase': b'api/',
187 b'apibase': b'api/',
188 b'apis': {},
188 b'apis': {},
189 b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'
189 b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'
190 }
190 }
191
191
192 Request for HTTPv2 service returns information about it
192 Request for HTTPv2 service returns information about it
193
193
194 $ sendhttpraw << EOF
194 $ sendhttpraw << EOF
195 > httprequest GET ?cmd=capabilities
195 > httprequest GET ?cmd=capabilities
196 > user-agent: test
196 > user-agent: test
197 > x-hgupgrade-1: exp-http-v2-0001 foo bar
197 > x-hgupgrade-1: exp-http-v2-0001 foo bar
198 > x-hgproto-1: cbor
198 > x-hgproto-1: cbor
199 > EOF
199 > EOF
200 using raw connection to peer
200 using raw connection to peer
201 s> GET /?cmd=capabilities HTTP/1.1\r\n
201 s> GET /?cmd=capabilities HTTP/1.1\r\n
202 s> Accept-Encoding: identity\r\n
202 s> Accept-Encoding: identity\r\n
203 s> user-agent: test\r\n
203 s> user-agent: test\r\n
204 s> x-hgproto-1: cbor\r\n
204 s> x-hgproto-1: cbor\r\n
205 s> x-hgupgrade-1: exp-http-v2-0001 foo bar\r\n
205 s> x-hgupgrade-1: exp-http-v2-0001 foo bar\r\n
206 s> host: $LOCALIP:$HGPORT\r\n (glob)
206 s> host: $LOCALIP:$HGPORT\r\n (glob)
207 s> \r\n
207 s> \r\n
208 s> makefile('rb', None)
208 s> makefile('rb', None)
209 s> HTTP/1.1 200 OK\r\n
209 s> HTTP/1.1 200 OK\r\n
210 s> Server: testing stub value\r\n
210 s> Server: testing stub value\r\n
211 s> Date: $HTTP_DATE$\r\n
211 s> Date: $HTTP_DATE$\r\n
212 s> Content-Type: application/mercurial-cbor\r\n
212 s> Content-Type: application/mercurial-cbor\r\n
213 s> Content-Length: *\r\n (glob)
213 s> Content-Length: *\r\n (glob)
214 s> \r\n
214 s> \r\n
215 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
215 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
216 cbor> {
216 cbor> {
217 b'apibase': b'api/',
217 b'apibase': b'api/',
218 b'apis': {
218 b'apis': {
219 b'exp-http-v2-0001': {
219 b'exp-http-v2-0001': {
220 b'commands': {
220 b'commands': {
221 b'branchmap': {
221 b'branchmap': {
222 b'args': {},
222 b'args': {},
223 b'permissions': [
223 b'permissions': [
224 b'pull'
224 b'pull'
225 ]
225 ]
226 },
226 },
227 b'capabilities': {
227 b'capabilities': {
228 b'args': {},
228 b'args': {},
229 b'permissions': [
229 b'permissions': [
230 b'pull'
230 b'pull'
231 ]
231 ]
232 },
232 },
233 b'changesetdata': {
233 b'changesetdata': {
234 b'args': {
234 b'args': {
235 b'fields': set([
235 b'fields': set([
236 b'parents',
236 b'parents',
237 b'revision'
237 b'revision'
238 ]),
238 ]),
239 b'noderange': [
239 b'noderange': [
240 [
240 [
241 b'0123456...'
241 b'0123456...'
242 ],
242 ],
243 [
243 [
244 b'abcdef...'
244 b'abcdef...'
245 ]
245 ]
246 ],
246 ],
247 b'nodes': [
247 b'nodes': [
248 b'0123456...'
248 b'0123456...'
249 ]
249 ]
250 },
250 },
251 b'permissions': [
251 b'permissions': [
252 b'pull'
252 b'pull'
253 ]
253 ]
254 },
254 },
255 b'filedata': {
255 b'filedata': {
256 b'args': {
256 b'args': {
257 b'fields': [
257 b'fields': [
258 b'parents',
258 b'parents',
259 b'revision'
259 b'revision'
260 ],
260 ],
261 b'haveparents': True,
261 b'nodes': [
262 b'nodes': [
262 b'0123456...'
263 b'0123456...'
263 ],
264 ],
264 b'path': b'foo.txt'
265 b'path': b'foo.txt'
265 },
266 },
266 b'permissions': [
267 b'permissions': [
267 b'pull'
268 b'pull'
268 ]
269 ]
269 },
270 },
270 b'heads': {
271 b'heads': {
271 b'args': {
272 b'args': {
272 b'publiconly': False
273 b'publiconly': False
273 },
274 },
274 b'permissions': [
275 b'permissions': [
275 b'pull'
276 b'pull'
276 ]
277 ]
277 },
278 },
278 b'known': {
279 b'known': {
279 b'args': {
280 b'args': {
280 b'nodes': [
281 b'nodes': [
281 b'deadbeef'
282 b'deadbeef'
282 ]
283 ]
283 },
284 },
284 b'permissions': [
285 b'permissions': [
285 b'pull'
286 b'pull'
286 ]
287 ]
287 },
288 },
288 b'listkeys': {
289 b'listkeys': {
289 b'args': {
290 b'args': {
290 b'namespace': b'ns'
291 b'namespace': b'ns'
291 },
292 },
292 b'permissions': [
293 b'permissions': [
293 b'pull'
294 b'pull'
294 ]
295 ]
295 },
296 },
296 b'lookup': {
297 b'lookup': {
297 b'args': {
298 b'args': {
298 b'key': b'foo'
299 b'key': b'foo'
299 },
300 },
300 b'permissions': [
301 b'permissions': [
301 b'pull'
302 b'pull'
302 ]
303 ]
303 },
304 },
304 b'manifestdata': {
305 b'manifestdata': {
305 b'args': {
306 b'args': {
306 b'fields': [
307 b'fields': [
307 b'parents',
308 b'parents',
308 b'revision'
309 b'revision'
309 ],
310 ],
311 b'haveparents': True,
310 b'nodes': [
312 b'nodes': [
311 b'0123456...'
313 b'0123456...'
312 ],
314 ],
313 b'tree': b''
315 b'tree': b''
314 },
316 },
315 b'permissions': [
317 b'permissions': [
316 b'pull'
318 b'pull'
317 ]
319 ]
318 },
320 },
319 b'pushkey': {
321 b'pushkey': {
320 b'args': {
322 b'args': {
321 b'key': b'key',
323 b'key': b'key',
322 b'namespace': b'ns',
324 b'namespace': b'ns',
323 b'new': b'new',
325 b'new': b'new',
324 b'old': b'old'
326 b'old': b'old'
325 },
327 },
326 b'permissions': [
328 b'permissions': [
327 b'push'
329 b'push'
328 ]
330 ]
329 }
331 }
330 },
332 },
331 b'compression': [
333 b'compression': [
332 {
334 {
333 b'name': b'zlib'
335 b'name': b'zlib'
334 }
336 }
335 ],
337 ],
336 b'framingmediatypes': [
338 b'framingmediatypes': [
337 b'application/mercurial-exp-framing-0005'
339 b'application/mercurial-exp-framing-0005'
338 ],
340 ],
339 b'rawrepoformats': [
341 b'rawrepoformats': [
340 b'generaldelta',
342 b'generaldelta',
341 b'revlogv1'
343 b'revlogv1'
342 ]
344 ]
343 }
345 }
344 },
346 },
345 b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'
347 b'v1capabilities': b'batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash'
346 }
348 }
347
349
348 capabilities command returns expected info
350 capabilities command returns expected info
349
351
350 $ sendhttpv2peerhandshake << EOF
352 $ sendhttpv2peerhandshake << EOF
351 > command capabilities
353 > command capabilities
352 > EOF
354 > EOF
353 creating http peer for wire protocol version 2
355 creating http peer for wire protocol version 2
354 s> GET /?cmd=capabilities HTTP/1.1\r\n
356 s> GET /?cmd=capabilities HTTP/1.1\r\n
355 s> Accept-Encoding: identity\r\n
357 s> Accept-Encoding: identity\r\n
356 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
358 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
357 s> x-hgproto-1: cbor\r\n
359 s> x-hgproto-1: cbor\r\n
358 s> x-hgupgrade-1: exp-http-v2-0001\r\n
360 s> x-hgupgrade-1: exp-http-v2-0001\r\n
359 s> accept: application/mercurial-0.1\r\n
361 s> accept: application/mercurial-0.1\r\n
360 s> host: $LOCALIP:$HGPORT\r\n (glob)
362 s> host: $LOCALIP:$HGPORT\r\n (glob)
361 s> user-agent: Mercurial debugwireproto\r\n
363 s> user-agent: Mercurial debugwireproto\r\n
362 s> \r\n
364 s> \r\n
363 s> makefile('rb', None)
365 s> makefile('rb', None)
364 s> HTTP/1.1 200 OK\r\n
366 s> HTTP/1.1 200 OK\r\n
365 s> Server: testing stub value\r\n
367 s> Server: testing stub value\r\n
366 s> Date: $HTTP_DATE$\r\n
368 s> Date: $HTTP_DATE$\r\n
367 s> Content-Type: application/mercurial-cbor\r\n
369 s> Content-Type: application/mercurial-cbor\r\n
368 s> Content-Length: *\r\n (glob)
370 s> Content-Length: *\r\n (glob)
369 s> \r\n
371 s> \r\n
370 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
372 s> \xa3GapibaseDapi/Dapis\xa1Pexp-http-v2-0001\xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1Nv1capabilitiesY\x01\xc5batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset compression=$BUNDLE2_COMPRESSIONS$ getbundle httpheader=1024 httpmediatype=0.1rx,0.1tx,0.2tx known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
371 sending capabilities command
373 sending capabilities command
372 s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
374 s> POST /api/exp-http-v2-0001/ro/capabilities HTTP/1.1\r\n
373 s> Accept-Encoding: identity\r\n
375 s> Accept-Encoding: identity\r\n
374 s> accept: application/mercurial-exp-framing-0005\r\n
376 s> accept: application/mercurial-exp-framing-0005\r\n
375 s> content-type: application/mercurial-exp-framing-0005\r\n
377 s> content-type: application/mercurial-exp-framing-0005\r\n
376 s> content-length: 27\r\n
378 s> content-length: 27\r\n
377 s> host: $LOCALIP:$HGPORT\r\n (glob)
379 s> host: $LOCALIP:$HGPORT\r\n (glob)
378 s> user-agent: Mercurial debugwireproto\r\n
380 s> user-agent: Mercurial debugwireproto\r\n
379 s> \r\n
381 s> \r\n
380 s> \x13\x00\x00\x01\x00\x01\x01\x11\xa1DnameLcapabilities
382 s> \x13\x00\x00\x01\x00\x01\x01\x11\xa1DnameLcapabilities
381 s> makefile('rb', None)
383 s> makefile('rb', None)
382 s> HTTP/1.1 200 OK\r\n
384 s> HTTP/1.1 200 OK\r\n
383 s> Server: testing stub value\r\n
385 s> Server: testing stub value\r\n
384 s> Date: $HTTP_DATE$\r\n
386 s> Date: $HTTP_DATE$\r\n
385 s> Content-Type: application/mercurial-exp-framing-0005\r\n
387 s> Content-Type: application/mercurial-exp-framing-0005\r\n
386 s> Transfer-Encoding: chunked\r\n
388 s> Transfer-Encoding: chunked\r\n
387 s> \r\n
389 s> \r\n
388 s> 13\r\n
390 s> 13\r\n
389 s> \x0b\x00\x00\x01\x00\x02\x011
391 s> \x0b\x00\x00\x01\x00\x02\x011
390 s> \xa1FstatusBok
392 s> \xa1FstatusBok
391 s> \r\n
393 s> \r\n
392 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
394 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
393 s> 2f4\r\n
395 s> 30e\r\n
394 s> \xec\x02\x00\x01\x00\x02\x001
396 s> \x06\x03\x00\x01\x00\x02\x001
395 s> \xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1
397 s> \xa4Hcommands\xaaIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullMchangesetdata\xa2Dargs\xa3Ffields\xd9\x01\x02\x82GparentsHrevisionInoderange\x82\x81J0123456...\x81Iabcdef...Enodes\x81J0123456...Kpermissions\x81DpullHfiledata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...DpathGfoo.txtKpermissions\x81DpullEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullLmanifestdata\xa2Dargs\xa4Ffields\x82GparentsHrevisionKhaveparents\xf5Enodes\x81J0123456...Dtree@Kpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyInamespaceBnsCnewCnewColdColdKpermissions\x81DpushKcompression\x81\xa1DnameDzlibQframingmediatypes\x81X&application/mercurial-exp-framing-0005Nrawrepoformats\x82LgeneraldeltaHrevlogv1
396 s> \r\n
398 s> \r\n
397 received frame(size=748; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
399 received frame(size=774; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
398 s> 8\r\n
400 s> 8\r\n
399 s> \x00\x00\x00\x01\x00\x02\x002
401 s> \x00\x00\x00\x01\x00\x02\x002
400 s> \r\n
402 s> \r\n
401 s> 0\r\n
403 s> 0\r\n
402 s> \r\n
404 s> \r\n
403 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
405 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
404 response: gen[
406 response: gen[
405 {
407 {
406 b'commands': {
408 b'commands': {
407 b'branchmap': {
409 b'branchmap': {
408 b'args': {},
410 b'args': {},
409 b'permissions': [
411 b'permissions': [
410 b'pull'
412 b'pull'
411 ]
413 ]
412 },
414 },
413 b'capabilities': {
415 b'capabilities': {
414 b'args': {},
416 b'args': {},
415 b'permissions': [
417 b'permissions': [
416 b'pull'
418 b'pull'
417 ]
419 ]
418 },
420 },
419 b'changesetdata': {
421 b'changesetdata': {
420 b'args': {
422 b'args': {
421 b'fields': set([
423 b'fields': set([
422 b'parents',
424 b'parents',
423 b'revision'
425 b'revision'
424 ]),
426 ]),
425 b'noderange': [
427 b'noderange': [
426 [
428 [
427 b'0123456...'
429 b'0123456...'
428 ],
430 ],
429 [
431 [
430 b'abcdef...'
432 b'abcdef...'
431 ]
433 ]
432 ],
434 ],
433 b'nodes': [
435 b'nodes': [
434 b'0123456...'
436 b'0123456...'
435 ]
437 ]
436 },
438 },
437 b'permissions': [
439 b'permissions': [
438 b'pull'
440 b'pull'
439 ]
441 ]
440 },
442 },
441 b'filedata': {
443 b'filedata': {
442 b'args': {
444 b'args': {
443 b'fields': [
445 b'fields': [
444 b'parents',
446 b'parents',
445 b'revision'
447 b'revision'
446 ],
448 ],
449 b'haveparents': True,
447 b'nodes': [
450 b'nodes': [
448 b'0123456...'
451 b'0123456...'
449 ],
452 ],
450 b'path': b'foo.txt'
453 b'path': b'foo.txt'
451 },
454 },
452 b'permissions': [
455 b'permissions': [
453 b'pull'
456 b'pull'
454 ]
457 ]
455 },
458 },
456 b'heads': {
459 b'heads': {
457 b'args': {
460 b'args': {
458 b'publiconly': False
461 b'publiconly': False
459 },
462 },
460 b'permissions': [
463 b'permissions': [
461 b'pull'
464 b'pull'
462 ]
465 ]
463 },
466 },
464 b'known': {
467 b'known': {
465 b'args': {
468 b'args': {
466 b'nodes': [
469 b'nodes': [
467 b'deadbeef'
470 b'deadbeef'
468 ]
471 ]
469 },
472 },
470 b'permissions': [
473 b'permissions': [
471 b'pull'
474 b'pull'
472 ]
475 ]
473 },
476 },
474 b'listkeys': {
477 b'listkeys': {
475 b'args': {
478 b'args': {
476 b'namespace': b'ns'
479 b'namespace': b'ns'
477 },
480 },
478 b'permissions': [
481 b'permissions': [
479 b'pull'
482 b'pull'
480 ]
483 ]
481 },
484 },
482 b'lookup': {
485 b'lookup': {
483 b'args': {
486 b'args': {
484 b'key': b'foo'
487 b'key': b'foo'
485 },
488 },
486 b'permissions': [
489 b'permissions': [
487 b'pull'
490 b'pull'
488 ]
491 ]
489 },
492 },
490 b'manifestdata': {
493 b'manifestdata': {
491 b'args': {
494 b'args': {
492 b'fields': [
495 b'fields': [
493 b'parents',
496 b'parents',
494 b'revision'
497 b'revision'
495 ],
498 ],
499 b'haveparents': True,
496 b'nodes': [
500 b'nodes': [
497 b'0123456...'
501 b'0123456...'
498 ],
502 ],
499 b'tree': b''
503 b'tree': b''
500 },
504 },
501 b'permissions': [
505 b'permissions': [
502 b'pull'
506 b'pull'
503 ]
507 ]
504 },
508 },
505 b'pushkey': {
509 b'pushkey': {
506 b'args': {
510 b'args': {
507 b'key': b'key',
511 b'key': b'key',
508 b'namespace': b'ns',
512 b'namespace': b'ns',
509 b'new': b'new',
513 b'new': b'new',
510 b'old': b'old'
514 b'old': b'old'
511 },
515 },
512 b'permissions': [
516 b'permissions': [
513 b'push'
517 b'push'
514 ]
518 ]
515 }
519 }
516 },
520 },
517 b'compression': [
521 b'compression': [
518 {
522 {
519 b'name': b'zlib'
523 b'name': b'zlib'
520 }
524 }
521 ],
525 ],
522 b'framingmediatypes': [
526 b'framingmediatypes': [
523 b'application/mercurial-exp-framing-0005'
527 b'application/mercurial-exp-framing-0005'
524 ],
528 ],
525 b'rawrepoformats': [
529 b'rawrepoformats': [
526 b'generaldelta',
530 b'generaldelta',
527 b'revlogv1'
531 b'revlogv1'
528 ]
532 ]
529 }
533 }
530 ]
534 ]
531
535
532 $ cat error.log
536 $ cat error.log
@@ -1,497 +1,604
1 $ . $TESTDIR/wireprotohelpers.sh
1 $ . $TESTDIR/wireprotohelpers.sh
2
2
3 $ hg init server
3 $ hg init server
4 $ enablehttpv2 server
4 $ enablehttpv2 server
5 $ cd server
5 $ cd server
6 $ echo a0 > a
6 $ echo a0 > a
7 $ echo b0 > b
7 $ echo b0 > b
8 $ mkdir -p dir0/child0 dir0/child1 dir1
8 $ mkdir -p dir0/child0 dir0/child1 dir1
9 $ echo c0 > dir0/c
9 $ echo c0 > dir0/c
10 $ echo d0 > dir0/d
10 $ echo d0 > dir0/d
11 $ echo e0 > dir0/child0/e
11 $ echo e0 > dir0/child0/e
12 $ echo f0 > dir0/child1/f
12 $ echo f0 > dir0/child1/f
13 $ hg -q commit -A -m 'commit 0'
13 $ hg -q commit -A -m 'commit 0'
14
14
15 $ echo a1 > a
15 $ echo a1 > a
16 $ echo d1 > dir0/d
16 $ echo d1 > dir0/d
17 $ hg commit -m 'commit 1'
17 $ hg commit -m 'commit 1'
18 $ echo f0 > dir0/child1/f
18 $ echo f0 > dir0/child1/f
19 $ hg commit -m 'commit 2'
19 $ hg commit -m 'commit 2'
20 nothing changed
20 nothing changed
21 [1]
21 [1]
22
22
23 $ hg -q up -r 0
23 $ hg -q up -r 0
24 $ echo a2 > a
24 $ echo a2 > a
25 $ hg commit -m 'commit 3'
25 $ hg commit -m 'commit 3'
26 created new head
26 created new head
27
27
28 $ hg log -G -T '{rev}:{node} {desc}\n'
28 $ hg log -G -T '{rev}:{node} {desc}\n'
29 @ 2:c8757a2ffe552850d1e0dfe60d295ebf64c196d9 commit 3
29 @ 2:c8757a2ffe552850d1e0dfe60d295ebf64c196d9 commit 3
30 |
30 |
31 | o 1:650165e803375748a94df471e5b58d85763e0b29 commit 1
31 | o 1:650165e803375748a94df471e5b58d85763e0b29 commit 1
32 |/
32 |/
33 o 0:6d85ca1270b377d320098556ba5bfad34a9ee12d commit 0
33 o 0:6d85ca1270b377d320098556ba5bfad34a9ee12d commit 0
34
34
35
35
36 $ hg --debug debugindex a
36 $ hg --debug debugindex a
37 rev linkrev nodeid p1 p2
37 rev linkrev nodeid p1 p2
38 0 0 2b4eb07319bfa077a40a2f04913659aef0da42da 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
38 0 0 2b4eb07319bfa077a40a2f04913659aef0da42da 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
39 1 1 9a38122997b3ac97be2a9aa2e556838341fdf2cc 2b4eb07319bfa077a40a2f04913659aef0da42da 0000000000000000000000000000000000000000
39 1 1 9a38122997b3ac97be2a9aa2e556838341fdf2cc 2b4eb07319bfa077a40a2f04913659aef0da42da 0000000000000000000000000000000000000000
40 2 2 0879345e39377229634b420c639454156726c6b6 2b4eb07319bfa077a40a2f04913659aef0da42da 0000000000000000000000000000000000000000
40 2 2 0879345e39377229634b420c639454156726c6b6 2b4eb07319bfa077a40a2f04913659aef0da42da 0000000000000000000000000000000000000000
41
41
42 $ hg --debug debugindex dir0/child0/e
42 $ hg --debug debugindex dir0/child0/e
43 rev linkrev nodeid p1 p2
43 rev linkrev nodeid p1 p2
44 0 0 bbba6c06b30f443d34ff841bc985c4d0827c6be4 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
44 0 0 bbba6c06b30f443d34ff841bc985c4d0827c6be4 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
45
45
46 $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
46 $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
47 $ cat hg.pid > $DAEMON_PIDS
47 $ cat hg.pid > $DAEMON_PIDS
48
48
49 Missing arguments is an error
49 Missing arguments is an error
50
50
51 $ sendhttpv2peer << EOF
51 $ sendhttpv2peer << EOF
52 > command filedata
52 > command filedata
53 > EOF
53 > EOF
54 creating http peer for wire protocol version 2
54 creating http peer for wire protocol version 2
55 sending filedata command
55 sending filedata command
56 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
56 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
57 s> Accept-Encoding: identity\r\n
57 s> Accept-Encoding: identity\r\n
58 s> accept: application/mercurial-exp-framing-0005\r\n
58 s> accept: application/mercurial-exp-framing-0005\r\n
59 s> content-type: application/mercurial-exp-framing-0005\r\n
59 s> content-type: application/mercurial-exp-framing-0005\r\n
60 s> content-length: 23\r\n
60 s> content-length: 23\r\n
61 s> host: $LOCALIP:$HGPORT\r\n (glob)
61 s> host: $LOCALIP:$HGPORT\r\n (glob)
62 s> user-agent: Mercurial debugwireproto\r\n
62 s> user-agent: Mercurial debugwireproto\r\n
63 s> \r\n
63 s> \r\n
64 s> \x0f\x00\x00\x01\x00\x01\x01\x11\xa1DnameHfiledata
64 s> \x0f\x00\x00\x01\x00\x01\x01\x11\xa1DnameHfiledata
65 s> makefile('rb', None)
65 s> makefile('rb', None)
66 s> HTTP/1.1 200 OK\r\n
66 s> HTTP/1.1 200 OK\r\n
67 s> Server: testing stub value\r\n
67 s> Server: testing stub value\r\n
68 s> Date: $HTTP_DATE$\r\n
68 s> Date: $HTTP_DATE$\r\n
69 s> Content-Type: application/mercurial-exp-framing-0005\r\n
69 s> Content-Type: application/mercurial-exp-framing-0005\r\n
70 s> Transfer-Encoding: chunked\r\n
70 s> Transfer-Encoding: chunked\r\n
71 s> \r\n
71 s> \r\n
72 s> 45\r\n
72 s> 45\r\n
73 s> =\x00\x00\x01\x00\x02\x012
73 s> =\x00\x00\x01\x00\x02\x012
74 s> \xa2Eerror\xa1GmessageX\x1enodes argument must be definedFstatusEerror
74 s> \xa2Eerror\xa1GmessageX\x1enodes argument must be definedFstatusEerror
75 s> \r\n
75 s> \r\n
76 received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
76 received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
77 s> 0\r\n
77 s> 0\r\n
78 s> \r\n
78 s> \r\n
79 abort: nodes argument must be defined!
79 abort: nodes argument must be defined!
80 [255]
80 [255]
81
81
82 $ sendhttpv2peer << EOF
82 $ sendhttpv2peer << EOF
83 > command filedata
83 > command filedata
84 > nodes eval:[]
84 > nodes eval:[]
85 > EOF
85 > EOF
86 creating http peer for wire protocol version 2
86 creating http peer for wire protocol version 2
87 sending filedata command
87 sending filedata command
88 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
88 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
89 s> Accept-Encoding: identity\r\n
89 s> Accept-Encoding: identity\r\n
90 s> accept: application/mercurial-exp-framing-0005\r\n
90 s> accept: application/mercurial-exp-framing-0005\r\n
91 s> content-type: application/mercurial-exp-framing-0005\r\n
91 s> content-type: application/mercurial-exp-framing-0005\r\n
92 s> content-length: 36\r\n
92 s> content-length: 36\r\n
93 s> host: $LOCALIP:$HGPORT\r\n (glob)
93 s> host: $LOCALIP:$HGPORT\r\n (glob)
94 s> user-agent: Mercurial debugwireproto\r\n
94 s> user-agent: Mercurial debugwireproto\r\n
95 s> \r\n
95 s> \r\n
96 s> \x1c\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Enodes\x80DnameHfiledata
96 s> \x1c\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Enodes\x80DnameHfiledata
97 s> makefile('rb', None)
97 s> makefile('rb', None)
98 s> HTTP/1.1 200 OK\r\n
98 s> HTTP/1.1 200 OK\r\n
99 s> Server: testing stub value\r\n
99 s> Server: testing stub value\r\n
100 s> Date: $HTTP_DATE$\r\n
100 s> Date: $HTTP_DATE$\r\n
101 s> Content-Type: application/mercurial-exp-framing-0005\r\n
101 s> Content-Type: application/mercurial-exp-framing-0005\r\n
102 s> Transfer-Encoding: chunked\r\n
102 s> Transfer-Encoding: chunked\r\n
103 s> \r\n
103 s> \r\n
104 s> 44\r\n
104 s> 44\r\n
105 s> <\x00\x00\x01\x00\x02\x012
105 s> <\x00\x00\x01\x00\x02\x012
106 s> \xa2Eerror\xa1GmessageX\x1dpath argument must be definedFstatusEerror
106 s> \xa2Eerror\xa1GmessageX\x1dpath argument must be definedFstatusEerror
107 s> \r\n
107 s> \r\n
108 received frame(size=60; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
108 received frame(size=60; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
109 s> 0\r\n
109 s> 0\r\n
110 s> \r\n
110 s> \r\n
111 abort: path argument must be defined!
111 abort: path argument must be defined!
112 [255]
112 [255]
113
113
114 Unknown node is an error
114 Unknown node is an error
115
115
116 $ sendhttpv2peer << EOF
116 $ sendhttpv2peer << EOF
117 > command filedata
117 > command filedata
118 > nodes eval:[b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa']
118 > nodes eval:[b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa']
119 > path eval:b'a'
119 > path eval:b'a'
120 > EOF
120 > EOF
121 creating http peer for wire protocol version 2
121 creating http peer for wire protocol version 2
122 sending filedata command
122 sending filedata command
123 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
123 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
124 s> Accept-Encoding: identity\r\n
124 s> Accept-Encoding: identity\r\n
125 s> accept: application/mercurial-exp-framing-0005\r\n
125 s> accept: application/mercurial-exp-framing-0005\r\n
126 s> content-type: application/mercurial-exp-framing-0005\r\n
126 s> content-type: application/mercurial-exp-framing-0005\r\n
127 s> content-length: 64\r\n
127 s> content-length: 64\r\n
128 s> host: $LOCALIP:$HGPORT\r\n (glob)
128 s> host: $LOCALIP:$HGPORT\r\n (glob)
129 s> user-agent: Mercurial debugwireproto\r\n
129 s> user-agent: Mercurial debugwireproto\r\n
130 s> \r\n
130 s> \r\n
131 s> 8\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81T\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaaDpathAaDnameHfiledata
131 s> 8\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81T\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaaDpathAaDnameHfiledata
132 s> makefile('rb', None)
132 s> makefile('rb', None)
133 s> HTTP/1.1 200 OK\r\n
133 s> HTTP/1.1 200 OK\r\n
134 s> Server: testing stub value\r\n
134 s> Server: testing stub value\r\n
135 s> Date: $HTTP_DATE$\r\n
135 s> Date: $HTTP_DATE$\r\n
136 s> Content-Type: application/mercurial-exp-framing-0005\r\n
136 s> Content-Type: application/mercurial-exp-framing-0005\r\n
137 s> Transfer-Encoding: chunked\r\n
137 s> Transfer-Encoding: chunked\r\n
138 s> \r\n
138 s> \r\n
139 s> 6b\r\n
139 s> 6b\r\n
140 s> c\x00\x00\x01\x00\x02\x012
140 s> c\x00\x00\x01\x00\x02\x012
141 s> \xa2Eerror\xa2Dargs\x81X(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGmessageUunknown file node: %sFstatusEerror
141 s> \xa2Eerror\xa2Dargs\x81X(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaGmessageUunknown file node: %sFstatusEerror
142 s> \r\n
142 s> \r\n
143 received frame(size=99; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
143 received frame(size=99; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
144 s> 0\r\n
144 s> 0\r\n
145 s> \r\n
145 s> \r\n
146 abort: unknown file node: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
146 abort: unknown file node: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
147 [255]
147 [255]
148
148
149 Fetching a single revision returns just metadata by default
149 Fetching a single revision returns just metadata by default
150
150
151 $ sendhttpv2peer << EOF
151 $ sendhttpv2peer << EOF
152 > command filedata
152 > command filedata
153 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
153 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
154 > path eval:b'a'
154 > path eval:b'a'
155 > EOF
155 > EOF
156 creating http peer for wire protocol version 2
156 creating http peer for wire protocol version 2
157 sending filedata command
157 sending filedata command
158 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
158 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
159 s> Accept-Encoding: identity\r\n
159 s> Accept-Encoding: identity\r\n
160 s> accept: application/mercurial-exp-framing-0005\r\n
160 s> accept: application/mercurial-exp-framing-0005\r\n
161 s> content-type: application/mercurial-exp-framing-0005\r\n
161 s> content-type: application/mercurial-exp-framing-0005\r\n
162 s> content-length: 64\r\n
162 s> content-length: 64\r\n
163 s> host: $LOCALIP:$HGPORT\r\n (glob)
163 s> host: $LOCALIP:$HGPORT\r\n (glob)
164 s> user-agent: Mercurial debugwireproto\r\n
164 s> user-agent: Mercurial debugwireproto\r\n
165 s> \r\n
165 s> \r\n
166 s> 8\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
166 s> 8\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
167 s> makefile('rb', None)
167 s> makefile('rb', None)
168 s> HTTP/1.1 200 OK\r\n
168 s> HTTP/1.1 200 OK\r\n
169 s> Server: testing stub value\r\n
169 s> Server: testing stub value\r\n
170 s> Date: $HTTP_DATE$\r\n
170 s> Date: $HTTP_DATE$\r\n
171 s> Content-Type: application/mercurial-exp-framing-0005\r\n
171 s> Content-Type: application/mercurial-exp-framing-0005\r\n
172 s> Transfer-Encoding: chunked\r\n
172 s> Transfer-Encoding: chunked\r\n
173 s> \r\n
173 s> \r\n
174 s> 13\r\n
174 s> 13\r\n
175 s> \x0b\x00\x00\x01\x00\x02\x011
175 s> \x0b\x00\x00\x01\x00\x02\x011
176 s> \xa1FstatusBok
176 s> \xa1FstatusBok
177 s> \r\n
177 s> \r\n
178 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
178 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
179 s> 30\r\n
179 s> 30\r\n
180 s> (\x00\x00\x01\x00\x02\x001
180 s> (\x00\x00\x01\x00\x02\x001
181 s> \xa1Jtotalitems\x01\xa1DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc
181 s> \xa1Jtotalitems\x01\xa1DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc
182 s> \r\n
182 s> \r\n
183 received frame(size=40; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
183 received frame(size=40; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
184 s> 8\r\n
184 s> 8\r\n
185 s> \x00\x00\x00\x01\x00\x02\x002
185 s> \x00\x00\x00\x01\x00\x02\x002
186 s> \r\n
186 s> \r\n
187 s> 0\r\n
187 s> 0\r\n
188 s> \r\n
188 s> \r\n
189 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
189 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
190 response: gen[
190 response: gen[
191 {
191 {
192 b'totalitems': 1
192 b'totalitems': 1
193 },
193 },
194 {
194 {
195 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
195 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
196 }
196 }
197 ]
197 ]
198
198
199 Requesting parents works
199 Requesting parents works
200
200
201 $ sendhttpv2peer << EOF
201 $ sendhttpv2peer << EOF
202 > command filedata
202 > command filedata
203 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
203 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
204 > path eval:b'a'
204 > path eval:b'a'
205 > fields eval:[b'parents']
205 > fields eval:[b'parents']
206 > EOF
206 > EOF
207 creating http peer for wire protocol version 2
207 creating http peer for wire protocol version 2
208 sending filedata command
208 sending filedata command
209 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
209 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
210 s> Accept-Encoding: identity\r\n
210 s> Accept-Encoding: identity\r\n
211 s> accept: application/mercurial-exp-framing-0005\r\n
211 s> accept: application/mercurial-exp-framing-0005\r\n
212 s> content-type: application/mercurial-exp-framing-0005\r\n
212 s> content-type: application/mercurial-exp-framing-0005\r\n
213 s> content-length: 80\r\n
213 s> content-length: 80\r\n
214 s> host: $LOCALIP:$HGPORT\r\n (glob)
214 s> host: $LOCALIP:$HGPORT\r\n (glob)
215 s> user-agent: Mercurial debugwireproto\r\n
215 s> user-agent: Mercurial debugwireproto\r\n
216 s> \r\n
216 s> \r\n
217 s> H\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81GparentsEnodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
217 s> H\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81GparentsEnodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
218 s> makefile('rb', None)
218 s> makefile('rb', None)
219 s> HTTP/1.1 200 OK\r\n
219 s> HTTP/1.1 200 OK\r\n
220 s> Server: testing stub value\r\n
220 s> Server: testing stub value\r\n
221 s> Date: $HTTP_DATE$\r\n
221 s> Date: $HTTP_DATE$\r\n
222 s> Content-Type: application/mercurial-exp-framing-0005\r\n
222 s> Content-Type: application/mercurial-exp-framing-0005\r\n
223 s> Transfer-Encoding: chunked\r\n
223 s> Transfer-Encoding: chunked\r\n
224 s> \r\n
224 s> \r\n
225 s> 13\r\n
225 s> 13\r\n
226 s> \x0b\x00\x00\x01\x00\x02\x011
226 s> \x0b\x00\x00\x01\x00\x02\x011
227 s> \xa1FstatusBok
227 s> \xa1FstatusBok
228 s> \r\n
228 s> \r\n
229 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
229 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
230 s> 63\r\n
230 s> 63\r\n
231 s> [\x00\x00\x01\x00\x02\x001
231 s> [\x00\x00\x01\x00\x02\x001
232 s> \xa1Jtotalitems\x01\xa2DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccGparents\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
232 s> \xa1Jtotalitems\x01\xa2DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccGparents\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
233 s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
233 s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
234 s> \r\n
234 s> \r\n
235 received frame(size=91; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
235 received frame(size=91; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
236 s> 8\r\n
236 s> 8\r\n
237 s> \x00\x00\x00\x01\x00\x02\x002
237 s> \x00\x00\x00\x01\x00\x02\x002
238 s> \r\n
238 s> \r\n
239 s> 0\r\n
239 s> 0\r\n
240 s> \r\n
240 s> \r\n
241 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
241 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
242 response: gen[
242 response: gen[
243 {
243 {
244 b'totalitems': 1
244 b'totalitems': 1
245 },
245 },
246 {
246 {
247 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
247 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
248 b'parents': [
248 b'parents': [
249 b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
249 b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
250 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
250 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
251 ]
251 ]
252 }
252 }
253 ]
253 ]
254
254
255 Requesting revision data works
255 Requesting revision data works
256 (haveparents defaults to False, so fulltext is emitted)
256
257
257 $ sendhttpv2peer << EOF
258 $ sendhttpv2peer << EOF
258 > command filedata
259 > command filedata
259 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
260 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
260 > path eval:b'a'
261 > path eval:b'a'
261 > fields eval:[b'revision']
262 > fields eval:[b'revision']
262 > EOF
263 > EOF
263 creating http peer for wire protocol version 2
264 creating http peer for wire protocol version 2
264 sending filedata command
265 sending filedata command
265 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
266 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
266 s> Accept-Encoding: identity\r\n
267 s> Accept-Encoding: identity\r\n
267 s> accept: application/mercurial-exp-framing-0005\r\n
268 s> accept: application/mercurial-exp-framing-0005\r\n
268 s> content-type: application/mercurial-exp-framing-0005\r\n
269 s> content-type: application/mercurial-exp-framing-0005\r\n
269 s> content-length: 81\r\n
270 s> content-length: 81\r\n
270 s> host: $LOCALIP:$HGPORT\r\n (glob)
271 s> host: $LOCALIP:$HGPORT\r\n (glob)
271 s> user-agent: Mercurial debugwireproto\r\n
272 s> user-agent: Mercurial debugwireproto\r\n
272 s> \r\n
273 s> \r\n
273 s> I\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
274 s> I\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
274 s> makefile('rb', None)
275 s> makefile('rb', None)
275 s> HTTP/1.1 200 OK\r\n
276 s> HTTP/1.1 200 OK\r\n
276 s> Server: testing stub value\r\n
277 s> Server: testing stub value\r\n
277 s> Date: $HTTP_DATE$\r\n
278 s> Date: $HTTP_DATE$\r\n
278 s> Content-Type: application/mercurial-exp-framing-0005\r\n
279 s> Content-Type: application/mercurial-exp-framing-0005\r\n
279 s> Transfer-Encoding: chunked\r\n
280 s> Transfer-Encoding: chunked\r\n
280 s> \r\n
281 s> \r\n
281 s> 13\r\n
282 s> 13\r\n
282 s> \x0b\x00\x00\x01\x00\x02\x011
283 s> \x0b\x00\x00\x01\x00\x02\x011
283 s> \xa1FstatusBok
284 s> \xa1FstatusBok
284 s> \r\n
285 s> \r\n
285 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
286 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
287 s> 42\r\n
288 s> :\x00\x00\x01\x00\x02\x001
289 s> \xa1Jtotalitems\x01\xa2DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccLrevisionsize\x03Ca1\n
290 s> \r\n
291 received frame(size=58; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
292 s> 8\r\n
293 s> \x00\x00\x00\x01\x00\x02\x002
294 s> \r\n
295 s> 0\r\n
296 s> \r\n
297 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
298 response: gen[
299 {
300 b'totalitems': 1
301 },
302 {
303 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
304 b'revisionsize': 3
305 },
306 b'a1\n'
307 ]
308
309 haveparents=False should be same as above
310
311 $ sendhttpv2peer << EOF
312 > command filedata
313 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
314 > path eval:b'a'
315 > fields eval:[b'revision']
316 > haveparents eval:False
317 > EOF
318 creating http peer for wire protocol version 2
319 sending filedata command
320 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
321 s> Accept-Encoding: identity\r\n
322 s> accept: application/mercurial-exp-framing-0005\r\n
323 s> content-type: application/mercurial-exp-framing-0005\r\n
324 s> content-length: 94\r\n
325 s> host: $LOCALIP:$HGPORT\r\n (glob)
326 s> user-agent: Mercurial debugwireproto\r\n
327 s> \r\n
328 s> V\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf4Enodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
329 s> makefile('rb', None)
330 s> HTTP/1.1 200 OK\r\n
331 s> Server: testing stub value\r\n
332 s> Date: $HTTP_DATE$\r\n
333 s> Content-Type: application/mercurial-exp-framing-0005\r\n
334 s> Transfer-Encoding: chunked\r\n
335 s> \r\n
336 s> 13\r\n
337 s> \x0b\x00\x00\x01\x00\x02\x011
338 s> \xa1FstatusBok
339 s> \r\n
340 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
341 s> 42\r\n
342 s> :\x00\x00\x01\x00\x02\x001
343 s> \xa1Jtotalitems\x01\xa2DnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccLrevisionsize\x03Ca1\n
344 s> \r\n
345 received frame(size=58; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
346 s> 8\r\n
347 s> \x00\x00\x00\x01\x00\x02\x002
348 s> \r\n
349 s> 0\r\n
350 s> \r\n
351 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
352 response: gen[
353 {
354 b'totalitems': 1
355 },
356 {
357 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
358 b'revisionsize': 3
359 },
360 b'a1\n'
361 ]
362
363 haveparents=True should emit a delta
364
365 $ sendhttpv2peer << EOF
366 > command filedata
367 > nodes eval:[b'\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
368 > path eval:b'a'
369 > fields eval:[b'revision']
370 > haveparents eval:True
371 > EOF
372 creating http peer for wire protocol version 2
373 sending filedata command
374 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
375 s> Accept-Encoding: identity\r\n
376 s> accept: application/mercurial-exp-framing-0005\r\n
377 s> content-type: application/mercurial-exp-framing-0005\r\n
378 s> content-length: 94\r\n
379 s> host: $LOCALIP:$HGPORT\r\n (glob)
380 s> user-agent: Mercurial debugwireproto\r\n
381 s> \r\n
382 s> V\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf5Enodes\x81T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
383 s> makefile('rb', None)
384 s> HTTP/1.1 200 OK\r\n
385 s> Server: testing stub value\r\n
386 s> Date: $HTTP_DATE$\r\n
387 s> Content-Type: application/mercurial-exp-framing-0005\r\n
388 s> Transfer-Encoding: chunked\r\n
389 s> \r\n
390 s> 13\r\n
391 s> \x0b\x00\x00\x01\x00\x02\x011
392 s> \xa1FstatusBok
393 s> \r\n
394 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
286 s> 6e\r\n
395 s> 6e\r\n
287 s> f\x00\x00\x01\x00\x02\x001
396 s> f\x00\x00\x01\x00\x02\x001
288 s> \xa1Jtotalitems\x01\xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
397 s> \xa1Jtotalitems\x01\xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
289 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccO\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n
398 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccO\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n
290 s> \r\n
399 s> \r\n
291 received frame(size=102; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
400 received frame(size=102; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
292 s> 8\r\n
401 s> 8\r\n
293 s> \x00\x00\x00\x01\x00\x02\x002
402 s> \x00\x00\x00\x01\x00\x02\x002
294 s> \r\n
403 s> \r\n
295 s> 0\r\n
404 s> 0\r\n
296 s> \r\n
405 s> \r\n
297 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
406 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
298 response: gen[
407 response: gen[
299 {
408 {
300 b'totalitems': 1
409 b'totalitems': 1
301 },
410 },
302 {
411 {
303 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
412 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
304 b'deltasize': 15,
413 b'deltasize': 15,
305 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
414 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
306 },
415 },
307 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n'
416 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n'
308 ]
417 ]
309
418
310 Requesting multiple revisions works
419 Requesting multiple revisions works
311 (first revision should be fulltext, subsequents are deltas)
420 (first revision is a fulltext since haveparents=False by default)
312
421
313 $ sendhttpv2peer << EOF
422 $ sendhttpv2peer << EOF
314 > command filedata
423 > command filedata
315 > nodes eval:['\x2b\x4e\xb0\x73\x19\xbf\xa0\x77\xa4\x0a\x2f\x04\x91\x36\x59\xae\xf0\xda\x42\xda', '\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
424 > nodes eval:['\x2b\x4e\xb0\x73\x19\xbf\xa0\x77\xa4\x0a\x2f\x04\x91\x36\x59\xae\xf0\xda\x42\xda', '\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc']
316 > path eval:b'a'
425 > path eval:b'a'
317 > fields eval:[b'revision']
426 > fields eval:[b'revision']
318 > EOF
427 > EOF
319 creating http peer for wire protocol version 2
428 creating http peer for wire protocol version 2
320 sending filedata command
429 sending filedata command
321 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
430 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
322 s> Accept-Encoding: identity\r\n
431 s> Accept-Encoding: identity\r\n
323 s> accept: application/mercurial-exp-framing-0005\r\n
432 s> accept: application/mercurial-exp-framing-0005\r\n
324 s> content-type: application/mercurial-exp-framing-0005\r\n
433 s> content-type: application/mercurial-exp-framing-0005\r\n
325 s> content-length: 102\r\n
434 s> content-length: 102\r\n
326 s> host: $LOCALIP:$HGPORT\r\n (glob)
435 s> host: $LOCALIP:$HGPORT\r\n (glob)
327 s> user-agent: Mercurial debugwireproto\r\n
436 s> user-agent: Mercurial debugwireproto\r\n
328 s> \r\n
437 s> \r\n
329 s> ^\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
438 s> ^\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
330 s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
439 s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccDpathAaDnameHfiledata
331 s> makefile('rb', None)
440 s> makefile('rb', None)
332 s> HTTP/1.1 200 OK\r\n
441 s> HTTP/1.1 200 OK\r\n
333 s> Server: testing stub value\r\n
442 s> Server: testing stub value\r\n
334 s> Date: $HTTP_DATE$\r\n
443 s> Date: $HTTP_DATE$\r\n
335 s> Content-Type: application/mercurial-exp-framing-0005\r\n
444 s> Content-Type: application/mercurial-exp-framing-0005\r\n
336 s> Transfer-Encoding: chunked\r\n
445 s> Transfer-Encoding: chunked\r\n
337 s> \r\n
446 s> \r\n
338 s> 13\r\n
447 s> 13\r\n
339 s> \x0b\x00\x00\x01\x00\x02\x011
448 s> \x0b\x00\x00\x01\x00\x02\x011
340 s> \xa1FstatusBok
449 s> \xa1FstatusBok
341 s> \r\n
450 s> \r\n
342 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
451 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
343 s> 9b\r\n
452 s> 9b\r\n
344 s> \x93\x00\x00\x01\x00\x02\x001
453 s> \x93\x00\x00\x01\x00\x02\x001
345 s> \xa1Jtotalitems\x02\xa2DnodeT+N\xb0s\x19\xbf\xa0w\xa4\n
454 s> \xa1Jtotalitems\x02\xa2DnodeT+N\xb0s\x19\xbf\xa0w\xa4\n
346 s> /\x04\x916Y\xae\xf0\xdaB\xdaLrevisionsize\x03Ca0\n
455 s> /\x04\x916Y\xae\xf0\xdaB\xdaLrevisionsize\x03Ca0\n
347 s> \xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
456 s> \xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
348 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccO\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n
457 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccO\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n
349 s> \r\n
458 s> \r\n
350 received frame(size=147; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
459 received frame(size=147; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
351 s> 8\r\n
460 s> 8\r\n
352 s> \x00\x00\x00\x01\x00\x02\x002
461 s> \x00\x00\x00\x01\x00\x02\x002
353 s> \r\n
462 s> \r\n
354 s> 0\r\n
463 s> 0\r\n
355 s> \r\n
464 s> \r\n
356 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
465 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
357 response: gen[
466 response: gen[
358 {
467 {
359 b'totalitems': 2
468 b'totalitems': 2
360 },
469 },
361 {
470 {
362 b'node': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
471 b'node': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
363 b'revisionsize': 3
472 b'revisionsize': 3
364 },
473 },
365 b'a0\n',
474 b'a0\n',
366 {
475 {
367 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
476 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
368 b'deltasize': 15,
477 b'deltasize': 15,
369 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
478 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
370 },
479 },
371 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n'
480 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n'
372 ]
481 ]
373
482
374 Revisions are sorted by DAG order, parents first
483 Revisions are sorted by DAG order, parents first
375
484
376 $ sendhttpv2peer << EOF
485 $ sendhttpv2peer << EOF
377 > command filedata
486 > command filedata
378 > nodes eval:['\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc', '\x2b\x4e\xb0\x73\x19\xbf\xa0\x77\xa4\x0a\x2f\x04\x91\x36\x59\xae\xf0\xda\x42\xda']
487 > nodes eval:['\x9a\x38\x12\x29\x97\xb3\xac\x97\xbe\x2a\x9a\xa2\xe5\x56\x83\x83\x41\xfd\xf2\xcc', '\x2b\x4e\xb0\x73\x19\xbf\xa0\x77\xa4\x0a\x2f\x04\x91\x36\x59\xae\xf0\xda\x42\xda']
379 > path eval:b'a'
488 > path eval:b'a'
380 > fields eval:[b'revision']
489 > fields eval:[b'revision']
381 > EOF
490 > EOF
382 creating http peer for wire protocol version 2
491 creating http peer for wire protocol version 2
383 sending filedata command
492 sending filedata command
384 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
493 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
385 s> Accept-Encoding: identity\r\n
494 s> Accept-Encoding: identity\r\n
386 s> accept: application/mercurial-exp-framing-0005\r\n
495 s> accept: application/mercurial-exp-framing-0005\r\n
387 s> content-type: application/mercurial-exp-framing-0005\r\n
496 s> content-type: application/mercurial-exp-framing-0005\r\n
388 s> content-length: 102\r\n
497 s> content-length: 102\r\n
389 s> host: $LOCALIP:$HGPORT\r\n (glob)
498 s> host: $LOCALIP:$HGPORT\r\n (glob)
390 s> user-agent: Mercurial debugwireproto\r\n
499 s> user-agent: Mercurial debugwireproto\r\n
391 s> \r\n
500 s> \r\n
392 s> ^\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccT+N\xb0s\x19\xbf\xa0w\xa4\n
501 s> ^\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82T\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccT+N\xb0s\x19\xbf\xa0w\xa4\n
393 s> /\x04\x916Y\xae\xf0\xdaB\xdaDpathAaDnameHfiledata
502 s> /\x04\x916Y\xae\xf0\xdaB\xdaDpathAaDnameHfiledata
394 s> makefile('rb', None)
503 s> makefile('rb', None)
395 s> HTTP/1.1 200 OK\r\n
504 s> HTTP/1.1 200 OK\r\n
396 s> Server: testing stub value\r\n
505 s> Server: testing stub value\r\n
397 s> Date: $HTTP_DATE$\r\n
506 s> Date: $HTTP_DATE$\r\n
398 s> Content-Type: application/mercurial-exp-framing-0005\r\n
507 s> Content-Type: application/mercurial-exp-framing-0005\r\n
399 s> Transfer-Encoding: chunked\r\n
508 s> Transfer-Encoding: chunked\r\n
400 s> \r\n
509 s> \r\n
401 s> 13\r\n
510 s> 13\r\n
402 s> \x0b\x00\x00\x01\x00\x02\x011
511 s> \x0b\x00\x00\x01\x00\x02\x011
403 s> \xa1FstatusBok
512 s> \xa1FstatusBok
404 s> \r\n
513 s> \r\n
405 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
514 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
406 s> 9b\r\n
515 s> 9b\r\n
407 s> \x93\x00\x00\x01\x00\x02\x001
516 s> \x93\x00\x00\x01\x00\x02\x001
408 s> \xa1Jtotalitems\x02\xa2DnodeT+N\xb0s\x19\xbf\xa0w\xa4\n
517 s> \xa1Jtotalitems\x02\xa2DnodeT+N\xb0s\x19\xbf\xa0w\xa4\n
409 s> /\x04\x916Y\xae\xf0\xdaB\xdaLrevisionsize\x03Ca0\n
518 s> /\x04\x916Y\xae\xf0\xdaB\xdaLrevisionsize\x03Ca0\n
410 s> \xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
519 s> \xa3MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
411 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccO\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n
520 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xccO\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n
412 s> \r\n
521 s> \r\n
413 received frame(size=147; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
522 received frame(size=147; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
414 s> 8\r\n
523 s> 8\r\n
415 s> \x00\x00\x00\x01\x00\x02\x002
524 s> \x00\x00\x00\x01\x00\x02\x002
416 s> \r\n
525 s> \r\n
417 s> 0\r\n
526 s> 0\r\n
418 s> \r\n
527 s> \r\n
419 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
528 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
420 response: gen[
529 response: gen[
421 {
530 {
422 b'totalitems': 2
531 b'totalitems': 2
423 },
532 },
424 {
533 {
425 b'node': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
534 b'node': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
426 b'revisionsize': 3
535 b'revisionsize': 3
427 },
536 },
428 b'a0\n',
537 b'a0\n',
429 {
538 {
430 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
539 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
431 b'deltasize': 15,
540 b'deltasize': 15,
432 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
541 b'node': b'\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
433 },
542 },
434 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n'
543 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a1\n'
435 ]
544 ]
436
545
437 Requesting parents and revision data works
546 Requesting parents and revision data works
438
547
439 $ sendhttpv2peer << EOF
548 $ sendhttpv2peer << EOF
440 > command filedata
549 > command filedata
441 > nodes eval:['\x08\x79\x34\x5e\x39\x37\x72\x29\x63\x4b\x42\x0c\x63\x94\x54\x15\x67\x26\xc6\xb6']
550 > nodes eval:['\x08\x79\x34\x5e\x39\x37\x72\x29\x63\x4b\x42\x0c\x63\x94\x54\x15\x67\x26\xc6\xb6']
442 > path eval:b'a'
551 > path eval:b'a'
443 > fields eval:[b'parents', b'revision']
552 > fields eval:[b'parents', b'revision']
444 > EOF
553 > EOF
445 creating http peer for wire protocol version 2
554 creating http peer for wire protocol version 2
446 sending filedata command
555 sending filedata command
447 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
556 s> POST /api/exp-http-v2-0001/ro/filedata HTTP/1.1\r\n
448 s> Accept-Encoding: identity\r\n
557 s> Accept-Encoding: identity\r\n
449 s> accept: application/mercurial-exp-framing-0005\r\n
558 s> accept: application/mercurial-exp-framing-0005\r\n
450 s> content-type: application/mercurial-exp-framing-0005\r\n
559 s> content-type: application/mercurial-exp-framing-0005\r\n
451 s> content-length: 89\r\n
560 s> content-length: 89\r\n
452 s> host: $LOCALIP:$HGPORT\r\n (glob)
561 s> host: $LOCALIP:$HGPORT\r\n (glob)
453 s> user-agent: Mercurial debugwireproto\r\n
562 s> user-agent: Mercurial debugwireproto\r\n
454 s> \r\n
563 s> \r\n
455 s> Q\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81T\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6DpathAaDnameHfiledata
564 s> Q\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x81T\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6DpathAaDnameHfiledata
456 s> makefile('rb', None)
565 s> makefile('rb', None)
457 s> HTTP/1.1 200 OK\r\n
566 s> HTTP/1.1 200 OK\r\n
458 s> Server: testing stub value\r\n
567 s> Server: testing stub value\r\n
459 s> Date: $HTTP_DATE$\r\n
568 s> Date: $HTTP_DATE$\r\n
460 s> Content-Type: application/mercurial-exp-framing-0005\r\n
569 s> Content-Type: application/mercurial-exp-framing-0005\r\n
461 s> Transfer-Encoding: chunked\r\n
570 s> Transfer-Encoding: chunked\r\n
462 s> \r\n
571 s> \r\n
463 s> 13\r\n
572 s> 13\r\n
464 s> \x0b\x00\x00\x01\x00\x02\x011
573 s> \x0b\x00\x00\x01\x00\x02\x011
465 s> \xa1FstatusBok
574 s> \xa1FstatusBok
466 s> \r\n
575 s> \r\n
467 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
576 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
468 s> a1\r\n
577 s> 75\r\n
469 s> \x99\x00\x00\x01\x00\x02\x001
578 s> m\x00\x00\x01\x00\x02\x001
470 s> \xa1Jtotalitems\x01\xa4MdeltabasenodeT+N\xb0s\x19\xbf\xa0w\xa4\n
579 s> \xa1Jtotalitems\x01\xa3DnodeT\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6Gparents\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
471 s> /\x04\x916Y\xae\xf0\xdaB\xdaIdeltasize\x0fDnodeT\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6Gparents\x82T+N\xb0s\x19\xbf\xa0w\xa4\n
580 s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Lrevisionsize\x03Ca2\n
472 s> /\x04\x916Y\xae\xf0\xdaB\xdaT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00O\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a2\n
473 s> \r\n
581 s> \r\n
474 received frame(size=153; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
582 received frame(size=109; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
475 s> 8\r\n
583 s> 8\r\n
476 s> \x00\x00\x00\x01\x00\x02\x002
584 s> \x00\x00\x00\x01\x00\x02\x002
477 s> \r\n
585 s> \r\n
478 s> 0\r\n
586 s> 0\r\n
479 s> \r\n
587 s> \r\n
480 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
588 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
481 response: gen[
589 response: gen[
482 {
590 {
483 b'totalitems': 1
591 b'totalitems': 1
484 },
592 },
485 {
593 {
486 b'deltabasenode': b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
487 b'deltasize': 15,
488 b'node': b'\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6',
594 b'node': b'\x08y4^97r)cKB\x0cc\x94T\x15g&\xc6\xb6',
489 b'parents': [
595 b'parents': [
490 b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
596 b'+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
491 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
597 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
492 ]
598 ],
599 b'revisionsize': 3
493 },
600 },
494 b'\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x03a2\n'
601 b'a2\n'
495 ]
602 ]
496
603
497 $ cat error.log
604 $ cat error.log
@@ -1,507 +1,694
1 $ . $TESTDIR/wireprotohelpers.sh
1 $ . $TESTDIR/wireprotohelpers.sh
2
2
3 $ hg init server
3 $ hg init server
4 $ enablehttpv2 server
4 $ enablehttpv2 server
5 $ cd server
5 $ cd server
6 $ echo a0 > a
6 $ echo a0 > a
7 $ echo b0 > b
7 $ echo b0 > b
8 $ mkdir -p dir0/child0 dir0/child1 dir1
8 $ mkdir -p dir0/child0 dir0/child1 dir1
9 $ echo c0 > dir0/c
9 $ echo c0 > dir0/c
10 $ echo d0 > dir0/d
10 $ echo d0 > dir0/d
11 $ echo e0 > dir0/child0/e
11 $ echo e0 > dir0/child0/e
12 $ echo f0 > dir0/child1/f
12 $ echo f0 > dir0/child1/f
13 $ hg -q commit -A -m 'commit 0'
13 $ hg -q commit -A -m 'commit 0'
14
14
15 $ echo a1 > a
15 $ echo a1 > a
16 $ echo d1 > dir0/d
16 $ echo d1 > dir0/d
17 $ hg commit -m 'commit 1'
17 $ hg commit -m 'commit 1'
18 $ echo f0 > dir0/child1/f
18 $ echo f0 > dir0/child1/f
19 $ hg commit -m 'commit 2'
19 $ hg commit -m 'commit 2'
20 nothing changed
20 nothing changed
21 [1]
21 [1]
22
22
23 $ hg -q up -r 0
23 $ hg -q up -r 0
24 $ echo a2 > a
24 $ echo a2 > a
25 $ hg commit -m 'commit 3'
25 $ hg commit -m 'commit 3'
26 created new head
26 created new head
27
27
28 $ hg log -G -T '{rev}:{node} {desc}\n'
28 $ hg log -G -T '{rev}:{node} {desc}\n'
29 @ 2:c8757a2ffe552850d1e0dfe60d295ebf64c196d9 commit 3
29 @ 2:c8757a2ffe552850d1e0dfe60d295ebf64c196d9 commit 3
30 |
30 |
31 | o 1:650165e803375748a94df471e5b58d85763e0b29 commit 1
31 | o 1:650165e803375748a94df471e5b58d85763e0b29 commit 1
32 |/
32 |/
33 o 0:6d85ca1270b377d320098556ba5bfad34a9ee12d commit 0
33 o 0:6d85ca1270b377d320098556ba5bfad34a9ee12d commit 0
34
34
35
35
36 $ hg --debug debugindex -m
36 $ hg --debug debugindex -m
37 rev linkrev nodeid p1 p2
37 rev linkrev nodeid p1 p2
38 0 0 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
38 0 0 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
39 1 1 91e0bdbfb0dde0023fa063edc1445f207a22eac7 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 0000000000000000000000000000000000000000
39 1 1 91e0bdbfb0dde0023fa063edc1445f207a22eac7 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 0000000000000000000000000000000000000000
40 2 2 46a6721b5edaf0ea04b79a5cb3218854a4d2aba0 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 0000000000000000000000000000000000000000
40 2 2 46a6721b5edaf0ea04b79a5cb3218854a4d2aba0 1b175b595f022cfab5b809cc0ed551bd0b3ff5e4 0000000000000000000000000000000000000000
41
41
42 $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
42 $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
43 $ cat hg.pid > $DAEMON_PIDS
43 $ cat hg.pid > $DAEMON_PIDS
44
44
45 Missing arguments is an error
45 Missing arguments is an error
46
46
47 $ sendhttpv2peer << EOF
47 $ sendhttpv2peer << EOF
48 > command manifestdata
48 > command manifestdata
49 > EOF
49 > EOF
50 creating http peer for wire protocol version 2
50 creating http peer for wire protocol version 2
51 sending manifestdata command
51 sending manifestdata command
52 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
52 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
53 s> Accept-Encoding: identity\r\n
53 s> Accept-Encoding: identity\r\n
54 s> accept: application/mercurial-exp-framing-0005\r\n
54 s> accept: application/mercurial-exp-framing-0005\r\n
55 s> content-type: application/mercurial-exp-framing-0005\r\n
55 s> content-type: application/mercurial-exp-framing-0005\r\n
56 s> content-length: 27\r\n
56 s> content-length: 27\r\n
57 s> host: $LOCALIP:$HGPORT\r\n (glob)
57 s> host: $LOCALIP:$HGPORT\r\n (glob)
58 s> user-agent: Mercurial debugwireproto\r\n
58 s> user-agent: Mercurial debugwireproto\r\n
59 s> \r\n
59 s> \r\n
60 s> \x13\x00\x00\x01\x00\x01\x01\x11\xa1DnameLmanifestdata
60 s> \x13\x00\x00\x01\x00\x01\x01\x11\xa1DnameLmanifestdata
61 s> makefile('rb', None)
61 s> makefile('rb', None)
62 s> HTTP/1.1 200 OK\r\n
62 s> HTTP/1.1 200 OK\r\n
63 s> Server: testing stub value\r\n
63 s> Server: testing stub value\r\n
64 s> Date: $HTTP_DATE$\r\n
64 s> Date: $HTTP_DATE$\r\n
65 s> Content-Type: application/mercurial-exp-framing-0005\r\n
65 s> Content-Type: application/mercurial-exp-framing-0005\r\n
66 s> Transfer-Encoding: chunked\r\n
66 s> Transfer-Encoding: chunked\r\n
67 s> \r\n
67 s> \r\n
68 s> 45\r\n
68 s> 45\r\n
69 s> =\x00\x00\x01\x00\x02\x012
69 s> =\x00\x00\x01\x00\x02\x012
70 s> \xa2Eerror\xa1GmessageX\x1enodes argument must be definedFstatusEerror
70 s> \xa2Eerror\xa1GmessageX\x1enodes argument must be definedFstatusEerror
71 s> \r\n
71 s> \r\n
72 received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
72 received frame(size=61; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
73 s> 0\r\n
73 s> 0\r\n
74 s> \r\n
74 s> \r\n
75 abort: nodes argument must be defined!
75 abort: nodes argument must be defined!
76 [255]
76 [255]
77
77
78 $ sendhttpv2peer << EOF
78 $ sendhttpv2peer << EOF
79 > command manifestdata
79 > command manifestdata
80 > nodes eval:[]
80 > nodes eval:[]
81 > EOF
81 > EOF
82 creating http peer for wire protocol version 2
82 creating http peer for wire protocol version 2
83 sending manifestdata command
83 sending manifestdata command
84 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
84 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
85 s> Accept-Encoding: identity\r\n
85 s> Accept-Encoding: identity\r\n
86 s> accept: application/mercurial-exp-framing-0005\r\n
86 s> accept: application/mercurial-exp-framing-0005\r\n
87 s> content-type: application/mercurial-exp-framing-0005\r\n
87 s> content-type: application/mercurial-exp-framing-0005\r\n
88 s> content-length: 40\r\n
88 s> content-length: 40\r\n
89 s> host: $LOCALIP:$HGPORT\r\n (glob)
89 s> host: $LOCALIP:$HGPORT\r\n (glob)
90 s> user-agent: Mercurial debugwireproto\r\n
90 s> user-agent: Mercurial debugwireproto\r\n
91 s> \r\n
91 s> \r\n
92 s> \x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Enodes\x80DnameLmanifestdata
92 s> \x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa1Enodes\x80DnameLmanifestdata
93 s> makefile('rb', None)
93 s> makefile('rb', None)
94 s> HTTP/1.1 200 OK\r\n
94 s> HTTP/1.1 200 OK\r\n
95 s> Server: testing stub value\r\n
95 s> Server: testing stub value\r\n
96 s> Date: $HTTP_DATE$\r\n
96 s> Date: $HTTP_DATE$\r\n
97 s> Content-Type: application/mercurial-exp-framing-0005\r\n
97 s> Content-Type: application/mercurial-exp-framing-0005\r\n
98 s> Transfer-Encoding: chunked\r\n
98 s> Transfer-Encoding: chunked\r\n
99 s> \r\n
99 s> \r\n
100 s> 44\r\n
100 s> 44\r\n
101 s> <\x00\x00\x01\x00\x02\x012
101 s> <\x00\x00\x01\x00\x02\x012
102 s> \xa2Eerror\xa1GmessageX\x1dtree argument must be definedFstatusEerror
102 s> \xa2Eerror\xa1GmessageX\x1dtree argument must be definedFstatusEerror
103 s> \r\n
103 s> \r\n
104 received frame(size=60; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
104 received frame(size=60; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
105 s> 0\r\n
105 s> 0\r\n
106 s> \r\n
106 s> \r\n
107 abort: tree argument must be defined!
107 abort: tree argument must be defined!
108 [255]
108 [255]
109
109
110 Unknown node is an error
110 Unknown node is an error
111
111
112 $ sendhttpv2peer << EOF
112 $ sendhttpv2peer << EOF
113 > command manifestdata
113 > command manifestdata
114 > nodes eval:[b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa']
114 > nodes eval:[b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa']
115 > tree eval:b''
115 > tree eval:b''
116 > EOF
116 > EOF
117 creating http peer for wire protocol version 2
117 creating http peer for wire protocol version 2
118 sending manifestdata command
118 sending manifestdata command
119 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
119 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
120 s> Accept-Encoding: identity\r\n
120 s> Accept-Encoding: identity\r\n
121 s> accept: application/mercurial-exp-framing-0005\r\n
121 s> accept: application/mercurial-exp-framing-0005\r\n
122 s> content-type: application/mercurial-exp-framing-0005\r\n
122 s> content-type: application/mercurial-exp-framing-0005\r\n
123 s> content-length: 67\r\n
123 s> content-length: 67\r\n
124 s> host: $LOCALIP:$HGPORT\r\n (glob)
124 s> host: $LOCALIP:$HGPORT\r\n (glob)
125 s> user-agent: Mercurial debugwireproto\r\n
125 s> user-agent: Mercurial debugwireproto\r\n
126 s> \r\n
126 s> \r\n
127 s> ;\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81T\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaaDtree@DnameLmanifestdata
127 s> ;\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81T\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaaDtree@DnameLmanifestdata
128 s> makefile('rb', None)
128 s> makefile('rb', None)
129 s> HTTP/1.1 200 OK\r\n
129 s> HTTP/1.1 200 OK\r\n
130 s> Server: testing stub value\r\n
130 s> Server: testing stub value\r\n
131 s> Date: $HTTP_DATE$\r\n
131 s> Date: $HTTP_DATE$\r\n
132 s> Content-Type: application/mercurial-exp-framing-0005\r\n
132 s> Content-Type: application/mercurial-exp-framing-0005\r\n
133 s> Transfer-Encoding: chunked\r\n
133 s> Transfer-Encoding: chunked\r\n
134 s> \r\n
134 s> \r\n
135 s> 51\r\n
135 s> 51\r\n
136 s> I\x00\x00\x01\x00\x02\x012
136 s> I\x00\x00\x01\x00\x02\x012
137 s> \xa2Eerror\xa2Dargs\x81T\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaaGmessagePunknown node: %sFstatusEerror
137 s> \xa2Eerror\xa2Dargs\x81T\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaaGmessagePunknown node: %sFstatusEerror
138 s> \r\n
138 s> \r\n
139 received frame(size=73; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
139 received frame(size=73; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=eos)
140 s> 0\r\n
140 s> 0\r\n
141 s> \r\n
141 s> \r\n
142 abort: unknown node: \xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa! (esc)
142 abort: unknown node: \xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa! (esc)
143 [255]
143 [255]
144
144
145 Fetching a single revision returns just metadata by default
145 Fetching a single revision returns just metadata by default
146
146
147 $ sendhttpv2peer << EOF
147 $ sendhttpv2peer << EOF
148 > command manifestdata
148 > command manifestdata
149 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
149 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
150 > tree eval:b''
150 > tree eval:b''
151 > EOF
151 > EOF
152 creating http peer for wire protocol version 2
152 creating http peer for wire protocol version 2
153 sending manifestdata command
153 sending manifestdata command
154 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
154 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
155 s> Accept-Encoding: identity\r\n
155 s> Accept-Encoding: identity\r\n
156 s> accept: application/mercurial-exp-framing-0005\r\n
156 s> accept: application/mercurial-exp-framing-0005\r\n
157 s> content-type: application/mercurial-exp-framing-0005\r\n
157 s> content-type: application/mercurial-exp-framing-0005\r\n
158 s> content-length: 67\r\n
158 s> content-length: 67\r\n
159 s> host: $LOCALIP:$HGPORT\r\n (glob)
159 s> host: $LOCALIP:$HGPORT\r\n (glob)
160 s> user-agent: Mercurial debugwireproto\r\n
160 s> user-agent: Mercurial debugwireproto\r\n
161 s> \r\n
161 s> \r\n
162 s> ;\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
162 s> ;\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa2Enodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
163 s> makefile('rb', None)
163 s> makefile('rb', None)
164 s> HTTP/1.1 200 OK\r\n
164 s> HTTP/1.1 200 OK\r\n
165 s> Server: testing stub value\r\n
165 s> Server: testing stub value\r\n
166 s> Date: $HTTP_DATE$\r\n
166 s> Date: $HTTP_DATE$\r\n
167 s> Content-Type: application/mercurial-exp-framing-0005\r\n
167 s> Content-Type: application/mercurial-exp-framing-0005\r\n
168 s> Transfer-Encoding: chunked\r\n
168 s> Transfer-Encoding: chunked\r\n
169 s> \r\n
169 s> \r\n
170 s> 13\r\n
170 s> 13\r\n
171 s> \x0b\x00\x00\x01\x00\x02\x011
171 s> \x0b\x00\x00\x01\x00\x02\x011
172 s> \xa1FstatusBok
172 s> \xa1FstatusBok
173 s> \r\n
173 s> \r\n
174 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
174 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
175 s> 30\r\n
175 s> 30\r\n
176 s> (\x00\x00\x01\x00\x02\x001
176 s> (\x00\x00\x01\x00\x02\x001
177 s> \xa1Jtotalitems\x01\xa1DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0
177 s> \xa1Jtotalitems\x01\xa1DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0
178 s> \r\n
178 s> \r\n
179 received frame(size=40; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
179 received frame(size=40; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
180 s> 8\r\n
180 s> 8\r\n
181 s> \x00\x00\x00\x01\x00\x02\x002
181 s> \x00\x00\x00\x01\x00\x02\x002
182 s> \r\n
182 s> \r\n
183 s> 0\r\n
183 s> 0\r\n
184 s> \r\n
184 s> \r\n
185 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
185 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
186 response: gen[
186 response: gen[
187 {
187 {
188 b'totalitems': 1
188 b'totalitems': 1
189 },
189 },
190 {
190 {
191 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
191 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
192 }
192 }
193 ]
193 ]
194
194
195 Requesting parents works
195 Requesting parents works
196
196
197 $ sendhttpv2peer << EOF
197 $ sendhttpv2peer << EOF
198 > command manifestdata
198 > command manifestdata
199 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
199 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
200 > tree eval:b''
200 > tree eval:b''
201 > fields eval:[b'parents']
201 > fields eval:[b'parents']
202 > EOF
202 > EOF
203 creating http peer for wire protocol version 2
203 creating http peer for wire protocol version 2
204 sending manifestdata command
204 sending manifestdata command
205 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
205 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
206 s> Accept-Encoding: identity\r\n
206 s> Accept-Encoding: identity\r\n
207 s> accept: application/mercurial-exp-framing-0005\r\n
207 s> accept: application/mercurial-exp-framing-0005\r\n
208 s> content-type: application/mercurial-exp-framing-0005\r\n
208 s> content-type: application/mercurial-exp-framing-0005\r\n
209 s> content-length: 83\r\n
209 s> content-length: 83\r\n
210 s> host: $LOCALIP:$HGPORT\r\n (glob)
210 s> host: $LOCALIP:$HGPORT\r\n (glob)
211 s> user-agent: Mercurial debugwireproto\r\n
211 s> user-agent: Mercurial debugwireproto\r\n
212 s> \r\n
212 s> \r\n
213 s> K\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81GparentsEnodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
213 s> K\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81GparentsEnodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
214 s> makefile('rb', None)
214 s> makefile('rb', None)
215 s> HTTP/1.1 200 OK\r\n
215 s> HTTP/1.1 200 OK\r\n
216 s> Server: testing stub value\r\n
216 s> Server: testing stub value\r\n
217 s> Date: $HTTP_DATE$\r\n
217 s> Date: $HTTP_DATE$\r\n
218 s> Content-Type: application/mercurial-exp-framing-0005\r\n
218 s> Content-Type: application/mercurial-exp-framing-0005\r\n
219 s> Transfer-Encoding: chunked\r\n
219 s> Transfer-Encoding: chunked\r\n
220 s> \r\n
220 s> \r\n
221 s> 13\r\n
221 s> 13\r\n
222 s> \x0b\x00\x00\x01\x00\x02\x011
222 s> \x0b\x00\x00\x01\x00\x02\x011
223 s> \xa1FstatusBok
223 s> \xa1FstatusBok
224 s> \r\n
224 s> \r\n
225 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
225 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
226 s> 63\r\n
226 s> 63\r\n
227 s> [\x00\x00\x01\x00\x02\x001
227 s> [\x00\x00\x01\x00\x02\x001
228 s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Gparents\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
228 s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Gparents\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
229 s> \r\n
229 s> \r\n
230 received frame(size=91; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
230 received frame(size=91; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
231 s> 8\r\n
231 s> 8\r\n
232 s> \x00\x00\x00\x01\x00\x02\x002
232 s> \x00\x00\x00\x01\x00\x02\x002
233 s> \r\n
233 s> \r\n
234 s> 0\r\n
234 s> 0\r\n
235 s> \r\n
235 s> \r\n
236 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
236 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
237 response: gen[
237 response: gen[
238 {
238 {
239 b'totalitems': 1
239 b'totalitems': 1
240 },
240 },
241 {
241 {
242 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
242 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
243 b'parents': [
243 b'parents': [
244 b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
244 b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
245 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
245 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
246 ]
246 ]
247 }
247 }
248 ]
248 ]
249
249
250 Requesting revision data works
250 Requesting revision data works
251 (haveparents defaults to false, so fulltext is emitted)
251
252
252 $ sendhttpv2peer << EOF
253 $ sendhttpv2peer << EOF
253 > command manifestdata
254 > command manifestdata
254 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
255 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
255 > tree eval:b''
256 > tree eval:b''
256 > fields eval:[b'revision']
257 > fields eval:[b'revision']
257 > EOF
258 > EOF
258 creating http peer for wire protocol version 2
259 creating http peer for wire protocol version 2
259 sending manifestdata command
260 sending manifestdata command
260 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
261 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
261 s> Accept-Encoding: identity\r\n
262 s> Accept-Encoding: identity\r\n
262 s> accept: application/mercurial-exp-framing-0005\r\n
263 s> accept: application/mercurial-exp-framing-0005\r\n
263 s> content-type: application/mercurial-exp-framing-0005\r\n
264 s> content-type: application/mercurial-exp-framing-0005\r\n
264 s> content-length: 84\r\n
265 s> content-length: 84\r\n
265 s> host: $LOCALIP:$HGPORT\r\n (glob)
266 s> host: $LOCALIP:$HGPORT\r\n (glob)
266 s> user-agent: Mercurial debugwireproto\r\n
267 s> user-agent: Mercurial debugwireproto\r\n
267 s> \r\n
268 s> \r\n
268 s> L\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
269 s> L\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
269 s> makefile('rb', None)
270 s> makefile('rb', None)
270 s> HTTP/1.1 200 OK\r\n
271 s> HTTP/1.1 200 OK\r\n
271 s> Server: testing stub value\r\n
272 s> Server: testing stub value\r\n
272 s> Date: $HTTP_DATE$\r\n
273 s> Date: $HTTP_DATE$\r\n
273 s> Content-Type: application/mercurial-exp-framing-0005\r\n
274 s> Content-Type: application/mercurial-exp-framing-0005\r\n
274 s> Transfer-Encoding: chunked\r\n
275 s> Transfer-Encoding: chunked\r\n
275 s> \r\n
276 s> \r\n
276 s> 13\r\n
277 s> 13\r\n
277 s> \x0b\x00\x00\x01\x00\x02\x011
278 s> \x0b\x00\x00\x01\x00\x02\x011
278 s> \xa1FstatusBok
279 s> \xa1FstatusBok
279 s> \r\n
280 s> \r\n
280 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
281 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
282 s> 167\r\n
283 s> _\x01\x00\x01\x00\x02\x001
284 s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Lrevisionsize\x19\x01$Y\x01$a\x000879345e39377229634b420c639454156726c6b6\n
285 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
286 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
287 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
288 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
289 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
290 s> \r\n
291 received frame(size=351; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
292 s> 8\r\n
293 s> \x00\x00\x00\x01\x00\x02\x002
294 s> \r\n
295 s> 0\r\n
296 s> \r\n
297 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
298 response: gen[
299 {
300 b'totalitems': 1
301 },
302 {
303 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
304 b'revisionsize': 292
305 },
306 b'a\x000879345e39377229634b420c639454156726c6b6\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n'
307 ]
308
309 haveparents=False yields same output
310
311 $ sendhttpv2peer << EOF
312 > command manifestdata
313 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
314 > tree eval:b''
315 > fields eval:[b'revision']
316 > haveparents eval:False
317 > EOF
318 creating http peer for wire protocol version 2
319 sending manifestdata command
320 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
321 s> Accept-Encoding: identity\r\n
322 s> accept: application/mercurial-exp-framing-0005\r\n
323 s> content-type: application/mercurial-exp-framing-0005\r\n
324 s> content-length: 97\r\n
325 s> host: $LOCALIP:$HGPORT\r\n (glob)
326 s> user-agent: Mercurial debugwireproto\r\n
327 s> \r\n
328 s> Y\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf4Enodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
329 s> makefile('rb', None)
330 s> HTTP/1.1 200 OK\r\n
331 s> Server: testing stub value\r\n
332 s> Date: $HTTP_DATE$\r\n
333 s> Content-Type: application/mercurial-exp-framing-0005\r\n
334 s> Transfer-Encoding: chunked\r\n
335 s> \r\n
336 s> 13\r\n
337 s> \x0b\x00\x00\x01\x00\x02\x011
338 s> \xa1FstatusBok
339 s> \r\n
340 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
341 s> 167\r\n
342 s> _\x01\x00\x01\x00\x02\x001
343 s> \xa1Jtotalitems\x01\xa2DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Lrevisionsize\x19\x01$Y\x01$a\x000879345e39377229634b420c639454156726c6b6\n
344 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
345 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
346 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
347 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
348 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
349 s> \r\n
350 received frame(size=351; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
351 s> 8\r\n
352 s> \x00\x00\x00\x01\x00\x02\x002
353 s> \r\n
354 s> 0\r\n
355 s> \r\n
356 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
357 response: gen[
358 {
359 b'totalitems': 1
360 },
361 {
362 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
363 b'revisionsize': 292
364 },
365 b'a\x000879345e39377229634b420c639454156726c6b6\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n'
366 ]
367
368 haveparents=True will emit delta
369
370 $ sendhttpv2peer << EOF
371 > command manifestdata
372 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
373 > tree eval:b''
374 > fields eval:[b'revision']
375 > haveparents eval:True
376 > EOF
377 creating http peer for wire protocol version 2
378 sending manifestdata command
379 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
380 s> Accept-Encoding: identity\r\n
381 s> accept: application/mercurial-exp-framing-0005\r\n
382 s> content-type: application/mercurial-exp-framing-0005\r\n
383 s> content-length: 97\r\n
384 s> host: $LOCALIP:$HGPORT\r\n (glob)
385 s> user-agent: Mercurial debugwireproto\r\n
386 s> \r\n
387 s> Y\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf5Enodes\x81TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
388 s> makefile('rb', None)
389 s> HTTP/1.1 200 OK\r\n
390 s> Server: testing stub value\r\n
391 s> Date: $HTTP_DATE$\r\n
392 s> Content-Type: application/mercurial-exp-framing-0005\r\n
393 s> Transfer-Encoding: chunked\r\n
394 s> \r\n
395 s> 13\r\n
396 s> \x0b\x00\x00\x01\x00\x02\x011
397 s> \xa1FstatusBok
398 s> \r\n
399 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
281 s> 98\r\n
400 s> 98\r\n
282 s> \x90\x00\x00\x01\x00\x02\x001
401 s> \x90\x00\x00\x01\x00\x02\x001
283 s> \xa1Jtotalitems\x01\xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
402 s> \xa1Jtotalitems\x01\xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
284 s> \r\n
403 s> \r\n
285 received frame(size=144; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
404 received frame(size=144; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
286 s> 8\r\n
405 s> 8\r\n
287 s> \x00\x00\x00\x01\x00\x02\x002
406 s> \x00\x00\x00\x01\x00\x02\x002
288 s> \r\n
407 s> \r\n
289 s> 0\r\n
408 s> 0\r\n
290 s> \r\n
409 s> \r\n
291 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
410 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
292 response: gen[
411 response: gen[
293 {
412 {
294 b'totalitems': 1
413 b'totalitems': 1
295 },
414 },
296 {
415 {
297 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
416 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
298 b'deltasize': 55,
417 b'deltasize': 55,
299 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
418 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
300 },
419 },
301 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
420 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
302 ]
421 ]
303
422
304 Requesting multiple revisions works
423 Requesting multiple revisions works
424 (haveparents defaults to false, so fulltext is emitted unless a parent
425 has been emitted)
305
426
306 $ sendhttpv2peer << EOF
427 $ sendhttpv2peer << EOF
307 > command manifestdata
428 > command manifestdata
308 > nodes eval:[b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4', b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
429 > nodes eval:[b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4', b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
309 > tree eval:b''
430 > tree eval:b''
310 > fields eval:[b'revision']
431 > fields eval:[b'revision']
311 > EOF
432 > EOF
312 creating http peer for wire protocol version 2
433 creating http peer for wire protocol version 2
313 sending manifestdata command
434 sending manifestdata command
314 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
435 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
315 s> Accept-Encoding: identity\r\n
436 s> Accept-Encoding: identity\r\n
316 s> accept: application/mercurial-exp-framing-0005\r\n
437 s> accept: application/mercurial-exp-framing-0005\r\n
317 s> content-type: application/mercurial-exp-framing-0005\r\n
438 s> content-type: application/mercurial-exp-framing-0005\r\n
318 s> content-length: 105\r\n
439 s> content-length: 105\r\n
319 s> host: $LOCALIP:$HGPORT\r\n (glob)
440 s> host: $LOCALIP:$HGPORT\r\n (glob)
320 s> user-agent: Mercurial debugwireproto\r\n
441 s> user-agent: Mercurial debugwireproto\r\n
321 s> \r\n
442 s> \r\n
322 s> a\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
443 s> a\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
323 s> makefile('rb', None)
444 s> makefile('rb', None)
324 s> HTTP/1.1 200 OK\r\n
445 s> HTTP/1.1 200 OK\r\n
325 s> Server: testing stub value\r\n
446 s> Server: testing stub value\r\n
326 s> Date: $HTTP_DATE$\r\n
447 s> Date: $HTTP_DATE$\r\n
327 s> Content-Type: application/mercurial-exp-framing-0005\r\n
448 s> Content-Type: application/mercurial-exp-framing-0005\r\n
328 s> Transfer-Encoding: chunked\r\n
449 s> Transfer-Encoding: chunked\r\n
329 s> \r\n
450 s> \r\n
330 s> 13\r\n
451 s> 13\r\n
331 s> \x0b\x00\x00\x01\x00\x02\x011
452 s> \x0b\x00\x00\x01\x00\x02\x011
332 s> \xa1FstatusBok
453 s> \xa1FstatusBok
333 s> \r\n
454 s> \r\n
334 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
455 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
335 s> 1ea\r\n
456 s> 1ea\r\n
336 s> \xe2\x01\x00\x01\x00\x02\x001
457 s> \xe2\x01\x00\x01\x00\x02\x001
337 s> \xa1Jtotalitems\x02\xa2DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
458 s> \xa1Jtotalitems\x02\xa2DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
338 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
459 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
339 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
460 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
340 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
461 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
341 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
462 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
342 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
463 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
343 s> \xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
464 s> \xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
344 s> \r\n
465 s> \r\n
345 received frame(size=482; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
466 received frame(size=482; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
346 s> 8\r\n
467 s> 8\r\n
347 s> \x00\x00\x00\x01\x00\x02\x002
468 s> \x00\x00\x00\x01\x00\x02\x002
348 s> \r\n
469 s> \r\n
349 s> 0\r\n
470 s> 0\r\n
350 s> \r\n
471 s> \r\n
351 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
472 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
352 response: gen[
473 response: gen[
353 {
474 {
354 b'totalitems': 2
475 b'totalitems': 2
355 },
476 },
356 {
477 {
357 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
478 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
358 b'revisionsize': 292
479 b'revisionsize': 292
359 },
480 },
360 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
481 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
361 {
482 {
362 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
483 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
363 b'deltasize': 55,
484 b'deltasize': 55,
364 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
485 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
365 },
486 },
366 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
487 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
367 ]
488 ]
368
489
490 With haveparents=True, first revision is a delta instead of fulltext
491
492 $ sendhttpv2peer << EOF
493 > command manifestdata
494 > nodes eval:[b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4', b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
495 > tree eval:b''
496 > fields eval:[b'revision']
497 > haveparents eval:True
498 > EOF
499 creating http peer for wire protocol version 2
500 sending manifestdata command
501 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
502 s> Accept-Encoding: identity\r\n
503 s> accept: application/mercurial-exp-framing-0005\r\n
504 s> content-type: application/mercurial-exp-framing-0005\r\n
505 s> content-length: 118\r\n
506 s> host: $LOCALIP:$HGPORT\r\n (glob)
507 s> user-agent: Mercurial debugwireproto\r\n
508 s> \r\n
509 s> n\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa4Ffields\x81HrevisionKhaveparents\xf5Enodes\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
510 s> makefile('rb', None)
511 s> HTTP/1.1 200 OK\r\n
512 s> Server: testing stub value\r\n
513 s> Date: $HTTP_DATE$\r\n
514 s> Content-Type: application/mercurial-exp-framing-0005\r\n
515 s> Transfer-Encoding: chunked\r\n
516 s> \r\n
517 s> 13\r\n
518 s> \x0b\x00\x00\x01\x00\x02\x011
519 s> \xa1FstatusBok
520 s> \r\n
521 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
522 s> 1ea\r\n
523 s> \xe2\x01\x00\x01\x00\x02\x001
524 s> \xa1Jtotalitems\x02\xa2DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
525 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
526 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
527 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
528 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
529 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
530 s> \xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
531 s> \r\n
532 received frame(size=482; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
533 s> 8\r\n
534 s> \x00\x00\x00\x01\x00\x02\x002
535 s> \r\n
536 s> 0\r\n
537 s> \r\n
538 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
539 response: gen[
540 {
541 b'totalitems': 2
542 },
543 {
544 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
545 b'revisionsize': 292
546 },
547 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
548 {
549 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
550 b'deltasize': 55,
551 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
552 },
553 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
554 ]
555
369 Revisions are sorted by DAG order, parents first
556 Revisions are sorted by DAG order, parents first
370
557
371 $ sendhttpv2peer << EOF
558 $ sendhttpv2peer << EOF
372 > command manifestdata
559 > command manifestdata
373 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0', b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4']
560 > nodes eval:[b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0', b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4']
374 > tree eval:b''
561 > tree eval:b''
375 > fields eval:[b'revision']
562 > fields eval:[b'revision']
376 > EOF
563 > EOF
377 creating http peer for wire protocol version 2
564 creating http peer for wire protocol version 2
378 sending manifestdata command
565 sending manifestdata command
379 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
566 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
380 s> Accept-Encoding: identity\r\n
567 s> Accept-Encoding: identity\r\n
381 s> accept: application/mercurial-exp-framing-0005\r\n
568 s> accept: application/mercurial-exp-framing-0005\r\n
382 s> content-type: application/mercurial-exp-framing-0005\r\n
569 s> content-type: application/mercurial-exp-framing-0005\r\n
383 s> content-length: 105\r\n
570 s> content-length: 105\r\n
384 s> host: $LOCALIP:$HGPORT\r\n (glob)
571 s> host: $LOCALIP:$HGPORT\r\n (glob)
385 s> user-agent: Mercurial debugwireproto\r\n
572 s> user-agent: Mercurial debugwireproto\r\n
386 s> \r\n
573 s> \r\n
387 s> a\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Dtree@DnameLmanifestdata
574 s> a\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x81HrevisionEnodes\x82TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Dtree@DnameLmanifestdata
388 s> makefile('rb', None)
575 s> makefile('rb', None)
389 s> HTTP/1.1 200 OK\r\n
576 s> HTTP/1.1 200 OK\r\n
390 s> Server: testing stub value\r\n
577 s> Server: testing stub value\r\n
391 s> Date: $HTTP_DATE$\r\n
578 s> Date: $HTTP_DATE$\r\n
392 s> Content-Type: application/mercurial-exp-framing-0005\r\n
579 s> Content-Type: application/mercurial-exp-framing-0005\r\n
393 s> Transfer-Encoding: chunked\r\n
580 s> Transfer-Encoding: chunked\r\n
394 s> \r\n
581 s> \r\n
395 s> 13\r\n
582 s> 13\r\n
396 s> \x0b\x00\x00\x01\x00\x02\x011
583 s> \x0b\x00\x00\x01\x00\x02\x011
397 s> \xa1FstatusBok
584 s> \xa1FstatusBok
398 s> \r\n
585 s> \r\n
399 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
586 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
400 s> 1ea\r\n
587 s> 1ea\r\n
401 s> \xe2\x01\x00\x01\x00\x02\x001
588 s> \xe2\x01\x00\x01\x00\x02\x001
402 s> \xa1Jtotalitems\x02\xa2DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
589 s> \xa1Jtotalitems\x02\xa2DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
403 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
590 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
404 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
591 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
405 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
592 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
406 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
593 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
407 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
594 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
408 s> \xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
595 s> \xa3MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
409 s> \r\n
596 s> \r\n
410 received frame(size=482; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
597 received frame(size=482; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
411 s> 8\r\n
598 s> 8\r\n
412 s> \x00\x00\x00\x01\x00\x02\x002
599 s> \x00\x00\x00\x01\x00\x02\x002
413 s> \r\n
600 s> \r\n
414 s> 0\r\n
601 s> 0\r\n
415 s> \r\n
602 s> \r\n
416 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
603 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
417 response: gen[
604 response: gen[
418 {
605 {
419 b'totalitems': 2
606 b'totalitems': 2
420 },
607 },
421 {
608 {
422 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
609 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
423 b'revisionsize': 292
610 b'revisionsize': 292
424 },
611 },
425 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
612 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
426 {
613 {
427 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
614 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
428 b'deltasize': 55,
615 b'deltasize': 55,
429 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
616 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0'
430 },
617 },
431 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
618 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
432 ]
619 ]
433
620
434 Requesting parents and revision data works
621 Requesting parents and revision data works
435
622
436 $ sendhttpv2peer << EOF
623 $ sendhttpv2peer << EOF
437 > command manifestdata
624 > command manifestdata
438 > nodes eval:[b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4', b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
625 > nodes eval:[b'\x1b\x17\x5b\x59\x5f\x02\x2c\xfa\xb5\xb8\x09\xcc\x0e\xd5\x51\xbd\x0b\x3f\xf5\xe4', b'\x46\xa6\x72\x1b\x5e\xda\xf0\xea\x04\xb7\x9a\x5c\xb3\x21\x88\x54\xa4\xd2\xab\xa0']
439 > tree eval:b''
626 > tree eval:b''
440 > fields eval:[b'parents', b'revision']
627 > fields eval:[b'parents', b'revision']
441 > EOF
628 > EOF
442 creating http peer for wire protocol version 2
629 creating http peer for wire protocol version 2
443 sending manifestdata command
630 sending manifestdata command
444 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
631 s> POST /api/exp-http-v2-0001/ro/manifestdata HTTP/1.1\r\n
445 s> Accept-Encoding: identity\r\n
632 s> Accept-Encoding: identity\r\n
446 s> accept: application/mercurial-exp-framing-0005\r\n
633 s> accept: application/mercurial-exp-framing-0005\r\n
447 s> content-type: application/mercurial-exp-framing-0005\r\n
634 s> content-type: application/mercurial-exp-framing-0005\r\n
448 s> content-length: 113\r\n
635 s> content-length: 113\r\n
449 s> host: $LOCALIP:$HGPORT\r\n (glob)
636 s> host: $LOCALIP:$HGPORT\r\n (glob)
450 s> user-agent: Mercurial debugwireproto\r\n
637 s> user-agent: Mercurial debugwireproto\r\n
451 s> \r\n
638 s> \r\n
452 s> i\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
639 s> i\x00\x00\x01\x00\x01\x01\x11\xa2Dargs\xa3Ffields\x82GparentsHrevisionEnodes\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4TF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Dtree@DnameLmanifestdata
453 s> makefile('rb', None)
640 s> makefile('rb', None)
454 s> HTTP/1.1 200 OK\r\n
641 s> HTTP/1.1 200 OK\r\n
455 s> Server: testing stub value\r\n
642 s> Server: testing stub value\r\n
456 s> Date: $HTTP_DATE$\r\n
643 s> Date: $HTTP_DATE$\r\n
457 s> Content-Type: application/mercurial-exp-framing-0005\r\n
644 s> Content-Type: application/mercurial-exp-framing-0005\r\n
458 s> Transfer-Encoding: chunked\r\n
645 s> Transfer-Encoding: chunked\r\n
459 s> \r\n
646 s> \r\n
460 s> 13\r\n
647 s> 13\r\n
461 s> \x0b\x00\x00\x01\x00\x02\x011
648 s> \x0b\x00\x00\x01\x00\x02\x011
462 s> \xa1FstatusBok
649 s> \xa1FstatusBok
463 s> \r\n
650 s> \r\n
464 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
651 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
465 s> 250\r\n
652 s> 250\r\n
466 s> H\x02\x00\x01\x00\x02\x001
653 s> H\x02\x00\x01\x00\x02\x001
467 s> \xa1Jtotalitems\x02\xa3DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Gparents\x82T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
654 s> \xa1Jtotalitems\x02\xa3DnodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Gparents\x82T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Lrevisionsize\x19\x01$Y\x01$a\x002b4eb07319bfa077a40a2f04913659aef0da42da\n
468 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
655 s> b\x00819e258d31a5e1606629f365bb902a1b21ee4216\n
469 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
656 s> dir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\n
470 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
657 s> dir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\n
471 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
658 s> dir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\n
472 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
659 s> dir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n
473 s> \xa4MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Gparents\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
660 s> \xa4MdeltabasenodeT\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4Ideltasize\x187DnodeTF\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0Gparents\x82T\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X7\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n
474 s> \r\n
661 s> \r\n
475 received frame(size=584; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
662 received frame(size=584; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
476 s> 8\r\n
663 s> 8\r\n
477 s> \x00\x00\x00\x01\x00\x02\x002
664 s> \x00\x00\x00\x01\x00\x02\x002
478 s> \r\n
665 s> \r\n
479 s> 0\r\n
666 s> 0\r\n
480 s> \r\n
667 s> \r\n
481 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
668 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
482 response: gen[
669 response: gen[
483 {
670 {
484 b'totalitems': 2
671 b'totalitems': 2
485 },
672 },
486 {
673 {
487 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
674 b'node': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
488 b'parents': [
675 b'parents': [
489 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
676 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
490 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
677 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
491 ],
678 ],
492 b'revisionsize': 292
679 b'revisionsize': 292
493 },
680 },
494 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
681 b'a\x002b4eb07319bfa077a40a2f04913659aef0da42da\nb\x00819e258d31a5e1606629f365bb902a1b21ee4216\ndir0/c\x00914445346a0ca0629bd47ceb5dfe07e4d4cf2501\ndir0/child0/e\x00bbba6c06b30f443d34ff841bc985c4d0827c6be4\ndir0/child1/f\x0012fc7dcd773b5a0a929ce195228083c6ddc9cec4\ndir0/d\x00538206dc971e521540d6843abfe6d16032f6d426\n',
495 {
682 {
496 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
683 b'deltabasenode': b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
497 b'deltasize': 55,
684 b'deltasize': 55,
498 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
685 b'node': b'F\xa6r\x1b^\xda\xf0\xea\x04\xb7\x9a\\\xb3!\x88T\xa4\xd2\xab\xa0',
499 b'parents': [
686 b'parents': [
500 b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
687 b'\x1b\x17[Y_\x02,\xfa\xb5\xb8\t\xcc\x0e\xd5Q\xbd\x0b?\xf5\xe4',
501 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
688 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
502 ]
689 ]
503 },
690 },
504 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
691 b'\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00+a\x000879345e39377229634b420c639454156726c6b6\n'
505 ]
692 ]
506
693
507 $ cat error.log
694 $ cat error.log
@@ -1,605 +1,617
1 Tests for wire protocol version 2 exchange.
1 Tests for wire protocol version 2 exchange.
2 Tests in this file should be folded into existing tests once protocol
2 Tests in this file should be folded into existing tests once protocol
3 v2 has enough features that it can be enabled via #testcase in existing
3 v2 has enough features that it can be enabled via #testcase in existing
4 tests.
4 tests.
5
5
6 $ . $TESTDIR/wireprotohelpers.sh
6 $ . $TESTDIR/wireprotohelpers.sh
7 $ enablehttpv2client
7 $ enablehttpv2client
8
8
9 $ hg init server-simple
9 $ hg init server-simple
10 $ enablehttpv2 server-simple
10 $ enablehttpv2 server-simple
11 $ cd server-simple
11 $ cd server-simple
12 $ cat >> .hg/hgrc << EOF
12 $ cat >> .hg/hgrc << EOF
13 > [phases]
13 > [phases]
14 > publish = false
14 > publish = false
15 > EOF
15 > EOF
16 $ echo a0 > a
16 $ echo a0 > a
17 $ echo b0 > b
17 $ echo b0 > b
18 $ hg -q commit -A -m 'commit 0'
18 $ hg -q commit -A -m 'commit 0'
19
19
20 $ echo a1 > a
20 $ echo a1 > a
21 $ hg commit -m 'commit 1'
21 $ hg commit -m 'commit 1'
22 $ hg phase --public -r .
22 $ hg phase --public -r .
23 $ echo a2 > a
23 $ echo a2 > a
24 $ hg commit -m 'commit 2'
24 $ hg commit -m 'commit 2'
25
25
26 $ hg -q up -r 0
26 $ hg -q up -r 0
27 $ echo b1 > b
27 $ echo b1 > b
28 $ hg -q commit -m 'head 2 commit 1'
28 $ hg -q commit -m 'head 2 commit 1'
29 $ echo b2 > b
29 $ echo b2 > b
30 $ hg -q commit -m 'head 2 commit 2'
30 $ hg -q commit -m 'head 2 commit 2'
31
31
32 $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
32 $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
33 $ cat hg.pid > $DAEMON_PIDS
33 $ cat hg.pid > $DAEMON_PIDS
34
34
35 $ cd ..
35 $ cd ..
36
36
37 Test basic clone
37 Test basic clone
38
38
39 $ hg --debug clone -U http://localhost:$HGPORT client-simple
39 $ hg --debug clone -U http://localhost:$HGPORT client-simple
40 using http://localhost:$HGPORT/
40 using http://localhost:$HGPORT/
41 sending capabilities command
41 sending capabilities command
42 query 1; heads
42 query 1; heads
43 sending 2 commands
43 sending 2 commands
44 sending command heads: {}
44 sending command heads: {}
45 sending command known: {
45 sending command known: {
46 'nodes': []
46 'nodes': []
47 }
47 }
48 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
48 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
49 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
49 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
50 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
50 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
51 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
51 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
52 received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
52 received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
53 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
53 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
54 sending 1 commands
54 sending 1 commands
55 sending command changesetdata: {
55 sending command changesetdata: {
56 'fields': set([
56 'fields': set([
57 'bookmarks',
57 'bookmarks',
58 'parents',
58 'parents',
59 'phase',
59 'phase',
60 'revision'
60 'revision'
61 ]),
61 ]),
62 'noderange': [
62 'noderange': [
63 [],
63 [],
64 [
64 [
65 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
65 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
66 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
66 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
67 ]
67 ]
68 ]
68 ]
69 }
69 }
70 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
70 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
71 received frame(size=871; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
71 received frame(size=871; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
72 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
72 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
73 add changeset 3390ef850073
73 add changeset 3390ef850073
74 add changeset 4432d83626e8
74 add changeset 4432d83626e8
75 add changeset cd2534766bec
75 add changeset cd2534766bec
76 add changeset e96ae20f4188
76 add changeset e96ae20f4188
77 add changeset caa2a465451d
77 add changeset caa2a465451d
78 checking for updated bookmarks
78 checking for updated bookmarks
79 sending 1 commands
79 sending 1 commands
80 sending command manifestdata: {
80 sending command manifestdata: {
81 'fields': set([
81 'fields': set([
82 'parents',
82 'parents',
83 'revision'
83 'revision'
84 ]),
84 ]),
85 'haveparents': True,
85 'nodes': [
86 'nodes': [
86 '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
87 '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
87 '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8',
88 '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8',
88 '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
89 '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
89 '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
90 '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
90 '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&'
91 '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&'
91 ],
92 ],
92 'tree': ''
93 'tree': ''
93 }
94 }
94 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
95 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
95 received frame(size=922; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
96 received frame(size=922; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
96 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
97 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
97 sending 2 commands
98 sending 2 commands
98 sending command filedata: {
99 sending command filedata: {
99 'fields': set([
100 'fields': set([
100 'parents',
101 'parents',
101 'revision'
102 'revision'
102 ]),
103 ]),
104 'haveparents': True,
103 'nodes': [
105 'nodes': [
104 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
106 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
105 '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
107 '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
106 '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
108 '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
107 ],
109 ],
108 'path': 'a'
110 'path': 'a'
109 }
111 }
110 sending command filedata: {
112 sending command filedata: {
111 'fields': set([
113 'fields': set([
112 'parents',
114 'parents',
113 'revision'
115 'revision'
114 ]),
116 ]),
117 'haveparents': True,
115 'nodes': [
118 'nodes': [
116 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
119 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
117 '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
120 '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
118 '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3'
121 '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3'
119 ],
122 ],
120 'path': 'b'
123 'path': 'b'
121 }
124 }
122 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
125 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
123 received frame(size=389; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
126 received frame(size=389; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
124 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
127 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
125 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
128 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
126 received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
129 received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
127 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
130 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
128 updating the branch cache
131 updating the branch cache
129 new changesets 3390ef850073:caa2a465451d (3 drafts)
132 new changesets 3390ef850073:caa2a465451d (3 drafts)
130
133
131 All changesets should have been transferred
134 All changesets should have been transferred
132
135
133 $ hg -R client-simple debugindex -c
136 $ hg -R client-simple debugindex -c
134 rev linkrev nodeid p1 p2
137 rev linkrev nodeid p1 p2
135 0 0 3390ef850073 000000000000 000000000000
138 0 0 3390ef850073 000000000000 000000000000
136 1 1 4432d83626e8 3390ef850073 000000000000
139 1 1 4432d83626e8 3390ef850073 000000000000
137 2 2 cd2534766bec 4432d83626e8 000000000000
140 2 2 cd2534766bec 4432d83626e8 000000000000
138 3 3 e96ae20f4188 3390ef850073 000000000000
141 3 3 e96ae20f4188 3390ef850073 000000000000
139 4 4 caa2a465451d e96ae20f4188 000000000000
142 4 4 caa2a465451d e96ae20f4188 000000000000
140
143
141 $ hg -R client-simple log -G -T '{rev} {node} {phase}\n'
144 $ hg -R client-simple log -G -T '{rev} {node} {phase}\n'
142 o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft
145 o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft
143 |
146 |
144 o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft
147 o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft
145 |
148 |
146 | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft
149 | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft
147 | |
150 | |
148 | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
151 | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
149 |/
152 |/
150 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
153 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
151
154
152
155
153 All manifests should have been transferred
156 All manifests should have been transferred
154
157
155 $ hg -R client-simple debugindex -m
158 $ hg -R client-simple debugindex -m
156 rev linkrev nodeid p1 p2
159 rev linkrev nodeid p1 p2
157 0 0 992f4779029a 000000000000 000000000000
160 0 0 992f4779029a 000000000000 000000000000
158 1 1 a988fb43583e 992f4779029a 000000000000
161 1 1 a988fb43583e 992f4779029a 000000000000
159 2 2 ec804e488c20 a988fb43583e 000000000000
162 2 2 ec804e488c20 a988fb43583e 000000000000
160 3 3 045c7f3927da 992f4779029a 000000000000
163 3 3 045c7f3927da 992f4779029a 000000000000
161 4 4 379cb0c2e664 045c7f3927da 000000000000
164 4 4 379cb0c2e664 045c7f3927da 000000000000
162
165
163 Cloning only a specific revision works
166 Cloning only a specific revision works
164
167
165 $ hg --debug clone -U -r 4432d83626e8 http://localhost:$HGPORT client-singlehead
168 $ hg --debug clone -U -r 4432d83626e8 http://localhost:$HGPORT client-singlehead
166 using http://localhost:$HGPORT/
169 using http://localhost:$HGPORT/
167 sending capabilities command
170 sending capabilities command
168 sending 1 commands
171 sending 1 commands
169 sending command lookup: {
172 sending command lookup: {
170 'key': '4432d83626e8'
173 'key': '4432d83626e8'
171 }
174 }
172 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
175 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
173 received frame(size=21; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
176 received frame(size=21; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
174 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
177 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
175 query 1; heads
178 query 1; heads
176 sending 2 commands
179 sending 2 commands
177 sending command heads: {}
180 sending command heads: {}
178 sending command known: {
181 sending command known: {
179 'nodes': []
182 'nodes': []
180 }
183 }
181 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
184 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
182 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
185 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
183 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
186 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
184 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
187 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
185 received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
188 received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
186 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
189 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
187 sending 1 commands
190 sending 1 commands
188 sending command changesetdata: {
191 sending command changesetdata: {
189 'fields': set([
192 'fields': set([
190 'bookmarks',
193 'bookmarks',
191 'parents',
194 'parents',
192 'phase',
195 'phase',
193 'revision'
196 'revision'
194 ]),
197 ]),
195 'noderange': [
198 'noderange': [
196 [],
199 [],
197 [
200 [
198 'D2\xd86&\xe8\xa9\x86U\xf0b\xec\x1f*C\xb0\x7f\x7f\xbb\xb0'
201 'D2\xd86&\xe8\xa9\x86U\xf0b\xec\x1f*C\xb0\x7f\x7f\xbb\xb0'
199 ]
202 ]
200 ]
203 ]
201 }
204 }
202 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
205 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
203 received frame(size=353; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
206 received frame(size=353; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
204 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
207 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
205 add changeset 3390ef850073
208 add changeset 3390ef850073
206 add changeset 4432d83626e8
209 add changeset 4432d83626e8
207 checking for updated bookmarks
210 checking for updated bookmarks
208 sending 1 commands
211 sending 1 commands
209 sending command manifestdata: {
212 sending command manifestdata: {
210 'fields': set([
213 'fields': set([
211 'parents',
214 'parents',
212 'revision'
215 'revision'
213 ]),
216 ]),
217 'haveparents': True,
214 'nodes': [
218 'nodes': [
215 '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
219 '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
216 '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8'
220 '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8'
217 ],
221 ],
218 'tree': ''
222 'tree': ''
219 }
223 }
220 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
224 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
221 received frame(size=376; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
225 received frame(size=376; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
222 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
226 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
223 sending 2 commands
227 sending 2 commands
224 sending command filedata: {
228 sending command filedata: {
225 'fields': set([
229 'fields': set([
226 'parents',
230 'parents',
227 'revision'
231 'revision'
228 ]),
232 ]),
233 'haveparents': True,
229 'nodes': [
234 'nodes': [
230 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
235 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
231 '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
236 '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc'
232 ],
237 ],
233 'path': 'a'
238 'path': 'a'
234 }
239 }
235 sending command filedata: {
240 sending command filedata: {
236 'fields': set([
241 'fields': set([
237 'parents',
242 'parents',
238 'revision'
243 'revision'
239 ]),
244 ]),
245 'haveparents': True,
240 'nodes': [
246 'nodes': [
241 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16'
247 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16'
242 ],
248 ],
243 'path': 'b'
249 'path': 'b'
244 }
250 }
245 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
251 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
246 received frame(size=249; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
252 received frame(size=249; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
247 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
253 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
248 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
254 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
249 received frame(size=109; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
255 received frame(size=109; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
250 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
256 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
251 updating the branch cache
257 updating the branch cache
252 new changesets 3390ef850073:4432d83626e8
258 new changesets 3390ef850073:4432d83626e8
253
259
254 $ cd client-singlehead
260 $ cd client-singlehead
255
261
256 $ hg log -G -T '{rev} {node} {phase}\n'
262 $ hg log -G -T '{rev} {node} {phase}\n'
257 o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
263 o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
258 |
264 |
259 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
265 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
260
266
261
267
262 $ hg debugindex -m
268 $ hg debugindex -m
263 rev linkrev nodeid p1 p2
269 rev linkrev nodeid p1 p2
264 0 0 992f4779029a 000000000000 000000000000
270 0 0 992f4779029a 000000000000 000000000000
265 1 1 a988fb43583e 992f4779029a 000000000000
271 1 1 a988fb43583e 992f4779029a 000000000000
266
272
267 Incremental pull works
273 Incremental pull works
268
274
269 $ hg --debug pull
275 $ hg --debug pull
270 pulling from http://localhost:$HGPORT/
276 pulling from http://localhost:$HGPORT/
271 using http://localhost:$HGPORT/
277 using http://localhost:$HGPORT/
272 sending capabilities command
278 sending capabilities command
273 query 1; heads
279 query 1; heads
274 sending 2 commands
280 sending 2 commands
275 sending command heads: {}
281 sending command heads: {}
276 sending command known: {
282 sending command known: {
277 'nodes': [
283 'nodes': [
278 'D2\xd86&\xe8\xa9\x86U\xf0b\xec\x1f*C\xb0\x7f\x7f\xbb\xb0'
284 'D2\xd86&\xe8\xa9\x86U\xf0b\xec\x1f*C\xb0\x7f\x7f\xbb\xb0'
279 ]
285 ]
280 }
286 }
281 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
287 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
282 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
288 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
283 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
289 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
284 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
290 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
285 received frame(size=2; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
291 received frame(size=2; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
286 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
292 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
287 searching for changes
293 searching for changes
288 all local heads known remotely
294 all local heads known remotely
289 sending 1 commands
295 sending 1 commands
290 sending command changesetdata: {
296 sending command changesetdata: {
291 'fields': set([
297 'fields': set([
292 'bookmarks',
298 'bookmarks',
293 'parents',
299 'parents',
294 'phase',
300 'phase',
295 'revision'
301 'revision'
296 ]),
302 ]),
297 'noderange': [
303 'noderange': [
298 [
304 [
299 'D2\xd86&\xe8\xa9\x86U\xf0b\xec\x1f*C\xb0\x7f\x7f\xbb\xb0'
305 'D2\xd86&\xe8\xa9\x86U\xf0b\xec\x1f*C\xb0\x7f\x7f\xbb\xb0'
300 ],
306 ],
301 [
307 [
302 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
308 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
303 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
309 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
304 ]
310 ]
305 ]
311 ]
306 }
312 }
307 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
313 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
308 received frame(size=571; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
314 received frame(size=571; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
309 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
315 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
310 add changeset cd2534766bec
316 add changeset cd2534766bec
311 add changeset e96ae20f4188
317 add changeset e96ae20f4188
312 add changeset caa2a465451d
318 add changeset caa2a465451d
313 checking for updated bookmarks
319 checking for updated bookmarks
314 sending 1 commands
320 sending 1 commands
315 sending command manifestdata: {
321 sending command manifestdata: {
316 'fields': set([
322 'fields': set([
317 'parents',
323 'parents',
318 'revision'
324 'revision'
319 ]),
325 ]),
326 'haveparents': True,
320 'nodes': [
327 'nodes': [
321 '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
328 '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
322 '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
329 '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
323 '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&'
330 '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&'
324 ],
331 ],
325 'tree': ''
332 'tree': ''
326 }
333 }
327 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
334 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
328 received frame(size=559; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
335 received frame(size=559; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
329 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
336 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
330 sending 2 commands
337 sending 2 commands
331 sending command filedata: {
338 sending command filedata: {
332 'fields': set([
339 'fields': set([
333 'parents',
340 'parents',
334 'revision'
341 'revision'
335 ]),
342 ]),
343 'haveparents': True,
336 'nodes': [
344 'nodes': [
337 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
345 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
338 '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
346 '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
339 ],
347 ],
340 'path': 'a'
348 'path': 'a'
341 }
349 }
342 sending command filedata: {
350 sending command filedata: {
343 'fields': set([
351 'fields': set([
344 'parents',
352 'parents',
345 'revision'
353 'revision'
346 ]),
354 ]),
355 'haveparents': True,
347 'nodes': [
356 'nodes': [
348 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
357 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
349 '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
358 '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
350 '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3'
359 '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3'
351 ],
360 ],
352 'path': 'b'
361 'path': 'b'
353 }
362 }
354 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
363 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
355 received frame(size=249; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
364 received frame(size=249; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
356 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
365 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
357 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
366 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
358 received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
367 received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
359 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
368 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
360 updating the branch cache
369 updating the branch cache
361 new changesets cd2534766bec:caa2a465451d (3 drafts)
370 new changesets cd2534766bec:caa2a465451d (3 drafts)
362 (run 'hg update' to get a working copy)
371 (run 'hg update' to get a working copy)
363
372
364 $ hg log -G -T '{rev} {node} {phase}\n'
373 $ hg log -G -T '{rev} {node} {phase}\n'
365 o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft
374 o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft
366 |
375 |
367 o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft
376 o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft
368 |
377 |
369 | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft
378 | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft
370 | |
379 | |
371 | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
380 | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
372 |/
381 |/
373 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
382 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
374
383
375
384
376 $ hg debugindex -m
385 $ hg debugindex -m
377 rev linkrev nodeid p1 p2
386 rev linkrev nodeid p1 p2
378 0 0 992f4779029a 000000000000 000000000000
387 0 0 992f4779029a 000000000000 000000000000
379 1 1 a988fb43583e 992f4779029a 000000000000
388 1 1 a988fb43583e 992f4779029a 000000000000
380 2 2 ec804e488c20 a988fb43583e 000000000000
389 2 2 ec804e488c20 a988fb43583e 000000000000
381 3 3 045c7f3927da 992f4779029a 000000000000
390 3 3 045c7f3927da 992f4779029a 000000000000
382 4 4 379cb0c2e664 045c7f3927da 000000000000
391 4 4 379cb0c2e664 045c7f3927da 000000000000
383
392
384 Phase-only update works
393 Phase-only update works
385
394
386 $ hg -R ../server-simple phase --public -r caa2a465451dd
395 $ hg -R ../server-simple phase --public -r caa2a465451dd
387 $ hg --debug pull
396 $ hg --debug pull
388 pulling from http://localhost:$HGPORT/
397 pulling from http://localhost:$HGPORT/
389 using http://localhost:$HGPORT/
398 using http://localhost:$HGPORT/
390 sending capabilities command
399 sending capabilities command
391 query 1; heads
400 query 1; heads
392 sending 2 commands
401 sending 2 commands
393 sending command heads: {}
402 sending command heads: {}
394 sending command known: {
403 sending command known: {
395 'nodes': [
404 'nodes': [
396 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f',
405 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f',
397 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1'
406 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1'
398 ]
407 ]
399 }
408 }
400 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
409 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
401 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
410 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
402 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
411 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
403 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
412 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
404 received frame(size=3; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
413 received frame(size=3; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
405 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
414 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
406 searching for changes
415 searching for changes
407 all remote heads known locally
416 all remote heads known locally
408 sending 1 commands
417 sending 1 commands
409 sending command changesetdata: {
418 sending command changesetdata: {
410 'fields': set([
419 'fields': set([
411 'bookmarks',
420 'bookmarks',
412 'parents',
421 'parents',
413 'phase',
422 'phase',
414 'revision'
423 'revision'
415 ]),
424 ]),
416 'noderange': [
425 'noderange': [
417 [
426 [
418 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
427 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
419 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
428 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
420 ],
429 ],
421 [
430 [
422 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
431 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
423 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
432 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
424 ]
433 ]
425 ]
434 ]
426 }
435 }
427 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
436 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
428 received frame(size=92; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
437 received frame(size=92; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
429 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
438 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
430 checking for updated bookmarks
439 checking for updated bookmarks
431 2 local changesets published
440 2 local changesets published
432 (run 'hg update' to get a working copy)
441 (run 'hg update' to get a working copy)
433
442
434 $ hg log -G -T '{rev} {node} {phase}\n'
443 $ hg log -G -T '{rev} {node} {phase}\n'
435 o 4 caa2a465451dd1facda0f5b12312c355584188a1 public
444 o 4 caa2a465451dd1facda0f5b12312c355584188a1 public
436 |
445 |
437 o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 public
446 o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 public
438 |
447 |
439 | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft
448 | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft
440 | |
449 | |
441 | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
450 | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public
442 |/
451 |/
443 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
452 o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public
444
453
445
454
446 $ cd ..
455 $ cd ..
447
456
448 Bookmarks are transferred on clone
457 Bookmarks are transferred on clone
449
458
450 $ hg -R server-simple bookmark -r 3390ef850073fbc2f0dfff2244342c8e9229013a book-1
459 $ hg -R server-simple bookmark -r 3390ef850073fbc2f0dfff2244342c8e9229013a book-1
451 $ hg -R server-simple bookmark -r cd2534766bece138c7c1afdc6825302f0f62d81f book-2
460 $ hg -R server-simple bookmark -r cd2534766bece138c7c1afdc6825302f0f62d81f book-2
452
461
453 $ hg --debug clone -U http://localhost:$HGPORT/ client-bookmarks
462 $ hg --debug clone -U http://localhost:$HGPORT/ client-bookmarks
454 using http://localhost:$HGPORT/
463 using http://localhost:$HGPORT/
455 sending capabilities command
464 sending capabilities command
456 query 1; heads
465 query 1; heads
457 sending 2 commands
466 sending 2 commands
458 sending command heads: {}
467 sending command heads: {}
459 sending command known: {
468 sending command known: {
460 'nodes': []
469 'nodes': []
461 }
470 }
462 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
471 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
463 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
472 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
464 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
473 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
465 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
474 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
466 received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
475 received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
467 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
476 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
468 sending 1 commands
477 sending 1 commands
469 sending command changesetdata: {
478 sending command changesetdata: {
470 'fields': set([
479 'fields': set([
471 'bookmarks',
480 'bookmarks',
472 'parents',
481 'parents',
473 'phase',
482 'phase',
474 'revision'
483 'revision'
475 ]),
484 ]),
476 'noderange': [
485 'noderange': [
477 [],
486 [],
478 [
487 [
479 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
488 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
480 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
489 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
481 ]
490 ]
482 ]
491 ]
483 }
492 }
484 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
493 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
485 received frame(size=909; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
494 received frame(size=909; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
486 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
495 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
487 add changeset 3390ef850073
496 add changeset 3390ef850073
488 add changeset 4432d83626e8
497 add changeset 4432d83626e8
489 add changeset cd2534766bec
498 add changeset cd2534766bec
490 add changeset e96ae20f4188
499 add changeset e96ae20f4188
491 add changeset caa2a465451d
500 add changeset caa2a465451d
492 checking for updated bookmarks
501 checking for updated bookmarks
493 adding remote bookmark book-1
502 adding remote bookmark book-1
494 adding remote bookmark book-2
503 adding remote bookmark book-2
495 sending 1 commands
504 sending 1 commands
496 sending command manifestdata: {
505 sending command manifestdata: {
497 'fields': set([
506 'fields': set([
498 'parents',
507 'parents',
499 'revision'
508 'revision'
500 ]),
509 ]),
510 'haveparents': True,
501 'nodes': [
511 'nodes': [
502 '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
512 '\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN&A',
503 '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8',
513 '\xa9\x88\xfbCX>\x87\x1d\x1e\xd5u\x0e\xe0t\xc6\xd8@\xbb\xbf\xc8',
504 '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
514 '\xec\x80NH\x8c \x88\xc25\t\x9a\x10 u\x13\xbe\xcd\xc3\xdd\xa5',
505 '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
515 '\x04\\\x7f9\'\xda\x13\xe7Z\xf8\xf0\xe4\xf0HI\xe4a\xa9x\x0f',
506 '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&'
516 '7\x9c\xb0\xc2\xe6d\\y\xdd\xc5\x9a\x1dG\'\xa9\xfb\x83\n\xeb&'
507 ],
517 ],
508 'tree': ''
518 'tree': ''
509 }
519 }
510 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
520 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
511 received frame(size=922; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
521 received frame(size=922; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
512 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
522 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
513 sending 2 commands
523 sending 2 commands
514 sending command filedata: {
524 sending command filedata: {
515 'fields': set([
525 'fields': set([
516 'parents',
526 'parents',
517 'revision'
527 'revision'
518 ]),
528 ]),
529 'haveparents': True,
519 'nodes': [
530 'nodes': [
520 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
531 '+N\xb0s\x19\xbf\xa0w\xa4\n/\x04\x916Y\xae\xf0\xdaB\xda',
521 '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
532 '\x9a8\x12)\x97\xb3\xac\x97\xbe*\x9a\xa2\xe5V\x83\x83A\xfd\xf2\xcc',
522 '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
533 '\xc2\xa2\x05\xc8\xb2\xad\xe2J\xf2`b\xe5<\xd5\xbc8\x01\xd6`\xda'
523 ],
534 ],
524 'path': 'a'
535 'path': 'a'
525 }
536 }
526 sending command filedata: {
537 sending command filedata: {
527 'fields': set([
538 'fields': set([
528 'parents',
539 'parents',
529 'revision'
540 'revision'
530 ]),
541 ]),
542 'haveparents': True,
531 'nodes': [
543 'nodes': [
532 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
544 '\x81\x9e%\x8d1\xa5\xe1`f)\xf3e\xbb\x90*\x1b!\xeeB\x16',
533 '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
545 '\xb1zk\xd3g=\x9a\xb8\xce\xd5\x81\xa2\t\xf6/=\xa5\xccEx',
534 '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3'
546 '\xc5\xb1\xf9\xd3n\x1c\xc18\xbf\xb6\xef\xb3\xde\xb7]\x8c\xcad\x94\xc3'
535 ],
547 ],
536 'path': 'b'
548 'path': 'b'
537 }
549 }
538 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
550 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
539 received frame(size=389; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
551 received frame(size=389; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
540 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
552 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
541 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
553 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
542 received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
554 received frame(size=389; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
543 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
555 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
544 updating the branch cache
556 updating the branch cache
545 new changesets 3390ef850073:caa2a465451d (1 drafts)
557 new changesets 3390ef850073:caa2a465451d (1 drafts)
546
558
547 $ hg -R client-bookmarks bookmarks
559 $ hg -R client-bookmarks bookmarks
548 book-1 0:3390ef850073
560 book-1 0:3390ef850073
549 book-2 2:cd2534766bec
561 book-2 2:cd2534766bec
550
562
551 Server-side bookmark moves are reflected during `hg pull`
563 Server-side bookmark moves are reflected during `hg pull`
552
564
553 $ hg -R server-simple bookmark -r cd2534766bece138c7c1afdc6825302f0f62d81f book-1
565 $ hg -R server-simple bookmark -r cd2534766bece138c7c1afdc6825302f0f62d81f book-1
554 moving bookmark 'book-1' forward from 3390ef850073
566 moving bookmark 'book-1' forward from 3390ef850073
555
567
556 $ hg -R client-bookmarks --debug pull
568 $ hg -R client-bookmarks --debug pull
557 pulling from http://localhost:$HGPORT/
569 pulling from http://localhost:$HGPORT/
558 using http://localhost:$HGPORT/
570 using http://localhost:$HGPORT/
559 sending capabilities command
571 sending capabilities command
560 query 1; heads
572 query 1; heads
561 sending 2 commands
573 sending 2 commands
562 sending command heads: {}
574 sending command heads: {}
563 sending command known: {
575 sending command known: {
564 'nodes': [
576 'nodes': [
565 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f',
577 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f',
566 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1'
578 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1'
567 ]
579 ]
568 }
580 }
569 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
581 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
570 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
582 received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
571 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
583 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
572 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
584 received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
573 received frame(size=3; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
585 received frame(size=3; request=3; stream=2; streamflags=; type=command-response; flags=continuation)
574 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
586 received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos)
575 searching for changes
587 searching for changes
576 all remote heads known locally
588 all remote heads known locally
577 sending 1 commands
589 sending 1 commands
578 sending command changesetdata: {
590 sending command changesetdata: {
579 'fields': set([
591 'fields': set([
580 'bookmarks',
592 'bookmarks',
581 'parents',
593 'parents',
582 'phase',
594 'phase',
583 'revision'
595 'revision'
584 ]),
596 ]),
585 'noderange': [
597 'noderange': [
586 [
598 [
587 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
599 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
588 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
600 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
589 ],
601 ],
590 [
602 [
591 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
603 '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1',
592 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
604 '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f'
593 ]
605 ]
594 ]
606 ]
595 }
607 }
596 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
608 received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation)
597 received frame(size=144; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
609 received frame(size=144; request=1; stream=2; streamflags=; type=command-response; flags=continuation)
598 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
610 received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos)
599 checking for updated bookmarks
611 checking for updated bookmarks
600 updating bookmark book-1
612 updating bookmark book-1
601 (run 'hg update' to get a working copy)
613 (run 'hg update' to get a working copy)
602
614
603 $ hg -R client-bookmarks bookmarks
615 $ hg -R client-bookmarks bookmarks
604 book-1 2:cd2534766bec
616 book-1 2:cd2534766bec
605 book-2 2:cd2534766bec
617 book-2 2:cd2534766bec
General Comments 0
You need to be logged in to leave comments. Login now