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