##// END OF EJS Templates
debugcommands: use command executor for invoking commands...
Gregory Szorc -
r37670:fe8c6f9f default
parent child Browse files
Show More
@@ -1,3117 +1,3119
1 1 # debugcommands.py - command processing for debug* commands
2 2 #
3 3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import codecs
11 11 import collections
12 12 import difflib
13 13 import errno
14 14 import operator
15 15 import os
16 16 import random
17 17 import re
18 18 import socket
19 19 import ssl
20 20 import stat
21 21 import string
22 22 import subprocess
23 23 import sys
24 24 import tempfile
25 25 import time
26 26
27 27 from .i18n import _
28 28 from .node import (
29 29 bin,
30 30 hex,
31 31 nullhex,
32 32 nullid,
33 33 nullrev,
34 34 short,
35 35 )
36 36 from .thirdparty import (
37 37 cbor,
38 38 )
39 39 from . import (
40 40 bundle2,
41 41 changegroup,
42 42 cmdutil,
43 43 color,
44 44 context,
45 45 dagparser,
46 46 dagutil,
47 47 encoding,
48 48 error,
49 49 exchange,
50 50 extensions,
51 51 filemerge,
52 52 fileset,
53 53 formatter,
54 54 hg,
55 55 httppeer,
56 56 localrepo,
57 57 lock as lockmod,
58 58 logcmdutil,
59 59 merge as mergemod,
60 60 obsolete,
61 61 obsutil,
62 62 phases,
63 63 policy,
64 64 pvec,
65 65 pycompat,
66 66 registrar,
67 67 repair,
68 68 revlog,
69 69 revset,
70 70 revsetlang,
71 71 scmutil,
72 72 setdiscovery,
73 73 simplemerge,
74 74 smartset,
75 75 sshpeer,
76 76 sslutil,
77 77 streamclone,
78 78 templater,
79 79 treediscovery,
80 80 upgrade,
81 81 url as urlmod,
82 82 util,
83 83 vfs as vfsmod,
84 84 wireprotoframing,
85 85 wireprotoserver,
86 86 )
87 87 from .utils import (
88 88 dateutil,
89 89 procutil,
90 90 stringutil,
91 91 )
92 92
93 93 release = lockmod.release
94 94
95 95 command = registrar.command()
96 96
97 97 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
98 98 def debugancestor(ui, repo, *args):
99 99 """find the ancestor revision of two revisions in a given index"""
100 100 if len(args) == 3:
101 101 index, rev1, rev2 = args
102 102 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
103 103 lookup = r.lookup
104 104 elif len(args) == 2:
105 105 if not repo:
106 106 raise error.Abort(_('there is no Mercurial repository here '
107 107 '(.hg not found)'))
108 108 rev1, rev2 = args
109 109 r = repo.changelog
110 110 lookup = repo.lookup
111 111 else:
112 112 raise error.Abort(_('either two or three arguments required'))
113 113 a = r.ancestor(lookup(rev1), lookup(rev2))
114 114 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
115 115
116 116 @command('debugapplystreamclonebundle', [], 'FILE')
117 117 def debugapplystreamclonebundle(ui, repo, fname):
118 118 """apply a stream clone bundle file"""
119 119 f = hg.openpath(ui, fname)
120 120 gen = exchange.readbundle(ui, f, fname)
121 121 gen.apply(repo)
122 122
123 123 @command('debugbuilddag',
124 124 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
125 125 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
126 126 ('n', 'new-file', None, _('add new file at each rev'))],
127 127 _('[OPTION]... [TEXT]'))
128 128 def debugbuilddag(ui, repo, text=None,
129 129 mergeable_file=False,
130 130 overwritten_file=False,
131 131 new_file=False):
132 132 """builds a repo with a given DAG from scratch in the current empty repo
133 133
134 134 The description of the DAG is read from stdin if not given on the
135 135 command line.
136 136
137 137 Elements:
138 138
139 139 - "+n" is a linear run of n nodes based on the current default parent
140 140 - "." is a single node based on the current default parent
141 141 - "$" resets the default parent to null (implied at the start);
142 142 otherwise the default parent is always the last node created
143 143 - "<p" sets the default parent to the backref p
144 144 - "*p" is a fork at parent p, which is a backref
145 145 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
146 146 - "/p2" is a merge of the preceding node and p2
147 147 - ":tag" defines a local tag for the preceding node
148 148 - "@branch" sets the named branch for subsequent nodes
149 149 - "#...\\n" is a comment up to the end of the line
150 150
151 151 Whitespace between the above elements is ignored.
152 152
153 153 A backref is either
154 154
155 155 - a number n, which references the node curr-n, where curr is the current
156 156 node, or
157 157 - the name of a local tag you placed earlier using ":tag", or
158 158 - empty to denote the default parent.
159 159
160 160 All string valued-elements are either strictly alphanumeric, or must
161 161 be enclosed in double quotes ("..."), with "\\" as escape character.
162 162 """
163 163
164 164 if text is None:
165 165 ui.status(_("reading DAG from stdin\n"))
166 166 text = ui.fin.read()
167 167
168 168 cl = repo.changelog
169 169 if len(cl) > 0:
170 170 raise error.Abort(_('repository is not empty'))
171 171
172 172 # determine number of revs in DAG
173 173 total = 0
174 174 for type, data in dagparser.parsedag(text):
175 175 if type == 'n':
176 176 total += 1
177 177
178 178 if mergeable_file:
179 179 linesperrev = 2
180 180 # make a file with k lines per rev
181 181 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
182 182 initialmergedlines.append("")
183 183
184 184 tags = []
185 185
186 186 wlock = lock = tr = None
187 187 try:
188 188 wlock = repo.wlock()
189 189 lock = repo.lock()
190 190 tr = repo.transaction("builddag")
191 191
192 192 at = -1
193 193 atbranch = 'default'
194 194 nodeids = []
195 195 id = 0
196 196 ui.progress(_('building'), id, unit=_('revisions'), total=total)
197 197 for type, data in dagparser.parsedag(text):
198 198 if type == 'n':
199 199 ui.note(('node %s\n' % pycompat.bytestr(data)))
200 200 id, ps = data
201 201
202 202 files = []
203 203 filecontent = {}
204 204
205 205 p2 = None
206 206 if mergeable_file:
207 207 fn = "mf"
208 208 p1 = repo[ps[0]]
209 209 if len(ps) > 1:
210 210 p2 = repo[ps[1]]
211 211 pa = p1.ancestor(p2)
212 212 base, local, other = [x[fn].data() for x in (pa, p1,
213 213 p2)]
214 214 m3 = simplemerge.Merge3Text(base, local, other)
215 215 ml = [l.strip() for l in m3.merge_lines()]
216 216 ml.append("")
217 217 elif at > 0:
218 218 ml = p1[fn].data().split("\n")
219 219 else:
220 220 ml = initialmergedlines
221 221 ml[id * linesperrev] += " r%i" % id
222 222 mergedtext = "\n".join(ml)
223 223 files.append(fn)
224 224 filecontent[fn] = mergedtext
225 225
226 226 if overwritten_file:
227 227 fn = "of"
228 228 files.append(fn)
229 229 filecontent[fn] = "r%i\n" % id
230 230
231 231 if new_file:
232 232 fn = "nf%i" % id
233 233 files.append(fn)
234 234 filecontent[fn] = "r%i\n" % id
235 235 if len(ps) > 1:
236 236 if not p2:
237 237 p2 = repo[ps[1]]
238 238 for fn in p2:
239 239 if fn.startswith("nf"):
240 240 files.append(fn)
241 241 filecontent[fn] = p2[fn].data()
242 242
243 243 def fctxfn(repo, cx, path):
244 244 if path in filecontent:
245 245 return context.memfilectx(repo, cx, path,
246 246 filecontent[path])
247 247 return None
248 248
249 249 if len(ps) == 0 or ps[0] < 0:
250 250 pars = [None, None]
251 251 elif len(ps) == 1:
252 252 pars = [nodeids[ps[0]], None]
253 253 else:
254 254 pars = [nodeids[p] for p in ps]
255 255 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
256 256 date=(id, 0),
257 257 user="debugbuilddag",
258 258 extra={'branch': atbranch})
259 259 nodeid = repo.commitctx(cx)
260 260 nodeids.append(nodeid)
261 261 at = id
262 262 elif type == 'l':
263 263 id, name = data
264 264 ui.note(('tag %s\n' % name))
265 265 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
266 266 elif type == 'a':
267 267 ui.note(('branch %s\n' % data))
268 268 atbranch = data
269 269 ui.progress(_('building'), id, unit=_('revisions'), total=total)
270 270 tr.close()
271 271
272 272 if tags:
273 273 repo.vfs.write("localtags", "".join(tags))
274 274 finally:
275 275 ui.progress(_('building'), None)
276 276 release(tr, lock, wlock)
277 277
278 278 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
279 279 indent_string = ' ' * indent
280 280 if all:
281 281 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
282 282 % indent_string)
283 283
284 284 def showchunks(named):
285 285 ui.write("\n%s%s\n" % (indent_string, named))
286 286 for deltadata in gen.deltaiter():
287 287 node, p1, p2, cs, deltabase, delta, flags = deltadata
288 288 ui.write("%s%s %s %s %s %s %d\n" %
289 289 (indent_string, hex(node), hex(p1), hex(p2),
290 290 hex(cs), hex(deltabase), len(delta)))
291 291
292 292 chunkdata = gen.changelogheader()
293 293 showchunks("changelog")
294 294 chunkdata = gen.manifestheader()
295 295 showchunks("manifest")
296 296 for chunkdata in iter(gen.filelogheader, {}):
297 297 fname = chunkdata['filename']
298 298 showchunks(fname)
299 299 else:
300 300 if isinstance(gen, bundle2.unbundle20):
301 301 raise error.Abort(_('use debugbundle2 for this file'))
302 302 chunkdata = gen.changelogheader()
303 303 for deltadata in gen.deltaiter():
304 304 node, p1, p2, cs, deltabase, delta, flags = deltadata
305 305 ui.write("%s%s\n" % (indent_string, hex(node)))
306 306
307 307 def _debugobsmarkers(ui, part, indent=0, **opts):
308 308 """display version and markers contained in 'data'"""
309 309 opts = pycompat.byteskwargs(opts)
310 310 data = part.read()
311 311 indent_string = ' ' * indent
312 312 try:
313 313 version, markers = obsolete._readmarkers(data)
314 314 except error.UnknownVersion as exc:
315 315 msg = "%sunsupported version: %s (%d bytes)\n"
316 316 msg %= indent_string, exc.version, len(data)
317 317 ui.write(msg)
318 318 else:
319 319 msg = "%sversion: %d (%d bytes)\n"
320 320 msg %= indent_string, version, len(data)
321 321 ui.write(msg)
322 322 fm = ui.formatter('debugobsolete', opts)
323 323 for rawmarker in sorted(markers):
324 324 m = obsutil.marker(None, rawmarker)
325 325 fm.startitem()
326 326 fm.plain(indent_string)
327 327 cmdutil.showmarker(fm, m)
328 328 fm.end()
329 329
330 330 def _debugphaseheads(ui, data, indent=0):
331 331 """display version and markers contained in 'data'"""
332 332 indent_string = ' ' * indent
333 333 headsbyphase = phases.binarydecode(data)
334 334 for phase in phases.allphases:
335 335 for head in headsbyphase[phase]:
336 336 ui.write(indent_string)
337 337 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
338 338
339 339 def _quasirepr(thing):
340 340 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
341 341 return '{%s}' % (
342 342 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
343 343 return pycompat.bytestr(repr(thing))
344 344
345 345 def _debugbundle2(ui, gen, all=None, **opts):
346 346 """lists the contents of a bundle2"""
347 347 if not isinstance(gen, bundle2.unbundle20):
348 348 raise error.Abort(_('not a bundle2 file'))
349 349 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
350 350 parttypes = opts.get(r'part_type', [])
351 351 for part in gen.iterparts():
352 352 if parttypes and part.type not in parttypes:
353 353 continue
354 354 ui.write('%s -- %s\n' % (part.type, _quasirepr(part.params)))
355 355 if part.type == 'changegroup':
356 356 version = part.params.get('version', '01')
357 357 cg = changegroup.getunbundler(version, part, 'UN')
358 358 if not ui.quiet:
359 359 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
360 360 if part.type == 'obsmarkers':
361 361 if not ui.quiet:
362 362 _debugobsmarkers(ui, part, indent=4, **opts)
363 363 if part.type == 'phase-heads':
364 364 if not ui.quiet:
365 365 _debugphaseheads(ui, part, indent=4)
366 366
367 367 @command('debugbundle',
368 368 [('a', 'all', None, _('show all details')),
369 369 ('', 'part-type', [], _('show only the named part type')),
370 370 ('', 'spec', None, _('print the bundlespec of the bundle'))],
371 371 _('FILE'),
372 372 norepo=True)
373 373 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
374 374 """lists the contents of a bundle"""
375 375 with hg.openpath(ui, bundlepath) as f:
376 376 if spec:
377 377 spec = exchange.getbundlespec(ui, f)
378 378 ui.write('%s\n' % spec)
379 379 return
380 380
381 381 gen = exchange.readbundle(ui, f, bundlepath)
382 382 if isinstance(gen, bundle2.unbundle20):
383 383 return _debugbundle2(ui, gen, all=all, **opts)
384 384 _debugchangegroup(ui, gen, all=all, **opts)
385 385
386 386 @command('debugcapabilities',
387 387 [], _('PATH'),
388 388 norepo=True)
389 389 def debugcapabilities(ui, path, **opts):
390 390 """lists the capabilities of a remote peer"""
391 391 opts = pycompat.byteskwargs(opts)
392 392 peer = hg.peer(ui, opts, path)
393 393 caps = peer.capabilities()
394 394 ui.write(('Main capabilities:\n'))
395 395 for c in sorted(caps):
396 396 ui.write((' %s\n') % c)
397 397 b2caps = bundle2.bundle2caps(peer)
398 398 if b2caps:
399 399 ui.write(('Bundle2 capabilities:\n'))
400 400 for key, values in sorted(b2caps.iteritems()):
401 401 ui.write((' %s\n') % key)
402 402 for v in values:
403 403 ui.write((' %s\n') % v)
404 404
405 405 @command('debugcheckstate', [], '')
406 406 def debugcheckstate(ui, repo):
407 407 """validate the correctness of the current dirstate"""
408 408 parent1, parent2 = repo.dirstate.parents()
409 409 m1 = repo[parent1].manifest()
410 410 m2 = repo[parent2].manifest()
411 411 errors = 0
412 412 for f in repo.dirstate:
413 413 state = repo.dirstate[f]
414 414 if state in "nr" and f not in m1:
415 415 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
416 416 errors += 1
417 417 if state in "a" and f in m1:
418 418 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
419 419 errors += 1
420 420 if state in "m" and f not in m1 and f not in m2:
421 421 ui.warn(_("%s in state %s, but not in either manifest\n") %
422 422 (f, state))
423 423 errors += 1
424 424 for f in m1:
425 425 state = repo.dirstate[f]
426 426 if state not in "nrm":
427 427 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
428 428 errors += 1
429 429 if errors:
430 430 error = _(".hg/dirstate inconsistent with current parent's manifest")
431 431 raise error.Abort(error)
432 432
433 433 @command('debugcolor',
434 434 [('', 'style', None, _('show all configured styles'))],
435 435 'hg debugcolor')
436 436 def debugcolor(ui, repo, **opts):
437 437 """show available color, effects or style"""
438 438 ui.write(('color mode: %s\n') % ui._colormode)
439 439 if opts.get(r'style'):
440 440 return _debugdisplaystyle(ui)
441 441 else:
442 442 return _debugdisplaycolor(ui)
443 443
444 444 def _debugdisplaycolor(ui):
445 445 ui = ui.copy()
446 446 ui._styles.clear()
447 447 for effect in color._activeeffects(ui).keys():
448 448 ui._styles[effect] = effect
449 449 if ui._terminfoparams:
450 450 for k, v in ui.configitems('color'):
451 451 if k.startswith('color.'):
452 452 ui._styles[k] = k[6:]
453 453 elif k.startswith('terminfo.'):
454 454 ui._styles[k] = k[9:]
455 455 ui.write(_('available colors:\n'))
456 456 # sort label with a '_' after the other to group '_background' entry.
457 457 items = sorted(ui._styles.items(),
458 458 key=lambda i: ('_' in i[0], i[0], i[1]))
459 459 for colorname, label in items:
460 460 ui.write(('%s\n') % colorname, label=label)
461 461
462 462 def _debugdisplaystyle(ui):
463 463 ui.write(_('available style:\n'))
464 464 width = max(len(s) for s in ui._styles)
465 465 for label, effects in sorted(ui._styles.items()):
466 466 ui.write('%s' % label, label=label)
467 467 if effects:
468 468 # 50
469 469 ui.write(': ')
470 470 ui.write(' ' * (max(0, width - len(label))))
471 471 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
472 472 ui.write('\n')
473 473
474 474 @command('debugcreatestreamclonebundle', [], 'FILE')
475 475 def debugcreatestreamclonebundle(ui, repo, fname):
476 476 """create a stream clone bundle file
477 477
478 478 Stream bundles are special bundles that are essentially archives of
479 479 revlog files. They are commonly used for cloning very quickly.
480 480 """
481 481 # TODO we may want to turn this into an abort when this functionality
482 482 # is moved into `hg bundle`.
483 483 if phases.hassecret(repo):
484 484 ui.warn(_('(warning: stream clone bundle will contain secret '
485 485 'revisions)\n'))
486 486
487 487 requirements, gen = streamclone.generatebundlev1(repo)
488 488 changegroup.writechunks(ui, gen, fname)
489 489
490 490 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
491 491
492 492 @command('debugdag',
493 493 [('t', 'tags', None, _('use tags as labels')),
494 494 ('b', 'branches', None, _('annotate with branch names')),
495 495 ('', 'dots', None, _('use dots for runs')),
496 496 ('s', 'spaces', None, _('separate elements by spaces'))],
497 497 _('[OPTION]... [FILE [REV]...]'),
498 498 optionalrepo=True)
499 499 def debugdag(ui, repo, file_=None, *revs, **opts):
500 500 """format the changelog or an index DAG as a concise textual description
501 501
502 502 If you pass a revlog index, the revlog's DAG is emitted. If you list
503 503 revision numbers, they get labeled in the output as rN.
504 504
505 505 Otherwise, the changelog DAG of the current repo is emitted.
506 506 """
507 507 spaces = opts.get(r'spaces')
508 508 dots = opts.get(r'dots')
509 509 if file_:
510 510 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
511 511 file_)
512 512 revs = set((int(r) for r in revs))
513 513 def events():
514 514 for r in rlog:
515 515 yield 'n', (r, list(p for p in rlog.parentrevs(r)
516 516 if p != -1))
517 517 if r in revs:
518 518 yield 'l', (r, "r%i" % r)
519 519 elif repo:
520 520 cl = repo.changelog
521 521 tags = opts.get(r'tags')
522 522 branches = opts.get(r'branches')
523 523 if tags:
524 524 labels = {}
525 525 for l, n in repo.tags().items():
526 526 labels.setdefault(cl.rev(n), []).append(l)
527 527 def events():
528 528 b = "default"
529 529 for r in cl:
530 530 if branches:
531 531 newb = cl.read(cl.node(r))[5]['branch']
532 532 if newb != b:
533 533 yield 'a', newb
534 534 b = newb
535 535 yield 'n', (r, list(p for p in cl.parentrevs(r)
536 536 if p != -1))
537 537 if tags:
538 538 ls = labels.get(r)
539 539 if ls:
540 540 for l in ls:
541 541 yield 'l', (r, l)
542 542 else:
543 543 raise error.Abort(_('need repo for changelog dag'))
544 544
545 545 for line in dagparser.dagtextlines(events(),
546 546 addspaces=spaces,
547 547 wraplabels=True,
548 548 wrapannotations=True,
549 549 wrapnonlinear=dots,
550 550 usedots=dots,
551 551 maxlinewidth=70):
552 552 ui.write(line)
553 553 ui.write("\n")
554 554
555 555 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
556 556 def debugdata(ui, repo, file_, rev=None, **opts):
557 557 """dump the contents of a data file revision"""
558 558 opts = pycompat.byteskwargs(opts)
559 559 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
560 560 if rev is not None:
561 561 raise error.CommandError('debugdata', _('invalid arguments'))
562 562 file_, rev = None, file_
563 563 elif rev is None:
564 564 raise error.CommandError('debugdata', _('invalid arguments'))
565 565 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
566 566 try:
567 567 ui.write(r.revision(r.lookup(rev), raw=True))
568 568 except KeyError:
569 569 raise error.Abort(_('invalid revision identifier %s') % rev)
570 570
571 571 @command('debugdate',
572 572 [('e', 'extended', None, _('try extended date formats'))],
573 573 _('[-e] DATE [RANGE]'),
574 574 norepo=True, optionalrepo=True)
575 575 def debugdate(ui, date, range=None, **opts):
576 576 """parse and display a date"""
577 577 if opts[r"extended"]:
578 578 d = dateutil.parsedate(date, util.extendeddateformats)
579 579 else:
580 580 d = dateutil.parsedate(date)
581 581 ui.write(("internal: %d %d\n") % d)
582 582 ui.write(("standard: %s\n") % dateutil.datestr(d))
583 583 if range:
584 584 m = dateutil.matchdate(range)
585 585 ui.write(("match: %s\n") % m(d[0]))
586 586
587 587 @command('debugdeltachain',
588 588 cmdutil.debugrevlogopts + cmdutil.formatteropts,
589 589 _('-c|-m|FILE'),
590 590 optionalrepo=True)
591 591 def debugdeltachain(ui, repo, file_=None, **opts):
592 592 """dump information about delta chains in a revlog
593 593
594 594 Output can be templatized. Available template keywords are:
595 595
596 596 :``rev``: revision number
597 597 :``chainid``: delta chain identifier (numbered by unique base)
598 598 :``chainlen``: delta chain length to this revision
599 599 :``prevrev``: previous revision in delta chain
600 600 :``deltatype``: role of delta / how it was computed
601 601 :``compsize``: compressed size of revision
602 602 :``uncompsize``: uncompressed size of revision
603 603 :``chainsize``: total size of compressed revisions in chain
604 604 :``chainratio``: total chain size divided by uncompressed revision size
605 605 (new delta chains typically start at ratio 2.00)
606 606 :``lindist``: linear distance from base revision in delta chain to end
607 607 of this revision
608 608 :``extradist``: total size of revisions not part of this delta chain from
609 609 base of delta chain to end of this revision; a measurement
610 610 of how much extra data we need to read/seek across to read
611 611 the delta chain for this revision
612 612 :``extraratio``: extradist divided by chainsize; another representation of
613 613 how much unrelated data is needed to load this delta chain
614 614
615 615 If the repository is configured to use the sparse read, additional keywords
616 616 are available:
617 617
618 618 :``readsize``: total size of data read from the disk for a revision
619 619 (sum of the sizes of all the blocks)
620 620 :``largestblock``: size of the largest block of data read from the disk
621 621 :``readdensity``: density of useful bytes in the data read from the disk
622 622 :``srchunks``: in how many data hunks the whole revision would be read
623 623
624 624 The sparse read can be enabled with experimental.sparse-read = True
625 625 """
626 626 opts = pycompat.byteskwargs(opts)
627 627 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
628 628 index = r.index
629 629 generaldelta = r.version & revlog.FLAG_GENERALDELTA
630 630 withsparseread = getattr(r, '_withsparseread', False)
631 631
632 632 def revinfo(rev):
633 633 e = index[rev]
634 634 compsize = e[1]
635 635 uncompsize = e[2]
636 636 chainsize = 0
637 637
638 638 if generaldelta:
639 639 if e[3] == e[5]:
640 640 deltatype = 'p1'
641 641 elif e[3] == e[6]:
642 642 deltatype = 'p2'
643 643 elif e[3] == rev - 1:
644 644 deltatype = 'prev'
645 645 elif e[3] == rev:
646 646 deltatype = 'base'
647 647 else:
648 648 deltatype = 'other'
649 649 else:
650 650 if e[3] == rev:
651 651 deltatype = 'base'
652 652 else:
653 653 deltatype = 'prev'
654 654
655 655 chain = r._deltachain(rev)[0]
656 656 for iterrev in chain:
657 657 e = index[iterrev]
658 658 chainsize += e[1]
659 659
660 660 return compsize, uncompsize, deltatype, chain, chainsize
661 661
662 662 fm = ui.formatter('debugdeltachain', opts)
663 663
664 664 fm.plain(' rev chain# chainlen prev delta '
665 665 'size rawsize chainsize ratio lindist extradist '
666 666 'extraratio')
667 667 if withsparseread:
668 668 fm.plain(' readsize largestblk rddensity srchunks')
669 669 fm.plain('\n')
670 670
671 671 chainbases = {}
672 672 for rev in r:
673 673 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
674 674 chainbase = chain[0]
675 675 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
676 676 start = r.start
677 677 length = r.length
678 678 basestart = start(chainbase)
679 679 revstart = start(rev)
680 680 lineardist = revstart + comp - basestart
681 681 extradist = lineardist - chainsize
682 682 try:
683 683 prevrev = chain[-2]
684 684 except IndexError:
685 685 prevrev = -1
686 686
687 687 chainratio = float(chainsize) / float(uncomp)
688 688 extraratio = float(extradist) / float(chainsize)
689 689
690 690 fm.startitem()
691 691 fm.write('rev chainid chainlen prevrev deltatype compsize '
692 692 'uncompsize chainsize chainratio lindist extradist '
693 693 'extraratio',
694 694 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
695 695 rev, chainid, len(chain), prevrev, deltatype, comp,
696 696 uncomp, chainsize, chainratio, lineardist, extradist,
697 697 extraratio,
698 698 rev=rev, chainid=chainid, chainlen=len(chain),
699 699 prevrev=prevrev, deltatype=deltatype, compsize=comp,
700 700 uncompsize=uncomp, chainsize=chainsize,
701 701 chainratio=chainratio, lindist=lineardist,
702 702 extradist=extradist, extraratio=extraratio)
703 703 if withsparseread:
704 704 readsize = 0
705 705 largestblock = 0
706 706 srchunks = 0
707 707
708 708 for revschunk in revlog._slicechunk(r, chain):
709 709 srchunks += 1
710 710 blkend = start(revschunk[-1]) + length(revschunk[-1])
711 711 blksize = blkend - start(revschunk[0])
712 712
713 713 readsize += blksize
714 714 if largestblock < blksize:
715 715 largestblock = blksize
716 716
717 717 readdensity = float(chainsize) / float(readsize)
718 718
719 719 fm.write('readsize largestblock readdensity srchunks',
720 720 ' %10d %10d %9.5f %8d',
721 721 readsize, largestblock, readdensity, srchunks,
722 722 readsize=readsize, largestblock=largestblock,
723 723 readdensity=readdensity, srchunks=srchunks)
724 724
725 725 fm.plain('\n')
726 726
727 727 fm.end()
728 728
729 729 @command('debugdirstate|debugstate',
730 730 [('', 'nodates', None, _('do not display the saved mtime')),
731 731 ('', 'datesort', None, _('sort by saved mtime'))],
732 732 _('[OPTION]...'))
733 733 def debugstate(ui, repo, **opts):
734 734 """show the contents of the current dirstate"""
735 735
736 736 nodates = opts.get(r'nodates')
737 737 datesort = opts.get(r'datesort')
738 738
739 739 timestr = ""
740 740 if datesort:
741 741 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
742 742 else:
743 743 keyfunc = None # sort by filename
744 744 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
745 745 if ent[3] == -1:
746 746 timestr = 'unset '
747 747 elif nodates:
748 748 timestr = 'set '
749 749 else:
750 750 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
751 751 time.localtime(ent[3]))
752 752 timestr = encoding.strtolocal(timestr)
753 753 if ent[1] & 0o20000:
754 754 mode = 'lnk'
755 755 else:
756 756 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
757 757 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
758 758 for f in repo.dirstate.copies():
759 759 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
760 760
761 761 @command('debugdiscovery',
762 762 [('', 'old', None, _('use old-style discovery')),
763 763 ('', 'nonheads', None,
764 764 _('use old-style discovery with non-heads included')),
765 765 ('', 'rev', [], 'restrict discovery to this set of revs'),
766 766 ] + cmdutil.remoteopts,
767 767 _('[--rev REV] [OTHER]'))
768 768 def debugdiscovery(ui, repo, remoteurl="default", **opts):
769 769 """runs the changeset discovery protocol in isolation"""
770 770 opts = pycompat.byteskwargs(opts)
771 771 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
772 772 remote = hg.peer(repo, opts, remoteurl)
773 773 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
774 774
775 775 # make sure tests are repeatable
776 776 random.seed(12323)
777 777
778 778 def doit(pushedrevs, remoteheads, remote=remote):
779 779 if opts.get('old'):
780 780 if not util.safehasattr(remote, 'branches'):
781 781 # enable in-client legacy support
782 782 remote = localrepo.locallegacypeer(remote.local())
783 783 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
784 784 force=True)
785 785 common = set(common)
786 786 if not opts.get('nonheads'):
787 787 ui.write(("unpruned common: %s\n") %
788 788 " ".join(sorted(short(n) for n in common)))
789 789 dag = dagutil.revlogdag(repo.changelog)
790 790 all = dag.ancestorset(dag.internalizeall(common))
791 791 common = dag.externalizeall(dag.headsetofconnecteds(all))
792 792 else:
793 793 nodes = None
794 794 if pushedrevs:
795 795 revs = scmutil.revrange(repo, pushedrevs)
796 796 nodes = [repo[r].node() for r in revs]
797 797 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
798 798 ancestorsof=nodes)
799 799 common = set(common)
800 800 rheads = set(hds)
801 801 lheads = set(repo.heads())
802 802 ui.write(("common heads: %s\n") %
803 803 " ".join(sorted(short(n) for n in common)))
804 804 if lheads <= common:
805 805 ui.write(("local is subset\n"))
806 806 elif rheads <= common:
807 807 ui.write(("remote is subset\n"))
808 808
809 809 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
810 810 localrevs = opts['rev']
811 811 doit(localrevs, remoterevs)
812 812
813 813 _chunksize = 4 << 10
814 814
815 815 @command('debugdownload',
816 816 [
817 817 ('o', 'output', '', _('path')),
818 818 ],
819 819 optionalrepo=True)
820 820 def debugdownload(ui, repo, url, output=None, **opts):
821 821 """download a resource using Mercurial logic and config
822 822 """
823 823 fh = urlmod.open(ui, url, output)
824 824
825 825 dest = ui
826 826 if output:
827 827 dest = open(output, "wb", _chunksize)
828 828 try:
829 829 data = fh.read(_chunksize)
830 830 while data:
831 831 dest.write(data)
832 832 data = fh.read(_chunksize)
833 833 finally:
834 834 if output:
835 835 dest.close()
836 836
837 837 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
838 838 def debugextensions(ui, **opts):
839 839 '''show information about active extensions'''
840 840 opts = pycompat.byteskwargs(opts)
841 841 exts = extensions.extensions(ui)
842 842 hgver = util.version()
843 843 fm = ui.formatter('debugextensions', opts)
844 844 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
845 845 isinternal = extensions.ismoduleinternal(extmod)
846 846 extsource = pycompat.fsencode(extmod.__file__)
847 847 if isinternal:
848 848 exttestedwith = [] # never expose magic string to users
849 849 else:
850 850 exttestedwith = getattr(extmod, 'testedwith', '').split()
851 851 extbuglink = getattr(extmod, 'buglink', None)
852 852
853 853 fm.startitem()
854 854
855 855 if ui.quiet or ui.verbose:
856 856 fm.write('name', '%s\n', extname)
857 857 else:
858 858 fm.write('name', '%s', extname)
859 859 if isinternal or hgver in exttestedwith:
860 860 fm.plain('\n')
861 861 elif not exttestedwith:
862 862 fm.plain(_(' (untested!)\n'))
863 863 else:
864 864 lasttestedversion = exttestedwith[-1]
865 865 fm.plain(' (%s!)\n' % lasttestedversion)
866 866
867 867 fm.condwrite(ui.verbose and extsource, 'source',
868 868 _(' location: %s\n'), extsource or "")
869 869
870 870 if ui.verbose:
871 871 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
872 872 fm.data(bundled=isinternal)
873 873
874 874 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
875 875 _(' tested with: %s\n'),
876 876 fm.formatlist(exttestedwith, name='ver'))
877 877
878 878 fm.condwrite(ui.verbose and extbuglink, 'buglink',
879 879 _(' bug reporting: %s\n'), extbuglink or "")
880 880
881 881 fm.end()
882 882
883 883 @command('debugfileset',
884 884 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
885 885 _('[-r REV] FILESPEC'))
886 886 def debugfileset(ui, repo, expr, **opts):
887 887 '''parse and apply a fileset specification'''
888 888 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
889 889 if ui.verbose:
890 890 tree = fileset.parse(expr)
891 891 ui.note(fileset.prettyformat(tree), "\n")
892 892
893 893 for f in ctx.getfileset(expr):
894 894 ui.write("%s\n" % f)
895 895
896 896 @command('debugformat',
897 897 [] + cmdutil.formatteropts,
898 898 _(''))
899 899 def debugformat(ui, repo, **opts):
900 900 """display format information about the current repository
901 901
902 902 Use --verbose to get extra information about current config value and
903 903 Mercurial default."""
904 904 opts = pycompat.byteskwargs(opts)
905 905 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
906 906 maxvariantlength = max(len('format-variant'), maxvariantlength)
907 907
908 908 def makeformatname(name):
909 909 return '%s:' + (' ' * (maxvariantlength - len(name)))
910 910
911 911 fm = ui.formatter('debugformat', opts)
912 912 if fm.isplain():
913 913 def formatvalue(value):
914 914 if util.safehasattr(value, 'startswith'):
915 915 return value
916 916 if value:
917 917 return 'yes'
918 918 else:
919 919 return 'no'
920 920 else:
921 921 formatvalue = pycompat.identity
922 922
923 923 fm.plain('format-variant')
924 924 fm.plain(' ' * (maxvariantlength - len('format-variant')))
925 925 fm.plain(' repo')
926 926 if ui.verbose:
927 927 fm.plain(' config default')
928 928 fm.plain('\n')
929 929 for fv in upgrade.allformatvariant:
930 930 fm.startitem()
931 931 repovalue = fv.fromrepo(repo)
932 932 configvalue = fv.fromconfig(repo)
933 933
934 934 if repovalue != configvalue:
935 935 namelabel = 'formatvariant.name.mismatchconfig'
936 936 repolabel = 'formatvariant.repo.mismatchconfig'
937 937 elif repovalue != fv.default:
938 938 namelabel = 'formatvariant.name.mismatchdefault'
939 939 repolabel = 'formatvariant.repo.mismatchdefault'
940 940 else:
941 941 namelabel = 'formatvariant.name.uptodate'
942 942 repolabel = 'formatvariant.repo.uptodate'
943 943
944 944 fm.write('name', makeformatname(fv.name), fv.name,
945 945 label=namelabel)
946 946 fm.write('repo', ' %3s', formatvalue(repovalue),
947 947 label=repolabel)
948 948 if fv.default != configvalue:
949 949 configlabel = 'formatvariant.config.special'
950 950 else:
951 951 configlabel = 'formatvariant.config.default'
952 952 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
953 953 label=configlabel)
954 954 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
955 955 label='formatvariant.default')
956 956 fm.plain('\n')
957 957 fm.end()
958 958
959 959 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
960 960 def debugfsinfo(ui, path="."):
961 961 """show information detected about current filesystem"""
962 962 ui.write(('path: %s\n') % path)
963 963 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
964 964 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
965 965 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
966 966 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
967 967 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
968 968 casesensitive = '(unknown)'
969 969 try:
970 970 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
971 971 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
972 972 except OSError:
973 973 pass
974 974 ui.write(('case-sensitive: %s\n') % casesensitive)
975 975
976 976 @command('debuggetbundle',
977 977 [('H', 'head', [], _('id of head node'), _('ID')),
978 978 ('C', 'common', [], _('id of common node'), _('ID')),
979 979 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
980 980 _('REPO FILE [-H|-C ID]...'),
981 981 norepo=True)
982 982 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
983 983 """retrieves a bundle from a repo
984 984
985 985 Every ID must be a full-length hex node id string. Saves the bundle to the
986 986 given file.
987 987 """
988 988 opts = pycompat.byteskwargs(opts)
989 989 repo = hg.peer(ui, opts, repopath)
990 990 if not repo.capable('getbundle'):
991 991 raise error.Abort("getbundle() not supported by target repository")
992 992 args = {}
993 993 if common:
994 994 args[r'common'] = [bin(s) for s in common]
995 995 if head:
996 996 args[r'heads'] = [bin(s) for s in head]
997 997 # TODO: get desired bundlecaps from command line.
998 998 args[r'bundlecaps'] = None
999 999 bundle = repo.getbundle('debug', **args)
1000 1000
1001 1001 bundletype = opts.get('type', 'bzip2').lower()
1002 1002 btypes = {'none': 'HG10UN',
1003 1003 'bzip2': 'HG10BZ',
1004 1004 'gzip': 'HG10GZ',
1005 1005 'bundle2': 'HG20'}
1006 1006 bundletype = btypes.get(bundletype)
1007 1007 if bundletype not in bundle2.bundletypes:
1008 1008 raise error.Abort(_('unknown bundle type specified with --type'))
1009 1009 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1010 1010
1011 1011 @command('debugignore', [], '[FILE]')
1012 1012 def debugignore(ui, repo, *files, **opts):
1013 1013 """display the combined ignore pattern and information about ignored files
1014 1014
1015 1015 With no argument display the combined ignore pattern.
1016 1016
1017 1017 Given space separated file names, shows if the given file is ignored and
1018 1018 if so, show the ignore rule (file and line number) that matched it.
1019 1019 """
1020 1020 ignore = repo.dirstate._ignore
1021 1021 if not files:
1022 1022 # Show all the patterns
1023 1023 ui.write("%s\n" % pycompat.byterepr(ignore))
1024 1024 else:
1025 1025 m = scmutil.match(repo[None], pats=files)
1026 1026 for f in m.files():
1027 1027 nf = util.normpath(f)
1028 1028 ignored = None
1029 1029 ignoredata = None
1030 1030 if nf != '.':
1031 1031 if ignore(nf):
1032 1032 ignored = nf
1033 1033 ignoredata = repo.dirstate._ignorefileandline(nf)
1034 1034 else:
1035 1035 for p in util.finddirs(nf):
1036 1036 if ignore(p):
1037 1037 ignored = p
1038 1038 ignoredata = repo.dirstate._ignorefileandline(p)
1039 1039 break
1040 1040 if ignored:
1041 1041 if ignored == nf:
1042 1042 ui.write(_("%s is ignored\n") % m.uipath(f))
1043 1043 else:
1044 1044 ui.write(_("%s is ignored because of "
1045 1045 "containing folder %s\n")
1046 1046 % (m.uipath(f), ignored))
1047 1047 ignorefile, lineno, line = ignoredata
1048 1048 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1049 1049 % (ignorefile, lineno, line))
1050 1050 else:
1051 1051 ui.write(_("%s is not ignored\n") % m.uipath(f))
1052 1052
1053 1053 @command('debugindex', cmdutil.debugrevlogopts +
1054 1054 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1055 1055 _('[-f FORMAT] -c|-m|FILE'),
1056 1056 optionalrepo=True)
1057 1057 def debugindex(ui, repo, file_=None, **opts):
1058 1058 """dump the contents of an index file"""
1059 1059 opts = pycompat.byteskwargs(opts)
1060 1060 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1061 1061 format = opts.get('format', 0)
1062 1062 if format not in (0, 1):
1063 1063 raise error.Abort(_("unknown format %d") % format)
1064 1064
1065 1065 if ui.debugflag:
1066 1066 shortfn = hex
1067 1067 else:
1068 1068 shortfn = short
1069 1069
1070 1070 # There might not be anything in r, so have a sane default
1071 1071 idlen = 12
1072 1072 for i in r:
1073 1073 idlen = len(shortfn(r.node(i)))
1074 1074 break
1075 1075
1076 1076 if format == 0:
1077 1077 if ui.verbose:
1078 1078 ui.write((" rev offset length linkrev"
1079 1079 " %s %s p2\n") % ("nodeid".ljust(idlen),
1080 1080 "p1".ljust(idlen)))
1081 1081 else:
1082 1082 ui.write((" rev linkrev %s %s p2\n") % (
1083 1083 "nodeid".ljust(idlen), "p1".ljust(idlen)))
1084 1084 elif format == 1:
1085 1085 if ui.verbose:
1086 1086 ui.write((" rev flag offset length size link p1"
1087 1087 " p2 %s\n") % "nodeid".rjust(idlen))
1088 1088 else:
1089 1089 ui.write((" rev flag size link p1 p2 %s\n") %
1090 1090 "nodeid".rjust(idlen))
1091 1091
1092 1092 for i in r:
1093 1093 node = r.node(i)
1094 1094 if format == 0:
1095 1095 try:
1096 1096 pp = r.parents(node)
1097 1097 except Exception:
1098 1098 pp = [nullid, nullid]
1099 1099 if ui.verbose:
1100 1100 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
1101 1101 i, r.start(i), r.length(i), r.linkrev(i),
1102 1102 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1103 1103 else:
1104 1104 ui.write("% 6d % 7d %s %s %s\n" % (
1105 1105 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
1106 1106 shortfn(pp[1])))
1107 1107 elif format == 1:
1108 1108 pr = r.parentrevs(i)
1109 1109 if ui.verbose:
1110 1110 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
1111 1111 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1112 1112 r.linkrev(i), pr[0], pr[1], shortfn(node)))
1113 1113 else:
1114 1114 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
1115 1115 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
1116 1116 shortfn(node)))
1117 1117
1118 1118 @command('debugindexdot', cmdutil.debugrevlogopts,
1119 1119 _('-c|-m|FILE'), optionalrepo=True)
1120 1120 def debugindexdot(ui, repo, file_=None, **opts):
1121 1121 """dump an index DAG as a graphviz dot file"""
1122 1122 opts = pycompat.byteskwargs(opts)
1123 1123 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1124 1124 ui.write(("digraph G {\n"))
1125 1125 for i in r:
1126 1126 node = r.node(i)
1127 1127 pp = r.parents(node)
1128 1128 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1129 1129 if pp[1] != nullid:
1130 1130 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1131 1131 ui.write("}\n")
1132 1132
1133 1133 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1134 1134 def debuginstall(ui, **opts):
1135 1135 '''test Mercurial installation
1136 1136
1137 1137 Returns 0 on success.
1138 1138 '''
1139 1139 opts = pycompat.byteskwargs(opts)
1140 1140
1141 1141 def writetemp(contents):
1142 1142 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1143 1143 f = os.fdopen(fd, r"wb")
1144 1144 f.write(contents)
1145 1145 f.close()
1146 1146 return name
1147 1147
1148 1148 problems = 0
1149 1149
1150 1150 fm = ui.formatter('debuginstall', opts)
1151 1151 fm.startitem()
1152 1152
1153 1153 # encoding
1154 1154 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1155 1155 err = None
1156 1156 try:
1157 1157 codecs.lookup(pycompat.sysstr(encoding.encoding))
1158 1158 except LookupError as inst:
1159 1159 err = stringutil.forcebytestr(inst)
1160 1160 problems += 1
1161 1161 fm.condwrite(err, 'encodingerror', _(" %s\n"
1162 1162 " (check that your locale is properly set)\n"), err)
1163 1163
1164 1164 # Python
1165 1165 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1166 1166 pycompat.sysexecutable)
1167 1167 fm.write('pythonver', _("checking Python version (%s)\n"),
1168 1168 ("%d.%d.%d" % sys.version_info[:3]))
1169 1169 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1170 1170 os.path.dirname(pycompat.fsencode(os.__file__)))
1171 1171
1172 1172 security = set(sslutil.supportedprotocols)
1173 1173 if sslutil.hassni:
1174 1174 security.add('sni')
1175 1175
1176 1176 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1177 1177 fm.formatlist(sorted(security), name='protocol',
1178 1178 fmt='%s', sep=','))
1179 1179
1180 1180 # These are warnings, not errors. So don't increment problem count. This
1181 1181 # may change in the future.
1182 1182 if 'tls1.2' not in security:
1183 1183 fm.plain(_(' TLS 1.2 not supported by Python install; '
1184 1184 'network connections lack modern security\n'))
1185 1185 if 'sni' not in security:
1186 1186 fm.plain(_(' SNI not supported by Python install; may have '
1187 1187 'connectivity issues with some servers\n'))
1188 1188
1189 1189 # TODO print CA cert info
1190 1190
1191 1191 # hg version
1192 1192 hgver = util.version()
1193 1193 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1194 1194 hgver.split('+')[0])
1195 1195 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1196 1196 '+'.join(hgver.split('+')[1:]))
1197 1197
1198 1198 # compiled modules
1199 1199 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1200 1200 policy.policy)
1201 1201 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1202 1202 os.path.dirname(pycompat.fsencode(__file__)))
1203 1203
1204 1204 if policy.policy in ('c', 'allow'):
1205 1205 err = None
1206 1206 try:
1207 1207 from .cext import (
1208 1208 base85,
1209 1209 bdiff,
1210 1210 mpatch,
1211 1211 osutil,
1212 1212 )
1213 1213 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1214 1214 except Exception as inst:
1215 1215 err = stringutil.forcebytestr(inst)
1216 1216 problems += 1
1217 1217 fm.condwrite(err, 'extensionserror', " %s\n", err)
1218 1218
1219 1219 compengines = util.compengines._engines.values()
1220 1220 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1221 1221 fm.formatlist(sorted(e.name() for e in compengines),
1222 1222 name='compengine', fmt='%s', sep=', '))
1223 1223 fm.write('compenginesavail', _('checking available compression engines '
1224 1224 '(%s)\n'),
1225 1225 fm.formatlist(sorted(e.name() for e in compengines
1226 1226 if e.available()),
1227 1227 name='compengine', fmt='%s', sep=', '))
1228 1228 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1229 1229 fm.write('compenginesserver', _('checking available compression engines '
1230 1230 'for wire protocol (%s)\n'),
1231 1231 fm.formatlist([e.name() for e in wirecompengines
1232 1232 if e.wireprotosupport()],
1233 1233 name='compengine', fmt='%s', sep=', '))
1234 1234 re2 = 'missing'
1235 1235 if util._re2:
1236 1236 re2 = 'available'
1237 1237 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1238 1238 fm.data(re2=bool(util._re2))
1239 1239
1240 1240 # templates
1241 1241 p = templater.templatepaths()
1242 1242 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1243 1243 fm.condwrite(not p, '', _(" no template directories found\n"))
1244 1244 if p:
1245 1245 m = templater.templatepath("map-cmdline.default")
1246 1246 if m:
1247 1247 # template found, check if it is working
1248 1248 err = None
1249 1249 try:
1250 1250 templater.templater.frommapfile(m)
1251 1251 except Exception as inst:
1252 1252 err = stringutil.forcebytestr(inst)
1253 1253 p = None
1254 1254 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1255 1255 else:
1256 1256 p = None
1257 1257 fm.condwrite(p, 'defaulttemplate',
1258 1258 _("checking default template (%s)\n"), m)
1259 1259 fm.condwrite(not m, 'defaulttemplatenotfound',
1260 1260 _(" template '%s' not found\n"), "default")
1261 1261 if not p:
1262 1262 problems += 1
1263 1263 fm.condwrite(not p, '',
1264 1264 _(" (templates seem to have been installed incorrectly)\n"))
1265 1265
1266 1266 # editor
1267 1267 editor = ui.geteditor()
1268 1268 editor = util.expandpath(editor)
1269 1269 editorbin = procutil.shellsplit(editor)[0]
1270 1270 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1271 1271 cmdpath = procutil.findexe(editorbin)
1272 1272 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1273 1273 _(" No commit editor set and can't find %s in PATH\n"
1274 1274 " (specify a commit editor in your configuration"
1275 1275 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1276 1276 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1277 1277 _(" Can't find editor '%s' in PATH\n"
1278 1278 " (specify a commit editor in your configuration"
1279 1279 " file)\n"), not cmdpath and editorbin)
1280 1280 if not cmdpath and editor != 'vi':
1281 1281 problems += 1
1282 1282
1283 1283 # check username
1284 1284 username = None
1285 1285 err = None
1286 1286 try:
1287 1287 username = ui.username()
1288 1288 except error.Abort as e:
1289 1289 err = stringutil.forcebytestr(e)
1290 1290 problems += 1
1291 1291
1292 1292 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1293 1293 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1294 1294 " (specify a username in your configuration file)\n"), err)
1295 1295
1296 1296 fm.condwrite(not problems, '',
1297 1297 _("no problems detected\n"))
1298 1298 if not problems:
1299 1299 fm.data(problems=problems)
1300 1300 fm.condwrite(problems, 'problems',
1301 1301 _("%d problems detected,"
1302 1302 " please check your install!\n"), problems)
1303 1303 fm.end()
1304 1304
1305 1305 return problems
1306 1306
1307 1307 @command('debugknown', [], _('REPO ID...'), norepo=True)
1308 1308 def debugknown(ui, repopath, *ids, **opts):
1309 1309 """test whether node ids are known to a repo
1310 1310
1311 1311 Every ID must be a full-length hex node id string. Returns a list of 0s
1312 1312 and 1s indicating unknown/known.
1313 1313 """
1314 1314 opts = pycompat.byteskwargs(opts)
1315 1315 repo = hg.peer(ui, opts, repopath)
1316 1316 if not repo.capable('known'):
1317 1317 raise error.Abort("known() not supported by target repository")
1318 1318 flags = repo.known([bin(s) for s in ids])
1319 1319 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1320 1320
1321 1321 @command('debuglabelcomplete', [], _('LABEL...'))
1322 1322 def debuglabelcomplete(ui, repo, *args):
1323 1323 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1324 1324 debugnamecomplete(ui, repo, *args)
1325 1325
1326 1326 @command('debuglocks',
1327 1327 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1328 1328 ('W', 'force-wlock', None,
1329 1329 _('free the working state lock (DANGEROUS)')),
1330 1330 ('s', 'set-lock', None, _('set the store lock until stopped')),
1331 1331 ('S', 'set-wlock', None,
1332 1332 _('set the working state lock until stopped'))],
1333 1333 _('[OPTION]...'))
1334 1334 def debuglocks(ui, repo, **opts):
1335 1335 """show or modify state of locks
1336 1336
1337 1337 By default, this command will show which locks are held. This
1338 1338 includes the user and process holding the lock, the amount of time
1339 1339 the lock has been held, and the machine name where the process is
1340 1340 running if it's not local.
1341 1341
1342 1342 Locks protect the integrity of Mercurial's data, so should be
1343 1343 treated with care. System crashes or other interruptions may cause
1344 1344 locks to not be properly released, though Mercurial will usually
1345 1345 detect and remove such stale locks automatically.
1346 1346
1347 1347 However, detecting stale locks may not always be possible (for
1348 1348 instance, on a shared filesystem). Removing locks may also be
1349 1349 blocked by filesystem permissions.
1350 1350
1351 1351 Setting a lock will prevent other commands from changing the data.
1352 1352 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1353 1353 The set locks are removed when the command exits.
1354 1354
1355 1355 Returns 0 if no locks are held.
1356 1356
1357 1357 """
1358 1358
1359 1359 if opts.get(r'force_lock'):
1360 1360 repo.svfs.unlink('lock')
1361 1361 if opts.get(r'force_wlock'):
1362 1362 repo.vfs.unlink('wlock')
1363 1363 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1364 1364 return 0
1365 1365
1366 1366 locks = []
1367 1367 try:
1368 1368 if opts.get(r'set_wlock'):
1369 1369 try:
1370 1370 locks.append(repo.wlock(False))
1371 1371 except error.LockHeld:
1372 1372 raise error.Abort(_('wlock is already held'))
1373 1373 if opts.get(r'set_lock'):
1374 1374 try:
1375 1375 locks.append(repo.lock(False))
1376 1376 except error.LockHeld:
1377 1377 raise error.Abort(_('lock is already held'))
1378 1378 if len(locks):
1379 1379 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1380 1380 return 0
1381 1381 finally:
1382 1382 release(*locks)
1383 1383
1384 1384 now = time.time()
1385 1385 held = 0
1386 1386
1387 1387 def report(vfs, name, method):
1388 1388 # this causes stale locks to get reaped for more accurate reporting
1389 1389 try:
1390 1390 l = method(False)
1391 1391 except error.LockHeld:
1392 1392 l = None
1393 1393
1394 1394 if l:
1395 1395 l.release()
1396 1396 else:
1397 1397 try:
1398 1398 st = vfs.lstat(name)
1399 1399 age = now - st[stat.ST_MTIME]
1400 1400 user = util.username(st.st_uid)
1401 1401 locker = vfs.readlock(name)
1402 1402 if ":" in locker:
1403 1403 host, pid = locker.split(':')
1404 1404 if host == socket.gethostname():
1405 1405 locker = 'user %s, process %s' % (user, pid)
1406 1406 else:
1407 1407 locker = 'user %s, process %s, host %s' \
1408 1408 % (user, pid, host)
1409 1409 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1410 1410 return 1
1411 1411 except OSError as e:
1412 1412 if e.errno != errno.ENOENT:
1413 1413 raise
1414 1414
1415 1415 ui.write(("%-6s free\n") % (name + ":"))
1416 1416 return 0
1417 1417
1418 1418 held += report(repo.svfs, "lock", repo.lock)
1419 1419 held += report(repo.vfs, "wlock", repo.wlock)
1420 1420
1421 1421 return held
1422 1422
1423 1423 @command('debugmergestate', [], '')
1424 1424 def debugmergestate(ui, repo, *args):
1425 1425 """print merge state
1426 1426
1427 1427 Use --verbose to print out information about whether v1 or v2 merge state
1428 1428 was chosen."""
1429 1429 def _hashornull(h):
1430 1430 if h == nullhex:
1431 1431 return 'null'
1432 1432 else:
1433 1433 return h
1434 1434
1435 1435 def printrecords(version):
1436 1436 ui.write(('* version %d records\n') % version)
1437 1437 if version == 1:
1438 1438 records = v1records
1439 1439 else:
1440 1440 records = v2records
1441 1441
1442 1442 for rtype, record in records:
1443 1443 # pretty print some record types
1444 1444 if rtype == 'L':
1445 1445 ui.write(('local: %s\n') % record)
1446 1446 elif rtype == 'O':
1447 1447 ui.write(('other: %s\n') % record)
1448 1448 elif rtype == 'm':
1449 1449 driver, mdstate = record.split('\0', 1)
1450 1450 ui.write(('merge driver: %s (state "%s")\n')
1451 1451 % (driver, mdstate))
1452 1452 elif rtype in 'FDC':
1453 1453 r = record.split('\0')
1454 1454 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1455 1455 if version == 1:
1456 1456 onode = 'not stored in v1 format'
1457 1457 flags = r[7]
1458 1458 else:
1459 1459 onode, flags = r[7:9]
1460 1460 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1461 1461 % (f, rtype, state, _hashornull(hash)))
1462 1462 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1463 1463 ui.write((' ancestor path: %s (node %s)\n')
1464 1464 % (afile, _hashornull(anode)))
1465 1465 ui.write((' other path: %s (node %s)\n')
1466 1466 % (ofile, _hashornull(onode)))
1467 1467 elif rtype == 'f':
1468 1468 filename, rawextras = record.split('\0', 1)
1469 1469 extras = rawextras.split('\0')
1470 1470 i = 0
1471 1471 extrastrings = []
1472 1472 while i < len(extras):
1473 1473 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1474 1474 i += 2
1475 1475
1476 1476 ui.write(('file extras: %s (%s)\n')
1477 1477 % (filename, ', '.join(extrastrings)))
1478 1478 elif rtype == 'l':
1479 1479 labels = record.split('\0', 2)
1480 1480 labels = [l for l in labels if len(l) > 0]
1481 1481 ui.write(('labels:\n'))
1482 1482 ui.write((' local: %s\n' % labels[0]))
1483 1483 ui.write((' other: %s\n' % labels[1]))
1484 1484 if len(labels) > 2:
1485 1485 ui.write((' base: %s\n' % labels[2]))
1486 1486 else:
1487 1487 ui.write(('unrecognized entry: %s\t%s\n')
1488 1488 % (rtype, record.replace('\0', '\t')))
1489 1489
1490 1490 # Avoid mergestate.read() since it may raise an exception for unsupported
1491 1491 # merge state records. We shouldn't be doing this, but this is OK since this
1492 1492 # command is pretty low-level.
1493 1493 ms = mergemod.mergestate(repo)
1494 1494
1495 1495 # sort so that reasonable information is on top
1496 1496 v1records = ms._readrecordsv1()
1497 1497 v2records = ms._readrecordsv2()
1498 1498 order = 'LOml'
1499 1499 def key(r):
1500 1500 idx = order.find(r[0])
1501 1501 if idx == -1:
1502 1502 return (1, r[1])
1503 1503 else:
1504 1504 return (0, idx)
1505 1505 v1records.sort(key=key)
1506 1506 v2records.sort(key=key)
1507 1507
1508 1508 if not v1records and not v2records:
1509 1509 ui.write(('no merge state found\n'))
1510 1510 elif not v2records:
1511 1511 ui.note(('no version 2 merge state\n'))
1512 1512 printrecords(1)
1513 1513 elif ms._v1v2match(v1records, v2records):
1514 1514 ui.note(('v1 and v2 states match: using v2\n'))
1515 1515 printrecords(2)
1516 1516 else:
1517 1517 ui.note(('v1 and v2 states mismatch: using v1\n'))
1518 1518 printrecords(1)
1519 1519 if ui.verbose:
1520 1520 printrecords(2)
1521 1521
1522 1522 @command('debugnamecomplete', [], _('NAME...'))
1523 1523 def debugnamecomplete(ui, repo, *args):
1524 1524 '''complete "names" - tags, open branch names, bookmark names'''
1525 1525
1526 1526 names = set()
1527 1527 # since we previously only listed open branches, we will handle that
1528 1528 # specially (after this for loop)
1529 1529 for name, ns in repo.names.iteritems():
1530 1530 if name != 'branches':
1531 1531 names.update(ns.listnames(repo))
1532 1532 names.update(tag for (tag, heads, tip, closed)
1533 1533 in repo.branchmap().iterbranches() if not closed)
1534 1534 completions = set()
1535 1535 if not args:
1536 1536 args = ['']
1537 1537 for a in args:
1538 1538 completions.update(n for n in names if n.startswith(a))
1539 1539 ui.write('\n'.join(sorted(completions)))
1540 1540 ui.write('\n')
1541 1541
1542 1542 @command('debugobsolete',
1543 1543 [('', 'flags', 0, _('markers flag')),
1544 1544 ('', 'record-parents', False,
1545 1545 _('record parent information for the precursor')),
1546 1546 ('r', 'rev', [], _('display markers relevant to REV')),
1547 1547 ('', 'exclusive', False, _('restrict display to markers only '
1548 1548 'relevant to REV')),
1549 1549 ('', 'index', False, _('display index of the marker')),
1550 1550 ('', 'delete', [], _('delete markers specified by indices')),
1551 1551 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1552 1552 _('[OBSOLETED [REPLACEMENT ...]]'))
1553 1553 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1554 1554 """create arbitrary obsolete marker
1555 1555
1556 1556 With no arguments, displays the list of obsolescence markers."""
1557 1557
1558 1558 opts = pycompat.byteskwargs(opts)
1559 1559
1560 1560 def parsenodeid(s):
1561 1561 try:
1562 1562 # We do not use revsingle/revrange functions here to accept
1563 1563 # arbitrary node identifiers, possibly not present in the
1564 1564 # local repository.
1565 1565 n = bin(s)
1566 1566 if len(n) != len(nullid):
1567 1567 raise TypeError()
1568 1568 return n
1569 1569 except TypeError:
1570 1570 raise error.Abort('changeset references must be full hexadecimal '
1571 1571 'node identifiers')
1572 1572
1573 1573 if opts.get('delete'):
1574 1574 indices = []
1575 1575 for v in opts.get('delete'):
1576 1576 try:
1577 1577 indices.append(int(v))
1578 1578 except ValueError:
1579 1579 raise error.Abort(_('invalid index value: %r') % v,
1580 1580 hint=_('use integers for indices'))
1581 1581
1582 1582 if repo.currenttransaction():
1583 1583 raise error.Abort(_('cannot delete obsmarkers in the middle '
1584 1584 'of transaction.'))
1585 1585
1586 1586 with repo.lock():
1587 1587 n = repair.deleteobsmarkers(repo.obsstore, indices)
1588 1588 ui.write(_('deleted %i obsolescence markers\n') % n)
1589 1589
1590 1590 return
1591 1591
1592 1592 if precursor is not None:
1593 1593 if opts['rev']:
1594 1594 raise error.Abort('cannot select revision when creating marker')
1595 1595 metadata = {}
1596 1596 metadata['user'] = opts['user'] or ui.username()
1597 1597 succs = tuple(parsenodeid(succ) for succ in successors)
1598 1598 l = repo.lock()
1599 1599 try:
1600 1600 tr = repo.transaction('debugobsolete')
1601 1601 try:
1602 1602 date = opts.get('date')
1603 1603 if date:
1604 1604 date = dateutil.parsedate(date)
1605 1605 else:
1606 1606 date = None
1607 1607 prec = parsenodeid(precursor)
1608 1608 parents = None
1609 1609 if opts['record_parents']:
1610 1610 if prec not in repo.unfiltered():
1611 1611 raise error.Abort('cannot used --record-parents on '
1612 1612 'unknown changesets')
1613 1613 parents = repo.unfiltered()[prec].parents()
1614 1614 parents = tuple(p.node() for p in parents)
1615 1615 repo.obsstore.create(tr, prec, succs, opts['flags'],
1616 1616 parents=parents, date=date,
1617 1617 metadata=metadata, ui=ui)
1618 1618 tr.close()
1619 1619 except ValueError as exc:
1620 1620 raise error.Abort(_('bad obsmarker input: %s') %
1621 1621 pycompat.bytestr(exc))
1622 1622 finally:
1623 1623 tr.release()
1624 1624 finally:
1625 1625 l.release()
1626 1626 else:
1627 1627 if opts['rev']:
1628 1628 revs = scmutil.revrange(repo, opts['rev'])
1629 1629 nodes = [repo[r].node() for r in revs]
1630 1630 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1631 1631 exclusive=opts['exclusive']))
1632 1632 markers.sort(key=lambda x: x._data)
1633 1633 else:
1634 1634 markers = obsutil.getmarkers(repo)
1635 1635
1636 1636 markerstoiter = markers
1637 1637 isrelevant = lambda m: True
1638 1638 if opts.get('rev') and opts.get('index'):
1639 1639 markerstoiter = obsutil.getmarkers(repo)
1640 1640 markerset = set(markers)
1641 1641 isrelevant = lambda m: m in markerset
1642 1642
1643 1643 fm = ui.formatter('debugobsolete', opts)
1644 1644 for i, m in enumerate(markerstoiter):
1645 1645 if not isrelevant(m):
1646 1646 # marker can be irrelevant when we're iterating over a set
1647 1647 # of markers (markerstoiter) which is bigger than the set
1648 1648 # of markers we want to display (markers)
1649 1649 # this can happen if both --index and --rev options are
1650 1650 # provided and thus we need to iterate over all of the markers
1651 1651 # to get the correct indices, but only display the ones that
1652 1652 # are relevant to --rev value
1653 1653 continue
1654 1654 fm.startitem()
1655 1655 ind = i if opts.get('index') else None
1656 1656 cmdutil.showmarker(fm, m, index=ind)
1657 1657 fm.end()
1658 1658
1659 1659 @command('debugpathcomplete',
1660 1660 [('f', 'full', None, _('complete an entire path')),
1661 1661 ('n', 'normal', None, _('show only normal files')),
1662 1662 ('a', 'added', None, _('show only added files')),
1663 1663 ('r', 'removed', None, _('show only removed files'))],
1664 1664 _('FILESPEC...'))
1665 1665 def debugpathcomplete(ui, repo, *specs, **opts):
1666 1666 '''complete part or all of a tracked path
1667 1667
1668 1668 This command supports shells that offer path name completion. It
1669 1669 currently completes only files already known to the dirstate.
1670 1670
1671 1671 Completion extends only to the next path segment unless
1672 1672 --full is specified, in which case entire paths are used.'''
1673 1673
1674 1674 def complete(path, acceptable):
1675 1675 dirstate = repo.dirstate
1676 1676 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1677 1677 rootdir = repo.root + pycompat.ossep
1678 1678 if spec != repo.root and not spec.startswith(rootdir):
1679 1679 return [], []
1680 1680 if os.path.isdir(spec):
1681 1681 spec += '/'
1682 1682 spec = spec[len(rootdir):]
1683 1683 fixpaths = pycompat.ossep != '/'
1684 1684 if fixpaths:
1685 1685 spec = spec.replace(pycompat.ossep, '/')
1686 1686 speclen = len(spec)
1687 1687 fullpaths = opts[r'full']
1688 1688 files, dirs = set(), set()
1689 1689 adddir, addfile = dirs.add, files.add
1690 1690 for f, st in dirstate.iteritems():
1691 1691 if f.startswith(spec) and st[0] in acceptable:
1692 1692 if fixpaths:
1693 1693 f = f.replace('/', pycompat.ossep)
1694 1694 if fullpaths:
1695 1695 addfile(f)
1696 1696 continue
1697 1697 s = f.find(pycompat.ossep, speclen)
1698 1698 if s >= 0:
1699 1699 adddir(f[:s])
1700 1700 else:
1701 1701 addfile(f)
1702 1702 return files, dirs
1703 1703
1704 1704 acceptable = ''
1705 1705 if opts[r'normal']:
1706 1706 acceptable += 'nm'
1707 1707 if opts[r'added']:
1708 1708 acceptable += 'a'
1709 1709 if opts[r'removed']:
1710 1710 acceptable += 'r'
1711 1711 cwd = repo.getcwd()
1712 1712 if not specs:
1713 1713 specs = ['.']
1714 1714
1715 1715 files, dirs = set(), set()
1716 1716 for spec in specs:
1717 1717 f, d = complete(spec, acceptable or 'nmar')
1718 1718 files.update(f)
1719 1719 dirs.update(d)
1720 1720 files.update(dirs)
1721 1721 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1722 1722 ui.write('\n')
1723 1723
1724 1724 @command('debugpeer', [], _('PATH'), norepo=True)
1725 1725 def debugpeer(ui, path):
1726 1726 """establish a connection to a peer repository"""
1727 1727 # Always enable peer request logging. Requires --debug to display
1728 1728 # though.
1729 1729 overrides = {
1730 1730 ('devel', 'debug.peer-request'): True,
1731 1731 }
1732 1732
1733 1733 with ui.configoverride(overrides):
1734 1734 peer = hg.peer(ui, {}, path)
1735 1735
1736 1736 local = peer.local() is not None
1737 1737 canpush = peer.canpush()
1738 1738
1739 1739 ui.write(_('url: %s\n') % peer.url())
1740 1740 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1741 1741 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1742 1742
1743 1743 @command('debugpickmergetool',
1744 1744 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1745 1745 ('', 'changedelete', None, _('emulate merging change and delete')),
1746 1746 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1747 1747 _('[PATTERN]...'),
1748 1748 inferrepo=True)
1749 1749 def debugpickmergetool(ui, repo, *pats, **opts):
1750 1750 """examine which merge tool is chosen for specified file
1751 1751
1752 1752 As described in :hg:`help merge-tools`, Mercurial examines
1753 1753 configurations below in this order to decide which merge tool is
1754 1754 chosen for specified file.
1755 1755
1756 1756 1. ``--tool`` option
1757 1757 2. ``HGMERGE`` environment variable
1758 1758 3. configurations in ``merge-patterns`` section
1759 1759 4. configuration of ``ui.merge``
1760 1760 5. configurations in ``merge-tools`` section
1761 1761 6. ``hgmerge`` tool (for historical reason only)
1762 1762 7. default tool for fallback (``:merge`` or ``:prompt``)
1763 1763
1764 1764 This command writes out examination result in the style below::
1765 1765
1766 1766 FILE = MERGETOOL
1767 1767
1768 1768 By default, all files known in the first parent context of the
1769 1769 working directory are examined. Use file patterns and/or -I/-X
1770 1770 options to limit target files. -r/--rev is also useful to examine
1771 1771 files in another context without actual updating to it.
1772 1772
1773 1773 With --debug, this command shows warning messages while matching
1774 1774 against ``merge-patterns`` and so on, too. It is recommended to
1775 1775 use this option with explicit file patterns and/or -I/-X options,
1776 1776 because this option increases amount of output per file according
1777 1777 to configurations in hgrc.
1778 1778
1779 1779 With -v/--verbose, this command shows configurations below at
1780 1780 first (only if specified).
1781 1781
1782 1782 - ``--tool`` option
1783 1783 - ``HGMERGE`` environment variable
1784 1784 - configuration of ``ui.merge``
1785 1785
1786 1786 If merge tool is chosen before matching against
1787 1787 ``merge-patterns``, this command can't show any helpful
1788 1788 information, even with --debug. In such case, information above is
1789 1789 useful to know why a merge tool is chosen.
1790 1790 """
1791 1791 opts = pycompat.byteskwargs(opts)
1792 1792 overrides = {}
1793 1793 if opts['tool']:
1794 1794 overrides[('ui', 'forcemerge')] = opts['tool']
1795 1795 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1796 1796
1797 1797 with ui.configoverride(overrides, 'debugmergepatterns'):
1798 1798 hgmerge = encoding.environ.get("HGMERGE")
1799 1799 if hgmerge is not None:
1800 1800 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1801 1801 uimerge = ui.config("ui", "merge")
1802 1802 if uimerge:
1803 1803 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1804 1804
1805 1805 ctx = scmutil.revsingle(repo, opts.get('rev'))
1806 1806 m = scmutil.match(ctx, pats, opts)
1807 1807 changedelete = opts['changedelete']
1808 1808 for path in ctx.walk(m):
1809 1809 fctx = ctx[path]
1810 1810 try:
1811 1811 if not ui.debugflag:
1812 1812 ui.pushbuffer(error=True)
1813 1813 tool, toolpath = filemerge._picktool(repo, ui, path,
1814 1814 fctx.isbinary(),
1815 1815 'l' in fctx.flags(),
1816 1816 changedelete)
1817 1817 finally:
1818 1818 if not ui.debugflag:
1819 1819 ui.popbuffer()
1820 1820 ui.write(('%s = %s\n') % (path, tool))
1821 1821
1822 1822 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1823 1823 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1824 1824 '''access the pushkey key/value protocol
1825 1825
1826 1826 With two args, list the keys in the given namespace.
1827 1827
1828 1828 With five args, set a key to new if it currently is set to old.
1829 1829 Reports success or failure.
1830 1830 '''
1831 1831
1832 1832 target = hg.peer(ui, {}, repopath)
1833 1833 if keyinfo:
1834 1834 key, old, new = keyinfo
1835 1835 with target.commandexecutor() as e:
1836 1836 r = e.callcommand('pushkey', {
1837 1837 'namespace': namespace,
1838 1838 'key': key,
1839 1839 'old': old,
1840 1840 'new': new,
1841 1841 }).result()
1842 1842
1843 1843 ui.status(pycompat.bytestr(r) + '\n')
1844 1844 return not r
1845 1845 else:
1846 1846 for k, v in sorted(target.listkeys(namespace).iteritems()):
1847 1847 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1848 1848 stringutil.escapestr(v)))
1849 1849
1850 1850 @command('debugpvec', [], _('A B'))
1851 1851 def debugpvec(ui, repo, a, b=None):
1852 1852 ca = scmutil.revsingle(repo, a)
1853 1853 cb = scmutil.revsingle(repo, b)
1854 1854 pa = pvec.ctxpvec(ca)
1855 1855 pb = pvec.ctxpvec(cb)
1856 1856 if pa == pb:
1857 1857 rel = "="
1858 1858 elif pa > pb:
1859 1859 rel = ">"
1860 1860 elif pa < pb:
1861 1861 rel = "<"
1862 1862 elif pa | pb:
1863 1863 rel = "|"
1864 1864 ui.write(_("a: %s\n") % pa)
1865 1865 ui.write(_("b: %s\n") % pb)
1866 1866 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1867 1867 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1868 1868 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1869 1869 pa.distance(pb), rel))
1870 1870
1871 1871 @command('debugrebuilddirstate|debugrebuildstate',
1872 1872 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1873 1873 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1874 1874 'the working copy parent')),
1875 1875 ],
1876 1876 _('[-r REV]'))
1877 1877 def debugrebuilddirstate(ui, repo, rev, **opts):
1878 1878 """rebuild the dirstate as it would look like for the given revision
1879 1879
1880 1880 If no revision is specified the first current parent will be used.
1881 1881
1882 1882 The dirstate will be set to the files of the given revision.
1883 1883 The actual working directory content or existing dirstate
1884 1884 information such as adds or removes is not considered.
1885 1885
1886 1886 ``minimal`` will only rebuild the dirstate status for files that claim to be
1887 1887 tracked but are not in the parent manifest, or that exist in the parent
1888 1888 manifest but are not in the dirstate. It will not change adds, removes, or
1889 1889 modified files that are in the working copy parent.
1890 1890
1891 1891 One use of this command is to make the next :hg:`status` invocation
1892 1892 check the actual file content.
1893 1893 """
1894 1894 ctx = scmutil.revsingle(repo, rev)
1895 1895 with repo.wlock():
1896 1896 dirstate = repo.dirstate
1897 1897 changedfiles = None
1898 1898 # See command doc for what minimal does.
1899 1899 if opts.get(r'minimal'):
1900 1900 manifestfiles = set(ctx.manifest().keys())
1901 1901 dirstatefiles = set(dirstate)
1902 1902 manifestonly = manifestfiles - dirstatefiles
1903 1903 dsonly = dirstatefiles - manifestfiles
1904 1904 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1905 1905 changedfiles = manifestonly | dsnotadded
1906 1906
1907 1907 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1908 1908
1909 1909 @command('debugrebuildfncache', [], '')
1910 1910 def debugrebuildfncache(ui, repo):
1911 1911 """rebuild the fncache file"""
1912 1912 repair.rebuildfncache(ui, repo)
1913 1913
1914 1914 @command('debugrename',
1915 1915 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1916 1916 _('[-r REV] FILE'))
1917 1917 def debugrename(ui, repo, file1, *pats, **opts):
1918 1918 """dump rename information"""
1919 1919
1920 1920 opts = pycompat.byteskwargs(opts)
1921 1921 ctx = scmutil.revsingle(repo, opts.get('rev'))
1922 1922 m = scmutil.match(ctx, (file1,) + pats, opts)
1923 1923 for abs in ctx.walk(m):
1924 1924 fctx = ctx[abs]
1925 1925 o = fctx.filelog().renamed(fctx.filenode())
1926 1926 rel = m.rel(abs)
1927 1927 if o:
1928 1928 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1929 1929 else:
1930 1930 ui.write(_("%s not renamed\n") % rel)
1931 1931
1932 1932 @command('debugrevlog', cmdutil.debugrevlogopts +
1933 1933 [('d', 'dump', False, _('dump index data'))],
1934 1934 _('-c|-m|FILE'),
1935 1935 optionalrepo=True)
1936 1936 def debugrevlog(ui, repo, file_=None, **opts):
1937 1937 """show data and statistics about a revlog"""
1938 1938 opts = pycompat.byteskwargs(opts)
1939 1939 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1940 1940
1941 1941 if opts.get("dump"):
1942 1942 numrevs = len(r)
1943 1943 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1944 1944 " rawsize totalsize compression heads chainlen\n"))
1945 1945 ts = 0
1946 1946 heads = set()
1947 1947
1948 1948 for rev in xrange(numrevs):
1949 1949 dbase = r.deltaparent(rev)
1950 1950 if dbase == -1:
1951 1951 dbase = rev
1952 1952 cbase = r.chainbase(rev)
1953 1953 clen = r.chainlen(rev)
1954 1954 p1, p2 = r.parentrevs(rev)
1955 1955 rs = r.rawsize(rev)
1956 1956 ts = ts + rs
1957 1957 heads -= set(r.parentrevs(rev))
1958 1958 heads.add(rev)
1959 1959 try:
1960 1960 compression = ts / r.end(rev)
1961 1961 except ZeroDivisionError:
1962 1962 compression = 0
1963 1963 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1964 1964 "%11d %5d %8d\n" %
1965 1965 (rev, p1, p2, r.start(rev), r.end(rev),
1966 1966 r.start(dbase), r.start(cbase),
1967 1967 r.start(p1), r.start(p2),
1968 1968 rs, ts, compression, len(heads), clen))
1969 1969 return 0
1970 1970
1971 1971 v = r.version
1972 1972 format = v & 0xFFFF
1973 1973 flags = []
1974 1974 gdelta = False
1975 1975 if v & revlog.FLAG_INLINE_DATA:
1976 1976 flags.append('inline')
1977 1977 if v & revlog.FLAG_GENERALDELTA:
1978 1978 gdelta = True
1979 1979 flags.append('generaldelta')
1980 1980 if not flags:
1981 1981 flags = ['(none)']
1982 1982
1983 1983 nummerges = 0
1984 1984 numfull = 0
1985 1985 numprev = 0
1986 1986 nump1 = 0
1987 1987 nump2 = 0
1988 1988 numother = 0
1989 1989 nump1prev = 0
1990 1990 nump2prev = 0
1991 1991 chainlengths = []
1992 1992 chainbases = []
1993 1993 chainspans = []
1994 1994
1995 1995 datasize = [None, 0, 0]
1996 1996 fullsize = [None, 0, 0]
1997 1997 deltasize = [None, 0, 0]
1998 1998 chunktypecounts = {}
1999 1999 chunktypesizes = {}
2000 2000
2001 2001 def addsize(size, l):
2002 2002 if l[0] is None or size < l[0]:
2003 2003 l[0] = size
2004 2004 if size > l[1]:
2005 2005 l[1] = size
2006 2006 l[2] += size
2007 2007
2008 2008 numrevs = len(r)
2009 2009 for rev in xrange(numrevs):
2010 2010 p1, p2 = r.parentrevs(rev)
2011 2011 delta = r.deltaparent(rev)
2012 2012 if format > 0:
2013 2013 addsize(r.rawsize(rev), datasize)
2014 2014 if p2 != nullrev:
2015 2015 nummerges += 1
2016 2016 size = r.length(rev)
2017 2017 if delta == nullrev:
2018 2018 chainlengths.append(0)
2019 2019 chainbases.append(r.start(rev))
2020 2020 chainspans.append(size)
2021 2021 numfull += 1
2022 2022 addsize(size, fullsize)
2023 2023 else:
2024 2024 chainlengths.append(chainlengths[delta] + 1)
2025 2025 baseaddr = chainbases[delta]
2026 2026 revaddr = r.start(rev)
2027 2027 chainbases.append(baseaddr)
2028 2028 chainspans.append((revaddr - baseaddr) + size)
2029 2029 addsize(size, deltasize)
2030 2030 if delta == rev - 1:
2031 2031 numprev += 1
2032 2032 if delta == p1:
2033 2033 nump1prev += 1
2034 2034 elif delta == p2:
2035 2035 nump2prev += 1
2036 2036 elif delta == p1:
2037 2037 nump1 += 1
2038 2038 elif delta == p2:
2039 2039 nump2 += 1
2040 2040 elif delta != nullrev:
2041 2041 numother += 1
2042 2042
2043 2043 # Obtain data on the raw chunks in the revlog.
2044 2044 segment = r._getsegmentforrevs(rev, rev)[1]
2045 2045 if segment:
2046 2046 chunktype = bytes(segment[0:1])
2047 2047 else:
2048 2048 chunktype = 'empty'
2049 2049
2050 2050 if chunktype not in chunktypecounts:
2051 2051 chunktypecounts[chunktype] = 0
2052 2052 chunktypesizes[chunktype] = 0
2053 2053
2054 2054 chunktypecounts[chunktype] += 1
2055 2055 chunktypesizes[chunktype] += size
2056 2056
2057 2057 # Adjust size min value for empty cases
2058 2058 for size in (datasize, fullsize, deltasize):
2059 2059 if size[0] is None:
2060 2060 size[0] = 0
2061 2061
2062 2062 numdeltas = numrevs - numfull
2063 2063 numoprev = numprev - nump1prev - nump2prev
2064 2064 totalrawsize = datasize[2]
2065 2065 datasize[2] /= numrevs
2066 2066 fulltotal = fullsize[2]
2067 2067 fullsize[2] /= numfull
2068 2068 deltatotal = deltasize[2]
2069 2069 if numrevs - numfull > 0:
2070 2070 deltasize[2] /= numrevs - numfull
2071 2071 totalsize = fulltotal + deltatotal
2072 2072 avgchainlen = sum(chainlengths) / numrevs
2073 2073 maxchainlen = max(chainlengths)
2074 2074 maxchainspan = max(chainspans)
2075 2075 compratio = 1
2076 2076 if totalsize:
2077 2077 compratio = totalrawsize / totalsize
2078 2078
2079 2079 basedfmtstr = '%%%dd\n'
2080 2080 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2081 2081
2082 2082 def dfmtstr(max):
2083 2083 return basedfmtstr % len(str(max))
2084 2084 def pcfmtstr(max, padding=0):
2085 2085 return basepcfmtstr % (len(str(max)), ' ' * padding)
2086 2086
2087 2087 def pcfmt(value, total):
2088 2088 if total:
2089 2089 return (value, 100 * float(value) / total)
2090 2090 else:
2091 2091 return value, 100.0
2092 2092
2093 2093 ui.write(('format : %d\n') % format)
2094 2094 ui.write(('flags : %s\n') % ', '.join(flags))
2095 2095
2096 2096 ui.write('\n')
2097 2097 fmt = pcfmtstr(totalsize)
2098 2098 fmt2 = dfmtstr(totalsize)
2099 2099 ui.write(('revisions : ') + fmt2 % numrevs)
2100 2100 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2101 2101 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2102 2102 ui.write(('revisions : ') + fmt2 % numrevs)
2103 2103 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2104 2104 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2105 2105 ui.write(('revision size : ') + fmt2 % totalsize)
2106 2106 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2107 2107 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2108 2108
2109 2109 def fmtchunktype(chunktype):
2110 2110 if chunktype == 'empty':
2111 2111 return ' %s : ' % chunktype
2112 2112 elif chunktype in pycompat.bytestr(string.ascii_letters):
2113 2113 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2114 2114 else:
2115 2115 return ' 0x%s : ' % hex(chunktype)
2116 2116
2117 2117 ui.write('\n')
2118 2118 ui.write(('chunks : ') + fmt2 % numrevs)
2119 2119 for chunktype in sorted(chunktypecounts):
2120 2120 ui.write(fmtchunktype(chunktype))
2121 2121 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2122 2122 ui.write(('chunks size : ') + fmt2 % totalsize)
2123 2123 for chunktype in sorted(chunktypecounts):
2124 2124 ui.write(fmtchunktype(chunktype))
2125 2125 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2126 2126
2127 2127 ui.write('\n')
2128 2128 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2129 2129 ui.write(('avg chain length : ') + fmt % avgchainlen)
2130 2130 ui.write(('max chain length : ') + fmt % maxchainlen)
2131 2131 ui.write(('max chain reach : ') + fmt % maxchainspan)
2132 2132 ui.write(('compression ratio : ') + fmt % compratio)
2133 2133
2134 2134 if format > 0:
2135 2135 ui.write('\n')
2136 2136 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2137 2137 % tuple(datasize))
2138 2138 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2139 2139 % tuple(fullsize))
2140 2140 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2141 2141 % tuple(deltasize))
2142 2142
2143 2143 if numdeltas > 0:
2144 2144 ui.write('\n')
2145 2145 fmt = pcfmtstr(numdeltas)
2146 2146 fmt2 = pcfmtstr(numdeltas, 4)
2147 2147 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2148 2148 if numprev > 0:
2149 2149 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2150 2150 numprev))
2151 2151 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2152 2152 numprev))
2153 2153 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2154 2154 numprev))
2155 2155 if gdelta:
2156 2156 ui.write(('deltas against p1 : ')
2157 2157 + fmt % pcfmt(nump1, numdeltas))
2158 2158 ui.write(('deltas against p2 : ')
2159 2159 + fmt % pcfmt(nump2, numdeltas))
2160 2160 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2161 2161 numdeltas))
2162 2162
2163 2163 @command('debugrevspec',
2164 2164 [('', 'optimize', None,
2165 2165 _('print parsed tree after optimizing (DEPRECATED)')),
2166 2166 ('', 'show-revs', True, _('print list of result revisions (default)')),
2167 2167 ('s', 'show-set', None, _('print internal representation of result set')),
2168 2168 ('p', 'show-stage', [],
2169 2169 _('print parsed tree at the given stage'), _('NAME')),
2170 2170 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2171 2171 ('', 'verify-optimized', False, _('verify optimized result')),
2172 2172 ],
2173 2173 ('REVSPEC'))
2174 2174 def debugrevspec(ui, repo, expr, **opts):
2175 2175 """parse and apply a revision specification
2176 2176
2177 2177 Use -p/--show-stage option to print the parsed tree at the given stages.
2178 2178 Use -p all to print tree at every stage.
2179 2179
2180 2180 Use --no-show-revs option with -s or -p to print only the set
2181 2181 representation or the parsed tree respectively.
2182 2182
2183 2183 Use --verify-optimized to compare the optimized result with the unoptimized
2184 2184 one. Returns 1 if the optimized result differs.
2185 2185 """
2186 2186 opts = pycompat.byteskwargs(opts)
2187 2187 aliases = ui.configitems('revsetalias')
2188 2188 stages = [
2189 2189 ('parsed', lambda tree: tree),
2190 2190 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2191 2191 ui.warn)),
2192 2192 ('concatenated', revsetlang.foldconcat),
2193 2193 ('analyzed', revsetlang.analyze),
2194 2194 ('optimized', revsetlang.optimize),
2195 2195 ]
2196 2196 if opts['no_optimized']:
2197 2197 stages = stages[:-1]
2198 2198 if opts['verify_optimized'] and opts['no_optimized']:
2199 2199 raise error.Abort(_('cannot use --verify-optimized with '
2200 2200 '--no-optimized'))
2201 2201 stagenames = set(n for n, f in stages)
2202 2202
2203 2203 showalways = set()
2204 2204 showchanged = set()
2205 2205 if ui.verbose and not opts['show_stage']:
2206 2206 # show parsed tree by --verbose (deprecated)
2207 2207 showalways.add('parsed')
2208 2208 showchanged.update(['expanded', 'concatenated'])
2209 2209 if opts['optimize']:
2210 2210 showalways.add('optimized')
2211 2211 if opts['show_stage'] and opts['optimize']:
2212 2212 raise error.Abort(_('cannot use --optimize with --show-stage'))
2213 2213 if opts['show_stage'] == ['all']:
2214 2214 showalways.update(stagenames)
2215 2215 else:
2216 2216 for n in opts['show_stage']:
2217 2217 if n not in stagenames:
2218 2218 raise error.Abort(_('invalid stage name: %s') % n)
2219 2219 showalways.update(opts['show_stage'])
2220 2220
2221 2221 treebystage = {}
2222 2222 printedtree = None
2223 2223 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2224 2224 for n, f in stages:
2225 2225 treebystage[n] = tree = f(tree)
2226 2226 if n in showalways or (n in showchanged and tree != printedtree):
2227 2227 if opts['show_stage'] or n != 'parsed':
2228 2228 ui.write(("* %s:\n") % n)
2229 2229 ui.write(revsetlang.prettyformat(tree), "\n")
2230 2230 printedtree = tree
2231 2231
2232 2232 if opts['verify_optimized']:
2233 2233 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2234 2234 brevs = revset.makematcher(treebystage['optimized'])(repo)
2235 2235 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2236 2236 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2237 2237 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2238 2238 arevs = list(arevs)
2239 2239 brevs = list(brevs)
2240 2240 if arevs == brevs:
2241 2241 return 0
2242 2242 ui.write(('--- analyzed\n'), label='diff.file_a')
2243 2243 ui.write(('+++ optimized\n'), label='diff.file_b')
2244 2244 sm = difflib.SequenceMatcher(None, arevs, brevs)
2245 2245 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2246 2246 if tag in ('delete', 'replace'):
2247 2247 for c in arevs[alo:ahi]:
2248 2248 ui.write('-%s\n' % c, label='diff.deleted')
2249 2249 if tag in ('insert', 'replace'):
2250 2250 for c in brevs[blo:bhi]:
2251 2251 ui.write('+%s\n' % c, label='diff.inserted')
2252 2252 if tag == 'equal':
2253 2253 for c in arevs[alo:ahi]:
2254 2254 ui.write(' %s\n' % c)
2255 2255 return 1
2256 2256
2257 2257 func = revset.makematcher(tree)
2258 2258 revs = func(repo)
2259 2259 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2260 2260 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2261 2261 if not opts['show_revs']:
2262 2262 return
2263 2263 for c in revs:
2264 2264 ui.write("%d\n" % c)
2265 2265
2266 2266 @command('debugserve', [
2267 2267 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2268 2268 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2269 2269 ('', 'logiofile', '', _('file to log server I/O to')),
2270 2270 ], '')
2271 2271 def debugserve(ui, repo, **opts):
2272 2272 """run a server with advanced settings
2273 2273
2274 2274 This command is similar to :hg:`serve`. It exists partially as a
2275 2275 workaround to the fact that ``hg serve --stdio`` must have specific
2276 2276 arguments for security reasons.
2277 2277 """
2278 2278 opts = pycompat.byteskwargs(opts)
2279 2279
2280 2280 if not opts['sshstdio']:
2281 2281 raise error.Abort(_('only --sshstdio is currently supported'))
2282 2282
2283 2283 logfh = None
2284 2284
2285 2285 if opts['logiofd'] and opts['logiofile']:
2286 2286 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2287 2287
2288 2288 if opts['logiofd']:
2289 2289 # Line buffered because output is line based.
2290 2290 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2291 2291 elif opts['logiofile']:
2292 2292 logfh = open(opts['logiofile'], 'ab', 1)
2293 2293
2294 2294 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2295 2295 s.serve_forever()
2296 2296
2297 2297 @command('debugsetparents', [], _('REV1 [REV2]'))
2298 2298 def debugsetparents(ui, repo, rev1, rev2=None):
2299 2299 """manually set the parents of the current working directory
2300 2300
2301 2301 This is useful for writing repository conversion tools, but should
2302 2302 be used with care. For example, neither the working directory nor the
2303 2303 dirstate is updated, so file status may be incorrect after running this
2304 2304 command.
2305 2305
2306 2306 Returns 0 on success.
2307 2307 """
2308 2308
2309 2309 node1 = scmutil.revsingle(repo, rev1).node()
2310 2310 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2311 2311
2312 2312 with repo.wlock():
2313 2313 repo.setparents(node1, node2)
2314 2314
2315 2315 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2316 2316 def debugssl(ui, repo, source=None, **opts):
2317 2317 '''test a secure connection to a server
2318 2318
2319 2319 This builds the certificate chain for the server on Windows, installing the
2320 2320 missing intermediates and trusted root via Windows Update if necessary. It
2321 2321 does nothing on other platforms.
2322 2322
2323 2323 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2324 2324 that server is used. See :hg:`help urls` for more information.
2325 2325
2326 2326 If the update succeeds, retry the original operation. Otherwise, the cause
2327 2327 of the SSL error is likely another issue.
2328 2328 '''
2329 2329 if not pycompat.iswindows:
2330 2330 raise error.Abort(_('certificate chain building is only possible on '
2331 2331 'Windows'))
2332 2332
2333 2333 if not source:
2334 2334 if not repo:
2335 2335 raise error.Abort(_("there is no Mercurial repository here, and no "
2336 2336 "server specified"))
2337 2337 source = "default"
2338 2338
2339 2339 source, branches = hg.parseurl(ui.expandpath(source))
2340 2340 url = util.url(source)
2341 2341 addr = None
2342 2342
2343 2343 defaultport = {'https': 443, 'ssh': 22}
2344 2344 if url.scheme in defaultport:
2345 2345 try:
2346 2346 addr = (url.host, int(url.port or defaultport[url.scheme]))
2347 2347 except ValueError:
2348 2348 raise error.Abort(_("malformed port number in URL"))
2349 2349 else:
2350 2350 raise error.Abort(_("only https and ssh connections are supported"))
2351 2351
2352 2352 from . import win32
2353 2353
2354 2354 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2355 2355 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2356 2356
2357 2357 try:
2358 2358 s.connect(addr)
2359 2359 cert = s.getpeercert(True)
2360 2360
2361 2361 ui.status(_('checking the certificate chain for %s\n') % url.host)
2362 2362
2363 2363 complete = win32.checkcertificatechain(cert, build=False)
2364 2364
2365 2365 if not complete:
2366 2366 ui.status(_('certificate chain is incomplete, updating... '))
2367 2367
2368 2368 if not win32.checkcertificatechain(cert):
2369 2369 ui.status(_('failed.\n'))
2370 2370 else:
2371 2371 ui.status(_('done.\n'))
2372 2372 else:
2373 2373 ui.status(_('full certificate chain is available\n'))
2374 2374 finally:
2375 2375 s.close()
2376 2376
2377 2377 @command('debugsub',
2378 2378 [('r', 'rev', '',
2379 2379 _('revision to check'), _('REV'))],
2380 2380 _('[-r REV] [REV]'))
2381 2381 def debugsub(ui, repo, rev=None):
2382 2382 ctx = scmutil.revsingle(repo, rev, None)
2383 2383 for k, v in sorted(ctx.substate.items()):
2384 2384 ui.write(('path %s\n') % k)
2385 2385 ui.write((' source %s\n') % v[0])
2386 2386 ui.write((' revision %s\n') % v[1])
2387 2387
2388 2388 @command('debugsuccessorssets',
2389 2389 [('', 'closest', False, _('return closest successors sets only'))],
2390 2390 _('[REV]'))
2391 2391 def debugsuccessorssets(ui, repo, *revs, **opts):
2392 2392 """show set of successors for revision
2393 2393
2394 2394 A successors set of changeset A is a consistent group of revisions that
2395 2395 succeed A. It contains non-obsolete changesets only unless closests
2396 2396 successors set is set.
2397 2397
2398 2398 In most cases a changeset A has a single successors set containing a single
2399 2399 successor (changeset A replaced by A').
2400 2400
2401 2401 A changeset that is made obsolete with no successors are called "pruned".
2402 2402 Such changesets have no successors sets at all.
2403 2403
2404 2404 A changeset that has been "split" will have a successors set containing
2405 2405 more than one successor.
2406 2406
2407 2407 A changeset that has been rewritten in multiple different ways is called
2408 2408 "divergent". Such changesets have multiple successor sets (each of which
2409 2409 may also be split, i.e. have multiple successors).
2410 2410
2411 2411 Results are displayed as follows::
2412 2412
2413 2413 <rev1>
2414 2414 <successors-1A>
2415 2415 <rev2>
2416 2416 <successors-2A>
2417 2417 <successors-2B1> <successors-2B2> <successors-2B3>
2418 2418
2419 2419 Here rev2 has two possible (i.e. divergent) successors sets. The first
2420 2420 holds one element, whereas the second holds three (i.e. the changeset has
2421 2421 been split).
2422 2422 """
2423 2423 # passed to successorssets caching computation from one call to another
2424 2424 cache = {}
2425 2425 ctx2str = bytes
2426 2426 node2str = short
2427 2427 for rev in scmutil.revrange(repo, revs):
2428 2428 ctx = repo[rev]
2429 2429 ui.write('%s\n'% ctx2str(ctx))
2430 2430 for succsset in obsutil.successorssets(repo, ctx.node(),
2431 2431 closest=opts[r'closest'],
2432 2432 cache=cache):
2433 2433 if succsset:
2434 2434 ui.write(' ')
2435 2435 ui.write(node2str(succsset[0]))
2436 2436 for node in succsset[1:]:
2437 2437 ui.write(' ')
2438 2438 ui.write(node2str(node))
2439 2439 ui.write('\n')
2440 2440
2441 2441 @command('debugtemplate',
2442 2442 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2443 2443 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2444 2444 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2445 2445 optionalrepo=True)
2446 2446 def debugtemplate(ui, repo, tmpl, **opts):
2447 2447 """parse and apply a template
2448 2448
2449 2449 If -r/--rev is given, the template is processed as a log template and
2450 2450 applied to the given changesets. Otherwise, it is processed as a generic
2451 2451 template.
2452 2452
2453 2453 Use --verbose to print the parsed tree.
2454 2454 """
2455 2455 revs = None
2456 2456 if opts[r'rev']:
2457 2457 if repo is None:
2458 2458 raise error.RepoError(_('there is no Mercurial repository here '
2459 2459 '(.hg not found)'))
2460 2460 revs = scmutil.revrange(repo, opts[r'rev'])
2461 2461
2462 2462 props = {}
2463 2463 for d in opts[r'define']:
2464 2464 try:
2465 2465 k, v = (e.strip() for e in d.split('=', 1))
2466 2466 if not k or k == 'ui':
2467 2467 raise ValueError
2468 2468 props[k] = v
2469 2469 except ValueError:
2470 2470 raise error.Abort(_('malformed keyword definition: %s') % d)
2471 2471
2472 2472 if ui.verbose:
2473 2473 aliases = ui.configitems('templatealias')
2474 2474 tree = templater.parse(tmpl)
2475 2475 ui.note(templater.prettyformat(tree), '\n')
2476 2476 newtree = templater.expandaliases(tree, aliases)
2477 2477 if newtree != tree:
2478 2478 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2479 2479
2480 2480 if revs is None:
2481 2481 tres = formatter.templateresources(ui, repo)
2482 2482 t = formatter.maketemplater(ui, tmpl, resources=tres)
2483 2483 ui.write(t.renderdefault(props))
2484 2484 else:
2485 2485 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2486 2486 for r in revs:
2487 2487 displayer.show(repo[r], **pycompat.strkwargs(props))
2488 2488 displayer.close()
2489 2489
2490 2490 @command('debuguigetpass', [
2491 2491 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2492 2492 ], _('[-p TEXT]'), norepo=True)
2493 2493 def debuguigetpass(ui, prompt=''):
2494 2494 """show prompt to type password"""
2495 2495 r = ui.getpass(prompt)
2496 2496 ui.write(('respose: %s\n') % r)
2497 2497
2498 2498 @command('debuguiprompt', [
2499 2499 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2500 2500 ], _('[-p TEXT]'), norepo=True)
2501 2501 def debuguiprompt(ui, prompt=''):
2502 2502 """show plain prompt"""
2503 2503 r = ui.prompt(prompt)
2504 2504 ui.write(('response: %s\n') % r)
2505 2505
2506 2506 @command('debugupdatecaches', [])
2507 2507 def debugupdatecaches(ui, repo, *pats, **opts):
2508 2508 """warm all known caches in the repository"""
2509 2509 with repo.wlock(), repo.lock():
2510 2510 repo.updatecaches(full=True)
2511 2511
2512 2512 @command('debugupgraderepo', [
2513 2513 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2514 2514 ('', 'run', False, _('performs an upgrade')),
2515 2515 ])
2516 2516 def debugupgraderepo(ui, repo, run=False, optimize=None):
2517 2517 """upgrade a repository to use different features
2518 2518
2519 2519 If no arguments are specified, the repository is evaluated for upgrade
2520 2520 and a list of problems and potential optimizations is printed.
2521 2521
2522 2522 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2523 2523 can be influenced via additional arguments. More details will be provided
2524 2524 by the command output when run without ``--run``.
2525 2525
2526 2526 During the upgrade, the repository will be locked and no writes will be
2527 2527 allowed.
2528 2528
2529 2529 At the end of the upgrade, the repository may not be readable while new
2530 2530 repository data is swapped in. This window will be as long as it takes to
2531 2531 rename some directories inside the ``.hg`` directory. On most machines, this
2532 2532 should complete almost instantaneously and the chances of a consumer being
2533 2533 unable to access the repository should be low.
2534 2534 """
2535 2535 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2536 2536
2537 2537 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2538 2538 inferrepo=True)
2539 2539 def debugwalk(ui, repo, *pats, **opts):
2540 2540 """show how files match on given patterns"""
2541 2541 opts = pycompat.byteskwargs(opts)
2542 2542 m = scmutil.match(repo[None], pats, opts)
2543 2543 ui.write(('matcher: %r\n' % m))
2544 2544 items = list(repo[None].walk(m))
2545 2545 if not items:
2546 2546 return
2547 2547 f = lambda fn: fn
2548 2548 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2549 2549 f = lambda fn: util.normpath(fn)
2550 2550 fmt = 'f %%-%ds %%-%ds %%s' % (
2551 2551 max([len(abs) for abs in items]),
2552 2552 max([len(m.rel(abs)) for abs in items]))
2553 2553 for abs in items:
2554 2554 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2555 2555 ui.write("%s\n" % line.rstrip())
2556 2556
2557 2557 @command('debugwhyunstable', [], _('REV'))
2558 2558 def debugwhyunstable(ui, repo, rev):
2559 2559 """explain instabilities of a changeset"""
2560 2560 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2561 2561 dnodes = ''
2562 2562 if entry.get('divergentnodes'):
2563 2563 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2564 2564 for ctx in entry['divergentnodes']) + ' '
2565 2565 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2566 2566 entry['reason'], entry['node']))
2567 2567
2568 2568 @command('debugwireargs',
2569 2569 [('', 'three', '', 'three'),
2570 2570 ('', 'four', '', 'four'),
2571 2571 ('', 'five', '', 'five'),
2572 2572 ] + cmdutil.remoteopts,
2573 2573 _('REPO [OPTIONS]... [ONE [TWO]]'),
2574 2574 norepo=True)
2575 2575 def debugwireargs(ui, repopath, *vals, **opts):
2576 2576 opts = pycompat.byteskwargs(opts)
2577 2577 repo = hg.peer(ui, opts, repopath)
2578 2578 for opt in cmdutil.remoteopts:
2579 2579 del opts[opt[1]]
2580 2580 args = {}
2581 2581 for k, v in opts.iteritems():
2582 2582 if v:
2583 2583 args[k] = v
2584 2584 args = pycompat.strkwargs(args)
2585 2585 # run twice to check that we don't mess up the stream for the next command
2586 2586 res1 = repo.debugwireargs(*vals, **args)
2587 2587 res2 = repo.debugwireargs(*vals, **args)
2588 2588 ui.write("%s\n" % res1)
2589 2589 if res1 != res2:
2590 2590 ui.warn("%s\n" % res2)
2591 2591
2592 2592 def _parsewirelangblocks(fh):
2593 2593 activeaction = None
2594 2594 blocklines = []
2595 2595
2596 2596 for line in fh:
2597 2597 line = line.rstrip()
2598 2598 if not line:
2599 2599 continue
2600 2600
2601 2601 if line.startswith(b'#'):
2602 2602 continue
2603 2603
2604 2604 if not line.startswith(' '):
2605 2605 # New block. Flush previous one.
2606 2606 if activeaction:
2607 2607 yield activeaction, blocklines
2608 2608
2609 2609 activeaction = line
2610 2610 blocklines = []
2611 2611 continue
2612 2612
2613 2613 # Else we start with an indent.
2614 2614
2615 2615 if not activeaction:
2616 2616 raise error.Abort(_('indented line outside of block'))
2617 2617
2618 2618 blocklines.append(line)
2619 2619
2620 2620 # Flush last block.
2621 2621 if activeaction:
2622 2622 yield activeaction, blocklines
2623 2623
2624 2624 @command('debugwireproto',
2625 2625 [
2626 2626 ('', 'localssh', False, _('start an SSH server for this repo')),
2627 2627 ('', 'peer', '', _('construct a specific version of the peer')),
2628 2628 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2629 2629 ] + cmdutil.remoteopts,
2630 2630 _('[PATH]'),
2631 2631 optionalrepo=True)
2632 2632 def debugwireproto(ui, repo, path=None, **opts):
2633 2633 """send wire protocol commands to a server
2634 2634
2635 2635 This command can be used to issue wire protocol commands to remote
2636 2636 peers and to debug the raw data being exchanged.
2637 2637
2638 2638 ``--localssh`` will start an SSH server against the current repository
2639 2639 and connect to that. By default, the connection will perform a handshake
2640 2640 and establish an appropriate peer instance.
2641 2641
2642 2642 ``--peer`` can be used to bypass the handshake protocol and construct a
2643 2643 peer instance using the specified class type. Valid values are ``raw``,
2644 2644 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2645 2645 raw data payloads and don't support higher-level command actions.
2646 2646
2647 2647 ``--noreadstderr`` can be used to disable automatic reading from stderr
2648 2648 of the peer (for SSH connections only). Disabling automatic reading of
2649 2649 stderr is useful for making output more deterministic.
2650 2650
2651 2651 Commands are issued via a mini language which is specified via stdin.
2652 2652 The language consists of individual actions to perform. An action is
2653 2653 defined by a block. A block is defined as a line with no leading
2654 2654 space followed by 0 or more lines with leading space. Blocks are
2655 2655 effectively a high-level command with additional metadata.
2656 2656
2657 2657 Lines beginning with ``#`` are ignored.
2658 2658
2659 2659 The following sections denote available actions.
2660 2660
2661 2661 raw
2662 2662 ---
2663 2663
2664 2664 Send raw data to the server.
2665 2665
2666 2666 The block payload contains the raw data to send as one atomic send
2667 2667 operation. The data may not actually be delivered in a single system
2668 2668 call: it depends on the abilities of the transport being used.
2669 2669
2670 2670 Each line in the block is de-indented and concatenated. Then, that
2671 2671 value is evaluated as a Python b'' literal. This allows the use of
2672 2672 backslash escaping, etc.
2673 2673
2674 2674 raw+
2675 2675 ----
2676 2676
2677 2677 Behaves like ``raw`` except flushes output afterwards.
2678 2678
2679 2679 command <X>
2680 2680 -----------
2681 2681
2682 2682 Send a request to run a named command, whose name follows the ``command``
2683 2683 string.
2684 2684
2685 2685 Arguments to the command are defined as lines in this block. The format of
2686 2686 each line is ``<key> <value>``. e.g.::
2687 2687
2688 2688 command listkeys
2689 2689 namespace bookmarks
2690 2690
2691 2691 If the value begins with ``eval:``, it will be interpreted as a Python
2692 2692 literal expression. Otherwise values are interpreted as Python b'' literals.
2693 2693 This allows sending complex types and encoding special byte sequences via
2694 2694 backslash escaping.
2695 2695
2696 2696 The following arguments have special meaning:
2697 2697
2698 2698 ``PUSHFILE``
2699 2699 When defined, the *push* mechanism of the peer will be used instead
2700 2700 of the static request-response mechanism and the content of the
2701 2701 file specified in the value of this argument will be sent as the
2702 2702 command payload.
2703 2703
2704 2704 This can be used to submit a local bundle file to the remote.
2705 2705
2706 2706 batchbegin
2707 2707 ----------
2708 2708
2709 2709 Instruct the peer to begin a batched send.
2710 2710
2711 2711 All ``command`` blocks are queued for execution until the next
2712 2712 ``batchsubmit`` block.
2713 2713
2714 2714 batchsubmit
2715 2715 -----------
2716 2716
2717 2717 Submit previously queued ``command`` blocks as a batch request.
2718 2718
2719 2719 This action MUST be paired with a ``batchbegin`` action.
2720 2720
2721 2721 httprequest <method> <path>
2722 2722 ---------------------------
2723 2723
2724 2724 (HTTP peer only)
2725 2725
2726 2726 Send an HTTP request to the peer.
2727 2727
2728 2728 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2729 2729
2730 2730 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2731 2731 headers to add to the request. e.g. ``Accept: foo``.
2732 2732
2733 2733 The following arguments are special:
2734 2734
2735 2735 ``BODYFILE``
2736 2736 The content of the file defined as the value to this argument will be
2737 2737 transferred verbatim as the HTTP request body.
2738 2738
2739 2739 ``frame <type> <flags> <payload>``
2740 2740 Send a unified protocol frame as part of the request body.
2741 2741
2742 2742 All frames will be collected and sent as the body to the HTTP
2743 2743 request.
2744 2744
2745 2745 close
2746 2746 -----
2747 2747
2748 2748 Close the connection to the server.
2749 2749
2750 2750 flush
2751 2751 -----
2752 2752
2753 2753 Flush data written to the server.
2754 2754
2755 2755 readavailable
2756 2756 -------------
2757 2757
2758 2758 Close the write end of the connection and read all available data from
2759 2759 the server.
2760 2760
2761 2761 If the connection to the server encompasses multiple pipes, we poll both
2762 2762 pipes and read available data.
2763 2763
2764 2764 readline
2765 2765 --------
2766 2766
2767 2767 Read a line of output from the server. If there are multiple output
2768 2768 pipes, reads only the main pipe.
2769 2769
2770 2770 ereadline
2771 2771 ---------
2772 2772
2773 2773 Like ``readline``, but read from the stderr pipe, if available.
2774 2774
2775 2775 read <X>
2776 2776 --------
2777 2777
2778 2778 ``read()`` N bytes from the server's main output pipe.
2779 2779
2780 2780 eread <X>
2781 2781 ---------
2782 2782
2783 2783 ``read()`` N bytes from the server's stderr pipe, if available.
2784 2784
2785 2785 Specifying Unified Frame-Based Protocol Frames
2786 2786 ----------------------------------------------
2787 2787
2788 2788 It is possible to emit a *Unified Frame-Based Protocol* by using special
2789 2789 syntax.
2790 2790
2791 2791 A frame is composed as a type, flags, and payload. These can be parsed
2792 2792 from a string of the form:
2793 2793
2794 2794 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
2795 2795
2796 2796 ``request-id`` and ``stream-id`` are integers defining the request and
2797 2797 stream identifiers.
2798 2798
2799 2799 ``type`` can be an integer value for the frame type or the string name
2800 2800 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
2801 2801 ``command-name``.
2802 2802
2803 2803 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
2804 2804 components. Each component (and there can be just one) can be an integer
2805 2805 or a flag name for stream flags or frame flags, respectively. Values are
2806 2806 resolved to integers and then bitwise OR'd together.
2807 2807
2808 2808 ``payload`` represents the raw frame payload. If it begins with
2809 2809 ``cbor:``, the following string is evaluated as Python code and the
2810 2810 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
2811 2811 as a Python byte string literal.
2812 2812 """
2813 2813 opts = pycompat.byteskwargs(opts)
2814 2814
2815 2815 if opts['localssh'] and not repo:
2816 2816 raise error.Abort(_('--localssh requires a repository'))
2817 2817
2818 2818 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
2819 2819 raise error.Abort(_('invalid value for --peer'),
2820 2820 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
2821 2821
2822 2822 if path and opts['localssh']:
2823 2823 raise error.Abort(_('cannot specify --localssh with an explicit '
2824 2824 'path'))
2825 2825
2826 2826 if ui.interactive():
2827 2827 ui.write(_('(waiting for commands on stdin)\n'))
2828 2828
2829 2829 blocks = list(_parsewirelangblocks(ui.fin))
2830 2830
2831 2831 proc = None
2832 2832 stdin = None
2833 2833 stdout = None
2834 2834 stderr = None
2835 2835 opener = None
2836 2836
2837 2837 if opts['localssh']:
2838 2838 # We start the SSH server in its own process so there is process
2839 2839 # separation. This prevents a whole class of potential bugs around
2840 2840 # shared state from interfering with server operation.
2841 2841 args = procutil.hgcmd() + [
2842 2842 '-R', repo.root,
2843 2843 'debugserve', '--sshstdio',
2844 2844 ]
2845 2845 proc = subprocess.Popen(args, stdin=subprocess.PIPE,
2846 2846 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
2847 2847 bufsize=0)
2848 2848
2849 2849 stdin = proc.stdin
2850 2850 stdout = proc.stdout
2851 2851 stderr = proc.stderr
2852 2852
2853 2853 # We turn the pipes into observers so we can log I/O.
2854 2854 if ui.verbose or opts['peer'] == 'raw':
2855 2855 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
2856 2856 logdata=True)
2857 2857 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
2858 2858 logdata=True)
2859 2859 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
2860 2860 logdata=True)
2861 2861
2862 2862 # --localssh also implies the peer connection settings.
2863 2863
2864 2864 url = 'ssh://localserver'
2865 2865 autoreadstderr = not opts['noreadstderr']
2866 2866
2867 2867 if opts['peer'] == 'ssh1':
2868 2868 ui.write(_('creating ssh peer for wire protocol version 1\n'))
2869 2869 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
2870 2870 None, autoreadstderr=autoreadstderr)
2871 2871 elif opts['peer'] == 'ssh2':
2872 2872 ui.write(_('creating ssh peer for wire protocol version 2\n'))
2873 2873 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
2874 2874 None, autoreadstderr=autoreadstderr)
2875 2875 elif opts['peer'] == 'raw':
2876 2876 ui.write(_('using raw connection to peer\n'))
2877 2877 peer = None
2878 2878 else:
2879 2879 ui.write(_('creating ssh peer from handshake results\n'))
2880 2880 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
2881 2881 autoreadstderr=autoreadstderr)
2882 2882
2883 2883 elif path:
2884 2884 # We bypass hg.peer() so we can proxy the sockets.
2885 2885 # TODO consider not doing this because we skip
2886 2886 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
2887 2887 u = util.url(path)
2888 2888 if u.scheme != 'http':
2889 2889 raise error.Abort(_('only http:// paths are currently supported'))
2890 2890
2891 2891 url, authinfo = u.authinfo()
2892 2892 openerargs = {
2893 2893 r'useragent': b'Mercurial debugwireproto',
2894 2894 }
2895 2895
2896 2896 # Turn pipes/sockets into observers so we can log I/O.
2897 2897 if ui.verbose:
2898 2898 openerargs.update({
2899 2899 r'loggingfh': ui,
2900 2900 r'loggingname': b's',
2901 2901 r'loggingopts': {
2902 2902 r'logdata': True,
2903 2903 r'logdataapis': False,
2904 2904 },
2905 2905 })
2906 2906
2907 2907 if ui.debugflag:
2908 2908 openerargs[r'loggingopts'][r'logdataapis'] = True
2909 2909
2910 2910 # Don't send default headers when in raw mode. This allows us to
2911 2911 # bypass most of the behavior of our URL handling code so we can
2912 2912 # have near complete control over what's sent on the wire.
2913 2913 if opts['peer'] == 'raw':
2914 2914 openerargs[r'sendaccept'] = False
2915 2915
2916 2916 opener = urlmod.opener(ui, authinfo, **openerargs)
2917 2917
2918 2918 if opts['peer'] == 'http2':
2919 2919 ui.write(_('creating http peer for wire protocol version 2\n'))
2920 2920 # We go through makepeer() because we need an API descriptor for
2921 2921 # the peer instance to be useful.
2922 2922 with ui.configoverride({
2923 2923 ('experimental', 'httppeer.advertise-v2'): True}):
2924 2924 peer = httppeer.makepeer(ui, path, opener=opener)
2925 2925
2926 2926 if not isinstance(peer, httppeer.httpv2peer):
2927 2927 raise error.Abort(_('could not instantiate HTTP peer for '
2928 2928 'wire protocol version 2'),
2929 2929 hint=_('the server may not have the feature '
2930 2930 'enabled or is not allowing this '
2931 2931 'client version'))
2932 2932
2933 2933 elif opts['peer'] == 'raw':
2934 2934 ui.write(_('using raw connection to peer\n'))
2935 2935 peer = None
2936 2936 elif opts['peer']:
2937 2937 raise error.Abort(_('--peer %s not supported with HTTP peers') %
2938 2938 opts['peer'])
2939 2939 else:
2940 2940 peer = httppeer.makepeer(ui, path, opener=opener)
2941 2941
2942 2942 # We /could/ populate stdin/stdout with sock.makefile()...
2943 2943 else:
2944 2944 raise error.Abort(_('unsupported connection configuration'))
2945 2945
2946 2946 batchedcommands = None
2947 2947
2948 2948 # Now perform actions based on the parsed wire language instructions.
2949 2949 for action, lines in blocks:
2950 2950 if action in ('raw', 'raw+'):
2951 2951 if not stdin:
2952 2952 raise error.Abort(_('cannot call raw/raw+ on this peer'))
2953 2953
2954 2954 # Concatenate the data together.
2955 2955 data = ''.join(l.lstrip() for l in lines)
2956 2956 data = stringutil.unescapestr(data)
2957 2957 stdin.write(data)
2958 2958
2959 2959 if action == 'raw+':
2960 2960 stdin.flush()
2961 2961 elif action == 'flush':
2962 2962 if not stdin:
2963 2963 raise error.Abort(_('cannot call flush on this peer'))
2964 2964 stdin.flush()
2965 2965 elif action.startswith('command'):
2966 2966 if not peer:
2967 2967 raise error.Abort(_('cannot send commands unless peer instance '
2968 2968 'is available'))
2969 2969
2970 2970 command = action.split(' ', 1)[1]
2971 2971
2972 2972 args = {}
2973 2973 for line in lines:
2974 2974 # We need to allow empty values.
2975 2975 fields = line.lstrip().split(' ', 1)
2976 2976 if len(fields) == 1:
2977 2977 key = fields[0]
2978 2978 value = ''
2979 2979 else:
2980 2980 key, value = fields
2981 2981
2982 2982 if value.startswith('eval:'):
2983 2983 value = stringutil.evalpythonliteral(value[5:])
2984 2984 else:
2985 2985 value = stringutil.unescapestr(value)
2986 2986
2987 2987 args[key] = value
2988 2988
2989 2989 if batchedcommands is not None:
2990 2990 batchedcommands.append((command, args))
2991 2991 continue
2992 2992
2993 2993 ui.status(_('sending %s command\n') % command)
2994 2994
2995 2995 if 'PUSHFILE' in args:
2996 2996 with open(args['PUSHFILE'], r'rb') as fh:
2997 2997 del args['PUSHFILE']
2998 2998 res, output = peer._callpush(command, fh,
2999 2999 **pycompat.strkwargs(args))
3000 3000 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3001 3001 ui.status(_('remote output: %s\n') %
3002 3002 stringutil.escapestr(output))
3003 3003 else:
3004 res = peer._call(command, **pycompat.strkwargs(args))
3004 with peer.commandexecutor() as e:
3005 res = e.callcommand(command, args).result()
3006
3005 3007 ui.status(_('response: %s\n') % stringutil.pprint(res))
3006 3008
3007 3009 elif action == 'batchbegin':
3008 3010 if batchedcommands is not None:
3009 3011 raise error.Abort(_('nested batchbegin not allowed'))
3010 3012
3011 3013 batchedcommands = []
3012 3014 elif action == 'batchsubmit':
3013 3015 # There is a batching API we could go through. But it would be
3014 3016 # difficult to normalize requests into function calls. It is easier
3015 3017 # to bypass this layer and normalize to commands + args.
3016 3018 ui.status(_('sending batch with %d sub-commands\n') %
3017 3019 len(batchedcommands))
3018 3020 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3019 3021 ui.status(_('response #%d: %s\n') %
3020 3022 (i, stringutil.escapestr(chunk)))
3021 3023
3022 3024 batchedcommands = None
3023 3025
3024 3026 elif action.startswith('httprequest '):
3025 3027 if not opener:
3026 3028 raise error.Abort(_('cannot use httprequest without an HTTP '
3027 3029 'peer'))
3028 3030
3029 3031 request = action.split(' ', 2)
3030 3032 if len(request) != 3:
3031 3033 raise error.Abort(_('invalid httprequest: expected format is '
3032 3034 '"httprequest <method> <path>'))
3033 3035
3034 3036 method, httppath = request[1:]
3035 3037 headers = {}
3036 3038 body = None
3037 3039 frames = []
3038 3040 for line in lines:
3039 3041 line = line.lstrip()
3040 3042 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3041 3043 if m:
3042 3044 headers[m.group(1)] = m.group(2)
3043 3045 continue
3044 3046
3045 3047 if line.startswith(b'BODYFILE '):
3046 3048 with open(line.split(b' ', 1), 'rb') as fh:
3047 3049 body = fh.read()
3048 3050 elif line.startswith(b'frame '):
3049 3051 frame = wireprotoframing.makeframefromhumanstring(
3050 3052 line[len(b'frame '):])
3051 3053
3052 3054 frames.append(frame)
3053 3055 else:
3054 3056 raise error.Abort(_('unknown argument to httprequest: %s') %
3055 3057 line)
3056 3058
3057 3059 url = path + httppath
3058 3060
3059 3061 if frames:
3060 3062 body = b''.join(bytes(f) for f in frames)
3061 3063
3062 3064 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3063 3065
3064 3066 # urllib.Request insists on using has_data() as a proxy for
3065 3067 # determining the request method. Override that to use our
3066 3068 # explicitly requested method.
3067 3069 req.get_method = lambda: method
3068 3070
3069 3071 try:
3070 3072 res = opener.open(req)
3071 3073 body = res.read()
3072 3074 except util.urlerr.urlerror as e:
3073 3075 e.read()
3074 3076 continue
3075 3077
3076 3078 if res.headers.get('Content-Type') == 'application/mercurial-cbor':
3077 3079 ui.write(_('cbor> %s\n') % stringutil.pprint(cbor.loads(body)))
3078 3080
3079 3081 elif action == 'close':
3080 3082 peer.close()
3081 3083 elif action == 'readavailable':
3082 3084 if not stdout or not stderr:
3083 3085 raise error.Abort(_('readavailable not available on this peer'))
3084 3086
3085 3087 stdin.close()
3086 3088 stdout.read()
3087 3089 stderr.read()
3088 3090
3089 3091 elif action == 'readline':
3090 3092 if not stdout:
3091 3093 raise error.Abort(_('readline not available on this peer'))
3092 3094 stdout.readline()
3093 3095 elif action == 'ereadline':
3094 3096 if not stderr:
3095 3097 raise error.Abort(_('ereadline not available on this peer'))
3096 3098 stderr.readline()
3097 3099 elif action.startswith('read '):
3098 3100 count = int(action.split(' ', 1)[1])
3099 3101 if not stdout:
3100 3102 raise error.Abort(_('read not available on this peer'))
3101 3103 stdout.read(count)
3102 3104 elif action.startswith('eread '):
3103 3105 count = int(action.split(' ', 1)[1])
3104 3106 if not stderr:
3105 3107 raise error.Abort(_('eread not available on this peer'))
3106 3108 stderr.read(count)
3107 3109 else:
3108 3110 raise error.Abort(_('unknown action: %s') % action)
3109 3111
3110 3112 if batchedcommands is not None:
3111 3113 raise error.Abort(_('unclosed "batchbegin" request'))
3112 3114
3113 3115 if peer:
3114 3116 peer.close()
3115 3117
3116 3118 if proc:
3117 3119 proc.kill()
@@ -1,335 +1,335
1 1 $ . $TESTDIR/wireprotohelpers.sh
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [web]
5 5 > push_ssl = false
6 6 > allow_push = *
7 7 > EOF
8 8
9 9 $ hg init server
10 10 $ cd server
11 11 $ touch a
12 12 $ hg -q commit -A -m initial
13 13 $ cd ..
14 14
15 15 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
16 16 $ cat hg.pid >> $DAEMON_PIDS
17 17
18 18 compression formats are advertised in compression capability
19 19
20 20 #if zstd
21 21 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zstd,zlib$' > /dev/null
22 22 #else
23 23 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=zlib$' > /dev/null
24 24 #endif
25 25
26 26 $ killdaemons.py
27 27
28 28 server.compressionengines can replace engines list wholesale
29 29
30 30 $ hg serve --config server.compressionengines=none -R server -p $HGPORT -d --pid-file hg.pid
31 31 $ cat hg.pid > $DAEMON_PIDS
32 32 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none$' > /dev/null
33 33
34 34 $ killdaemons.py
35 35
36 36 Order of engines can also change
37 37
38 38 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
39 39 $ cat hg.pid > $DAEMON_PIDS
40 40 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' | tr ' ' '\n' | grep '^compression=none,zlib$' > /dev/null
41 41
42 42 $ killdaemons.py
43 43
44 44 Start a default server again
45 45
46 46 $ hg serve -R server -p $HGPORT -d --pid-file hg.pid
47 47 $ cat hg.pid > $DAEMON_PIDS
48 48
49 49 Server should send application/mercurial-0.1 to clients if no Accept is used
50 50
51 51 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
52 52 200 Script output follows
53 53 content-type: application/mercurial-0.1
54 54 date: $HTTP_DATE$
55 55 server: testing stub value
56 56 transfer-encoding: chunked
57 57
58 58 Server should send application/mercurial-0.1 when client says it wants it
59 59
60 60 $ get-with-headers.py --hgproto '0.1' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
61 61 200 Script output follows
62 62 content-type: application/mercurial-0.1
63 63 date: $HTTP_DATE$
64 64 server: testing stub value
65 65 transfer-encoding: chunked
66 66
67 67 Server should send application/mercurial-0.2 when client says it wants it
68 68
69 69 $ get-with-headers.py --hgproto '0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
70 70 200 Script output follows
71 71 content-type: application/mercurial-0.2
72 72 date: $HTTP_DATE$
73 73 server: testing stub value
74 74 transfer-encoding: chunked
75 75
76 76 $ get-with-headers.py --hgproto '0.1 0.2' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
77 77 200 Script output follows
78 78 content-type: application/mercurial-0.2
79 79 date: $HTTP_DATE$
80 80 server: testing stub value
81 81 transfer-encoding: chunked
82 82
83 83 Requesting a compression format that server doesn't support results will fall back to 0.1
84 84
85 85 $ get-with-headers.py --hgproto '0.2 comp=aa' --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' -
86 86 200 Script output follows
87 87 content-type: application/mercurial-0.1
88 88 date: $HTTP_DATE$
89 89 server: testing stub value
90 90 transfer-encoding: chunked
91 91
92 92 #if zstd
93 93 zstd is used if available
94 94
95 95 $ get-with-headers.py --hgproto '0.2 comp=zstd' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
96 96 $ f --size --hexdump --bytes 36 --sha1 resp
97 97 resp: size=248, sha1=4d8d8f87fb82bd542ce52881fdc94f850748
98 98 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
99 99 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 73 74 64 |t follows...zstd|
100 100 0020: 28 b5 2f fd |(./.|
101 101
102 102 #endif
103 103
104 104 application/mercurial-0.2 is not yet used on non-streaming responses
105 105
106 106 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=heads' -
107 107 200 Script output follows
108 108 content-length: 41
109 109 content-type: application/mercurial-0.1
110 110 date: $HTTP_DATE$
111 111 server: testing stub value
112 112
113 113 e93700bd72895c5addab234c56d4024b487a362f
114 114
115 115 Now test protocol preference usage
116 116
117 117 $ killdaemons.py
118 118 $ hg serve --config server.compressionengines=none,zlib -R server -p $HGPORT -d --pid-file hg.pid
119 119 $ cat hg.pid > $DAEMON_PIDS
120 120
121 121 No Accept will send 0.1+zlib, even though "none" is preferred b/c "none" isn't supported on 0.1
122 122
123 123 $ get-with-headers.py --headeronly $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' Content-Type
124 124 200 Script output follows
125 125 content-type: application/mercurial-0.1
126 126
127 127 $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
128 128 $ f --size --hexdump --bytes 28 --sha1 resp
129 129 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
130 130 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
131 131 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
132 132
133 133 Explicit 0.1 will send zlib because "none" isn't supported on 0.1
134 134
135 135 $ get-with-headers.py --hgproto '0.1' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
136 136 $ f --size --hexdump --bytes 28 --sha1 resp
137 137 resp: size=227, sha1=35a4c074da74f32f5440da3cbf04
138 138 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
139 139 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 78 |t follows..x|
140 140
141 141 0.2 with no compression will get "none" because that is server's preference
142 142 (spec says ZL and UN are implicitly supported)
143 143
144 144 $ get-with-headers.py --hgproto '0.2' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
145 145 $ f --size --hexdump --bytes 32 --sha1 resp
146 146 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
147 147 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
148 148 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
149 149
150 150 Client receives server preference even if local order doesn't match
151 151
152 152 $ get-with-headers.py --hgproto '0.2 comp=zlib,none' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
153 153 $ f --size --hexdump --bytes 32 --sha1 resp
154 154 resp: size=432, sha1=ac931b412ec185a02e0e5bcff98dac83
155 155 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
156 156 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 6e 6f 6e 65 |t follows...none|
157 157
158 158 Client receives only supported format even if not server preferred format
159 159
160 160 $ get-with-headers.py --hgproto '0.2 comp=zlib' $LOCALIP:$HGPORT '?cmd=getbundle&heads=e93700bd72895c5addab234c56d4024b487a362f&common=0000000000000000000000000000000000000000' > resp
161 161 $ f --size --hexdump --bytes 33 --sha1 resp
162 162 resp: size=232, sha1=a1c727f0c9693ca15742a75c30419bc36
163 163 0000: 32 30 30 20 53 63 72 69 70 74 20 6f 75 74 70 75 |200 Script outpu|
164 164 0010: 74 20 66 6f 6c 6c 6f 77 73 0a 0a 04 7a 6c 69 62 |t follows...zlib|
165 165 0020: 78 |x|
166 166
167 167 $ killdaemons.py
168 168 $ cd ..
169 169
170 170 Test listkeys for listing namespaces
171 171
172 172 $ hg init empty
173 173 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
174 174 $ cat hg.pid > $DAEMON_PIDS
175 175
176 176 $ hg --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
177 177 > command listkeys
178 178 > namespace namespaces
179 179 > EOF
180 180 s> GET /?cmd=capabilities HTTP/1.1\r\n
181 181 s> Accept-Encoding: identity\r\n
182 182 s> accept: application/mercurial-0.1\r\n
183 183 s> host: $LOCALIP:$HGPORT\r\n (glob)
184 184 s> user-agent: Mercurial debugwireproto\r\n
185 185 s> \r\n
186 186 s> makefile('rb', None)
187 187 s> HTTP/1.1 200 Script output follows\r\n
188 188 s> Server: testing stub value\r\n
189 189 s> Date: $HTTP_DATE$\r\n
190 190 s> Content-Type: application/mercurial-0.1\r\n
191 191 s> Content-Length: *\r\n (glob)
192 192 s> \r\n
193 193 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
194 194 sending listkeys command
195 195 s> GET /?cmd=listkeys HTTP/1.1\r\n
196 196 s> Accept-Encoding: identity\r\n
197 197 s> vary: X-HgArg-1,X-HgProto-1\r\n
198 198 s> x-hgarg-1: namespace=namespaces\r\n
199 199 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
200 200 s> accept: application/mercurial-0.1\r\n
201 201 s> host: $LOCALIP:$HGPORT\r\n (glob)
202 202 s> user-agent: Mercurial debugwireproto\r\n
203 203 s> \r\n
204 204 s> makefile('rb', None)
205 205 s> HTTP/1.1 200 Script output follows\r\n
206 206 s> Server: testing stub value\r\n
207 207 s> Date: $HTTP_DATE$\r\n
208 208 s> Content-Type: application/mercurial-0.1\r\n
209 209 s> Content-Length: 30\r\n
210 210 s> \r\n
211 211 s> bookmarks\t\n
212 212 s> namespaces\t\n
213 213 s> phases\t
214 response: b'bookmarks\t\nnamespaces\t\nphases\t'
214 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
215 215
216 216 Same thing, but with "httprequest" command
217 217
218 218 $ hg --verbose debugwireproto --peer raw http://$LOCALIP:$HGPORT << EOF
219 219 > httprequest GET ?cmd=listkeys
220 220 > user-agent: test
221 221 > x-hgarg-1: namespace=namespaces
222 222 > EOF
223 223 using raw connection to peer
224 224 s> GET /?cmd=listkeys HTTP/1.1\r\n
225 225 s> Accept-Encoding: identity\r\n
226 226 s> user-agent: test\r\n
227 227 s> x-hgarg-1: namespace=namespaces\r\n
228 228 s> host: $LOCALIP:$HGPORT\r\n (glob)
229 229 s> \r\n
230 230 s> makefile('rb', None)
231 231 s> HTTP/1.1 200 Script output follows\r\n
232 232 s> Server: testing stub value\r\n
233 233 s> Date: $HTTP_DATE$\r\n
234 234 s> Content-Type: application/mercurial-0.1\r\n
235 235 s> Content-Length: 30\r\n
236 236 s> \r\n
237 237 s> bookmarks\t\n
238 238 s> namespaces\t\n
239 239 s> phases\t
240 240
241 241 Client with HTTPv2 enabled advertises that and gets old capabilities response from old server
242 242
243 243 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
244 244 > command heads
245 245 > EOF
246 246 s> GET /?cmd=capabilities HTTP/1.1\r\n
247 247 s> Accept-Encoding: identity\r\n
248 248 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
249 249 s> x-hgproto-1: cbor\r\n
250 250 s> x-hgupgrade-1: exp-http-v2-0001\r\n
251 251 s> accept: application/mercurial-0.1\r\n
252 252 s> host: $LOCALIP:$HGPORT\r\n (glob)
253 253 s> user-agent: Mercurial debugwireproto\r\n
254 254 s> \r\n
255 255 s> makefile('rb', None)
256 256 s> HTTP/1.1 200 Script output follows\r\n
257 257 s> Server: testing stub value\r\n
258 258 s> Date: $HTTP_DATE$\r\n
259 259 s> Content-Type: application/mercurial-0.1\r\n
260 260 s> Content-Length: 458\r\n
261 261 s> \r\n
262 262 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
263 263 sending heads command
264 264 s> GET /?cmd=heads HTTP/1.1\r\n
265 265 s> Accept-Encoding: identity\r\n
266 266 s> vary: X-HgProto-1\r\n
267 267 s> x-hgproto-1: 0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull\r\n
268 268 s> accept: application/mercurial-0.1\r\n
269 269 s> host: $LOCALIP:$HGPORT\r\n (glob)
270 270 s> user-agent: Mercurial debugwireproto\r\n
271 271 s> \r\n
272 272 s> makefile('rb', None)
273 273 s> HTTP/1.1 200 Script output follows\r\n
274 274 s> Server: testing stub value\r\n
275 275 s> Date: $HTTP_DATE$\r\n
276 276 s> Content-Type: application/mercurial-0.1\r\n
277 277 s> Content-Length: 41\r\n
278 278 s> \r\n
279 279 s> 0000000000000000000000000000000000000000\n
280 response: b'0000000000000000000000000000000000000000\n'
280 response: [b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00']
281 281
282 282 $ killdaemons.py
283 283 $ enablehttpv2 empty
284 284 $ hg -R empty serve -p $HGPORT -d --pid-file hg.pid
285 285 $ cat hg.pid > $DAEMON_PIDS
286 286
287 287 Client with HTTPv2 enabled automatically upgrades if the server supports it
288 288
289 289 $ hg --config experimental.httppeer.advertise-v2=true --verbose debugwireproto http://$LOCALIP:$HGPORT << EOF
290 290 > command heads
291 291 > EOF
292 292 s> GET /?cmd=capabilities HTTP/1.1\r\n
293 293 s> Accept-Encoding: identity\r\n
294 294 s> vary: X-HgProto-1,X-HgUpgrade-1\r\n
295 295 s> x-hgproto-1: cbor\r\n
296 296 s> x-hgupgrade-1: exp-http-v2-0001\r\n
297 297 s> accept: application/mercurial-0.1\r\n
298 298 s> host: $LOCALIP:$HGPORT\r\n (glob)
299 299 s> user-agent: Mercurial debugwireproto\r\n
300 300 s> \r\n
301 301 s> makefile('rb', None)
302 302 s> HTTP/1.1 200 OK\r\n
303 303 s> Server: testing stub value\r\n
304 304 s> Date: $HTTP_DATE$\r\n
305 305 s> Content-Type: application/mercurial-cbor\r\n
306 306 s> Content-Length: *\r\n (glob)
307 307 s> \r\n
308 308 s> \xa3Dapis\xa1Pexp-http-v2-0001\xa2Hcommands\xa7Eheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyCfooKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyCkeyCnewCnewColdColdInamespaceBnsKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlibGapibaseDapi/Nv1capabilitiesY\x01\xcabatch 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
309 309 sending heads command
310 310 s> POST /api/exp-http-v2-0001/ro/heads HTTP/1.1\r\n
311 311 s> Accept-Encoding: identity\r\n
312 312 s> accept: application/mercurial-exp-framing-0003\r\n
313 313 s> content-type: application/mercurial-exp-framing-0003\r\n
314 314 s> content-length: 20\r\n
315 315 s> host: $LOCALIP:$HGPORT\r\n (glob)
316 316 s> user-agent: Mercurial debugwireproto\r\n
317 317 s> \r\n
318 318 s> \x0c\x00\x00\x01\x00\x01\x01\x11\xa1DnameEheads
319 319 s> makefile('rb', None)
320 320 s> HTTP/1.1 200 OK\r\n
321 321 s> Server: testing stub value\r\n
322 322 s> Date: $HTTP_DATE$\r\n
323 323 s> Content-Type: application/mercurial-exp-framing-0003\r\n
324 324 s> Transfer-Encoding: chunked\r\n
325 325 s> \r\n
326 326 s> 1e\r\n
327 327 s> \x16\x00\x00\x01\x00\x02\x01F
328 328 s> \x81T\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
329 329 s> \r\n
330 330 received frame(size=22; request=1; stream=2; streamflags=stream-begin; type=bytes-response; flags=eos|cbor)
331 331 s> 0\r\n
332 332 s> \r\n
333 333 response: [[b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00']]
334 334
335 335 $ killdaemons.py
@@ -1,2167 +1,2167
1 1 $ cat > hgrc-sshv2 << EOF
2 2 > %include $HGRCPATH
3 3 > [experimental]
4 4 > sshpeer.advertise-v2 = true
5 5 > sshserver.support-v2 = true
6 6 > EOF
7 7
8 8 Helper function to run protocol tests against multiple protocol versions.
9 9 This is easier than using #testcases because managing differences between
10 10 protocols with inline conditional output is hard to read.
11 11
12 12 $ debugwireproto() {
13 13 > commands=`cat -`
14 14 > echo 'testing ssh1'
15 15 > echo "${commands}" | hg --verbose debugwireproto --localssh
16 16 > echo ""
17 17 > echo 'testing ssh2'
18 18 > echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh
19 19 > }
20 20
21 21 $ cat >> $HGRCPATH << EOF
22 22 > [ui]
23 23 > ssh = $PYTHON "$TESTDIR/dummyssh"
24 24 > [devel]
25 25 > debug.peer-request = true
26 26 > [extensions]
27 27 > sshprotoext = $TESTDIR/sshprotoext.py
28 28 > EOF
29 29
30 30 $ hg init server
31 31 $ cd server
32 32 $ echo 0 > foo
33 33 $ hg -q add foo
34 34 $ hg commit -m initial
35 35
36 36 A no-op connection performs a handshake
37 37
38 38 $ hg debugwireproto --localssh << EOF
39 39 > EOF
40 40 creating ssh peer from handshake results
41 41
42 42 Raw peers don't perform any activity
43 43
44 44 $ hg debugwireproto --localssh --peer raw << EOF
45 45 > EOF
46 46 using raw connection to peer
47 47 $ hg debugwireproto --localssh --peer ssh1 << EOF
48 48 > EOF
49 49 creating ssh peer for wire protocol version 1
50 50 $ hg debugwireproto --localssh --peer ssh2 << EOF
51 51 > EOF
52 52 creating ssh peer for wire protocol version 2
53 53
54 54 Test a normal behaving server, for sanity
55 55
56 56 $ cd ..
57 57
58 58 $ hg --debug debugpeer ssh://user@dummy/server
59 59 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
60 60 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
61 61 devel-peer-request: hello
62 62 sending hello command
63 63 devel-peer-request: between
64 64 devel-peer-request: pairs: 81 bytes
65 65 sending between command
66 66 remote: 413
67 67 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
68 68 remote: 1
69 69 devel-peer-request: protocaps
70 70 devel-peer-request: caps: * bytes (glob)
71 71 sending protocaps command
72 72 url: ssh://user@dummy/server
73 73 local: no
74 74 pushable: yes
75 75
76 76 Server should answer the "hello" command in isolation
77 77
78 78 $ hg -R server debugwireproto --localssh --peer raw << EOF
79 79 > raw
80 80 > hello\n
81 81 > readline
82 82 > readline
83 83 > EOF
84 84 using raw connection to peer
85 85 i> write(6) -> 6:
86 86 i> hello\n
87 87 o> readline() -> 4:
88 88 o> 413\n
89 89 o> readline() -> 413:
90 90 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
91 91
92 92 `hg debugserve --sshstdio` works
93 93
94 94 $ cd server
95 95 $ hg debugserve --sshstdio << EOF
96 96 > hello
97 97 > EOF
98 98 413
99 99 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
100 100
101 101 I/O logging works
102 102
103 103 $ hg debugserve --sshstdio --logiofd 1 << EOF
104 104 > hello
105 105 > EOF
106 106 o> write(4) -> 4:
107 107 o> 413\n
108 108 o> write(413) -> 413:
109 109 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
110 110 413
111 111 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
112 112 o> flush() -> None
113 113
114 114 $ hg debugserve --sshstdio --logiofile $TESTTMP/io << EOF
115 115 > hello
116 116 > EOF
117 117 413
118 118 capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
119 119
120 120 $ cat $TESTTMP/io
121 121 o> write(4) -> 4:
122 122 o> 413\n
123 123 o> write(413) -> 413:
124 124 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
125 125 o> flush() -> None
126 126
127 127 $ cd ..
128 128
129 129 >=0.9.1 clients send a "hello" + "between" for the null range as part of handshake.
130 130 Server should reply with capabilities and should send "1\n\n" as a successful
131 131 reply with empty response to the "between".
132 132
133 133 $ hg -R server debugwireproto --localssh --peer raw << EOF
134 134 > raw
135 135 > hello\n
136 136 > readline
137 137 > readline
138 138 > raw
139 139 > between\n
140 140 > pairs 81\n
141 141 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
142 142 > readline
143 143 > readline
144 144 > EOF
145 145 using raw connection to peer
146 146 i> write(6) -> 6:
147 147 i> hello\n
148 148 o> readline() -> 4:
149 149 o> 413\n
150 150 o> readline() -> 413:
151 151 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
152 152 i> write(98) -> 98:
153 153 i> between\n
154 154 i> pairs 81\n
155 155 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
156 156 o> readline() -> 2:
157 157 o> 1\n
158 158 o> readline() -> 1:
159 159 o> \n
160 160
161 161 SSH banner is not printed by default, ignored by clients
162 162
163 163 $ SSHSERVERMODE=banner hg debugpeer ssh://user@dummy/server
164 164 url: ssh://user@dummy/server
165 165 local: no
166 166 pushable: yes
167 167
168 168 --debug will print the banner
169 169
170 170 $ SSHSERVERMODE=banner hg --debug debugpeer ssh://user@dummy/server
171 171 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
172 172 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
173 173 devel-peer-request: hello
174 174 sending hello command
175 175 devel-peer-request: between
176 176 devel-peer-request: pairs: 81 bytes
177 177 sending between command
178 178 remote: banner: line 0
179 179 remote: banner: line 1
180 180 remote: banner: line 2
181 181 remote: banner: line 3
182 182 remote: banner: line 4
183 183 remote: banner: line 5
184 184 remote: banner: line 6
185 185 remote: banner: line 7
186 186 remote: banner: line 8
187 187 remote: banner: line 9
188 188 remote: 413
189 189 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
190 190 remote: 1
191 191 devel-peer-request: protocaps
192 192 devel-peer-request: caps: * bytes (glob)
193 193 sending protocaps command
194 194 url: ssh://user@dummy/server
195 195 local: no
196 196 pushable: yes
197 197
198 198 And test the banner with the raw protocol
199 199
200 200 $ SSHSERVERMODE=banner hg -R server debugwireproto --localssh --peer raw << EOF
201 201 > raw
202 202 > hello\n
203 203 > readline
204 204 > readline
205 205 > readline
206 206 > readline
207 207 > readline
208 208 > readline
209 209 > readline
210 210 > readline
211 211 > readline
212 212 > readline
213 213 > readline
214 214 > readline
215 215 > raw
216 216 > between\n
217 217 > pairs 81\n
218 218 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
219 219 > readline
220 220 > readline
221 221 > EOF
222 222 using raw connection to peer
223 223 i> write(6) -> 6:
224 224 i> hello\n
225 225 o> readline() -> 15:
226 226 o> banner: line 0\n
227 227 o> readline() -> 15:
228 228 o> banner: line 1\n
229 229 o> readline() -> 15:
230 230 o> banner: line 2\n
231 231 o> readline() -> 15:
232 232 o> banner: line 3\n
233 233 o> readline() -> 15:
234 234 o> banner: line 4\n
235 235 o> readline() -> 15:
236 236 o> banner: line 5\n
237 237 o> readline() -> 15:
238 238 o> banner: line 6\n
239 239 o> readline() -> 15:
240 240 o> banner: line 7\n
241 241 o> readline() -> 15:
242 242 o> banner: line 8\n
243 243 o> readline() -> 15:
244 244 o> banner: line 9\n
245 245 o> readline() -> 4:
246 246 o> 413\n
247 247 o> readline() -> 413:
248 248 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
249 249 i> write(98) -> 98:
250 250 i> between\n
251 251 i> pairs 81\n
252 252 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
253 253 o> readline() -> 2:
254 254 o> 1\n
255 255 o> readline() -> 1:
256 256 o> \n
257 257
258 258 Connecting to a <0.9.1 server that doesn't support the hello command.
259 259 The client should refuse, as we dropped support for connecting to such
260 260 servers.
261 261
262 262 $ SSHSERVERMODE=no-hello hg --debug debugpeer ssh://user@dummy/server
263 263 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
264 264 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
265 265 devel-peer-request: hello
266 266 sending hello command
267 267 devel-peer-request: between
268 268 devel-peer-request: pairs: 81 bytes
269 269 sending between command
270 270 remote: 0
271 271 remote: 1
272 272 abort: no suitable response from remote hg!
273 273 [255]
274 274
275 275 Sending an unknown command to the server results in an empty response to that command
276 276
277 277 $ hg -R server debugwireproto --localssh --peer raw << EOF
278 278 > raw
279 279 > pre-hello\n
280 280 > readline
281 281 > raw
282 282 > hello\n
283 283 > readline
284 284 > raw
285 285 > between\n
286 286 > pairs 81\n
287 287 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
288 288 > readline
289 289 > readline
290 290 > EOF
291 291 using raw connection to peer
292 292 i> write(10) -> 10:
293 293 i> pre-hello\n
294 294 o> readline() -> 2:
295 295 o> 0\n
296 296 i> write(6) -> 6:
297 297 i> hello\n
298 298 o> readline() -> 4:
299 299 o> 413\n
300 300 i> write(98) -> 98:
301 301 i> between\n
302 302 i> pairs 81\n
303 303 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
304 304 o> readline() -> 413:
305 305 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
306 306 o> readline() -> 2:
307 307 o> 1\n
308 308
309 309 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-no-args --debug debugpeer ssh://user@dummy/server
310 310 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
311 311 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
312 312 sending no-args command
313 313 devel-peer-request: hello
314 314 sending hello command
315 315 devel-peer-request: between
316 316 devel-peer-request: pairs: 81 bytes
317 317 sending between command
318 318 remote: 0
319 319 remote: 413
320 320 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
321 321 remote: 1
322 322 devel-peer-request: protocaps
323 323 devel-peer-request: caps: * bytes (glob)
324 324 sending protocaps command
325 325 url: ssh://user@dummy/server
326 326 local: no
327 327 pushable: yes
328 328
329 329 Send multiple unknown commands before hello
330 330
331 331 $ hg -R server debugwireproto --localssh --peer raw << EOF
332 332 > raw
333 333 > unknown1\n
334 334 > readline
335 335 > raw
336 336 > unknown2\n
337 337 > readline
338 338 > raw
339 339 > unknown3\n
340 340 > readline
341 341 > raw
342 342 > hello\n
343 343 > readline
344 344 > readline
345 345 > raw
346 346 > between\n
347 347 > pairs 81\n
348 348 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
349 349 > readline
350 350 > readline
351 351 > EOF
352 352 using raw connection to peer
353 353 i> write(9) -> 9:
354 354 i> unknown1\n
355 355 o> readline() -> 2:
356 356 o> 0\n
357 357 i> write(9) -> 9:
358 358 i> unknown2\n
359 359 o> readline() -> 2:
360 360 o> 0\n
361 361 i> write(9) -> 9:
362 362 i> unknown3\n
363 363 o> readline() -> 2:
364 364 o> 0\n
365 365 i> write(6) -> 6:
366 366 i> hello\n
367 367 o> readline() -> 4:
368 368 o> 413\n
369 369 o> readline() -> 413:
370 370 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
371 371 i> write(98) -> 98:
372 372 i> between\n
373 373 i> pairs 81\n
374 374 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
375 375 o> readline() -> 2:
376 376 o> 1\n
377 377 o> readline() -> 1:
378 378 o> \n
379 379
380 380 $ hg --config sshpeer.mode=extra-handshake-commands --config sshpeer.handshake-mode=pre-multiple-no-args --debug debugpeer ssh://user@dummy/server
381 381 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
382 382 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
383 383 sending unknown1 command
384 384 sending unknown2 command
385 385 sending unknown3 command
386 386 devel-peer-request: hello
387 387 sending hello command
388 388 devel-peer-request: between
389 389 devel-peer-request: pairs: 81 bytes
390 390 sending between command
391 391 remote: 0
392 392 remote: 0
393 393 remote: 0
394 394 remote: 413
395 395 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
396 396 remote: 1
397 397 devel-peer-request: protocaps
398 398 devel-peer-request: caps: * bytes (glob)
399 399 sending protocaps command
400 400 url: ssh://user@dummy/server
401 401 local: no
402 402 pushable: yes
403 403
404 404 Send an unknown command before hello that has arguments
405 405
406 406 $ cd server
407 407
408 408 $ hg debugwireproto --localssh --peer raw << EOF
409 409 > raw
410 410 > with-args\n
411 411 > foo 13\n
412 412 > value for foo\n
413 413 > bar 13\n
414 414 > value for bar\n
415 415 > readline
416 416 > readline
417 417 > readline
418 418 > readline
419 419 > readline
420 420 > raw
421 421 > hello\n
422 422 > readline
423 423 > readline
424 424 > raw
425 425 > between\n
426 426 > pairs 81\n
427 427 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
428 428 > readline
429 429 > readline
430 430 > EOF
431 431 using raw connection to peer
432 432 i> write(52) -> 52:
433 433 i> with-args\n
434 434 i> foo 13\n
435 435 i> value for foo\n
436 436 i> bar 13\n
437 437 i> value for bar\n
438 438 o> readline() -> 2:
439 439 o> 0\n
440 440 o> readline() -> 2:
441 441 o> 0\n
442 442 o> readline() -> 2:
443 443 o> 0\n
444 444 o> readline() -> 2:
445 445 o> 0\n
446 446 o> readline() -> 2:
447 447 o> 0\n
448 448 i> write(6) -> 6:
449 449 i> hello\n
450 450 o> readline() -> 4:
451 451 o> 413\n
452 452 o> readline() -> 413:
453 453 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
454 454 i> write(98) -> 98:
455 455 i> between\n
456 456 i> pairs 81\n
457 457 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
458 458 o> readline() -> 2:
459 459 o> 1\n
460 460 o> readline() -> 1:
461 461 o> \n
462 462
463 463 Send an unknown command having an argument that looks numeric
464 464
465 465 $ hg debugwireproto --localssh --peer raw << EOF
466 466 > raw
467 467 > unknown\n
468 468 > foo 1\n
469 469 > 0\n
470 470 > readline
471 471 > readline
472 472 > readline
473 473 > raw
474 474 > hello\n
475 475 > readline
476 476 > readline
477 477 > raw
478 478 > between\n
479 479 > pairs 81\n
480 480 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
481 481 > readline
482 482 > readline
483 483 > EOF
484 484 using raw connection to peer
485 485 i> write(16) -> 16:
486 486 i> unknown\n
487 487 i> foo 1\n
488 488 i> 0\n
489 489 o> readline() -> 2:
490 490 o> 0\n
491 491 o> readline() -> 2:
492 492 o> 0\n
493 493 o> readline() -> 2:
494 494 o> 0\n
495 495 i> write(6) -> 6:
496 496 i> hello\n
497 497 o> readline() -> 4:
498 498 o> 413\n
499 499 o> readline() -> 413:
500 500 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
501 501 i> write(98) -> 98:
502 502 i> between\n
503 503 i> pairs 81\n
504 504 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
505 505 o> readline() -> 2:
506 506 o> 1\n
507 507 o> readline() -> 1:
508 508 o> \n
509 509
510 510 $ hg debugwireproto --localssh --peer raw << EOF
511 511 > raw
512 512 > unknown\n
513 513 > foo 1\n
514 514 > 1\n
515 515 > readline
516 516 > readline
517 517 > readline
518 518 > raw
519 519 > hello\n
520 520 > readline
521 521 > readline
522 522 > raw
523 523 > between\n
524 524 > pairs 81\n
525 525 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
526 526 > readline
527 527 > readline
528 528 > EOF
529 529 using raw connection to peer
530 530 i> write(16) -> 16:
531 531 i> unknown\n
532 532 i> foo 1\n
533 533 i> 1\n
534 534 o> readline() -> 2:
535 535 o> 0\n
536 536 o> readline() -> 2:
537 537 o> 0\n
538 538 o> readline() -> 2:
539 539 o> 0\n
540 540 i> write(6) -> 6:
541 541 i> hello\n
542 542 o> readline() -> 4:
543 543 o> 413\n
544 544 o> readline() -> 413:
545 545 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
546 546 i> write(98) -> 98:
547 547 i> between\n
548 548 i> pairs 81\n
549 549 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
550 550 o> readline() -> 2:
551 551 o> 1\n
552 552 o> readline() -> 1:
553 553 o> \n
554 554
555 555 When sending a dict argument value, it is serialized to
556 556 "<arg> <item count>" followed by "<key> <len>\n<value>" for each item
557 557 in the dict.
558 558
559 559 Dictionary value for unknown command
560 560
561 561 $ hg debugwireproto --localssh --peer raw << EOF
562 562 > raw
563 563 > unknown\n
564 564 > dict 3\n
565 565 > key1 3\n
566 566 > foo\n
567 567 > key2 3\n
568 568 > bar\n
569 569 > key3 3\n
570 570 > baz\n
571 571 > readline
572 572 > readline
573 573 > readline
574 574 > readline
575 575 > readline
576 576 > readline
577 577 > readline
578 578 > readline
579 579 > raw
580 580 > hello\n
581 581 > readline
582 582 > readline
583 583 > EOF
584 584 using raw connection to peer
585 585 i> write(48) -> 48:
586 586 i> unknown\n
587 587 i> dict 3\n
588 588 i> key1 3\n
589 589 i> foo\n
590 590 i> key2 3\n
591 591 i> bar\n
592 592 i> key3 3\n
593 593 i> baz\n
594 594 o> readline() -> 2:
595 595 o> 0\n
596 596 o> readline() -> 2:
597 597 o> 0\n
598 598 o> readline() -> 2:
599 599 o> 0\n
600 600 o> readline() -> 2:
601 601 o> 0\n
602 602 o> readline() -> 2:
603 603 o> 0\n
604 604 o> readline() -> 2:
605 605 o> 0\n
606 606 o> readline() -> 2:
607 607 o> 0\n
608 608 o> readline() -> 2:
609 609 o> 0\n
610 610 i> write(6) -> 6:
611 611 i> hello\n
612 612 o> readline() -> 4:
613 613 o> 413\n
614 614 o> readline() -> 413:
615 615 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
616 616
617 617 Incomplete dictionary send
618 618
619 619 $ hg debugwireproto --localssh --peer raw << EOF
620 620 > raw
621 621 > unknown\n
622 622 > dict 3\n
623 623 > key1 3\n
624 624 > foo\n
625 625 > readline
626 626 > readline
627 627 > readline
628 628 > readline
629 629 > EOF
630 630 using raw connection to peer
631 631 i> write(26) -> 26:
632 632 i> unknown\n
633 633 i> dict 3\n
634 634 i> key1 3\n
635 635 i> foo\n
636 636 o> readline() -> 2:
637 637 o> 0\n
638 638 o> readline() -> 2:
639 639 o> 0\n
640 640 o> readline() -> 2:
641 641 o> 0\n
642 642 o> readline() -> 2:
643 643 o> 0\n
644 644
645 645 Incomplete value send
646 646
647 647 $ hg debugwireproto --localssh --peer raw << EOF
648 648 > raw
649 649 > unknown\n
650 650 > dict 3\n
651 651 > key1 3\n
652 652 > fo
653 653 > readline
654 654 > readline
655 655 > readline
656 656 > EOF
657 657 using raw connection to peer
658 658 i> write(24) -> 24:
659 659 i> unknown\n
660 660 i> dict 3\n
661 661 i> key1 3\n
662 662 i> fo
663 663 o> readline() -> 2:
664 664 o> 0\n
665 665 o> readline() -> 2:
666 666 o> 0\n
667 667 o> readline() -> 2:
668 668 o> 0\n
669 669
670 670 Send a command line with spaces
671 671
672 672 $ hg debugwireproto --localssh --peer raw << EOF
673 673 > raw
674 674 > unknown withspace\n
675 675 > readline
676 676 > raw
677 677 > hello\n
678 678 > readline
679 679 > readline
680 680 > raw
681 681 > between\n
682 682 > pairs 81\n
683 683 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
684 684 > readline
685 685 > readline
686 686 > EOF
687 687 using raw connection to peer
688 688 i> write(18) -> 18:
689 689 i> unknown withspace\n
690 690 o> readline() -> 2:
691 691 o> 0\n
692 692 i> write(6) -> 6:
693 693 i> hello\n
694 694 o> readline() -> 4:
695 695 o> 413\n
696 696 o> readline() -> 413:
697 697 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
698 698 i> write(98) -> 98:
699 699 i> between\n
700 700 i> pairs 81\n
701 701 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
702 702 o> readline() -> 2:
703 703 o> 1\n
704 704 o> readline() -> 1:
705 705 o> \n
706 706
707 707 $ hg debugwireproto --localssh --peer raw << EOF
708 708 > raw
709 709 > unknown with multiple spaces\n
710 710 > readline
711 711 > raw
712 712 > hello\n
713 713 > readline
714 714 > readline
715 715 > raw
716 716 > between\n
717 717 > pairs 81\n
718 718 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
719 719 > readline
720 720 > EOF
721 721 using raw connection to peer
722 722 i> write(29) -> 29:
723 723 i> unknown with multiple spaces\n
724 724 o> readline() -> 2:
725 725 o> 0\n
726 726 i> write(6) -> 6:
727 727 i> hello\n
728 728 o> readline() -> 4:
729 729 o> 413\n
730 730 o> readline() -> 413:
731 731 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
732 732 i> write(98) -> 98:
733 733 i> between\n
734 734 i> pairs 81\n
735 735 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
736 736 o> readline() -> 2:
737 737 o> 1\n
738 738
739 739 $ hg debugwireproto --localssh --peer raw << EOF
740 740 > raw
741 741 > unknown with spaces\n
742 742 > key 10\n
743 743 > some value\n
744 744 > readline
745 745 > readline
746 746 > readline
747 747 > raw
748 748 > hello\n
749 749 > readline
750 750 > readline
751 751 > raw
752 752 > between\n
753 753 > pairs 81\n
754 754 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
755 755 > readline
756 756 > readline
757 757 > EOF
758 758 using raw connection to peer
759 759 i> write(38) -> 38:
760 760 i> unknown with spaces\n
761 761 i> key 10\n
762 762 i> some value\n
763 763 o> readline() -> 2:
764 764 o> 0\n
765 765 o> readline() -> 2:
766 766 o> 0\n
767 767 o> readline() -> 2:
768 768 o> 0\n
769 769 i> write(6) -> 6:
770 770 i> hello\n
771 771 o> readline() -> 4:
772 772 o> 413\n
773 773 o> readline() -> 413:
774 774 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
775 775 i> write(98) -> 98:
776 776 i> between\n
777 777 i> pairs 81\n
778 778 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
779 779 o> readline() -> 2:
780 780 o> 1\n
781 781 o> readline() -> 1:
782 782 o> \n
783 783 Send an unknown command after the "between"
784 784
785 785 $ hg debugwireproto --localssh --peer raw << EOF
786 786 > raw
787 787 > hello\n
788 788 > readline
789 789 > readline
790 790 > raw
791 791 > between\n
792 792 > pairs 81\n
793 793 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
794 794 > readline
795 795 > readline
796 796 > EOF
797 797 using raw connection to peer
798 798 i> write(6) -> 6:
799 799 i> hello\n
800 800 o> readline() -> 4:
801 801 o> 413\n
802 802 o> readline() -> 413:
803 803 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
804 804 i> write(105) -> 105:
805 805 i> between\n
806 806 i> pairs 81\n
807 807 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000unknown
808 808 o> readline() -> 2:
809 809 o> 1\n
810 810 o> readline() -> 1:
811 811 o> \n
812 812
813 813 And one with arguments
814 814
815 815 $ hg debugwireproto --localssh --peer raw << EOF
816 816 > raw
817 817 > hello\n
818 818 > between\n
819 819 > pairs 81\n
820 820 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
821 821 > readline
822 822 > readline
823 823 > readline
824 824 > readline
825 825 > raw
826 826 > unknown\n
827 827 > foo 5\n
828 828 > \nvalue\n
829 829 > bar 3\n
830 830 > baz\n
831 831 > readline
832 832 > readline
833 833 > readline
834 834 > EOF
835 835 using raw connection to peer
836 836 i> write(104) -> 104:
837 837 i> hello\n
838 838 i> between\n
839 839 i> pairs 81\n
840 840 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
841 841 o> readline() -> 4:
842 842 o> 413\n
843 843 o> readline() -> 413:
844 844 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
845 845 o> readline() -> 2:
846 846 o> 1\n
847 847 o> readline() -> 1:
848 848 o> \n
849 849 i> write(31) -> 31:
850 850 i> unknown\n
851 851 i> foo 5\n
852 852 i> \n
853 853 i> value\n
854 854 i> bar 3\n
855 855 i> baz\n
856 856 o> readline() -> 2:
857 857 o> 0\n
858 858 o> readline() -> 2:
859 859 o> 0\n
860 860 o> readline() -> 0:
861 861
862 862 Send a valid command before the handshake
863 863
864 864 $ hg debugwireproto --localssh --peer raw << EOF
865 865 > raw
866 866 > heads\n
867 867 > readline
868 868 > raw
869 869 > hello\n
870 870 > between\n
871 871 > pairs 81\n
872 872 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
873 873 > readline
874 874 > readline
875 875 > readline
876 876 > readline
877 877 > EOF
878 878 using raw connection to peer
879 879 i> write(6) -> 6:
880 880 i> heads\n
881 881 o> readline() -> 3:
882 882 o> 41\n
883 883 i> write(104) -> 104:
884 884 i> hello\n
885 885 i> between\n
886 886 i> pairs 81\n
887 887 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
888 888 o> readline() -> 41:
889 889 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
890 890 o> readline() -> 4:
891 891 o> 413\n
892 892 o> readline() -> 413:
893 893 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
894 894 o> readline() -> 2:
895 895 o> 1\n
896 896
897 897 And a variation that doesn't send the between command
898 898
899 899 $ hg debugwireproto --localssh --peer raw << EOF
900 900 > raw
901 901 > heads\n
902 902 > readline
903 903 > raw
904 904 > hello\n
905 905 > readline
906 906 > readline
907 907 > EOF
908 908 using raw connection to peer
909 909 i> write(6) -> 6:
910 910 i> heads\n
911 911 o> readline() -> 3:
912 912 o> 41\n
913 913 i> write(6) -> 6:
914 914 i> hello\n
915 915 o> readline() -> 41:
916 916 o> 68986213bd4485ea51533535e3fc9e78007a711f\n
917 917 o> readline() -> 4:
918 918 o> 413\n
919 919
920 920 Send an upgrade request to a server that doesn't support that command
921 921
922 922 $ hg debugwireproto --localssh --peer raw << EOF
923 923 > raw
924 924 > upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
925 925 > readline
926 926 > raw
927 927 > hello\n
928 928 > between\n
929 929 > pairs 81\n
930 930 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
931 931 > readline
932 932 > readline
933 933 > readline
934 934 > readline
935 935 > EOF
936 936 using raw connection to peer
937 937 i> write(77) -> 77:
938 938 i> upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=irrelevant1%2Cirrelevant2\n
939 939 o> readline() -> 2:
940 940 o> 0\n
941 941 i> write(104) -> 104:
942 942 i> hello\n
943 943 i> between\n
944 944 i> pairs 81\n
945 945 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
946 946 o> readline() -> 4:
947 947 o> 413\n
948 948 o> readline() -> 413:
949 949 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
950 950 o> readline() -> 2:
951 951 o> 1\n
952 952 o> readline() -> 1:
953 953 o> \n
954 954
955 955 $ cd ..
956 956
957 957 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
958 958 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
959 959 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
960 960 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
961 961 devel-peer-request: hello
962 962 sending hello command
963 963 devel-peer-request: between
964 964 devel-peer-request: pairs: 81 bytes
965 965 sending between command
966 966 remote: 0
967 967 remote: 413
968 968 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
969 969 remote: 1
970 970 devel-peer-request: protocaps
971 971 devel-peer-request: caps: * bytes (glob)
972 972 sending protocaps command
973 973 url: ssh://user@dummy/server
974 974 local: no
975 975 pushable: yes
976 976
977 977 Enable version 2 support on server. We need to do this in hgrc because we can't
978 978 use --config with `hg serve --stdio`.
979 979
980 980 $ cat >> server/.hg/hgrc << EOF
981 981 > [experimental]
982 982 > sshserver.support-v2 = true
983 983 > EOF
984 984
985 985 Send an upgrade request to a server that supports upgrade
986 986
987 987 $ cd server
988 988
989 989 $ hg debugwireproto --localssh --peer raw << EOF
990 990 > raw
991 991 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
992 992 > hello\n
993 993 > between\n
994 994 > pairs 81\n
995 995 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
996 996 > readline
997 997 > readline
998 998 > readline
999 999 > EOF
1000 1000 using raw connection to peer
1001 1001 i> write(153) -> 153:
1002 1002 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1003 1003 i> hello\n
1004 1004 i> between\n
1005 1005 i> pairs 81\n
1006 1006 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1007 1007 o> readline() -> 44:
1008 1008 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1009 1009 o> readline() -> 4:
1010 1010 o> 412\n
1011 1011 o> readline() -> 413:
1012 1012 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1013 1013
1014 1014 $ cd ..
1015 1015
1016 1016 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugpeer ssh://user@dummy/server
1017 1017 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1018 1018 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1019 1019 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1020 1020 devel-peer-request: hello
1021 1021 sending hello command
1022 1022 devel-peer-request: between
1023 1023 devel-peer-request: pairs: 81 bytes
1024 1024 sending between command
1025 1025 protocol upgraded to exp-ssh-v2-0001
1026 1026 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1027 1027 devel-peer-request: protocaps
1028 1028 devel-peer-request: caps: * bytes (glob)
1029 1029 sending protocaps command
1030 1030 url: ssh://user@dummy/server
1031 1031 local: no
1032 1032 pushable: yes
1033 1033
1034 1034 Verify the peer has capabilities
1035 1035
1036 1036 $ hg --config experimental.sshpeer.advertise-v2=true --debug debugcapabilities ssh://user@dummy/server
1037 1037 running * "*/tests/dummyssh" 'user@dummy' 'hg -R server serve --stdio' (glob) (no-windows !)
1038 1038 running * "*\tests/dummyssh" "user@dummy" "hg -R server serve --stdio" (glob) (windows !)
1039 1039 sending upgrade request: * proto=exp-ssh-v2-0001 (glob)
1040 1040 devel-peer-request: hello
1041 1041 sending hello command
1042 1042 devel-peer-request: between
1043 1043 devel-peer-request: pairs: 81 bytes
1044 1044 sending between command
1045 1045 protocol upgraded to exp-ssh-v2-0001
1046 1046 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1047 1047 devel-peer-request: protocaps
1048 1048 devel-peer-request: caps: * bytes (glob)
1049 1049 sending protocaps command
1050 1050 Main capabilities:
1051 1051 batch
1052 1052 branchmap
1053 1053 $USUAL_BUNDLE2_CAPS_SERVER$
1054 1054 changegroupsubset
1055 1055 getbundle
1056 1056 known
1057 1057 lookup
1058 1058 protocaps
1059 1059 pushkey
1060 1060 streamreqs=generaldelta,revlogv1
1061 1061 unbundle=HG10GZ,HG10BZ,HG10UN
1062 1062 unbundlehash
1063 1063 Bundle2 capabilities:
1064 1064 HG20
1065 1065 bookmarks
1066 1066 changegroup
1067 1067 01
1068 1068 02
1069 1069 digests
1070 1070 md5
1071 1071 sha1
1072 1072 sha512
1073 1073 error
1074 1074 abort
1075 1075 unsupportedcontent
1076 1076 pushraced
1077 1077 pushkey
1078 1078 hgtagsfnodes
1079 1079 listkeys
1080 1080 phases
1081 1081 heads
1082 1082 pushkey
1083 1083 remote-changegroup
1084 1084 http
1085 1085 https
1086 1086 rev-branch-cache
1087 1087
1088 1088 Command after upgrade to version 2 is processed
1089 1089
1090 1090 $ cd server
1091 1091
1092 1092 $ hg debugwireproto --localssh --peer raw << EOF
1093 1093 > raw
1094 1094 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1095 1095 > hello\n
1096 1096 > between\n
1097 1097 > pairs 81\n
1098 1098 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1099 1099 > readline
1100 1100 > readline
1101 1101 > readline
1102 1102 > raw
1103 1103 > hello\n
1104 1104 > readline
1105 1105 > readline
1106 1106 > EOF
1107 1107 using raw connection to peer
1108 1108 i> write(153) -> 153:
1109 1109 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1110 1110 i> hello\n
1111 1111 i> between\n
1112 1112 i> pairs 81\n
1113 1113 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1114 1114 o> readline() -> 44:
1115 1115 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1116 1116 o> readline() -> 4:
1117 1117 o> 412\n
1118 1118 o> readline() -> 413:
1119 1119 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1120 1120 i> write(6) -> 6:
1121 1121 i> hello\n
1122 1122 o> readline() -> 4:
1123 1123 o> 397\n
1124 1124 o> readline() -> 397:
1125 1125 o> capabilities: branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1126 1126
1127 1127 Multiple upgrades is not allowed
1128 1128
1129 1129 $ hg debugwireproto --localssh --peer raw << EOF
1130 1130 > raw
1131 1131 > upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1132 1132 > hello\n
1133 1133 > between\n
1134 1134 > pairs 81\n
1135 1135 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1136 1136 > readline
1137 1137 > readline
1138 1138 > readline
1139 1139 > raw
1140 1140 > upgrade another-token proto=irrelevant\n
1141 1141 > hello\n
1142 1142 > readline
1143 1143 > readavailable
1144 1144 > EOF
1145 1145 using raw connection to peer
1146 1146 i> write(153) -> 153:
1147 1147 i> upgrade this-is-some-token proto=exp-ssh-v2-0001\n
1148 1148 i> hello\n
1149 1149 i> between\n
1150 1150 i> pairs 81\n
1151 1151 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1152 1152 o> readline() -> 44:
1153 1153 o> upgraded this-is-some-token exp-ssh-v2-0001\n
1154 1154 o> readline() -> 4:
1155 1155 o> 412\n
1156 1156 o> readline() -> 413:
1157 1157 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1158 1158 i> write(45) -> 45:
1159 1159 i> upgrade another-token proto=irrelevant\n
1160 1160 i> hello\n
1161 1161 o> readline() -> 1:
1162 1162 o> \n
1163 1163 o> read(-1) -> 0:
1164 1164 e> read(-1) -> 42:
1165 1165 e> cannot upgrade protocols multiple times\n
1166 1166 e> -\n
1167 1167
1168 1168 Malformed upgrade request line (not exactly 3 space delimited tokens)
1169 1169
1170 1170 $ hg debugwireproto --localssh --peer raw << EOF
1171 1171 > raw
1172 1172 > upgrade\n
1173 1173 > readline
1174 1174 > EOF
1175 1175 using raw connection to peer
1176 1176 i> write(8) -> 8:
1177 1177 i> upgrade\n
1178 1178 o> readline() -> 2:
1179 1179 o> 0\n
1180 1180
1181 1181 $ hg debugwireproto --localssh --peer raw << EOF
1182 1182 > raw
1183 1183 > upgrade token\n
1184 1184 > readline
1185 1185 > EOF
1186 1186 using raw connection to peer
1187 1187 i> write(14) -> 14:
1188 1188 i> upgrade token\n
1189 1189 o> readline() -> 2:
1190 1190 o> 0\n
1191 1191
1192 1192 $ hg debugwireproto --localssh --peer raw << EOF
1193 1193 > raw
1194 1194 > upgrade token foo=bar extra-token\n
1195 1195 > readline
1196 1196 > EOF
1197 1197 using raw connection to peer
1198 1198 i> write(34) -> 34:
1199 1199 i> upgrade token foo=bar extra-token\n
1200 1200 o> readline() -> 2:
1201 1201 o> 0\n
1202 1202
1203 1203 Upgrade request to unsupported protocol is ignored
1204 1204
1205 1205 $ hg debugwireproto --localssh --peer raw << EOF
1206 1206 > raw
1207 1207 > upgrade this-is-some-token proto=unknown1,unknown2\n
1208 1208 > readline
1209 1209 > raw
1210 1210 > hello\n
1211 1211 > readline
1212 1212 > readline
1213 1213 > raw
1214 1214 > between\n
1215 1215 > pairs 81\n
1216 1216 > 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1217 1217 > readline
1218 1218 > readline
1219 1219 > EOF
1220 1220 using raw connection to peer
1221 1221 i> write(51) -> 51:
1222 1222 i> upgrade this-is-some-token proto=unknown1,unknown2\n
1223 1223 o> readline() -> 2:
1224 1224 o> 0\n
1225 1225 i> write(6) -> 6:
1226 1226 i> hello\n
1227 1227 o> readline() -> 4:
1228 1228 o> 413\n
1229 1229 o> readline() -> 413:
1230 1230 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1231 1231 i> write(98) -> 98:
1232 1232 i> between\n
1233 1233 i> pairs 81\n
1234 1234 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1235 1235 o> readline() -> 2:
1236 1236 o> 1\n
1237 1237 o> readline() -> 1:
1238 1238 o> \n
1239 1239
1240 1240 Upgrade request must be followed by hello + between
1241 1241
1242 1242 $ hg debugwireproto --localssh --peer raw << EOF
1243 1243 > raw
1244 1244 > upgrade token proto=exp-ssh-v2-0001\n
1245 1245 > invalid\n
1246 1246 > readline
1247 1247 > readavailable
1248 1248 > EOF
1249 1249 using raw connection to peer
1250 1250 i> write(44) -> 44:
1251 1251 i> upgrade token proto=exp-ssh-v2-0001\n
1252 1252 i> invalid\n
1253 1253 o> readline() -> 1:
1254 1254 o> \n
1255 1255 o> read(-1) -> 0:
1256 1256 e> read(-1) -> 46:
1257 1257 e> malformed handshake protocol: missing hello\n
1258 1258 e> -\n
1259 1259
1260 1260 $ hg debugwireproto --localssh --peer raw << EOF
1261 1261 > raw
1262 1262 > upgrade token proto=exp-ssh-v2-0001\n
1263 1263 > hello\n
1264 1264 > invalid\n
1265 1265 > readline
1266 1266 > readavailable
1267 1267 > EOF
1268 1268 using raw connection to peer
1269 1269 i> write(50) -> 50:
1270 1270 i> upgrade token proto=exp-ssh-v2-0001\n
1271 1271 i> hello\n
1272 1272 i> invalid\n
1273 1273 o> readline() -> 1:
1274 1274 o> \n
1275 1275 o> read(-1) -> 0:
1276 1276 e> read(-1) -> 48:
1277 1277 e> malformed handshake protocol: missing between\n
1278 1278 e> -\n
1279 1279
1280 1280 $ hg debugwireproto --localssh --peer raw << EOF
1281 1281 > raw
1282 1282 > upgrade token proto=exp-ssh-v2-0001\n
1283 1283 > hello\n
1284 1284 > between\n
1285 1285 > invalid\n
1286 1286 > readline
1287 1287 > readavailable
1288 1288 > EOF
1289 1289 using raw connection to peer
1290 1290 i> write(58) -> 58:
1291 1291 i> upgrade token proto=exp-ssh-v2-0001\n
1292 1292 i> hello\n
1293 1293 i> between\n
1294 1294 i> invalid\n
1295 1295 o> readline() -> 1:
1296 1296 o> \n
1297 1297 o> read(-1) -> 0:
1298 1298 e> read(-1) -> 49:
1299 1299 e> malformed handshake protocol: missing pairs 81\n
1300 1300 e> -\n
1301 1301
1302 1302 Legacy commands are not exposed to version 2 of protocol
1303 1303
1304 1304 TODO re-enable these once we're back to actually using v2 commands
1305 1305
1306 1306 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1307 1307 > command branches
1308 1308 > nodes 0000000000000000000000000000000000000000
1309 1309 > EOF
1310 1310 creating ssh peer from handshake results
1311 1311 sending branches command
1312 1312 response:
1313 1313
1314 1314 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1315 1315 > command changegroup
1316 1316 > roots 0000000000000000000000000000000000000000
1317 1317 > EOF
1318 1318 creating ssh peer from handshake results
1319 1319 sending changegroup command
1320 1320 response:
1321 1321
1322 1322 $ hg --config experimental.sshpeer.advertise-v2=true debugwireproto --localssh << EOF
1323 1323 > command changegroupsubset
1324 1324 > bases 0000000000000000000000000000000000000000
1325 1325 > heads 0000000000000000000000000000000000000000
1326 1326 > EOF
1327 1327 creating ssh peer from handshake results
1328 1328 sending changegroupsubset command
1329 1329 response:
1330 1330
1331 1331 $ cd ..
1332 1332
1333 1333 Test listkeys for listing namespaces
1334 1334
1335 1335 $ hg init empty
1336 1336 $ cd empty
1337 1337 $ debugwireproto << EOF
1338 1338 > command listkeys
1339 1339 > namespace namespaces
1340 1340 > EOF
1341 1341 testing ssh1
1342 1342 creating ssh peer from handshake results
1343 1343 i> write(104) -> 104:
1344 1344 i> hello\n
1345 1345 i> between\n
1346 1346 i> pairs 81\n
1347 1347 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1348 1348 i> flush() -> None
1349 1349 o> readline() -> 4:
1350 1350 o> 413\n
1351 1351 o> readline() -> 413:
1352 1352 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1353 1353 o> readline() -> 2:
1354 1354 o> 1\n
1355 1355 o> readline() -> 1:
1356 1356 o> \n
1357 1357 sending listkeys command
1358 1358 i> write(9) -> 9:
1359 1359 i> listkeys\n
1360 1360 i> write(13) -> 13:
1361 1361 i> namespace 10\n
1362 1362 i> write(10) -> 10: namespaces
1363 1363 i> flush() -> None
1364 1364 o> bufferedreadline() -> 3:
1365 1365 o> 30\n
1366 1366 o> bufferedread(30) -> 30:
1367 1367 o> bookmarks\t\n
1368 1368 o> namespaces\t\n
1369 1369 o> phases\t
1370 response: b'bookmarks\t\nnamespaces\t\nphases\t'
1370 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
1371 1371
1372 1372 testing ssh2
1373 1373 creating ssh peer from handshake results
1374 1374 i> write(171) -> 171:
1375 1375 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1376 1376 i> hello\n
1377 1377 i> between\n
1378 1378 i> pairs 81\n
1379 1379 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1380 1380 i> flush() -> None
1381 1381 o> readline() -> 62:
1382 1382 o> upgraded * exp-ssh-v2-0001\n (glob)
1383 1383 o> readline() -> 4:
1384 1384 o> 412\n
1385 1385 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1386 1386 o> read(1) -> 1:
1387 1387 o> \n
1388 1388 sending listkeys command
1389 1389 i> write(9) -> 9:
1390 1390 i> listkeys\n
1391 1391 i> write(13) -> 13:
1392 1392 i> namespace 10\n
1393 1393 i> write(10) -> 10: namespaces
1394 1394 i> flush() -> None
1395 1395 o> bufferedreadline() -> 3:
1396 1396 o> 30\n
1397 1397 o> bufferedread(30) -> 30:
1398 1398 o> bookmarks\t\n
1399 1399 o> namespaces\t\n
1400 1400 o> phases\t
1401 response: b'bookmarks\t\nnamespaces\t\nphases\t'
1401 response: {b'bookmarks': b'', b'namespaces': b'', b'phases': b''}
1402 1402
1403 1403 $ cd ..
1404 1404
1405 1405 Test listkeys for bookmarks
1406 1406
1407 1407 $ hg init bookmarkrepo
1408 1408 $ cd bookmarkrepo
1409 1409 $ echo 0 > foo
1410 1410 $ hg add foo
1411 1411 $ hg -q commit -m initial
1412 1412 $ echo 1 > foo
1413 1413 $ hg commit -m second
1414 1414
1415 1415 With no bookmarks set
1416 1416
1417 1417 $ debugwireproto << EOF
1418 1418 > command listkeys
1419 1419 > namespace bookmarks
1420 1420 > EOF
1421 1421 testing ssh1
1422 1422 creating ssh peer from handshake results
1423 1423 i> write(104) -> 104:
1424 1424 i> hello\n
1425 1425 i> between\n
1426 1426 i> pairs 81\n
1427 1427 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1428 1428 i> flush() -> None
1429 1429 o> readline() -> 4:
1430 1430 o> 413\n
1431 1431 o> readline() -> 413:
1432 1432 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1433 1433 o> readline() -> 2:
1434 1434 o> 1\n
1435 1435 o> readline() -> 1:
1436 1436 o> \n
1437 1437 sending listkeys command
1438 1438 i> write(9) -> 9:
1439 1439 i> listkeys\n
1440 1440 i> write(12) -> 12:
1441 1441 i> namespace 9\n
1442 1442 i> write(9) -> 9: bookmarks
1443 1443 i> flush() -> None
1444 1444 o> bufferedreadline() -> 2:
1445 1445 o> 0\n
1446 response: b''
1446 response: {}
1447 1447
1448 1448 testing ssh2
1449 1449 creating ssh peer from handshake results
1450 1450 i> write(171) -> 171:
1451 1451 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1452 1452 i> hello\n
1453 1453 i> between\n
1454 1454 i> pairs 81\n
1455 1455 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1456 1456 i> flush() -> None
1457 1457 o> readline() -> 62:
1458 1458 o> upgraded * exp-ssh-v2-0001\n (glob)
1459 1459 o> readline() -> 4:
1460 1460 o> 412\n
1461 1461 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1462 1462 o> read(1) -> 1:
1463 1463 o> \n
1464 1464 sending listkeys command
1465 1465 i> write(9) -> 9:
1466 1466 i> listkeys\n
1467 1467 i> write(12) -> 12:
1468 1468 i> namespace 9\n
1469 1469 i> write(9) -> 9: bookmarks
1470 1470 i> flush() -> None
1471 1471 o> bufferedreadline() -> 2:
1472 1472 o> 0\n
1473 response: b''
1473 response: {}
1474 1474
1475 1475 With a single bookmark set
1476 1476
1477 1477 $ hg book -r 0 bookA
1478 1478 $ debugwireproto << EOF
1479 1479 > command listkeys
1480 1480 > namespace bookmarks
1481 1481 > EOF
1482 1482 testing ssh1
1483 1483 creating ssh peer from handshake results
1484 1484 i> write(104) -> 104:
1485 1485 i> hello\n
1486 1486 i> between\n
1487 1487 i> pairs 81\n
1488 1488 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1489 1489 i> flush() -> None
1490 1490 o> readline() -> 4:
1491 1491 o> 413\n
1492 1492 o> readline() -> 413:
1493 1493 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1494 1494 o> readline() -> 2:
1495 1495 o> 1\n
1496 1496 o> readline() -> 1:
1497 1497 o> \n
1498 1498 sending listkeys command
1499 1499 i> write(9) -> 9:
1500 1500 i> listkeys\n
1501 1501 i> write(12) -> 12:
1502 1502 i> namespace 9\n
1503 1503 i> write(9) -> 9: bookmarks
1504 1504 i> flush() -> None
1505 1505 o> bufferedreadline() -> 3:
1506 1506 o> 46\n
1507 1507 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1508 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f'
1508 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'}
1509 1509
1510 1510 testing ssh2
1511 1511 creating ssh peer from handshake results
1512 1512 i> write(171) -> 171:
1513 1513 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1514 1514 i> hello\n
1515 1515 i> between\n
1516 1516 i> pairs 81\n
1517 1517 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1518 1518 i> flush() -> None
1519 1519 o> readline() -> 62:
1520 1520 o> upgraded * exp-ssh-v2-0001\n (glob)
1521 1521 o> readline() -> 4:
1522 1522 o> 412\n
1523 1523 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1524 1524 o> read(1) -> 1:
1525 1525 o> \n
1526 1526 sending listkeys command
1527 1527 i> write(9) -> 9:
1528 1528 i> listkeys\n
1529 1529 i> write(12) -> 12:
1530 1530 i> namespace 9\n
1531 1531 i> write(9) -> 9: bookmarks
1532 1532 i> flush() -> None
1533 1533 o> bufferedreadline() -> 3:
1534 1534 o> 46\n
1535 1535 o> bufferedread(46) -> 46: bookA\t68986213bd4485ea51533535e3fc9e78007a711f
1536 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f'
1536 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f'}
1537 1537
1538 1538 With multiple bookmarks set
1539 1539
1540 1540 $ hg book -r 1 bookB
1541 1541 $ debugwireproto << EOF
1542 1542 > command listkeys
1543 1543 > namespace bookmarks
1544 1544 > EOF
1545 1545 testing ssh1
1546 1546 creating ssh peer from handshake results
1547 1547 i> write(104) -> 104:
1548 1548 i> hello\n
1549 1549 i> between\n
1550 1550 i> pairs 81\n
1551 1551 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1552 1552 i> flush() -> None
1553 1553 o> readline() -> 4:
1554 1554 o> 413\n
1555 1555 o> readline() -> 413:
1556 1556 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1557 1557 o> readline() -> 2:
1558 1558 o> 1\n
1559 1559 o> readline() -> 1:
1560 1560 o> \n
1561 1561 sending listkeys command
1562 1562 i> write(9) -> 9:
1563 1563 i> listkeys\n
1564 1564 i> write(12) -> 12:
1565 1565 i> namespace 9\n
1566 1566 i> write(9) -> 9: bookmarks
1567 1567 i> flush() -> None
1568 1568 o> bufferedreadline() -> 3:
1569 1569 o> 93\n
1570 1570 o> bufferedread(93) -> 93:
1571 1571 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1572 1572 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1573 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f\nbookB\t1880f3755e2e52e3199e0ee5638128b08642f34d'
1573 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'}
1574 1574
1575 1575 testing ssh2
1576 1576 creating ssh peer from handshake results
1577 1577 i> write(171) -> 171:
1578 1578 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1579 1579 i> hello\n
1580 1580 i> between\n
1581 1581 i> pairs 81\n
1582 1582 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1583 1583 i> flush() -> None
1584 1584 o> readline() -> 62:
1585 1585 o> upgraded * exp-ssh-v2-0001\n (glob)
1586 1586 o> readline() -> 4:
1587 1587 o> 412\n
1588 1588 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1589 1589 o> read(1) -> 1:
1590 1590 o> \n
1591 1591 sending listkeys command
1592 1592 i> write(9) -> 9:
1593 1593 i> listkeys\n
1594 1594 i> write(12) -> 12:
1595 1595 i> namespace 9\n
1596 1596 i> write(9) -> 9: bookmarks
1597 1597 i> flush() -> None
1598 1598 o> bufferedreadline() -> 3:
1599 1599 o> 93\n
1600 1600 o> bufferedread(93) -> 93:
1601 1601 o> bookA\t68986213bd4485ea51533535e3fc9e78007a711f\n
1602 1602 o> bookB\t1880f3755e2e52e3199e0ee5638128b08642f34d
1603 response: b'bookA\t68986213bd4485ea51533535e3fc9e78007a711f\nbookB\t1880f3755e2e52e3199e0ee5638128b08642f34d'
1603 response: {b'bookA': b'68986213bd4485ea51533535e3fc9e78007a711f', b'bookB': b'1880f3755e2e52e3199e0ee5638128b08642f34d'}
1604 1604
1605 1605 Test pushkey for bookmarks
1606 1606
1607 1607 $ debugwireproto << EOF
1608 1608 > command pushkey
1609 1609 > namespace bookmarks
1610 1610 > key remote
1611 1611 > old
1612 1612 > new 68986213bd4485ea51533535e3fc9e78007a711f
1613 1613 > EOF
1614 1614 testing ssh1
1615 1615 creating ssh peer from handshake results
1616 1616 i> write(104) -> 104:
1617 1617 i> hello\n
1618 1618 i> between\n
1619 1619 i> pairs 81\n
1620 1620 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1621 1621 i> flush() -> None
1622 1622 o> readline() -> 4:
1623 1623 o> 413\n
1624 1624 o> readline() -> 413:
1625 1625 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1626 1626 o> readline() -> 2:
1627 1627 o> 1\n
1628 1628 o> readline() -> 1:
1629 1629 o> \n
1630 1630 sending pushkey command
1631 1631 i> write(8) -> 8:
1632 1632 i> pushkey\n
1633 1633 i> write(6) -> 6:
1634 1634 i> key 6\n
1635 1635 i> write(6) -> 6: remote
1636 1636 i> write(12) -> 12:
1637 1637 i> namespace 9\n
1638 1638 i> write(9) -> 9: bookmarks
1639 1639 i> write(7) -> 7:
1640 1640 i> new 40\n
1641 1641 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1642 1642 i> write(6) -> 6:
1643 1643 i> old 0\n
1644 1644 i> flush() -> None
1645 1645 o> bufferedreadline() -> 2:
1646 1646 o> 2\n
1647 1647 o> bufferedread(2) -> 2:
1648 1648 o> 1\n
1649 response: b'1\n'
1649 response: True
1650 1650
1651 1651 testing ssh2
1652 1652 creating ssh peer from handshake results
1653 1653 i> write(171) -> 171:
1654 1654 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1655 1655 i> hello\n
1656 1656 i> between\n
1657 1657 i> pairs 81\n
1658 1658 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1659 1659 i> flush() -> None
1660 1660 o> readline() -> 62:
1661 1661 o> upgraded * exp-ssh-v2-0001\n (glob)
1662 1662 o> readline() -> 4:
1663 1663 o> 412\n
1664 1664 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1665 1665 o> read(1) -> 1:
1666 1666 o> \n
1667 1667 sending pushkey command
1668 1668 i> write(8) -> 8:
1669 1669 i> pushkey\n
1670 1670 i> write(6) -> 6:
1671 1671 i> key 6\n
1672 1672 i> write(6) -> 6: remote
1673 1673 i> write(12) -> 12:
1674 1674 i> namespace 9\n
1675 1675 i> write(9) -> 9: bookmarks
1676 1676 i> write(7) -> 7:
1677 1677 i> new 40\n
1678 1678 i> write(40) -> 40: 68986213bd4485ea51533535e3fc9e78007a711f
1679 1679 i> write(6) -> 6:
1680 1680 i> old 0\n
1681 1681 i> flush() -> None
1682 1682 o> bufferedreadline() -> 2:
1683 1683 o> 2\n
1684 1684 o> bufferedread(2) -> 2:
1685 1685 o> 1\n
1686 response: b'1\n'
1686 response: True
1687 1687
1688 1688 $ hg bookmarks
1689 1689 bookA 0:68986213bd44
1690 1690 bookB 1:1880f3755e2e
1691 1691 remote 0:68986213bd44
1692 1692
1693 1693 $ cd ..
1694 1694
1695 1695 Test listkeys for phases
1696 1696
1697 1697 $ hg init phasesrepo
1698 1698 $ cd phasesrepo
1699 1699
1700 1700 Phases on empty repo
1701 1701
1702 1702 $ debugwireproto << EOF
1703 1703 > command listkeys
1704 1704 > namespace phases
1705 1705 > EOF
1706 1706 testing ssh1
1707 1707 creating ssh peer from handshake results
1708 1708 i> write(104) -> 104:
1709 1709 i> hello\n
1710 1710 i> between\n
1711 1711 i> pairs 81\n
1712 1712 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1713 1713 i> flush() -> None
1714 1714 o> readline() -> 4:
1715 1715 o> 413\n
1716 1716 o> readline() -> 413:
1717 1717 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1718 1718 o> readline() -> 2:
1719 1719 o> 1\n
1720 1720 o> readline() -> 1:
1721 1721 o> \n
1722 1722 sending listkeys command
1723 1723 i> write(9) -> 9:
1724 1724 i> listkeys\n
1725 1725 i> write(12) -> 12:
1726 1726 i> namespace 6\n
1727 1727 i> write(6) -> 6: phases
1728 1728 i> flush() -> None
1729 1729 o> bufferedreadline() -> 3:
1730 1730 o> 15\n
1731 1731 o> bufferedread(15) -> 15: publishing\tTrue
1732 response: b'publishing\tTrue'
1732 response: {b'publishing': b'True'}
1733 1733
1734 1734 testing ssh2
1735 1735 creating ssh peer from handshake results
1736 1736 i> write(171) -> 171:
1737 1737 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1738 1738 i> hello\n
1739 1739 i> between\n
1740 1740 i> pairs 81\n
1741 1741 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1742 1742 i> flush() -> None
1743 1743 o> readline() -> 62:
1744 1744 o> upgraded * exp-ssh-v2-0001\n (glob)
1745 1745 o> readline() -> 4:
1746 1746 o> 412\n
1747 1747 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1748 1748 o> read(1) -> 1:
1749 1749 o> \n
1750 1750 sending listkeys command
1751 1751 i> write(9) -> 9:
1752 1752 i> listkeys\n
1753 1753 i> write(12) -> 12:
1754 1754 i> namespace 6\n
1755 1755 i> write(6) -> 6: phases
1756 1756 i> flush() -> None
1757 1757 o> bufferedreadline() -> 3:
1758 1758 o> 15\n
1759 1759 o> bufferedread(15) -> 15: publishing\tTrue
1760 response: b'publishing\tTrue'
1760 response: {b'publishing': b'True'}
1761 1761
1762 1762 Create some commits
1763 1763
1764 1764 $ echo 0 > foo
1765 1765 $ hg add foo
1766 1766 $ hg -q commit -m initial
1767 1767 $ hg phase --public
1768 1768 $ echo 1 > foo
1769 1769 $ hg commit -m 'head 1 commit 1'
1770 1770 $ echo 2 > foo
1771 1771 $ hg commit -m 'head 1 commit 2'
1772 1772 $ hg -q up 0
1773 1773 $ echo 1a > foo
1774 1774 $ hg commit -m 'head 2 commit 1'
1775 1775 created new head
1776 1776 $ echo 2a > foo
1777 1777 $ hg commit -m 'head 2 commit 2'
1778 1778
1779 1779 Two draft heads
1780 1780
1781 1781 $ debugwireproto << EOF
1782 1782 > command listkeys
1783 1783 > namespace phases
1784 1784 > EOF
1785 1785 testing ssh1
1786 1786 creating ssh peer from handshake results
1787 1787 i> write(104) -> 104:
1788 1788 i> hello\n
1789 1789 i> between\n
1790 1790 i> pairs 81\n
1791 1791 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1792 1792 i> flush() -> None
1793 1793 o> readline() -> 4:
1794 1794 o> 413\n
1795 1795 o> readline() -> 413:
1796 1796 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1797 1797 o> readline() -> 2:
1798 1798 o> 1\n
1799 1799 o> readline() -> 1:
1800 1800 o> \n
1801 1801 sending listkeys command
1802 1802 i> write(9) -> 9:
1803 1803 i> listkeys\n
1804 1804 i> write(12) -> 12:
1805 1805 i> namespace 6\n
1806 1806 i> write(6) -> 6: phases
1807 1807 i> flush() -> None
1808 1808 o> bufferedreadline() -> 4:
1809 1809 o> 101\n
1810 1810 o> bufferedread(101) -> 101:
1811 1811 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1812 1812 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1813 1813 o> publishing\tTrue
1814 response: b'20b8a89289d80036e6c4e87c2083e3bea1586637\t1\nc4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1814 response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1815 1815
1816 1816 testing ssh2
1817 1817 creating ssh peer from handshake results
1818 1818 i> write(171) -> 171:
1819 1819 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1820 1820 i> hello\n
1821 1821 i> between\n
1822 1822 i> pairs 81\n
1823 1823 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1824 1824 i> flush() -> None
1825 1825 o> readline() -> 62:
1826 1826 o> upgraded * exp-ssh-v2-0001\n (glob)
1827 1827 o> readline() -> 4:
1828 1828 o> 412\n
1829 1829 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1830 1830 o> read(1) -> 1:
1831 1831 o> \n
1832 1832 sending listkeys command
1833 1833 i> write(9) -> 9:
1834 1834 i> listkeys\n
1835 1835 i> write(12) -> 12:
1836 1836 i> namespace 6\n
1837 1837 i> write(6) -> 6: phases
1838 1838 i> flush() -> None
1839 1839 o> bufferedreadline() -> 4:
1840 1840 o> 101\n
1841 1841 o> bufferedread(101) -> 101:
1842 1842 o> 20b8a89289d80036e6c4e87c2083e3bea1586637\t1\n
1843 1843 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1844 1844 o> publishing\tTrue
1845 response: b'20b8a89289d80036e6c4e87c2083e3bea1586637\t1\nc4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1845 response: {b'20b8a89289d80036e6c4e87c2083e3bea1586637': b'1', b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1846 1846
1847 1847 Single draft head
1848 1848
1849 1849 $ hg phase --public -r 2
1850 1850 $ debugwireproto << EOF
1851 1851 > command listkeys
1852 1852 > namespace phases
1853 1853 > EOF
1854 1854 testing ssh1
1855 1855 creating ssh peer from handshake results
1856 1856 i> write(104) -> 104:
1857 1857 i> hello\n
1858 1858 i> between\n
1859 1859 i> pairs 81\n
1860 1860 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1861 1861 i> flush() -> None
1862 1862 o> readline() -> 4:
1863 1863 o> 413\n
1864 1864 o> readline() -> 413:
1865 1865 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1866 1866 o> readline() -> 2:
1867 1867 o> 1\n
1868 1868 o> readline() -> 1:
1869 1869 o> \n
1870 1870 sending listkeys command
1871 1871 i> write(9) -> 9:
1872 1872 i> listkeys\n
1873 1873 i> write(12) -> 12:
1874 1874 i> namespace 6\n
1875 1875 i> write(6) -> 6: phases
1876 1876 i> flush() -> None
1877 1877 o> bufferedreadline() -> 3:
1878 1878 o> 58\n
1879 1879 o> bufferedread(58) -> 58:
1880 1880 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1881 1881 o> publishing\tTrue
1882 response: b'c4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1882 response: {b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1883 1883
1884 1884 testing ssh2
1885 1885 creating ssh peer from handshake results
1886 1886 i> write(171) -> 171:
1887 1887 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1888 1888 i> hello\n
1889 1889 i> between\n
1890 1890 i> pairs 81\n
1891 1891 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1892 1892 i> flush() -> None
1893 1893 o> readline() -> 62:
1894 1894 o> upgraded * exp-ssh-v2-0001\n (glob)
1895 1895 o> readline() -> 4:
1896 1896 o> 412\n
1897 1897 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1898 1898 o> read(1) -> 1:
1899 1899 o> \n
1900 1900 sending listkeys command
1901 1901 i> write(9) -> 9:
1902 1902 i> listkeys\n
1903 1903 i> write(12) -> 12:
1904 1904 i> namespace 6\n
1905 1905 i> write(6) -> 6: phases
1906 1906 i> flush() -> None
1907 1907 o> bufferedreadline() -> 3:
1908 1908 o> 58\n
1909 1909 o> bufferedread(58) -> 58:
1910 1910 o> c4750011d906c18ea2f0527419cbc1a544435150\t1\n
1911 1911 o> publishing\tTrue
1912 response: b'c4750011d906c18ea2f0527419cbc1a544435150\t1\npublishing\tTrue'
1912 response: {b'c4750011d906c18ea2f0527419cbc1a544435150': b'1', b'publishing': b'True'}
1913 1913
1914 1914 All public heads
1915 1915
1916 1916 $ hg phase --public -r 4
1917 1917 $ debugwireproto << EOF
1918 1918 > command listkeys
1919 1919 > namespace phases
1920 1920 > EOF
1921 1921 testing ssh1
1922 1922 creating ssh peer from handshake results
1923 1923 i> write(104) -> 104:
1924 1924 i> hello\n
1925 1925 i> between\n
1926 1926 i> pairs 81\n
1927 1927 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1928 1928 i> flush() -> None
1929 1929 o> readline() -> 4:
1930 1930 o> 413\n
1931 1931 o> readline() -> 413:
1932 1932 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
1933 1933 o> readline() -> 2:
1934 1934 o> 1\n
1935 1935 o> readline() -> 1:
1936 1936 o> \n
1937 1937 sending listkeys command
1938 1938 i> write(9) -> 9:
1939 1939 i> listkeys\n
1940 1940 i> write(12) -> 12:
1941 1941 i> namespace 6\n
1942 1942 i> write(6) -> 6: phases
1943 1943 i> flush() -> None
1944 1944 o> bufferedreadline() -> 3:
1945 1945 o> 15\n
1946 1946 o> bufferedread(15) -> 15: publishing\tTrue
1947 response: b'publishing\tTrue'
1947 response: {b'publishing': b'True'}
1948 1948
1949 1949 testing ssh2
1950 1950 creating ssh peer from handshake results
1951 1951 i> write(171) -> 171:
1952 1952 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
1953 1953 i> hello\n
1954 1954 i> between\n
1955 1955 i> pairs 81\n
1956 1956 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1957 1957 i> flush() -> None
1958 1958 o> readline() -> 62:
1959 1959 o> upgraded * exp-ssh-v2-0001\n (glob)
1960 1960 o> readline() -> 4:
1961 1961 o> 412\n
1962 1962 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
1963 1963 o> read(1) -> 1:
1964 1964 o> \n
1965 1965 sending listkeys command
1966 1966 i> write(9) -> 9:
1967 1967 i> listkeys\n
1968 1968 i> write(12) -> 12:
1969 1969 i> namespace 6\n
1970 1970 i> write(6) -> 6: phases
1971 1971 i> flush() -> None
1972 1972 o> bufferedreadline() -> 3:
1973 1973 o> 15\n
1974 1974 o> bufferedread(15) -> 15: publishing\tTrue
1975 response: b'publishing\tTrue'
1975 response: {b'publishing': b'True'}
1976 1976
1977 1977 Setting public phase via pushkey
1978 1978
1979 1979 $ hg phase --draft --force -r .
1980 1980
1981 1981 $ debugwireproto << EOF
1982 1982 > command pushkey
1983 1983 > namespace phases
1984 1984 > key 7127240a084fd9dc86fe8d1f98e26229161ec82b
1985 1985 > old 1
1986 1986 > new 0
1987 1987 > EOF
1988 1988 testing ssh1
1989 1989 creating ssh peer from handshake results
1990 1990 i> write(104) -> 104:
1991 1991 i> hello\n
1992 1992 i> between\n
1993 1993 i> pairs 81\n
1994 1994 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
1995 1995 i> flush() -> None
1996 1996 o> readline() -> 4:
1997 1997 o> 413\n
1998 1998 o> readline() -> 413:
1999 1999 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
2000 2000 o> readline() -> 2:
2001 2001 o> 1\n
2002 2002 o> readline() -> 1:
2003 2003 o> \n
2004 2004 sending pushkey command
2005 2005 i> write(8) -> 8:
2006 2006 i> pushkey\n
2007 2007 i> write(7) -> 7:
2008 2008 i> key 40\n
2009 2009 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2010 2010 i> write(12) -> 12:
2011 2011 i> namespace 6\n
2012 2012 i> write(6) -> 6: phases
2013 2013 i> write(6) -> 6:
2014 2014 i> new 1\n
2015 2015 i> write(1) -> 1: 0
2016 2016 i> write(6) -> 6:
2017 2017 i> old 1\n
2018 2018 i> write(1) -> 1: 1
2019 2019 i> flush() -> None
2020 2020 o> bufferedreadline() -> 2:
2021 2021 o> 2\n
2022 2022 o> bufferedread(2) -> 2:
2023 2023 o> 1\n
2024 response: b'1\n'
2024 response: True
2025 2025
2026 2026 testing ssh2
2027 2027 creating ssh peer from handshake results
2028 2028 i> write(171) -> 171:
2029 2029 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2030 2030 i> hello\n
2031 2031 i> between\n
2032 2032 i> pairs 81\n
2033 2033 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2034 2034 i> flush() -> None
2035 2035 o> readline() -> 62:
2036 2036 o> upgraded * exp-ssh-v2-0001\n (glob)
2037 2037 o> readline() -> 4:
2038 2038 o> 412\n
2039 2039 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
2040 2040 o> read(1) -> 1:
2041 2041 o> \n
2042 2042 sending pushkey command
2043 2043 i> write(8) -> 8:
2044 2044 i> pushkey\n
2045 2045 i> write(7) -> 7:
2046 2046 i> key 40\n
2047 2047 i> write(40) -> 40: 7127240a084fd9dc86fe8d1f98e26229161ec82b
2048 2048 i> write(12) -> 12:
2049 2049 i> namespace 6\n
2050 2050 i> write(6) -> 6: phases
2051 2051 i> write(6) -> 6:
2052 2052 i> new 1\n
2053 2053 i> write(1) -> 1: 0
2054 2054 i> write(6) -> 6:
2055 2055 i> old 1\n
2056 2056 i> write(1) -> 1: 1
2057 2057 i> flush() -> None
2058 2058 o> bufferedreadline() -> 2:
2059 2059 o> 2\n
2060 2060 o> bufferedread(2) -> 2:
2061 2061 o> 1\n
2062 response: b'1\n'
2062 response: True
2063 2063
2064 2064 $ hg phase .
2065 2065 4: public
2066 2066
2067 2067 $ cd ..
2068 2068
2069 2069 Test batching of requests
2070 2070
2071 2071 $ hg init batching
2072 2072 $ cd batching
2073 2073 $ echo 0 > foo
2074 2074 $ hg add foo
2075 2075 $ hg -q commit -m initial
2076 2076 $ hg phase --public
2077 2077 $ echo 1 > foo
2078 2078 $ hg commit -m 'commit 1'
2079 2079 $ hg -q up 0
2080 2080 $ echo 2 > foo
2081 2081 $ hg commit -m 'commit 2'
2082 2082 created new head
2083 2083 $ hg book -r 1 bookA
2084 2084 $ hg book -r 2 bookB
2085 2085
2086 2086 $ debugwireproto << EOF
2087 2087 > batchbegin
2088 2088 > command heads
2089 2089 > command listkeys
2090 2090 > namespace bookmarks
2091 2091 > command listkeys
2092 2092 > namespace phases
2093 2093 > batchsubmit
2094 2094 > EOF
2095 2095 testing ssh1
2096 2096 creating ssh peer from handshake results
2097 2097 i> write(104) -> 104:
2098 2098 i> hello\n
2099 2099 i> between\n
2100 2100 i> pairs 81\n
2101 2101 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2102 2102 i> flush() -> None
2103 2103 o> readline() -> 4:
2104 2104 o> 413\n
2105 2105 o> readline() -> 413:
2106 2106 o> capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash\n
2107 2107 o> readline() -> 2:
2108 2108 o> 1\n
2109 2109 o> readline() -> 1:
2110 2110 o> \n
2111 2111 sending batch with 3 sub-commands
2112 2112 i> write(6) -> 6:
2113 2113 i> batch\n
2114 2114 i> write(4) -> 4:
2115 2115 i> * 0\n
2116 2116 i> write(8) -> 8:
2117 2117 i> cmds 61\n
2118 2118 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2119 2119 i> flush() -> None
2120 2120 o> bufferedreadline() -> 4:
2121 2121 o> 278\n
2122 2122 o> bufferedread(278) -> 278:
2123 2123 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2124 2124 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2125 2125 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2126 2126 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2127 2127 o> publishing\tTrue
2128 2128 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2129 2129 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2130 2130 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
2131 2131
2132 2132 testing ssh2
2133 2133 creating ssh peer from handshake results
2134 2134 i> write(171) -> 171:
2135 2135 i> upgrade * proto=exp-ssh-v2-0001\n (glob)
2136 2136 i> hello\n
2137 2137 i> between\n
2138 2138 i> pairs 81\n
2139 2139 i> 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000
2140 2140 i> flush() -> None
2141 2141 o> readline() -> 62:
2142 2142 o> upgraded * exp-ssh-v2-0001\n (glob)
2143 2143 o> readline() -> 4:
2144 2144 o> 412\n
2145 2145 o> read(412) -> 412: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS_SERVER$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
2146 2146 o> read(1) -> 1:
2147 2147 o> \n
2148 2148 sending batch with 3 sub-commands
2149 2149 i> write(6) -> 6:
2150 2150 i> batch\n
2151 2151 i> write(4) -> 4:
2152 2152 i> * 0\n
2153 2153 i> write(8) -> 8:
2154 2154 i> cmds 61\n
2155 2155 i> write(61) -> 61: heads ;listkeys namespace=bookmarks;listkeys namespace=phases
2156 2156 i> flush() -> None
2157 2157 o> bufferedreadline() -> 4:
2158 2158 o> 278\n
2159 2159 o> bufferedread(278) -> 278:
2160 2160 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2161 2161 o> ;bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2162 2162 o> bookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6;4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\n
2163 2163 o> bfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\n
2164 2164 o> publishing\tTrue
2165 2165 response #0: bfebe6bd38eebc6f8202e419c1171268987ea6a6 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\n
2166 2166 response #1: bookA\t4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\nbookB\tbfebe6bd38eebc6f8202e419c1171268987ea6a6
2167 2167 response #2: 4ee3fcef1c800fa2bf23e20af7c83ff111d9c7ab\t1\nbfebe6bd38eebc6f8202e419c1171268987ea6a6\t1\npublishing\tTrue
General Comments 0
You need to be logged in to leave comments. Login now