##// END OF EJS Templates
debug-delta-chain: print less data by default...
marmoute -
r51969:786b6225 default
parent child Browse files
Show More
@@ -1,4751 +1,4751 b''
1 1 # debugcommands.py - command processing for debug* commands
2 2 #
3 3 # Copyright 2005-2016 Olivia Mackall <olivia@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
9 9 import binascii
10 10 import codecs
11 11 import collections
12 12 import contextlib
13 13 import difflib
14 14 import errno
15 15 import glob
16 16 import operator
17 17 import os
18 18 import platform
19 19 import random
20 20 import re
21 21 import socket
22 22 import ssl
23 23 import stat
24 24 import subprocess
25 25 import sys
26 26 import time
27 27
28 28 from .i18n import _
29 29 from .node import (
30 30 bin,
31 31 hex,
32 32 nullrev,
33 33 short,
34 34 )
35 35 from .pycompat import (
36 36 open,
37 37 )
38 38 from . import (
39 39 bundle2,
40 40 bundlerepo,
41 41 changegroup,
42 42 cmdutil,
43 43 color,
44 44 context,
45 45 copies,
46 46 dagparser,
47 47 dirstateutils,
48 48 encoding,
49 49 error,
50 50 exchange,
51 51 extensions,
52 52 filelog,
53 53 filemerge,
54 54 filesetlang,
55 55 formatter,
56 56 hg,
57 57 httppeer,
58 58 localrepo,
59 59 lock as lockmod,
60 60 logcmdutil,
61 61 manifest,
62 62 mergestate as mergestatemod,
63 63 metadata,
64 64 obsolete,
65 65 obsutil,
66 66 pathutil,
67 67 phases,
68 68 policy,
69 69 pvec,
70 70 pycompat,
71 71 registrar,
72 72 repair,
73 73 repoview,
74 74 requirements,
75 75 revlog,
76 76 revset,
77 77 revsetlang,
78 78 scmutil,
79 79 setdiscovery,
80 80 simplemerge,
81 81 sshpeer,
82 82 sslutil,
83 83 streamclone,
84 84 strip,
85 85 tags as tagsmod,
86 86 templater,
87 87 treediscovery,
88 88 upgrade,
89 89 url as urlmod,
90 90 util,
91 91 verify,
92 92 vfs as vfsmod,
93 93 wireprotoframing,
94 94 wireprotoserver,
95 95 )
96 96 from .interfaces import repository
97 97 from .stabletailgraph import stabletailsort
98 98 from .utils import (
99 99 cborutil,
100 100 compression,
101 101 dateutil,
102 102 procutil,
103 103 stringutil,
104 104 urlutil,
105 105 )
106 106
107 107 from .revlogutils import (
108 108 debug as revlog_debug,
109 109 nodemap,
110 110 rewrite,
111 111 sidedata,
112 112 )
113 113
114 114 release = lockmod.release
115 115
116 116 table = {}
117 117 table.update(strip.command._table)
118 118 command = registrar.command(table)
119 119
120 120
121 121 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
122 122 def debugancestor(ui, repo, *args):
123 123 """find the ancestor revision of two revisions in a given index"""
124 124 if len(args) == 3:
125 125 index, rev1, rev2 = args
126 126 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
127 127 lookup = r.lookup
128 128 elif len(args) == 2:
129 129 if not repo:
130 130 raise error.Abort(
131 131 _(b'there is no Mercurial repository here (.hg not found)')
132 132 )
133 133 rev1, rev2 = args
134 134 r = repo.changelog
135 135 lookup = repo.lookup
136 136 else:
137 137 raise error.Abort(_(b'either two or three arguments required'))
138 138 a = r.ancestor(lookup(rev1), lookup(rev2))
139 139 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
140 140
141 141
142 142 @command(b'debugantivirusrunning', [])
143 143 def debugantivirusrunning(ui, repo):
144 144 """attempt to trigger an antivirus scanner to see if one is active"""
145 145 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
146 146 f.write(
147 147 util.b85decode(
148 148 # This is a base85-armored version of the EICAR test file. See
149 149 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
150 150 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
151 151 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
152 152 )
153 153 )
154 154 # Give an AV engine time to scan the file.
155 155 time.sleep(2)
156 156 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
157 157
158 158
159 159 @command(b'debugapplystreamclonebundle', [], b'FILE')
160 160 def debugapplystreamclonebundle(ui, repo, fname):
161 161 """apply a stream clone bundle file"""
162 162 f = hg.openpath(ui, fname)
163 163 gen = exchange.readbundle(ui, f, fname)
164 164 gen.apply(repo)
165 165
166 166
167 167 @command(
168 168 b'debugbuilddag',
169 169 [
170 170 (
171 171 b'm',
172 172 b'mergeable-file',
173 173 None,
174 174 _(b'add single file mergeable changes'),
175 175 ),
176 176 (
177 177 b'o',
178 178 b'overwritten-file',
179 179 None,
180 180 _(b'add single file all revs overwrite'),
181 181 ),
182 182 (b'n', b'new-file', None, _(b'add new file at each rev')),
183 183 (
184 184 b'',
185 185 b'from-existing',
186 186 None,
187 187 _(b'continue from a non-empty repository'),
188 188 ),
189 189 ],
190 190 _(b'[OPTION]... [TEXT]'),
191 191 )
192 192 def debugbuilddag(
193 193 ui,
194 194 repo,
195 195 text=None,
196 196 mergeable_file=False,
197 197 overwritten_file=False,
198 198 new_file=False,
199 199 from_existing=False,
200 200 ):
201 201 """builds a repo with a given DAG from scratch in the current empty repo
202 202
203 203 The description of the DAG is read from stdin if not given on the
204 204 command line.
205 205
206 206 Elements:
207 207
208 208 - "+n" is a linear run of n nodes based on the current default parent
209 209 - "." is a single node based on the current default parent
210 210 - "$" resets the default parent to null (implied at the start);
211 211 otherwise the default parent is always the last node created
212 212 - "<p" sets the default parent to the backref p
213 213 - "*p" is a fork at parent p, which is a backref
214 214 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
215 215 - "/p2" is a merge of the preceding node and p2
216 216 - ":tag" defines a local tag for the preceding node
217 217 - "@branch" sets the named branch for subsequent nodes
218 218 - "#...\\n" is a comment up to the end of the line
219 219
220 220 Whitespace between the above elements is ignored.
221 221
222 222 A backref is either
223 223
224 224 - a number n, which references the node curr-n, where curr is the current
225 225 node, or
226 226 - the name of a local tag you placed earlier using ":tag", or
227 227 - empty to denote the default parent.
228 228
229 229 All string valued-elements are either strictly alphanumeric, or must
230 230 be enclosed in double quotes ("..."), with "\\" as escape character.
231 231 """
232 232
233 233 if text is None:
234 234 ui.status(_(b"reading DAG from stdin\n"))
235 235 text = ui.fin.read()
236 236
237 237 cl = repo.changelog
238 238 if len(cl) > 0 and not from_existing:
239 239 raise error.Abort(_(b'repository is not empty'))
240 240
241 241 # determine number of revs in DAG
242 242 total = 0
243 243 for type, data in dagparser.parsedag(text):
244 244 if type == b'n':
245 245 total += 1
246 246
247 247 if mergeable_file:
248 248 linesperrev = 2
249 249 # make a file with k lines per rev
250 250 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
251 251 initialmergedlines.append(b"")
252 252
253 253 tags = []
254 254 progress = ui.makeprogress(
255 255 _(b'building'), unit=_(b'revisions'), total=total
256 256 )
257 257 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
258 258 at = -1
259 259 atbranch = b'default'
260 260 nodeids = []
261 261 id = 0
262 262 progress.update(id)
263 263 for type, data in dagparser.parsedag(text):
264 264 if type == b'n':
265 265 ui.note((b'node %s\n' % pycompat.bytestr(data)))
266 266 id, ps = data
267 267
268 268 files = []
269 269 filecontent = {}
270 270
271 271 p2 = None
272 272 if mergeable_file:
273 273 fn = b"mf"
274 274 p1 = repo[ps[0]]
275 275 if len(ps) > 1:
276 276 p2 = repo[ps[1]]
277 277 pa = p1.ancestor(p2)
278 278 base, local, other = [
279 279 x[fn].data() for x in (pa, p1, p2)
280 280 ]
281 281 m3 = simplemerge.Merge3Text(base, local, other)
282 282 ml = [
283 283 l.strip()
284 284 for l in simplemerge.render_minimized(m3)[0]
285 285 ]
286 286 ml.append(b"")
287 287 elif at > 0:
288 288 ml = p1[fn].data().split(b"\n")
289 289 else:
290 290 ml = initialmergedlines
291 291 ml[id * linesperrev] += b" r%i" % id
292 292 mergedtext = b"\n".join(ml)
293 293 files.append(fn)
294 294 filecontent[fn] = mergedtext
295 295
296 296 if overwritten_file:
297 297 fn = b"of"
298 298 files.append(fn)
299 299 filecontent[fn] = b"r%i\n" % id
300 300
301 301 if new_file:
302 302 fn = b"nf%i" % id
303 303 files.append(fn)
304 304 filecontent[fn] = b"r%i\n" % id
305 305 if len(ps) > 1:
306 306 if not p2:
307 307 p2 = repo[ps[1]]
308 308 for fn in p2:
309 309 if fn.startswith(b"nf"):
310 310 files.append(fn)
311 311 filecontent[fn] = p2[fn].data()
312 312
313 313 def fctxfn(repo, cx, path):
314 314 if path in filecontent:
315 315 return context.memfilectx(
316 316 repo, cx, path, filecontent[path]
317 317 )
318 318 return None
319 319
320 320 if len(ps) == 0 or ps[0] < 0:
321 321 pars = [None, None]
322 322 elif len(ps) == 1:
323 323 pars = [nodeids[ps[0]], None]
324 324 else:
325 325 pars = [nodeids[p] for p in ps]
326 326 cx = context.memctx(
327 327 repo,
328 328 pars,
329 329 b"r%i" % id,
330 330 files,
331 331 fctxfn,
332 332 date=(id, 0),
333 333 user=b"debugbuilddag",
334 334 extra={b'branch': atbranch},
335 335 )
336 336 nodeid = repo.commitctx(cx)
337 337 nodeids.append(nodeid)
338 338 at = id
339 339 elif type == b'l':
340 340 id, name = data
341 341 ui.note((b'tag %s\n' % name))
342 342 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
343 343 elif type == b'a':
344 344 ui.note((b'branch %s\n' % data))
345 345 atbranch = data
346 346 progress.update(id)
347 347
348 348 if tags:
349 349 repo.vfs.write(b"localtags", b"".join(tags))
350 350
351 351
352 352 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
353 353 indent_string = b' ' * indent
354 354 if all:
355 355 ui.writenoi18n(
356 356 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
357 357 % indent_string
358 358 )
359 359
360 360 def showchunks(named):
361 361 ui.write(b"\n%s%s\n" % (indent_string, named))
362 362 for deltadata in gen.deltaiter():
363 363 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
364 364 ui.write(
365 365 b"%s%s %s %s %s %s %d\n"
366 366 % (
367 367 indent_string,
368 368 hex(node),
369 369 hex(p1),
370 370 hex(p2),
371 371 hex(cs),
372 372 hex(deltabase),
373 373 len(delta),
374 374 )
375 375 )
376 376
377 377 gen.changelogheader()
378 378 showchunks(b"changelog")
379 379 gen.manifestheader()
380 380 showchunks(b"manifest")
381 381 for chunkdata in iter(gen.filelogheader, {}):
382 382 fname = chunkdata[b'filename']
383 383 showchunks(fname)
384 384 else:
385 385 if isinstance(gen, bundle2.unbundle20):
386 386 raise error.Abort(_(b'use debugbundle2 for this file'))
387 387 gen.changelogheader()
388 388 for deltadata in gen.deltaiter():
389 389 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
390 390 ui.write(b"%s%s\n" % (indent_string, hex(node)))
391 391
392 392
393 393 def _debugobsmarkers(ui, part, indent=0, **opts):
394 394 """display version and markers contained in 'data'"""
395 395 data = part.read()
396 396 indent_string = b' ' * indent
397 397 try:
398 398 version, markers = obsolete._readmarkers(data)
399 399 except error.UnknownVersion as exc:
400 400 msg = b"%sunsupported version: %s (%d bytes)\n"
401 401 msg %= indent_string, exc.version, len(data)
402 402 ui.write(msg)
403 403 else:
404 404 msg = b"%sversion: %d (%d bytes)\n"
405 405 msg %= indent_string, version, len(data)
406 406 ui.write(msg)
407 407 fm = ui.formatter(b'debugobsolete', pycompat.byteskwargs(opts))
408 408 for rawmarker in sorted(markers):
409 409 m = obsutil.marker(None, rawmarker)
410 410 fm.startitem()
411 411 fm.plain(indent_string)
412 412 cmdutil.showmarker(fm, m)
413 413 fm.end()
414 414
415 415
416 416 def _debugphaseheads(ui, data, indent=0):
417 417 """display version and markers contained in 'data'"""
418 418 indent_string = b' ' * indent
419 419 headsbyphase = phases.binarydecode(data)
420 420 for phase in phases.allphases:
421 421 for head in headsbyphase[phase]:
422 422 ui.write(indent_string)
423 423 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
424 424
425 425
426 426 def _quasirepr(thing):
427 427 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
428 428 return b'{%s}' % (
429 429 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
430 430 )
431 431 return pycompat.bytestr(repr(thing))
432 432
433 433
434 434 def _debugbundle2(ui, gen, all=None, **opts):
435 435 """lists the contents of a bundle2"""
436 436 if not isinstance(gen, bundle2.unbundle20):
437 437 raise error.Abort(_(b'not a bundle2 file'))
438 438 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
439 439 parttypes = opts.get('part_type', [])
440 440 for part in gen.iterparts():
441 441 if parttypes and part.type not in parttypes:
442 442 continue
443 443 msg = b'%s -- %s (mandatory: %r)\n'
444 444 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
445 445 if part.type == b'changegroup':
446 446 version = part.params.get(b'version', b'01')
447 447 cg = changegroup.getunbundler(version, part, b'UN')
448 448 if not ui.quiet:
449 449 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
450 450 if part.type == b'obsmarkers':
451 451 if not ui.quiet:
452 452 _debugobsmarkers(ui, part, indent=4, **opts)
453 453 if part.type == b'phase-heads':
454 454 if not ui.quiet:
455 455 _debugphaseheads(ui, part, indent=4)
456 456
457 457
458 458 @command(
459 459 b'debugbundle',
460 460 [
461 461 (b'a', b'all', None, _(b'show all details')),
462 462 (b'', b'part-type', [], _(b'show only the named part type')),
463 463 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
464 464 ],
465 465 _(b'FILE'),
466 466 norepo=True,
467 467 )
468 468 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
469 469 """lists the contents of a bundle"""
470 470 with hg.openpath(ui, bundlepath) as f:
471 471 if spec:
472 472 spec = exchange.getbundlespec(ui, f)
473 473 ui.write(b'%s\n' % spec)
474 474 return
475 475
476 476 gen = exchange.readbundle(ui, f, bundlepath)
477 477 if isinstance(gen, bundle2.unbundle20):
478 478 return _debugbundle2(ui, gen, all=all, **opts)
479 479 _debugchangegroup(ui, gen, all=all, **opts)
480 480
481 481
482 482 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
483 483 def debugcapabilities(ui, path, **opts):
484 484 """lists the capabilities of a remote peer"""
485 485 peer = hg.peer(ui, pycompat.byteskwargs(opts), path)
486 486 try:
487 487 caps = peer.capabilities()
488 488 ui.writenoi18n(b'Main capabilities:\n')
489 489 for c in sorted(caps):
490 490 ui.write(b' %s\n' % c)
491 491 b2caps = bundle2.bundle2caps(peer)
492 492 if b2caps:
493 493 ui.writenoi18n(b'Bundle2 capabilities:\n')
494 494 for key, values in sorted(b2caps.items()):
495 495 ui.write(b' %s\n' % key)
496 496 for v in values:
497 497 ui.write(b' %s\n' % v)
498 498 finally:
499 499 peer.close()
500 500
501 501
502 502 @command(
503 503 b'debugchangedfiles',
504 504 [
505 505 (
506 506 b'',
507 507 b'compute',
508 508 False,
509 509 b"compute information instead of reading it from storage",
510 510 ),
511 511 ],
512 512 b'REV',
513 513 )
514 514 def debugchangedfiles(ui, repo, rev, **opts):
515 515 """list the stored files changes for a revision"""
516 516 ctx = logcmdutil.revsingle(repo, rev, None)
517 517 files = None
518 518
519 519 if opts['compute']:
520 520 files = metadata.compute_all_files_changes(ctx)
521 521 else:
522 522 sd = repo.changelog.sidedata(ctx.rev())
523 523 files_block = sd.get(sidedata.SD_FILES)
524 524 if files_block is not None:
525 525 files = metadata.decode_files_sidedata(sd)
526 526 if files is not None:
527 527 for f in sorted(files.touched):
528 528 if f in files.added:
529 529 action = b"added"
530 530 elif f in files.removed:
531 531 action = b"removed"
532 532 elif f in files.merged:
533 533 action = b"merged"
534 534 elif f in files.salvaged:
535 535 action = b"salvaged"
536 536 else:
537 537 action = b"touched"
538 538
539 539 copy_parent = b""
540 540 copy_source = b""
541 541 if f in files.copied_from_p1:
542 542 copy_parent = b"p1"
543 543 copy_source = files.copied_from_p1[f]
544 544 elif f in files.copied_from_p2:
545 545 copy_parent = b"p2"
546 546 copy_source = files.copied_from_p2[f]
547 547
548 548 data = (action, copy_parent, f, copy_source)
549 549 template = b"%-8s %2s: %s, %s;\n"
550 550 ui.write(template % data)
551 551
552 552
553 553 @command(b'debugcheckstate', [], b'')
554 554 def debugcheckstate(ui, repo):
555 555 """validate the correctness of the current dirstate"""
556 556 errors = verify.verifier(repo)._verify_dirstate()
557 557 if errors:
558 558 errstr = _(b"dirstate inconsistent with current parent's manifest")
559 559 raise error.Abort(errstr)
560 560
561 561
562 562 @command(
563 563 b'debugcolor',
564 564 [(b'', b'style', None, _(b'show all configured styles'))],
565 565 b'hg debugcolor',
566 566 )
567 567 def debugcolor(ui, repo, **opts):
568 568 """show available color, effects or style"""
569 569 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
570 570 if opts.get('style'):
571 571 return _debugdisplaystyle(ui)
572 572 else:
573 573 return _debugdisplaycolor(ui)
574 574
575 575
576 576 def _debugdisplaycolor(ui):
577 577 ui = ui.copy()
578 578 ui._styles.clear()
579 579 for effect in color._activeeffects(ui).keys():
580 580 ui._styles[effect] = effect
581 581 if ui._terminfoparams:
582 582 for k, v in ui.configitems(b'color'):
583 583 if k.startswith(b'color.'):
584 584 ui._styles[k] = k[6:]
585 585 elif k.startswith(b'terminfo.'):
586 586 ui._styles[k] = k[9:]
587 587 ui.write(_(b'available colors:\n'))
588 588 # sort label with a '_' after the other to group '_background' entry.
589 589 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
590 590 for colorname, label in items:
591 591 ui.write(b'%s\n' % colorname, label=label)
592 592
593 593
594 594 def _debugdisplaystyle(ui):
595 595 ui.write(_(b'available style:\n'))
596 596 if not ui._styles:
597 597 return
598 598 width = max(len(s) for s in ui._styles)
599 599 for label, effects in sorted(ui._styles.items()):
600 600 ui.write(b'%s' % label, label=label)
601 601 if effects:
602 602 # 50
603 603 ui.write(b': ')
604 604 ui.write(b' ' * (max(0, width - len(label))))
605 605 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
606 606 ui.write(b'\n')
607 607
608 608
609 609 @command(b'debugcreatestreamclonebundle', [], b'FILE')
610 610 def debugcreatestreamclonebundle(ui, repo, fname):
611 611 """create a stream clone bundle file
612 612
613 613 Stream bundles are special bundles that are essentially archives of
614 614 revlog files. They are commonly used for cloning very quickly.
615 615
616 616 This command creates a "version 1" stream clone, which is deprecated in
617 617 favor of newer versions of the stream protocol. Bundles using such newer
618 618 versions can be generated using the `hg bundle` command.
619 619 """
620 620 # TODO we may want to turn this into an abort when this functionality
621 621 # is moved into `hg bundle`.
622 622 if phases.hassecret(repo):
623 623 ui.warn(
624 624 _(
625 625 b'(warning: stream clone bundle will contain secret '
626 626 b'revisions)\n'
627 627 )
628 628 )
629 629
630 630 requirements, gen = streamclone.generatebundlev1(repo)
631 631 changegroup.writechunks(ui, gen, fname)
632 632
633 633 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
634 634
635 635
636 636 @command(
637 637 b'debugdag',
638 638 [
639 639 (b't', b'tags', None, _(b'use tags as labels')),
640 640 (b'b', b'branches', None, _(b'annotate with branch names')),
641 641 (b'', b'dots', None, _(b'use dots for runs')),
642 642 (b's', b'spaces', None, _(b'separate elements by spaces')),
643 643 ],
644 644 _(b'[OPTION]... [FILE [REV]...]'),
645 645 optionalrepo=True,
646 646 )
647 647 def debugdag(ui, repo, file_=None, *revs, **opts):
648 648 """format the changelog or an index DAG as a concise textual description
649 649
650 650 If you pass a revlog index, the revlog's DAG is emitted. If you list
651 651 revision numbers, they get labeled in the output as rN.
652 652
653 653 Otherwise, the changelog DAG of the current repo is emitted.
654 654 """
655 655 spaces = opts.get('spaces')
656 656 dots = opts.get('dots')
657 657 if file_:
658 658 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
659 659 revs = {int(r) for r in revs}
660 660
661 661 def events():
662 662 for r in rlog:
663 663 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
664 664 if r in revs:
665 665 yield b'l', (r, b"r%i" % r)
666 666
667 667 elif repo:
668 668 cl = repo.changelog
669 669 tags = opts.get('tags')
670 670 branches = opts.get('branches')
671 671 if tags:
672 672 labels = {}
673 673 for l, n in repo.tags().items():
674 674 labels.setdefault(cl.rev(n), []).append(l)
675 675
676 676 def events():
677 677 b = b"default"
678 678 for r in cl:
679 679 if branches:
680 680 newb = cl.read(cl.node(r))[5][b'branch']
681 681 if newb != b:
682 682 yield b'a', newb
683 683 b = newb
684 684 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
685 685 if tags:
686 686 ls = labels.get(r)
687 687 if ls:
688 688 for l in ls:
689 689 yield b'l', (r, l)
690 690
691 691 else:
692 692 raise error.Abort(_(b'need repo for changelog dag'))
693 693
694 694 for line in dagparser.dagtextlines(
695 695 events(),
696 696 addspaces=spaces,
697 697 wraplabels=True,
698 698 wrapannotations=True,
699 699 wrapnonlinear=dots,
700 700 usedots=dots,
701 701 maxlinewidth=70,
702 702 ):
703 703 ui.write(line)
704 704 ui.write(b"\n")
705 705
706 706
707 707 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
708 708 def debugdata(ui, repo, file_, rev=None, **opts):
709 709 """dump the contents of a data file revision"""
710 710 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
711 711 if rev is not None:
712 712 raise error.InputError(
713 713 _(b'cannot specify a revision with other arguments')
714 714 )
715 715 file_, rev = None, file_
716 716 elif rev is None:
717 717 raise error.InputError(_(b'please specify a revision'))
718 718 r = cmdutil.openstorage(
719 719 repo, b'debugdata', file_, pycompat.byteskwargs(opts)
720 720 )
721 721 try:
722 722 ui.write(r.rawdata(r.lookup(rev)))
723 723 except KeyError:
724 724 raise error.Abort(_(b'invalid revision identifier %s') % rev)
725 725
726 726
727 727 @command(
728 728 b'debugdate',
729 729 [(b'e', b'extended', None, _(b'try extended date formats'))],
730 730 _(b'[-e] DATE [RANGE]'),
731 731 norepo=True,
732 732 optionalrepo=True,
733 733 )
734 734 def debugdate(ui, date, range=None, **opts):
735 735 """parse and display a date"""
736 736 if opts["extended"]:
737 737 d = dateutil.parsedate(date, dateutil.extendeddateformats)
738 738 else:
739 739 d = dateutil.parsedate(date)
740 740 ui.writenoi18n(b"internal: %d %d\n" % d)
741 741 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
742 742 if range:
743 743 m = dateutil.matchdate(range)
744 744 ui.writenoi18n(b"match: %s\n" % m(d[0]))
745 745
746 746
747 747 @command(
748 748 b'debugdeltachain',
749 749 [
750 750 (
751 751 b'r',
752 752 b'rev',
753 753 [],
754 754 _('restrict processing to these revlog revisions'),
755 755 ),
756 756 (
757 757 b'',
758 758 b'all-info',
759 True,
759 False,
760 760 _('compute all information unless specified otherwise'),
761 761 ),
762 762 (
763 763 b'',
764 764 b'size-info',
765 765 None,
766 766 _('compute information related to deltas size'),
767 767 ),
768 768 (
769 769 b'',
770 770 b'dist-info',
771 771 None,
772 772 _('compute information related to base distance'),
773 773 ),
774 774 (
775 775 b'',
776 776 b'sparse-info',
777 777 None,
778 778 _('compute information related to sparse read'),
779 779 ),
780 780 ]
781 781 + cmdutil.debugrevlogopts
782 782 + cmdutil.formatteropts,
783 783 _(b'-c|-m|FILE'),
784 784 optionalrepo=True,
785 785 )
786 786 def debugdeltachain(ui, repo, file_=None, **opts):
787 787 """dump information about delta chains in a revlog
788 788
789 789 Output can be templatized. Available template keywords are:
790 790
791 791 :``rev``: revision number
792 792 :``p1``: parent 1 revision number (for reference)
793 793 :``p2``: parent 2 revision number (for reference)
794 794
795 795 :``chainid``: delta chain identifier (numbered by unique base)
796 796 :``chainlen``: delta chain length to this revision
797 797
798 798 :``prevrev``: previous revision in delta chain
799 799 :``deltatype``: role of delta / how it was computed
800 800 - base: a full snapshot
801 801 - snap: an intermediate snapshot
802 802 - p1: a delta against the first parent
803 803 - p2: a delta against the second parent
804 804 - skip1: a delta against the same base as p1
805 805 (when p1 has empty delta
806 806 - skip2: a delta against the same base as p2
807 807 (when p2 has empty delta
808 808 - prev: a delta against the previous revision
809 809 - other: a delta against an arbitrary revision
810 810
811 811 :``compsize``: compressed size of revision
812 812 :``uncompsize``: uncompressed size of revision
813 813 :``chainsize``: total size of compressed revisions in chain
814 814 :``chainratio``: total chain size divided by uncompressed revision size
815 815 (new delta chains typically start at ratio 2.00)
816 816
817 817 :``lindist``: linear distance from base revision in delta chain to end
818 818 of this revision
819 819 :``extradist``: total size of revisions not part of this delta chain from
820 820 base of delta chain to end of this revision; a measurement
821 821 of how much extra data we need to read/seek across to read
822 822 the delta chain for this revision
823 823 :``extraratio``: extradist divided by chainsize; another representation of
824 824 how much unrelated data is needed to load this delta chain
825 825
826 826 If the repository is configured to use the sparse read, additional keywords
827 827 are available:
828 828
829 829 :``readsize``: total size of data read from the disk for a revision
830 830 (sum of the sizes of all the blocks)
831 831 :``largestblock``: size of the largest block of data read from the disk
832 832 :``readdensity``: density of useful bytes in the data read from the disk
833 833 :``srchunks``: in how many data hunks the whole revision would be read
834 834
835 835 It is possible to select the information to be computed, this can provide a
836 836 noticeable speedup to the command in some cases.
837 837
838 838 Always computed:
839 839
840 840 - ``rev``
841 841 - ``p1``
842 842 - ``p2``
843 843 - ``chainid``
844 844 - ``chainlen``
845 845 - ``prevrev``
846 846 - ``deltatype``
847 847
848 848 Computed with --no-size-info
849 849
850 850 - ``compsize``
851 851 - ``uncompsize``
852 852 - ``chainsize``
853 853 - ``chainratio``
854 854
855 855 Computed with --no-dist-info
856 856
857 857 - ``lindist``
858 858 - ``extradist``
859 859 - ``extraratio``
860 860
861 861 Skipped with --no-sparse-info
862 862
863 863 - ``readsize``
864 864 - ``largestblock``
865 865 - ``readdensity``
866 866 - ``srchunks``
867 867
868 868 --
869 869
870 870 The sparse read can be enabled with experimental.sparse-read = True
871 871 """
872 872 revs = None
873 873 revs_opt = opts.pop('rev', [])
874 874 if revs_opt:
875 875 revs = [int(r) for r in revs_opt]
876 876
877 all_info = opts.pop('all_info', True)
877 all_info = opts.pop('all_info', False)
878 878 size_info = opts.pop('size_info', None)
879 879 if size_info is None:
880 880 size_info = all_info
881 881 dist_info = opts.pop('dist_info', None)
882 882 if dist_info is None:
883 883 dist_info = all_info
884 884 sparse_info = opts.pop('sparse_info', None)
885 885 if sparse_info is None:
886 886 sparse_info = all_info
887 887
888 888 revlog = cmdutil.openrevlog(
889 889 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts)
890 890 )
891 891 fm = ui.formatter(b'debugdeltachain', pycompat.byteskwargs(opts))
892 892
893 893 lines = revlog_debug.debug_delta_chain(
894 894 revlog,
895 895 revs=revs,
896 896 size_info=size_info,
897 897 dist_info=dist_info,
898 898 sparse_info=sparse_info,
899 899 )
900 900 # first entry is the header
901 901 header = next(lines)
902 902 fm.plain(header)
903 903 for entry in lines:
904 904 label = b' '.join(e[0] for e in entry)
905 905 format = b' '.join(e[1] for e in entry)
906 906 values = [e[3] for e in entry]
907 907 data = dict((e[2], e[3]) for e in entry)
908 908 fm.startitem()
909 909 fm.write(label, format, *values, **data)
910 910 fm.plain(b'\n')
911 911 fm.end()
912 912
913 913
914 914 @command(
915 915 b'debug-delta-find',
916 916 cmdutil.debugrevlogopts
917 917 + cmdutil.formatteropts
918 918 + [
919 919 (
920 920 b'',
921 921 b'source',
922 922 b'full',
923 923 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
924 924 ),
925 925 ],
926 926 _(b'-c|-m|FILE REV'),
927 927 optionalrepo=True,
928 928 )
929 929 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
930 930 """display the computation to get to a valid delta for storing REV
931 931
932 932 This command will replay the process used to find the "best" delta to store
933 933 a revision and display information about all the steps used to get to that
934 934 result.
935 935
936 936 By default, the process is fed with a the full-text for the revision. This
937 937 can be controlled with the --source flag.
938 938
939 939 The revision use the revision number of the target storage (not changelog
940 940 revision number).
941 941
942 942 note: the process is initiated from a full text of the revision to store.
943 943 """
944 944 if arg_2 is None:
945 945 file_ = None
946 946 rev = arg_1
947 947 else:
948 948 file_ = arg_1
949 949 rev = arg_2
950 950
951 951 rev = int(rev)
952 952
953 953 revlog = cmdutil.openrevlog(
954 954 repo, b'debugdeltachain', file_, pycompat.byteskwargs(opts)
955 955 )
956 956 p1r, p2r = revlog.parentrevs(rev)
957 957
958 958 if source == b'full':
959 959 base_rev = nullrev
960 960 elif source == b'storage':
961 961 base_rev = revlog.deltaparent(rev)
962 962 elif source == b'p1':
963 963 base_rev = p1r
964 964 elif source == b'p2':
965 965 base_rev = p2r
966 966 elif source == b'prev':
967 967 base_rev = rev - 1
968 968 else:
969 969 raise error.InputError(b"invalid --source value: %s" % source)
970 970
971 971 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
972 972
973 973
974 974 @command(
975 975 b'debugdirstate|debugstate',
976 976 [
977 977 (
978 978 b'',
979 979 b'nodates',
980 980 None,
981 981 _(b'do not display the saved mtime (DEPRECATED)'),
982 982 ),
983 983 (b'', b'dates', True, _(b'display the saved mtime')),
984 984 (b'', b'datesort', None, _(b'sort by saved mtime')),
985 985 (
986 986 b'',
987 987 b'docket',
988 988 False,
989 989 _(b'display the docket (metadata file) instead'),
990 990 ),
991 991 (
992 992 b'',
993 993 b'all',
994 994 False,
995 995 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
996 996 ),
997 997 ],
998 998 _(b'[OPTION]...'),
999 999 )
1000 1000 def debugstate(ui, repo, **opts):
1001 1001 """show the contents of the current dirstate"""
1002 1002
1003 1003 if opts.get("docket"):
1004 1004 if not repo.dirstate._use_dirstate_v2:
1005 1005 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1006 1006
1007 1007 docket = repo.dirstate._map.docket
1008 1008 (
1009 1009 start_offset,
1010 1010 root_nodes,
1011 1011 nodes_with_entry,
1012 1012 nodes_with_copy,
1013 1013 unused_bytes,
1014 1014 _unused,
1015 1015 ignore_pattern,
1016 1016 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1017 1017
1018 1018 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1019 1019 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1020 1020 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1021 1021 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1022 1022 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1023 1023 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1024 1024 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1025 1025 ui.write(
1026 1026 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1027 1027 )
1028 1028 return
1029 1029
1030 1030 nodates = not opts['dates']
1031 1031 if opts.get('nodates') is not None:
1032 1032 nodates = True
1033 1033 datesort = opts.get('datesort')
1034 1034
1035 1035 if datesort:
1036 1036
1037 1037 def keyfunc(entry):
1038 1038 filename, _state, _mode, _size, mtime = entry
1039 1039 return (mtime, filename)
1040 1040
1041 1041 else:
1042 1042 keyfunc = None # sort by filename
1043 1043 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1044 1044 entries.sort(key=keyfunc)
1045 1045 for entry in entries:
1046 1046 filename, state, mode, size, mtime = entry
1047 1047 if mtime == -1:
1048 1048 timestr = b'unset '
1049 1049 elif nodates:
1050 1050 timestr = b'set '
1051 1051 else:
1052 1052 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1053 1053 timestr = encoding.strtolocal(timestr)
1054 1054 if mode & 0o20000:
1055 1055 mode = b'lnk'
1056 1056 else:
1057 1057 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1058 1058 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1059 1059 for f in repo.dirstate.copies():
1060 1060 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1061 1061
1062 1062
1063 1063 @command(
1064 1064 b'debugdirstateignorepatternshash',
1065 1065 [],
1066 1066 _(b''),
1067 1067 )
1068 1068 def debugdirstateignorepatternshash(ui, repo, **opts):
1069 1069 """show the hash of ignore patterns stored in dirstate if v2,
1070 1070 or nothing for dirstate-v2
1071 1071 """
1072 1072 if repo.dirstate._use_dirstate_v2:
1073 1073 docket = repo.dirstate._map.docket
1074 1074 hash_len = 20 # 160 bits for SHA-1
1075 1075 hash_bytes = docket.tree_metadata[-hash_len:]
1076 1076 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1077 1077
1078 1078
1079 1079 @command(
1080 1080 b'debugdiscovery',
1081 1081 [
1082 1082 (b'', b'old', None, _(b'use old-style discovery')),
1083 1083 (
1084 1084 b'',
1085 1085 b'nonheads',
1086 1086 None,
1087 1087 _(b'use old-style discovery with non-heads included'),
1088 1088 ),
1089 1089 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1090 1090 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1091 1091 (
1092 1092 b'',
1093 1093 b'local-as-revs',
1094 1094 b"",
1095 1095 b'treat local has having these revisions only',
1096 1096 ),
1097 1097 (
1098 1098 b'',
1099 1099 b'remote-as-revs',
1100 1100 b"",
1101 1101 b'use local as remote, with only these revisions',
1102 1102 ),
1103 1103 ]
1104 1104 + cmdutil.remoteopts
1105 1105 + cmdutil.formatteropts,
1106 1106 _(b'[--rev REV] [OTHER]'),
1107 1107 )
1108 1108 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1109 1109 """runs the changeset discovery protocol in isolation
1110 1110
1111 1111 The local peer can be "replaced" by a subset of the local repository by
1112 1112 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1113 1113 can be "replaced" by a subset of the local repository using the
1114 1114 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1115 1115 discovery situations.
1116 1116
1117 1117 The following developer oriented config are relevant for people playing with this command:
1118 1118
1119 1119 * devel.discovery.exchange-heads=True
1120 1120
1121 1121 If False, the discovery will not start with
1122 1122 remote head fetching and local head querying.
1123 1123
1124 1124 * devel.discovery.grow-sample=True
1125 1125
1126 1126 If False, the sample size used in set discovery will not be increased
1127 1127 through the process
1128 1128
1129 1129 * devel.discovery.grow-sample.dynamic=True
1130 1130
1131 1131 When discovery.grow-sample.dynamic is True, the default, the sample size is
1132 1132 adapted to the shape of the undecided set (it is set to the max of:
1133 1133 <target-size>, len(roots(undecided)), len(heads(undecided)
1134 1134
1135 1135 * devel.discovery.grow-sample.rate=1.05
1136 1136
1137 1137 the rate at which the sample grow
1138 1138
1139 1139 * devel.discovery.randomize=True
1140 1140
1141 1141 If andom sampling during discovery are deterministic. It is meant for
1142 1142 integration tests.
1143 1143
1144 1144 * devel.discovery.sample-size=200
1145 1145
1146 1146 Control the initial size of the discovery sample
1147 1147
1148 1148 * devel.discovery.sample-size.initial=100
1149 1149
1150 1150 Control the initial size of the discovery for initial change
1151 1151 """
1152 1152 unfi = repo.unfiltered()
1153 1153
1154 1154 # setup potential extra filtering
1155 1155 local_revs = opts["local_as_revs"]
1156 1156 remote_revs = opts["remote_as_revs"]
1157 1157
1158 1158 # make sure tests are repeatable
1159 1159 random.seed(int(opts['seed']))
1160 1160
1161 1161 if not remote_revs:
1162 1162 path = urlutil.get_unique_pull_path_obj(
1163 1163 b'debugdiscovery', ui, remoteurl
1164 1164 )
1165 1165 branches = (path.branch, [])
1166 1166 remote = hg.peer(repo, pycompat.byteskwargs(opts), path)
1167 1167 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1168 1168 else:
1169 1169 branches = (None, [])
1170 1170 remote_filtered_revs = logcmdutil.revrange(
1171 1171 unfi, [b"not (::(%s))" % remote_revs]
1172 1172 )
1173 1173 remote_filtered_revs = frozenset(remote_filtered_revs)
1174 1174
1175 1175 def remote_func(x):
1176 1176 return remote_filtered_revs
1177 1177
1178 1178 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1179 1179
1180 1180 remote = repo.peer()
1181 1181 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1182 1182
1183 1183 if local_revs:
1184 1184 local_filtered_revs = logcmdutil.revrange(
1185 1185 unfi, [b"not (::(%s))" % local_revs]
1186 1186 )
1187 1187 local_filtered_revs = frozenset(local_filtered_revs)
1188 1188
1189 1189 def local_func(x):
1190 1190 return local_filtered_revs
1191 1191
1192 1192 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1193 1193 repo = repo.filtered(b'debug-discovery-local-filter')
1194 1194
1195 1195 data = {}
1196 1196 if opts.get('old'):
1197 1197
1198 1198 def doit(pushedrevs, remoteheads, remote=remote):
1199 1199 if not hasattr(remote, 'branches'):
1200 1200 # enable in-client legacy support
1201 1201 remote = localrepo.locallegacypeer(remote.local())
1202 1202 if remote_revs:
1203 1203 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1204 1204 remote._repo = r
1205 1205 common, _in, hds = treediscovery.findcommonincoming(
1206 1206 repo, remote, force=True, audit=data
1207 1207 )
1208 1208 common = set(common)
1209 1209 if not opts.get('nonheads'):
1210 1210 ui.writenoi18n(
1211 1211 b"unpruned common: %s\n"
1212 1212 % b" ".join(sorted(short(n) for n in common))
1213 1213 )
1214 1214
1215 1215 clnode = repo.changelog.node
1216 1216 common = repo.revs(b'heads(::%ln)', common)
1217 1217 common = {clnode(r) for r in common}
1218 1218 return common, hds
1219 1219
1220 1220 else:
1221 1221
1222 1222 def doit(pushedrevs, remoteheads, remote=remote):
1223 1223 nodes = None
1224 1224 if pushedrevs:
1225 1225 revs = logcmdutil.revrange(repo, pushedrevs)
1226 1226 nodes = [repo[r].node() for r in revs]
1227 1227 common, any, hds = setdiscovery.findcommonheads(
1228 1228 ui,
1229 1229 repo,
1230 1230 remote,
1231 1231 ancestorsof=nodes,
1232 1232 audit=data,
1233 1233 abortwhenunrelated=False,
1234 1234 )
1235 1235 return common, hds
1236 1236
1237 1237 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1238 1238 localrevs = opts['rev']
1239 1239
1240 1240 fm = ui.formatter(b'debugdiscovery', pycompat.byteskwargs(opts))
1241 1241 if fm.strict_format:
1242 1242
1243 1243 @contextlib.contextmanager
1244 1244 def may_capture_output():
1245 1245 ui.pushbuffer()
1246 1246 yield
1247 1247 data[b'output'] = ui.popbuffer()
1248 1248
1249 1249 else:
1250 1250 may_capture_output = util.nullcontextmanager
1251 1251 with may_capture_output():
1252 1252 with util.timedcm('debug-discovery') as t:
1253 1253 common, hds = doit(localrevs, remoterevs)
1254 1254
1255 1255 # compute all statistics
1256 1256 if len(common) == 1 and repo.nullid in common:
1257 1257 common = set()
1258 1258 heads_common = set(common)
1259 1259 heads_remote = set(hds)
1260 1260 heads_local = set(repo.heads())
1261 1261 # note: they cannot be a local or remote head that is in common and not
1262 1262 # itself a head of common.
1263 1263 heads_common_local = heads_common & heads_local
1264 1264 heads_common_remote = heads_common & heads_remote
1265 1265 heads_common_both = heads_common & heads_remote & heads_local
1266 1266
1267 1267 all = repo.revs(b'all()')
1268 1268 common = repo.revs(b'::%ln', common)
1269 1269 roots_common = repo.revs(b'roots(::%ld)', common)
1270 1270 missing = repo.revs(b'not ::%ld', common)
1271 1271 heads_missing = repo.revs(b'heads(%ld)', missing)
1272 1272 roots_missing = repo.revs(b'roots(%ld)', missing)
1273 1273 assert len(common) + len(missing) == len(all)
1274 1274
1275 1275 initial_undecided = repo.revs(
1276 1276 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1277 1277 )
1278 1278 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1279 1279 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1280 1280 common_initial_undecided = initial_undecided & common
1281 1281 missing_initial_undecided = initial_undecided & missing
1282 1282
1283 1283 data[b'elapsed'] = t.elapsed
1284 1284 data[b'nb-common-heads'] = len(heads_common)
1285 1285 data[b'nb-common-heads-local'] = len(heads_common_local)
1286 1286 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1287 1287 data[b'nb-common-heads-both'] = len(heads_common_both)
1288 1288 data[b'nb-common-roots'] = len(roots_common)
1289 1289 data[b'nb-head-local'] = len(heads_local)
1290 1290 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1291 1291 data[b'nb-head-remote'] = len(heads_remote)
1292 1292 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1293 1293 heads_common_remote
1294 1294 )
1295 1295 data[b'nb-revs'] = len(all)
1296 1296 data[b'nb-revs-common'] = len(common)
1297 1297 data[b'nb-revs-missing'] = len(missing)
1298 1298 data[b'nb-missing-heads'] = len(heads_missing)
1299 1299 data[b'nb-missing-roots'] = len(roots_missing)
1300 1300 data[b'nb-ini_und'] = len(initial_undecided)
1301 1301 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1302 1302 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1303 1303 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1304 1304 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1305 1305
1306 1306 fm.startitem()
1307 1307 fm.data(**pycompat.strkwargs(data))
1308 1308 # display discovery summary
1309 1309 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1310 1310 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1311 1311 if b'total-round-trips-heads' in data:
1312 1312 fm.plain(
1313 1313 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1314 1314 )
1315 1315 if b'total-round-trips-branches' in data:
1316 1316 fm.plain(
1317 1317 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1318 1318 % data
1319 1319 )
1320 1320 if b'total-round-trips-between' in data:
1321 1321 fm.plain(
1322 1322 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1323 1323 )
1324 1324 fm.plain(b"queries: %(total-queries)9d\n" % data)
1325 1325 if b'total-queries-branches' in data:
1326 1326 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1327 1327 if b'total-queries-between' in data:
1328 1328 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1329 1329 fm.plain(b"heads summary:\n")
1330 1330 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1331 1331 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1332 1332 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1333 1333 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1334 1334 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1335 1335 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1336 1336 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1337 1337 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1338 1338 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1339 1339 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1340 1340 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1341 1341 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1342 1342 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1343 1343 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1344 1344 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1345 1345 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1346 1346 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1347 1347 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1348 1348 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1349 1349 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1350 1350 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1351 1351 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1352 1352
1353 1353 if ui.verbose:
1354 1354 fm.plain(
1355 1355 b"common heads: %s\n"
1356 1356 % b" ".join(sorted(short(n) for n in heads_common))
1357 1357 )
1358 1358 fm.end()
1359 1359
1360 1360
1361 1361 _chunksize = 4 << 10
1362 1362
1363 1363
1364 1364 @command(
1365 1365 b'debugdownload',
1366 1366 [
1367 1367 (b'o', b'output', b'', _(b'path')),
1368 1368 ],
1369 1369 optionalrepo=True,
1370 1370 )
1371 1371 def debugdownload(ui, repo, url, output=None, **opts):
1372 1372 """download a resource using Mercurial logic and config"""
1373 1373 fh = urlmod.open(ui, url, output)
1374 1374
1375 1375 dest = ui
1376 1376 if output:
1377 1377 dest = open(output, b"wb", _chunksize)
1378 1378 try:
1379 1379 data = fh.read(_chunksize)
1380 1380 while data:
1381 1381 dest.write(data)
1382 1382 data = fh.read(_chunksize)
1383 1383 finally:
1384 1384 if output:
1385 1385 dest.close()
1386 1386
1387 1387
1388 1388 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1389 1389 def debugextensions(ui, repo, **opts):
1390 1390 '''show information about active extensions'''
1391 1391 exts = extensions.extensions(ui)
1392 1392 hgver = util.version()
1393 1393 fm = ui.formatter(b'debugextensions', pycompat.byteskwargs(opts))
1394 1394 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1395 1395 isinternal = extensions.ismoduleinternal(extmod)
1396 1396 extsource = None
1397 1397
1398 1398 if hasattr(extmod, '__file__'):
1399 1399 extsource = pycompat.fsencode(extmod.__file__)
1400 1400 elif getattr(sys, 'oxidized', False):
1401 1401 extsource = pycompat.sysexecutable
1402 1402 if isinternal:
1403 1403 exttestedwith = [] # never expose magic string to users
1404 1404 else:
1405 1405 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1406 1406 extbuglink = getattr(extmod, 'buglink', None)
1407 1407
1408 1408 fm.startitem()
1409 1409
1410 1410 if ui.quiet or ui.verbose:
1411 1411 fm.write(b'name', b'%s\n', extname)
1412 1412 else:
1413 1413 fm.write(b'name', b'%s', extname)
1414 1414 if isinternal or hgver in exttestedwith:
1415 1415 fm.plain(b'\n')
1416 1416 elif not exttestedwith:
1417 1417 fm.plain(_(b' (untested!)\n'))
1418 1418 else:
1419 1419 lasttestedversion = exttestedwith[-1]
1420 1420 fm.plain(b' (%s!)\n' % lasttestedversion)
1421 1421
1422 1422 fm.condwrite(
1423 1423 ui.verbose and extsource,
1424 1424 b'source',
1425 1425 _(b' location: %s\n'),
1426 1426 extsource or b"",
1427 1427 )
1428 1428
1429 1429 if ui.verbose:
1430 1430 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1431 1431 fm.data(bundled=isinternal)
1432 1432
1433 1433 fm.condwrite(
1434 1434 ui.verbose and exttestedwith,
1435 1435 b'testedwith',
1436 1436 _(b' tested with: %s\n'),
1437 1437 fm.formatlist(exttestedwith, name=b'ver'),
1438 1438 )
1439 1439
1440 1440 fm.condwrite(
1441 1441 ui.verbose and extbuglink,
1442 1442 b'buglink',
1443 1443 _(b' bug reporting: %s\n'),
1444 1444 extbuglink or b"",
1445 1445 )
1446 1446
1447 1447 fm.end()
1448 1448
1449 1449
1450 1450 @command(
1451 1451 b'debugfileset',
1452 1452 [
1453 1453 (
1454 1454 b'r',
1455 1455 b'rev',
1456 1456 b'',
1457 1457 _(b'apply the filespec on this revision'),
1458 1458 _(b'REV'),
1459 1459 ),
1460 1460 (
1461 1461 b'',
1462 1462 b'all-files',
1463 1463 False,
1464 1464 _(b'test files from all revisions and working directory'),
1465 1465 ),
1466 1466 (
1467 1467 b's',
1468 1468 b'show-matcher',
1469 1469 None,
1470 1470 _(b'print internal representation of matcher'),
1471 1471 ),
1472 1472 (
1473 1473 b'p',
1474 1474 b'show-stage',
1475 1475 [],
1476 1476 _(b'print parsed tree at the given stage'),
1477 1477 _(b'NAME'),
1478 1478 ),
1479 1479 ],
1480 1480 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1481 1481 )
1482 1482 def debugfileset(ui, repo, expr, **opts):
1483 1483 '''parse and apply a fileset specification'''
1484 1484 from . import fileset
1485 1485
1486 1486 fileset.symbols # force import of fileset so we have predicates to optimize
1487 1487
1488 1488 ctx = logcmdutil.revsingle(repo, opts.get('rev'), None)
1489 1489
1490 1490 stages = [
1491 1491 (b'parsed', pycompat.identity),
1492 1492 (b'analyzed', filesetlang.analyze),
1493 1493 (b'optimized', filesetlang.optimize),
1494 1494 ]
1495 1495 stagenames = {n for n, f in stages}
1496 1496
1497 1497 showalways = set()
1498 1498 if ui.verbose and not opts['show_stage']:
1499 1499 # show parsed tree by --verbose (deprecated)
1500 1500 showalways.add(b'parsed')
1501 1501 if opts['show_stage'] == [b'all']:
1502 1502 showalways.update(stagenames)
1503 1503 else:
1504 1504 for n in opts['show_stage']:
1505 1505 if n not in stagenames:
1506 1506 raise error.Abort(_(b'invalid stage name: %s') % n)
1507 1507 showalways.update(opts['show_stage'])
1508 1508
1509 1509 tree = filesetlang.parse(expr)
1510 1510 for n, f in stages:
1511 1511 tree = f(tree)
1512 1512 if n in showalways:
1513 1513 if opts['show_stage'] or n != b'parsed':
1514 1514 ui.write(b"* %s:\n" % n)
1515 1515 ui.write(filesetlang.prettyformat(tree), b"\n")
1516 1516
1517 1517 files = set()
1518 1518 if opts['all_files']:
1519 1519 for r in repo:
1520 1520 c = repo[r]
1521 1521 files.update(c.files())
1522 1522 files.update(c.substate)
1523 1523 if opts['all_files'] or ctx.rev() is None:
1524 1524 wctx = repo[None]
1525 1525 files.update(
1526 1526 repo.dirstate.walk(
1527 1527 scmutil.matchall(repo),
1528 1528 subrepos=list(wctx.substate),
1529 1529 unknown=True,
1530 1530 ignored=True,
1531 1531 )
1532 1532 )
1533 1533 files.update(wctx.substate)
1534 1534 else:
1535 1535 files.update(ctx.files())
1536 1536 files.update(ctx.substate)
1537 1537
1538 1538 m = ctx.matchfileset(repo.getcwd(), expr)
1539 1539 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
1540 1540 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1541 1541 for f in sorted(files):
1542 1542 if not m(f):
1543 1543 continue
1544 1544 ui.write(b"%s\n" % f)
1545 1545
1546 1546
1547 1547 @command(
1548 1548 b"debug-repair-issue6528",
1549 1549 [
1550 1550 (
1551 1551 b'',
1552 1552 b'to-report',
1553 1553 b'',
1554 1554 _(b'build a report of affected revisions to this file'),
1555 1555 _(b'FILE'),
1556 1556 ),
1557 1557 (
1558 1558 b'',
1559 1559 b'from-report',
1560 1560 b'',
1561 1561 _(b'repair revisions listed in this report file'),
1562 1562 _(b'FILE'),
1563 1563 ),
1564 1564 (
1565 1565 b'',
1566 1566 b'paranoid',
1567 1567 False,
1568 1568 _(b'check that both detection methods do the same thing'),
1569 1569 ),
1570 1570 ]
1571 1571 + cmdutil.dryrunopts,
1572 1572 )
1573 1573 def debug_repair_issue6528(ui, repo, **opts):
1574 1574 """find affected revisions and repair them. See issue6528 for more details.
1575 1575
1576 1576 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1577 1577 computation of affected revisions for a given repository across clones.
1578 1578 The report format is line-based (with empty lines ignored):
1579 1579
1580 1580 ```
1581 1581 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1582 1582 ```
1583 1583
1584 1584 There can be multiple broken revisions per filelog, they are separated by
1585 1585 a comma with no spaces. The only space is between the revision(s) and the
1586 1586 filename.
1587 1587
1588 1588 Note that this does *not* mean that this repairs future affected revisions,
1589 1589 that needs a separate fix at the exchange level that was introduced in
1590 1590 Mercurial 5.9.1.
1591 1591
1592 1592 There is a `--paranoid` flag to test that the fast implementation is correct
1593 1593 by checking it against the slow implementation. Since this matter is quite
1594 1594 urgent and testing every edge-case is probably quite costly, we use this
1595 1595 method to test on large repositories as a fuzzing method of sorts.
1596 1596 """
1597 1597 cmdutil.check_incompatible_arguments(
1598 1598 opts, 'to_report', ['from_report', 'dry_run']
1599 1599 )
1600 1600 dry_run = opts.get('dry_run')
1601 1601 to_report = opts.get('to_report')
1602 1602 from_report = opts.get('from_report')
1603 1603 paranoid = opts.get('paranoid')
1604 1604 # TODO maybe add filelog pattern and revision pattern parameters to help
1605 1605 # narrow down the search for users that know what they're looking for?
1606 1606
1607 1607 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1608 1608 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1609 1609 raise error.Abort(_(msg))
1610 1610
1611 1611 rewrite.repair_issue6528(
1612 1612 ui,
1613 1613 repo,
1614 1614 dry_run=dry_run,
1615 1615 to_report=to_report,
1616 1616 from_report=from_report,
1617 1617 paranoid=paranoid,
1618 1618 )
1619 1619
1620 1620
1621 1621 @command(b'debugformat', [] + cmdutil.formatteropts)
1622 1622 def debugformat(ui, repo, **opts):
1623 1623 """display format information about the current repository
1624 1624
1625 1625 Use --verbose to get extra information about current config value and
1626 1626 Mercurial default."""
1627 1627 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1628 1628 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1629 1629
1630 1630 def makeformatname(name):
1631 1631 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1632 1632
1633 1633 fm = ui.formatter(b'debugformat', pycompat.byteskwargs(opts))
1634 1634 if fm.isplain():
1635 1635
1636 1636 def formatvalue(value):
1637 1637 if hasattr(value, 'startswith'):
1638 1638 return value
1639 1639 if value:
1640 1640 return b'yes'
1641 1641 else:
1642 1642 return b'no'
1643 1643
1644 1644 else:
1645 1645 formatvalue = pycompat.identity
1646 1646
1647 1647 fm.plain(b'format-variant')
1648 1648 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1649 1649 fm.plain(b' repo')
1650 1650 if ui.verbose:
1651 1651 fm.plain(b' config default')
1652 1652 fm.plain(b'\n')
1653 1653 for fv in upgrade.allformatvariant:
1654 1654 fm.startitem()
1655 1655 repovalue = fv.fromrepo(repo)
1656 1656 configvalue = fv.fromconfig(repo)
1657 1657
1658 1658 if repovalue != configvalue:
1659 1659 namelabel = b'formatvariant.name.mismatchconfig'
1660 1660 repolabel = b'formatvariant.repo.mismatchconfig'
1661 1661 elif repovalue != fv.default:
1662 1662 namelabel = b'formatvariant.name.mismatchdefault'
1663 1663 repolabel = b'formatvariant.repo.mismatchdefault'
1664 1664 else:
1665 1665 namelabel = b'formatvariant.name.uptodate'
1666 1666 repolabel = b'formatvariant.repo.uptodate'
1667 1667
1668 1668 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1669 1669 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1670 1670 if fv.default != configvalue:
1671 1671 configlabel = b'formatvariant.config.special'
1672 1672 else:
1673 1673 configlabel = b'formatvariant.config.default'
1674 1674 fm.condwrite(
1675 1675 ui.verbose,
1676 1676 b'config',
1677 1677 b' %6s',
1678 1678 formatvalue(configvalue),
1679 1679 label=configlabel,
1680 1680 )
1681 1681 fm.condwrite(
1682 1682 ui.verbose,
1683 1683 b'default',
1684 1684 b' %7s',
1685 1685 formatvalue(fv.default),
1686 1686 label=b'formatvariant.default',
1687 1687 )
1688 1688 fm.plain(b'\n')
1689 1689 fm.end()
1690 1690
1691 1691
1692 1692 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1693 1693 def debugfsinfo(ui, path=b"."):
1694 1694 """show information detected about current filesystem"""
1695 1695 ui.writenoi18n(b'path: %s\n' % path)
1696 1696 ui.writenoi18n(
1697 1697 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1698 1698 )
1699 1699 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1700 1700 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1701 1701 ui.writenoi18n(
1702 1702 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1703 1703 )
1704 1704 ui.writenoi18n(
1705 1705 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1706 1706 )
1707 1707 casesensitive = b'(unknown)'
1708 1708 try:
1709 1709 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1710 1710 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1711 1711 except OSError:
1712 1712 pass
1713 1713 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1714 1714
1715 1715
1716 1716 @command(
1717 1717 b'debuggetbundle',
1718 1718 [
1719 1719 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1720 1720 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1721 1721 (
1722 1722 b't',
1723 1723 b'type',
1724 1724 b'bzip2',
1725 1725 _(b'bundle compression type to use'),
1726 1726 _(b'TYPE'),
1727 1727 ),
1728 1728 ],
1729 1729 _(b'REPO FILE [-H|-C ID]...'),
1730 1730 norepo=True,
1731 1731 )
1732 1732 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1733 1733 """retrieves a bundle from a repo
1734 1734
1735 1735 Every ID must be a full-length hex node id string. Saves the bundle to the
1736 1736 given file.
1737 1737 """
1738 1738 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
1739 1739 if not repo.capable(b'getbundle'):
1740 1740 raise error.Abort(b"getbundle() not supported by target repository")
1741 1741 args = {}
1742 1742 if common:
1743 1743 args['common'] = [bin(s) for s in common]
1744 1744 if head:
1745 1745 args['heads'] = [bin(s) for s in head]
1746 1746 # TODO: get desired bundlecaps from command line.
1747 1747 args['bundlecaps'] = None
1748 1748 bundle = repo.getbundle(b'debug', **args)
1749 1749
1750 1750 bundletype = opts.get('type', b'bzip2').lower()
1751 1751 btypes = {
1752 1752 b'none': b'HG10UN',
1753 1753 b'bzip2': b'HG10BZ',
1754 1754 b'gzip': b'HG10GZ',
1755 1755 b'bundle2': b'HG20',
1756 1756 }
1757 1757 bundletype = btypes.get(bundletype)
1758 1758 if bundletype not in bundle2.bundletypes:
1759 1759 raise error.Abort(_(b'unknown bundle type specified with --type'))
1760 1760 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1761 1761
1762 1762
1763 1763 @command(b'debugignore', [], b'[FILE]...')
1764 1764 def debugignore(ui, repo, *files, **opts):
1765 1765 """display the combined ignore pattern and information about ignored files
1766 1766
1767 1767 With no argument display the combined ignore pattern.
1768 1768
1769 1769 Given space separated file names, shows if the given file is ignored and
1770 1770 if so, show the ignore rule (file and line number) that matched it.
1771 1771 """
1772 1772 ignore = repo.dirstate._ignore
1773 1773 if not files:
1774 1774 # Show all the patterns
1775 1775 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1776 1776 else:
1777 1777 m = scmutil.match(repo[None], pats=files)
1778 1778 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1779 1779 for f in m.files():
1780 1780 nf = util.normpath(f)
1781 1781 ignored = None
1782 1782 ignoredata = None
1783 1783 if nf != b'.':
1784 1784 if ignore(nf):
1785 1785 ignored = nf
1786 1786 ignoredata = repo.dirstate._ignorefileandline(nf)
1787 1787 else:
1788 1788 for p in pathutil.finddirs(nf):
1789 1789 if ignore(p):
1790 1790 ignored = p
1791 1791 ignoredata = repo.dirstate._ignorefileandline(p)
1792 1792 break
1793 1793 if ignored:
1794 1794 if ignored == nf:
1795 1795 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1796 1796 else:
1797 1797 ui.write(
1798 1798 _(
1799 1799 b"%s is ignored because of "
1800 1800 b"containing directory %s\n"
1801 1801 )
1802 1802 % (uipathfn(f), ignored)
1803 1803 )
1804 1804 ignorefile, lineno, line = ignoredata
1805 1805 ui.write(
1806 1806 _(b"(ignore rule in %s, line %d: '%s')\n")
1807 1807 % (ignorefile, lineno, line)
1808 1808 )
1809 1809 else:
1810 1810 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1811 1811
1812 1812
1813 1813 @command(
1814 1814 b'debug-revlog-index|debugindex',
1815 1815 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1816 1816 _(b'-c|-m|FILE'),
1817 1817 )
1818 1818 def debugindex(ui, repo, file_=None, **opts):
1819 1819 """dump index data for a revlog"""
1820 1820 opts = pycompat.byteskwargs(opts)
1821 1821 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1822 1822
1823 1823 fm = ui.formatter(b'debugindex', opts)
1824 1824
1825 1825 revlog = getattr(store, '_revlog', store)
1826 1826
1827 1827 return revlog_debug.debug_index(
1828 1828 ui,
1829 1829 repo,
1830 1830 formatter=fm,
1831 1831 revlog=revlog,
1832 1832 full_node=ui.debugflag,
1833 1833 )
1834 1834
1835 1835
1836 1836 @command(
1837 1837 b'debugindexdot',
1838 1838 cmdutil.debugrevlogopts,
1839 1839 _(b'-c|-m|FILE'),
1840 1840 optionalrepo=True,
1841 1841 )
1842 1842 def debugindexdot(ui, repo, file_=None, **opts):
1843 1843 """dump an index DAG as a graphviz dot file"""
1844 1844 r = cmdutil.openstorage(
1845 1845 repo, b'debugindexdot', file_, pycompat.byteskwargs(opts)
1846 1846 )
1847 1847 ui.writenoi18n(b"digraph G {\n")
1848 1848 for i in r:
1849 1849 node = r.node(i)
1850 1850 pp = r.parents(node)
1851 1851 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1852 1852 if pp[1] != repo.nullid:
1853 1853 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1854 1854 ui.write(b"}\n")
1855 1855
1856 1856
1857 1857 @command(b'debugindexstats', [])
1858 1858 def debugindexstats(ui, repo):
1859 1859 """show stats related to the changelog index"""
1860 1860 repo.changelog.shortest(repo.nullid, 1)
1861 1861 index = repo.changelog.index
1862 1862 if not hasattr(index, 'stats'):
1863 1863 raise error.Abort(_(b'debugindexstats only works with native code'))
1864 1864 for k, v in sorted(index.stats().items()):
1865 1865 ui.write(b'%s: %d\n' % (k, v))
1866 1866
1867 1867
1868 1868 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1869 1869 def debuginstall(ui, **opts):
1870 1870 """test Mercurial installation
1871 1871
1872 1872 Returns 0 on success.
1873 1873 """
1874 1874 problems = 0
1875 1875
1876 1876 fm = ui.formatter(b'debuginstall', pycompat.byteskwargs(opts))
1877 1877 fm.startitem()
1878 1878
1879 1879 # encoding might be unknown or wrong. don't translate these messages.
1880 1880 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1881 1881 err = None
1882 1882 try:
1883 1883 codecs.lookup(pycompat.sysstr(encoding.encoding))
1884 1884 except LookupError as inst:
1885 1885 err = stringutil.forcebytestr(inst)
1886 1886 problems += 1
1887 1887 fm.condwrite(
1888 1888 err,
1889 1889 b'encodingerror',
1890 1890 b" %s\n (check that your locale is properly set)\n",
1891 1891 err,
1892 1892 )
1893 1893
1894 1894 # Python
1895 1895 pythonlib = None
1896 1896 if hasattr(os, '__file__'):
1897 1897 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1898 1898 elif getattr(sys, 'oxidized', False):
1899 1899 pythonlib = pycompat.sysexecutable
1900 1900
1901 1901 fm.write(
1902 1902 b'pythonexe',
1903 1903 _(b"checking Python executable (%s)\n"),
1904 1904 pycompat.sysexecutable or _(b"unknown"),
1905 1905 )
1906 1906 fm.write(
1907 1907 b'pythonimplementation',
1908 1908 _(b"checking Python implementation (%s)\n"),
1909 1909 pycompat.sysbytes(platform.python_implementation()),
1910 1910 )
1911 1911 fm.write(
1912 1912 b'pythonver',
1913 1913 _(b"checking Python version (%s)\n"),
1914 1914 (b"%d.%d.%d" % sys.version_info[:3]),
1915 1915 )
1916 1916 fm.write(
1917 1917 b'pythonlib',
1918 1918 _(b"checking Python lib (%s)...\n"),
1919 1919 pythonlib or _(b"unknown"),
1920 1920 )
1921 1921
1922 1922 try:
1923 1923 from . import rustext # pytype: disable=import-error
1924 1924
1925 1925 rustext.__doc__ # trigger lazy import
1926 1926 except ImportError:
1927 1927 rustext = None
1928 1928
1929 1929 security = set(sslutil.supportedprotocols)
1930 1930 if sslutil.hassni:
1931 1931 security.add(b'sni')
1932 1932
1933 1933 fm.write(
1934 1934 b'pythonsecurity',
1935 1935 _(b"checking Python security support (%s)\n"),
1936 1936 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
1937 1937 )
1938 1938
1939 1939 # These are warnings, not errors. So don't increment problem count. This
1940 1940 # may change in the future.
1941 1941 if b'tls1.2' not in security:
1942 1942 fm.plain(
1943 1943 _(
1944 1944 b' TLS 1.2 not supported by Python install; '
1945 1945 b'network connections lack modern security\n'
1946 1946 )
1947 1947 )
1948 1948 if b'sni' not in security:
1949 1949 fm.plain(
1950 1950 _(
1951 1951 b' SNI not supported by Python install; may have '
1952 1952 b'connectivity issues with some servers\n'
1953 1953 )
1954 1954 )
1955 1955
1956 1956 fm.plain(
1957 1957 _(
1958 1958 b"checking Rust extensions (%s)\n"
1959 1959 % (b'missing' if rustext is None else b'installed')
1960 1960 ),
1961 1961 )
1962 1962
1963 1963 # TODO print CA cert info
1964 1964
1965 1965 # hg version
1966 1966 hgver = util.version()
1967 1967 fm.write(
1968 1968 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
1969 1969 )
1970 1970 fm.write(
1971 1971 b'hgverextra',
1972 1972 _(b"checking Mercurial custom build (%s)\n"),
1973 1973 b'+'.join(hgver.split(b'+')[1:]),
1974 1974 )
1975 1975
1976 1976 # compiled modules
1977 1977 hgmodules = None
1978 1978 if hasattr(sys.modules[__name__], '__file__'):
1979 1979 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
1980 1980 elif getattr(sys, 'oxidized', False):
1981 1981 hgmodules = pycompat.sysexecutable
1982 1982
1983 1983 fm.write(
1984 1984 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
1985 1985 )
1986 1986 fm.write(
1987 1987 b'hgmodules',
1988 1988 _(b"checking installed modules (%s)...\n"),
1989 1989 hgmodules or _(b"unknown"),
1990 1990 )
1991 1991
1992 1992 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
1993 1993 rustext = rustandc # for now, that's the only case
1994 1994 cext = policy.policy in (b'c', b'allow') or rustandc
1995 1995 nopure = cext or rustext
1996 1996 if nopure:
1997 1997 err = None
1998 1998 try:
1999 1999 if cext:
2000 2000 from .cext import ( # pytype: disable=import-error
2001 2001 base85,
2002 2002 bdiff,
2003 2003 mpatch,
2004 2004 osutil,
2005 2005 )
2006 2006
2007 2007 # quiet pyflakes
2008 2008 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2009 2009 if rustext:
2010 2010 from .rustext import ( # pytype: disable=import-error
2011 2011 ancestor,
2012 2012 dirstate,
2013 2013 )
2014 2014
2015 2015 dir(ancestor), dir(dirstate) # quiet pyflakes
2016 2016 except Exception as inst:
2017 2017 err = stringutil.forcebytestr(inst)
2018 2018 problems += 1
2019 2019 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2020 2020
2021 2021 compengines = util.compengines._engines.values()
2022 2022 fm.write(
2023 2023 b'compengines',
2024 2024 _(b'checking registered compression engines (%s)\n'),
2025 2025 fm.formatlist(
2026 2026 sorted(e.name() for e in compengines),
2027 2027 name=b'compengine',
2028 2028 fmt=b'%s',
2029 2029 sep=b', ',
2030 2030 ),
2031 2031 )
2032 2032 fm.write(
2033 2033 b'compenginesavail',
2034 2034 _(b'checking available compression engines (%s)\n'),
2035 2035 fm.formatlist(
2036 2036 sorted(e.name() for e in compengines if e.available()),
2037 2037 name=b'compengine',
2038 2038 fmt=b'%s',
2039 2039 sep=b', ',
2040 2040 ),
2041 2041 )
2042 2042 wirecompengines = compression.compengines.supportedwireengines(
2043 2043 compression.SERVERROLE
2044 2044 )
2045 2045 fm.write(
2046 2046 b'compenginesserver',
2047 2047 _(
2048 2048 b'checking available compression engines '
2049 2049 b'for wire protocol (%s)\n'
2050 2050 ),
2051 2051 fm.formatlist(
2052 2052 [e.name() for e in wirecompengines if e.wireprotosupport()],
2053 2053 name=b'compengine',
2054 2054 fmt=b'%s',
2055 2055 sep=b', ',
2056 2056 ),
2057 2057 )
2058 2058 re2 = b'missing'
2059 2059 if util.has_re2():
2060 2060 re2 = b'available'
2061 2061 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2062 2062 fm.data(re2=bool(util._re2))
2063 2063
2064 2064 # templates
2065 2065 p = templater.templatedir()
2066 2066 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2067 2067 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2068 2068 if p:
2069 2069 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2070 2070 if m:
2071 2071 # template found, check if it is working
2072 2072 err = None
2073 2073 try:
2074 2074 templater.templater.frommapfile(m)
2075 2075 except Exception as inst:
2076 2076 err = stringutil.forcebytestr(inst)
2077 2077 p = None
2078 2078 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2079 2079 else:
2080 2080 p = None
2081 2081 fm.condwrite(
2082 2082 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2083 2083 )
2084 2084 fm.condwrite(
2085 2085 not m,
2086 2086 b'defaulttemplatenotfound',
2087 2087 _(b" template '%s' not found\n"),
2088 2088 b"default",
2089 2089 )
2090 2090 if not p:
2091 2091 problems += 1
2092 2092 fm.condwrite(
2093 2093 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2094 2094 )
2095 2095
2096 2096 # editor
2097 2097 editor = ui.geteditor()
2098 2098 editor = util.expandpath(editor)
2099 2099 editorbin = procutil.shellsplit(editor)[0]
2100 2100 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2101 2101 cmdpath = procutil.findexe(editorbin)
2102 2102 fm.condwrite(
2103 2103 not cmdpath and editor == b'vi',
2104 2104 b'vinotfound',
2105 2105 _(
2106 2106 b" No commit editor set and can't find %s in PATH\n"
2107 2107 b" (specify a commit editor in your configuration"
2108 2108 b" file)\n"
2109 2109 ),
2110 2110 not cmdpath and editor == b'vi' and editorbin,
2111 2111 )
2112 2112 fm.condwrite(
2113 2113 not cmdpath and editor != b'vi',
2114 2114 b'editornotfound',
2115 2115 _(
2116 2116 b" Can't find editor '%s' in PATH\n"
2117 2117 b" (specify a commit editor in your configuration"
2118 2118 b" file)\n"
2119 2119 ),
2120 2120 not cmdpath and editorbin,
2121 2121 )
2122 2122 if not cmdpath and editor != b'vi':
2123 2123 problems += 1
2124 2124
2125 2125 # check username
2126 2126 username = None
2127 2127 err = None
2128 2128 try:
2129 2129 username = ui.username()
2130 2130 except error.Abort as e:
2131 2131 err = e.message
2132 2132 problems += 1
2133 2133
2134 2134 fm.condwrite(
2135 2135 username, b'username', _(b"checking username (%s)\n"), username
2136 2136 )
2137 2137 fm.condwrite(
2138 2138 err,
2139 2139 b'usernameerror',
2140 2140 _(
2141 2141 b"checking username...\n %s\n"
2142 2142 b" (specify a username in your configuration file)\n"
2143 2143 ),
2144 2144 err,
2145 2145 )
2146 2146
2147 2147 for name, mod in extensions.extensions():
2148 2148 handler = getattr(mod, 'debuginstall', None)
2149 2149 if handler is not None:
2150 2150 problems += handler(ui, fm)
2151 2151
2152 2152 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2153 2153 if not problems:
2154 2154 fm.data(problems=problems)
2155 2155 fm.condwrite(
2156 2156 problems,
2157 2157 b'problems',
2158 2158 _(b"%d problems detected, please check your install!\n"),
2159 2159 problems,
2160 2160 )
2161 2161 fm.end()
2162 2162
2163 2163 return problems
2164 2164
2165 2165
2166 2166 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2167 2167 def debugknown(ui, repopath, *ids, **opts):
2168 2168 """test whether node ids are known to a repo
2169 2169
2170 2170 Every ID must be a full-length hex node id string. Returns a list of 0s
2171 2171 and 1s indicating unknown/known.
2172 2172 """
2173 2173 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
2174 2174 if not repo.capable(b'known'):
2175 2175 raise error.Abort(b"known() not supported by target repository")
2176 2176 flags = repo.known([bin(s) for s in ids])
2177 2177 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2178 2178
2179 2179
2180 2180 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2181 2181 def debuglabelcomplete(ui, repo, *args):
2182 2182 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2183 2183 debugnamecomplete(ui, repo, *args)
2184 2184
2185 2185
2186 2186 @command(
2187 2187 b'debuglocks',
2188 2188 [
2189 2189 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2190 2190 (
2191 2191 b'W',
2192 2192 b'force-free-wlock',
2193 2193 None,
2194 2194 _(b'free the working state lock (DANGEROUS)'),
2195 2195 ),
2196 2196 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2197 2197 (
2198 2198 b'S',
2199 2199 b'set-wlock',
2200 2200 None,
2201 2201 _(b'set the working state lock until stopped'),
2202 2202 ),
2203 2203 ],
2204 2204 _(b'[OPTION]...'),
2205 2205 )
2206 2206 def debuglocks(ui, repo, **opts):
2207 2207 """show or modify state of locks
2208 2208
2209 2209 By default, this command will show which locks are held. This
2210 2210 includes the user and process holding the lock, the amount of time
2211 2211 the lock has been held, and the machine name where the process is
2212 2212 running if it's not local.
2213 2213
2214 2214 Locks protect the integrity of Mercurial's data, so should be
2215 2215 treated with care. System crashes or other interruptions may cause
2216 2216 locks to not be properly released, though Mercurial will usually
2217 2217 detect and remove such stale locks automatically.
2218 2218
2219 2219 However, detecting stale locks may not always be possible (for
2220 2220 instance, on a shared filesystem). Removing locks may also be
2221 2221 blocked by filesystem permissions.
2222 2222
2223 2223 Setting a lock will prevent other commands from changing the data.
2224 2224 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2225 2225 The set locks are removed when the command exits.
2226 2226
2227 2227 Returns 0 if no locks are held.
2228 2228
2229 2229 """
2230 2230
2231 2231 if opts.get('force_free_lock'):
2232 2232 repo.svfs.tryunlink(b'lock')
2233 2233 if opts.get('force_free_wlock'):
2234 2234 repo.vfs.tryunlink(b'wlock')
2235 2235 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2236 2236 return 0
2237 2237
2238 2238 locks = []
2239 2239 try:
2240 2240 if opts.get('set_wlock'):
2241 2241 try:
2242 2242 locks.append(repo.wlock(False))
2243 2243 except error.LockHeld:
2244 2244 raise error.Abort(_(b'wlock is already held'))
2245 2245 if opts.get('set_lock'):
2246 2246 try:
2247 2247 locks.append(repo.lock(False))
2248 2248 except error.LockHeld:
2249 2249 raise error.Abort(_(b'lock is already held'))
2250 2250 if len(locks):
2251 2251 try:
2252 2252 if ui.interactive():
2253 2253 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2254 2254 ui.promptchoice(prompt)
2255 2255 else:
2256 2256 msg = b"%d locks held, waiting for signal\n"
2257 2257 msg %= len(locks)
2258 2258 ui.status(msg)
2259 2259 while True: # XXX wait for a signal
2260 2260 time.sleep(0.1)
2261 2261 except KeyboardInterrupt:
2262 2262 msg = b"signal-received releasing locks\n"
2263 2263 ui.status(msg)
2264 2264 return 0
2265 2265 finally:
2266 2266 release(*locks)
2267 2267
2268 2268 now = time.time()
2269 2269 held = 0
2270 2270
2271 2271 def report(vfs, name, method):
2272 2272 # this causes stale locks to get reaped for more accurate reporting
2273 2273 try:
2274 2274 l = method(False)
2275 2275 except error.LockHeld:
2276 2276 l = None
2277 2277
2278 2278 if l:
2279 2279 l.release()
2280 2280 else:
2281 2281 try:
2282 2282 st = vfs.lstat(name)
2283 2283 age = now - st[stat.ST_MTIME]
2284 2284 user = util.username(st.st_uid)
2285 2285 locker = vfs.readlock(name)
2286 2286 if b":" in locker:
2287 2287 host, pid = locker.split(b':')
2288 2288 if host == socket.gethostname():
2289 2289 locker = b'user %s, process %s' % (user or b'None', pid)
2290 2290 else:
2291 2291 locker = b'user %s, process %s, host %s' % (
2292 2292 user or b'None',
2293 2293 pid,
2294 2294 host,
2295 2295 )
2296 2296 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2297 2297 return 1
2298 2298 except FileNotFoundError:
2299 2299 pass
2300 2300
2301 2301 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2302 2302 return 0
2303 2303
2304 2304 held += report(repo.svfs, b"lock", repo.lock)
2305 2305 held += report(repo.vfs, b"wlock", repo.wlock)
2306 2306
2307 2307 return held
2308 2308
2309 2309
2310 2310 @command(
2311 2311 b'debugmanifestfulltextcache',
2312 2312 [
2313 2313 (b'', b'clear', False, _(b'clear the cache')),
2314 2314 (
2315 2315 b'a',
2316 2316 b'add',
2317 2317 [],
2318 2318 _(b'add the given manifest nodes to the cache'),
2319 2319 _(b'NODE'),
2320 2320 ),
2321 2321 ],
2322 2322 b'',
2323 2323 )
2324 2324 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2325 2325 """show, clear or amend the contents of the manifest fulltext cache"""
2326 2326
2327 2327 def getcache():
2328 2328 r = repo.manifestlog.getstorage(b'')
2329 2329 try:
2330 2330 return r._fulltextcache
2331 2331 except AttributeError:
2332 2332 msg = _(
2333 2333 b"Current revlog implementation doesn't appear to have a "
2334 2334 b"manifest fulltext cache\n"
2335 2335 )
2336 2336 raise error.Abort(msg)
2337 2337
2338 2338 if opts.get('clear'):
2339 2339 with repo.wlock():
2340 2340 cache = getcache()
2341 2341 cache.clear(clear_persisted_data=True)
2342 2342 return
2343 2343
2344 2344 if add:
2345 2345 with repo.wlock():
2346 2346 m = repo.manifestlog
2347 2347 store = m.getstorage(b'')
2348 2348 for n in add:
2349 2349 try:
2350 2350 manifest = m[store.lookup(n)]
2351 2351 except error.LookupError as e:
2352 2352 raise error.Abort(
2353 2353 bytes(e), hint=b"Check your manifest node id"
2354 2354 )
2355 2355 manifest.read() # stores revisision in cache too
2356 2356 return
2357 2357
2358 2358 cache = getcache()
2359 2359 if not len(cache):
2360 2360 ui.write(_(b'cache empty\n'))
2361 2361 else:
2362 2362 ui.write(
2363 2363 _(
2364 2364 b'cache contains %d manifest entries, in order of most to '
2365 2365 b'least recent:\n'
2366 2366 )
2367 2367 % (len(cache),)
2368 2368 )
2369 2369 totalsize = 0
2370 2370 for nodeid in cache:
2371 2371 # Use cache.get to not update the LRU order
2372 2372 data = cache.peek(nodeid)
2373 2373 size = len(data)
2374 2374 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2375 2375 ui.write(
2376 2376 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2377 2377 )
2378 2378 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2379 2379 ui.write(
2380 2380 _(b'total cache data size %s, on-disk %s\n')
2381 2381 % (util.bytecount(totalsize), util.bytecount(ondisk))
2382 2382 )
2383 2383
2384 2384
2385 2385 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2386 2386 def debugmergestate(ui, repo, *args, **opts):
2387 2387 """print merge state
2388 2388
2389 2389 Use --verbose to print out information about whether v1 or v2 merge state
2390 2390 was chosen."""
2391 2391
2392 2392 if ui.verbose:
2393 2393 ms = mergestatemod.mergestate(repo)
2394 2394
2395 2395 # sort so that reasonable information is on top
2396 2396 v1records = ms._readrecordsv1()
2397 2397 v2records = ms._readrecordsv2()
2398 2398
2399 2399 if not v1records and not v2records:
2400 2400 pass
2401 2401 elif not v2records:
2402 2402 ui.writenoi18n(b'no version 2 merge state\n')
2403 2403 elif ms._v1v2match(v1records, v2records):
2404 2404 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2405 2405 else:
2406 2406 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2407 2407
2408 2408 if not opts['template']:
2409 2409 opts['template'] = (
2410 2410 b'{if(commits, "", "no merge state found\n")}'
2411 2411 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2412 2412 b'{files % "file: {path} (state \\"{state}\\")\n'
2413 2413 b'{if(local_path, "'
2414 2414 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2415 2415 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2416 2416 b' other path: {other_path} (node {other_node})\n'
2417 2417 b'")}'
2418 2418 b'{if(rename_side, "'
2419 2419 b' rename side: {rename_side}\n'
2420 2420 b' renamed path: {renamed_path}\n'
2421 2421 b'")}'
2422 2422 b'{extras % " extra: {key} = {value}\n"}'
2423 2423 b'"}'
2424 2424 b'{extras % "extra: {file} ({key} = {value})\n"}'
2425 2425 )
2426 2426
2427 2427 ms = mergestatemod.mergestate.read(repo)
2428 2428
2429 2429 fm = ui.formatter(b'debugmergestate', pycompat.byteskwargs(opts))
2430 2430 fm.startitem()
2431 2431
2432 2432 fm_commits = fm.nested(b'commits')
2433 2433 if ms.active():
2434 2434 for name, node, label_index in (
2435 2435 (b'local', ms.local, 0),
2436 2436 (b'other', ms.other, 1),
2437 2437 ):
2438 2438 fm_commits.startitem()
2439 2439 fm_commits.data(name=name)
2440 2440 fm_commits.data(node=hex(node))
2441 2441 if ms._labels and len(ms._labels) > label_index:
2442 2442 fm_commits.data(label=ms._labels[label_index])
2443 2443 fm_commits.end()
2444 2444
2445 2445 fm_files = fm.nested(b'files')
2446 2446 if ms.active():
2447 2447 for f in ms:
2448 2448 fm_files.startitem()
2449 2449 fm_files.data(path=f)
2450 2450 state = ms._state[f]
2451 2451 fm_files.data(state=state[0])
2452 2452 if state[0] in (
2453 2453 mergestatemod.MERGE_RECORD_UNRESOLVED,
2454 2454 mergestatemod.MERGE_RECORD_RESOLVED,
2455 2455 ):
2456 2456 fm_files.data(local_key=state[1])
2457 2457 fm_files.data(local_path=state[2])
2458 2458 fm_files.data(ancestor_path=state[3])
2459 2459 fm_files.data(ancestor_node=state[4])
2460 2460 fm_files.data(other_path=state[5])
2461 2461 fm_files.data(other_node=state[6])
2462 2462 fm_files.data(local_flags=state[7])
2463 2463 elif state[0] in (
2464 2464 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2465 2465 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2466 2466 ):
2467 2467 fm_files.data(renamed_path=state[1])
2468 2468 fm_files.data(rename_side=state[2])
2469 2469 fm_extras = fm_files.nested(b'extras')
2470 2470 for k, v in sorted(ms.extras(f).items()):
2471 2471 fm_extras.startitem()
2472 2472 fm_extras.data(key=k)
2473 2473 fm_extras.data(value=v)
2474 2474 fm_extras.end()
2475 2475
2476 2476 fm_files.end()
2477 2477
2478 2478 fm_extras = fm.nested(b'extras')
2479 2479 for f, d in sorted(ms.allextras().items()):
2480 2480 if f in ms:
2481 2481 # If file is in mergestate, we have already processed it's extras
2482 2482 continue
2483 2483 for k, v in d.items():
2484 2484 fm_extras.startitem()
2485 2485 fm_extras.data(file=f)
2486 2486 fm_extras.data(key=k)
2487 2487 fm_extras.data(value=v)
2488 2488 fm_extras.end()
2489 2489
2490 2490 fm.end()
2491 2491
2492 2492
2493 2493 @command(b'debugnamecomplete', [], _(b'NAME...'))
2494 2494 def debugnamecomplete(ui, repo, *args):
2495 2495 '''complete "names" - tags, open branch names, bookmark names'''
2496 2496
2497 2497 names = set()
2498 2498 # since we previously only listed open branches, we will handle that
2499 2499 # specially (after this for loop)
2500 2500 for name, ns in repo.names.items():
2501 2501 if name != b'branches':
2502 2502 names.update(ns.listnames(repo))
2503 2503 names.update(
2504 2504 tag
2505 2505 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2506 2506 if not closed
2507 2507 )
2508 2508 completions = set()
2509 2509 if not args:
2510 2510 args = [b'']
2511 2511 for a in args:
2512 2512 completions.update(n for n in names if n.startswith(a))
2513 2513 ui.write(b'\n'.join(sorted(completions)))
2514 2514 ui.write(b'\n')
2515 2515
2516 2516
2517 2517 @command(
2518 2518 b'debugnodemap',
2519 2519 (
2520 2520 cmdutil.debugrevlogopts
2521 2521 + [
2522 2522 (
2523 2523 b'',
2524 2524 b'dump-new',
2525 2525 False,
2526 2526 _(b'write a (new) persistent binary nodemap on stdout'),
2527 2527 ),
2528 2528 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2529 2529 (
2530 2530 b'',
2531 2531 b'check',
2532 2532 False,
2533 2533 _(b'check that the data on disk data are correct.'),
2534 2534 ),
2535 2535 (
2536 2536 b'',
2537 2537 b'metadata',
2538 2538 False,
2539 2539 _(b'display the on disk meta data for the nodemap'),
2540 2540 ),
2541 2541 ]
2542 2542 ),
2543 2543 _(b'-c|-m|FILE'),
2544 2544 )
2545 2545 def debugnodemap(ui, repo, file_=None, **opts):
2546 2546 """write and inspect on disk nodemap"""
2547 2547 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
2548 2548 if file_ is not None:
2549 2549 raise error.InputError(
2550 2550 _(b'cannot specify a file with other arguments')
2551 2551 )
2552 2552 elif file_ is None:
2553 2553 opts['changelog'] = True
2554 2554 r = cmdutil.openstorage(
2555 2555 repo.unfiltered(), b'debugnodemap', file_, pycompat.byteskwargs(opts)
2556 2556 )
2557 2557 if isinstance(r, (manifest.manifestrevlog, filelog.filelog)):
2558 2558 r = r._revlog
2559 2559 if opts['dump_new']:
2560 2560 if hasattr(r.index, "nodemap_data_all"):
2561 2561 data = r.index.nodemap_data_all()
2562 2562 else:
2563 2563 data = nodemap.persistent_data(r.index)
2564 2564 ui.write(data)
2565 2565 elif opts['dump_disk']:
2566 2566 nm_data = nodemap.persisted_data(r)
2567 2567 if nm_data is not None:
2568 2568 docket, data = nm_data
2569 2569 ui.write(data[:])
2570 2570 elif opts['check']:
2571 2571 nm_data = nodemap.persisted_data(r)
2572 2572 if nm_data is not None:
2573 2573 docket, data = nm_data
2574 2574 return nodemap.check_data(ui, r.index, data)
2575 2575 elif opts['metadata']:
2576 2576 nm_data = nodemap.persisted_data(r)
2577 2577 if nm_data is not None:
2578 2578 docket, data = nm_data
2579 2579 ui.write((b"uid: %s\n") % docket.uid)
2580 2580 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2581 2581 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2582 2582 ui.write((b"data-length: %d\n") % docket.data_length)
2583 2583 ui.write((b"data-unused: %d\n") % docket.data_unused)
2584 2584 unused_perc = docket.data_unused * 100.0 / docket.data_length
2585 2585 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2586 2586
2587 2587
2588 2588 @command(
2589 2589 b'debugobsolete',
2590 2590 [
2591 2591 (b'', b'flags', 0, _(b'markers flag')),
2592 2592 (
2593 2593 b'',
2594 2594 b'record-parents',
2595 2595 False,
2596 2596 _(b'record parent information for the precursor'),
2597 2597 ),
2598 2598 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2599 2599 (
2600 2600 b'',
2601 2601 b'exclusive',
2602 2602 False,
2603 2603 _(b'restrict display to markers only relevant to REV'),
2604 2604 ),
2605 2605 (b'', b'index', False, _(b'display index of the marker')),
2606 2606 (b'', b'delete', [], _(b'delete markers specified by indices')),
2607 2607 ]
2608 2608 + cmdutil.commitopts2
2609 2609 + cmdutil.formatteropts,
2610 2610 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2611 2611 )
2612 2612 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2613 2613 """create arbitrary obsolete marker
2614 2614
2615 2615 With no arguments, displays the list of obsolescence markers."""
2616 2616
2617 2617 def parsenodeid(s):
2618 2618 try:
2619 2619 # We do not use revsingle/revrange functions here to accept
2620 2620 # arbitrary node identifiers, possibly not present in the
2621 2621 # local repository.
2622 2622 n = bin(s)
2623 2623 if len(n) != repo.nodeconstants.nodelen:
2624 2624 raise ValueError
2625 2625 return n
2626 2626 except ValueError:
2627 2627 raise error.InputError(
2628 2628 b'changeset references must be full hexadecimal '
2629 2629 b'node identifiers'
2630 2630 )
2631 2631
2632 2632 if opts.get('delete'):
2633 2633 indices = []
2634 2634 for v in opts.get('delete'):
2635 2635 try:
2636 2636 indices.append(int(v))
2637 2637 except ValueError:
2638 2638 raise error.InputError(
2639 2639 _(b'invalid index value: %r') % v,
2640 2640 hint=_(b'use integers for indices'),
2641 2641 )
2642 2642
2643 2643 if repo.currenttransaction():
2644 2644 raise error.Abort(
2645 2645 _(b'cannot delete obsmarkers in the middle of transaction.')
2646 2646 )
2647 2647
2648 2648 with repo.lock():
2649 2649 n = repair.deleteobsmarkers(repo.obsstore, indices)
2650 2650 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2651 2651
2652 2652 return
2653 2653
2654 2654 if precursor is not None:
2655 2655 if opts['rev']:
2656 2656 raise error.InputError(
2657 2657 b'cannot select revision when creating marker'
2658 2658 )
2659 2659 metadata = {}
2660 2660 metadata[b'user'] = encoding.fromlocal(opts['user'] or ui.username())
2661 2661 succs = tuple(parsenodeid(succ) for succ in successors)
2662 2662 l = repo.lock()
2663 2663 try:
2664 2664 tr = repo.transaction(b'debugobsolete')
2665 2665 try:
2666 2666 date = opts.get('date')
2667 2667 if date:
2668 2668 date = dateutil.parsedate(date)
2669 2669 else:
2670 2670 date = None
2671 2671 prec = parsenodeid(precursor)
2672 2672 parents = None
2673 2673 if opts['record_parents']:
2674 2674 if prec not in repo.unfiltered():
2675 2675 raise error.Abort(
2676 2676 b'cannot used --record-parents on '
2677 2677 b'unknown changesets'
2678 2678 )
2679 2679 parents = repo.unfiltered()[prec].parents()
2680 2680 parents = tuple(p.node() for p in parents)
2681 2681 repo.obsstore.create(
2682 2682 tr,
2683 2683 prec,
2684 2684 succs,
2685 2685 opts['flags'],
2686 2686 parents=parents,
2687 2687 date=date,
2688 2688 metadata=metadata,
2689 2689 ui=ui,
2690 2690 )
2691 2691 tr.close()
2692 2692 except ValueError as exc:
2693 2693 raise error.Abort(
2694 2694 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2695 2695 )
2696 2696 finally:
2697 2697 tr.release()
2698 2698 finally:
2699 2699 l.release()
2700 2700 else:
2701 2701 if opts['rev']:
2702 2702 revs = logcmdutil.revrange(repo, opts['rev'])
2703 2703 nodes = [repo[r].node() for r in revs]
2704 2704 markers = list(
2705 2705 obsutil.getmarkers(
2706 2706 repo, nodes=nodes, exclusive=opts['exclusive']
2707 2707 )
2708 2708 )
2709 2709 markers.sort(key=lambda x: x._data)
2710 2710 else:
2711 2711 markers = obsutil.getmarkers(repo)
2712 2712
2713 2713 markerstoiter = markers
2714 2714 isrelevant = lambda m: True
2715 2715 if opts.get('rev') and opts.get('index'):
2716 2716 markerstoiter = obsutil.getmarkers(repo)
2717 2717 markerset = set(markers)
2718 2718 isrelevant = lambda m: m in markerset
2719 2719
2720 2720 fm = ui.formatter(b'debugobsolete', pycompat.byteskwargs(opts))
2721 2721 for i, m in enumerate(markerstoiter):
2722 2722 if not isrelevant(m):
2723 2723 # marker can be irrelevant when we're iterating over a set
2724 2724 # of markers (markerstoiter) which is bigger than the set
2725 2725 # of markers we want to display (markers)
2726 2726 # this can happen if both --index and --rev options are
2727 2727 # provided and thus we need to iterate over all of the markers
2728 2728 # to get the correct indices, but only display the ones that
2729 2729 # are relevant to --rev value
2730 2730 continue
2731 2731 fm.startitem()
2732 2732 ind = i if opts.get('index') else None
2733 2733 cmdutil.showmarker(fm, m, index=ind)
2734 2734 fm.end()
2735 2735
2736 2736
2737 2737 @command(
2738 2738 b'debugp1copies',
2739 2739 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2740 2740 _(b'[-r REV]'),
2741 2741 )
2742 2742 def debugp1copies(ui, repo, **opts):
2743 2743 """dump copy information compared to p1"""
2744 2744
2745 2745 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
2746 2746 for dst, src in ctx.p1copies().items():
2747 2747 ui.write(b'%s -> %s\n' % (src, dst))
2748 2748
2749 2749
2750 2750 @command(
2751 2751 b'debugp2copies',
2752 2752 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2753 2753 _(b'[-r REV]'),
2754 2754 )
2755 2755 def debugp2copies(ui, repo, **opts):
2756 2756 """dump copy information compared to p2"""
2757 2757
2758 2758 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
2759 2759 for dst, src in ctx.p2copies().items():
2760 2760 ui.write(b'%s -> %s\n' % (src, dst))
2761 2761
2762 2762
2763 2763 @command(
2764 2764 b'debugpathcomplete',
2765 2765 [
2766 2766 (b'f', b'full', None, _(b'complete an entire path')),
2767 2767 (b'n', b'normal', None, _(b'show only normal files')),
2768 2768 (b'a', b'added', None, _(b'show only added files')),
2769 2769 (b'r', b'removed', None, _(b'show only removed files')),
2770 2770 ],
2771 2771 _(b'FILESPEC...'),
2772 2772 )
2773 2773 def debugpathcomplete(ui, repo, *specs, **opts):
2774 2774 """complete part or all of a tracked path
2775 2775
2776 2776 This command supports shells that offer path name completion. It
2777 2777 currently completes only files already known to the dirstate.
2778 2778
2779 2779 Completion extends only to the next path segment unless
2780 2780 --full is specified, in which case entire paths are used."""
2781 2781
2782 2782 def complete(path, acceptable):
2783 2783 dirstate = repo.dirstate
2784 2784 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2785 2785 rootdir = repo.root + pycompat.ossep
2786 2786 if spec != repo.root and not spec.startswith(rootdir):
2787 2787 return [], []
2788 2788 if os.path.isdir(spec):
2789 2789 spec += b'/'
2790 2790 spec = spec[len(rootdir) :]
2791 2791 fixpaths = pycompat.ossep != b'/'
2792 2792 if fixpaths:
2793 2793 spec = spec.replace(pycompat.ossep, b'/')
2794 2794 speclen = len(spec)
2795 2795 fullpaths = opts['full']
2796 2796 files, dirs = set(), set()
2797 2797 adddir, addfile = dirs.add, files.add
2798 2798 for f, st in dirstate.items():
2799 2799 if f.startswith(spec) and st.state in acceptable:
2800 2800 if fixpaths:
2801 2801 f = f.replace(b'/', pycompat.ossep)
2802 2802 if fullpaths:
2803 2803 addfile(f)
2804 2804 continue
2805 2805 s = f.find(pycompat.ossep, speclen)
2806 2806 if s >= 0:
2807 2807 adddir(f[:s])
2808 2808 else:
2809 2809 addfile(f)
2810 2810 return files, dirs
2811 2811
2812 2812 acceptable = b''
2813 2813 if opts['normal']:
2814 2814 acceptable += b'nm'
2815 2815 if opts['added']:
2816 2816 acceptable += b'a'
2817 2817 if opts['removed']:
2818 2818 acceptable += b'r'
2819 2819 cwd = repo.getcwd()
2820 2820 if not specs:
2821 2821 specs = [b'.']
2822 2822
2823 2823 files, dirs = set(), set()
2824 2824 for spec in specs:
2825 2825 f, d = complete(spec, acceptable or b'nmar')
2826 2826 files.update(f)
2827 2827 dirs.update(d)
2828 2828 files.update(dirs)
2829 2829 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2830 2830 ui.write(b'\n')
2831 2831
2832 2832
2833 2833 @command(
2834 2834 b'debugpathcopies',
2835 2835 cmdutil.walkopts,
2836 2836 b'hg debugpathcopies REV1 REV2 [FILE]',
2837 2837 inferrepo=True,
2838 2838 )
2839 2839 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2840 2840 """show copies between two revisions"""
2841 2841 ctx1 = scmutil.revsingle(repo, rev1)
2842 2842 ctx2 = scmutil.revsingle(repo, rev2)
2843 2843 m = scmutil.match(ctx1, pats, opts)
2844 2844 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2845 2845 ui.write(b'%s -> %s\n' % (src, dst))
2846 2846
2847 2847
2848 2848 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2849 2849 def debugpeer(ui, path):
2850 2850 """establish a connection to a peer repository"""
2851 2851 # Always enable peer request logging. Requires --debug to display
2852 2852 # though.
2853 2853 overrides = {
2854 2854 (b'devel', b'debug.peer-request'): True,
2855 2855 }
2856 2856
2857 2857 with ui.configoverride(overrides):
2858 2858 peer = hg.peer(ui, {}, path)
2859 2859
2860 2860 try:
2861 2861 local = peer.local() is not None
2862 2862 canpush = peer.canpush()
2863 2863
2864 2864 ui.write(_(b'url: %s\n') % peer.url())
2865 2865 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2866 2866 ui.write(
2867 2867 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2868 2868 )
2869 2869 finally:
2870 2870 peer.close()
2871 2871
2872 2872
2873 2873 @command(
2874 2874 b'debugpickmergetool',
2875 2875 [
2876 2876 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2877 2877 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2878 2878 ]
2879 2879 + cmdutil.walkopts
2880 2880 + cmdutil.mergetoolopts,
2881 2881 _(b'[PATTERN]...'),
2882 2882 inferrepo=True,
2883 2883 )
2884 2884 def debugpickmergetool(ui, repo, *pats, **opts):
2885 2885 """examine which merge tool is chosen for specified file
2886 2886
2887 2887 As described in :hg:`help merge-tools`, Mercurial examines
2888 2888 configurations below in this order to decide which merge tool is
2889 2889 chosen for specified file.
2890 2890
2891 2891 1. ``--tool`` option
2892 2892 2. ``HGMERGE`` environment variable
2893 2893 3. configurations in ``merge-patterns`` section
2894 2894 4. configuration of ``ui.merge``
2895 2895 5. configurations in ``merge-tools`` section
2896 2896 6. ``hgmerge`` tool (for historical reason only)
2897 2897 7. default tool for fallback (``:merge`` or ``:prompt``)
2898 2898
2899 2899 This command writes out examination result in the style below::
2900 2900
2901 2901 FILE = MERGETOOL
2902 2902
2903 2903 By default, all files known in the first parent context of the
2904 2904 working directory are examined. Use file patterns and/or -I/-X
2905 2905 options to limit target files. -r/--rev is also useful to examine
2906 2906 files in another context without actual updating to it.
2907 2907
2908 2908 With --debug, this command shows warning messages while matching
2909 2909 against ``merge-patterns`` and so on, too. It is recommended to
2910 2910 use this option with explicit file patterns and/or -I/-X options,
2911 2911 because this option increases amount of output per file according
2912 2912 to configurations in hgrc.
2913 2913
2914 2914 With -v/--verbose, this command shows configurations below at
2915 2915 first (only if specified).
2916 2916
2917 2917 - ``--tool`` option
2918 2918 - ``HGMERGE`` environment variable
2919 2919 - configuration of ``ui.merge``
2920 2920
2921 2921 If merge tool is chosen before matching against
2922 2922 ``merge-patterns``, this command can't show any helpful
2923 2923 information, even with --debug. In such case, information above is
2924 2924 useful to know why a merge tool is chosen.
2925 2925 """
2926 2926 overrides = {}
2927 2927 if opts['tool']:
2928 2928 overrides[(b'ui', b'forcemerge')] = opts['tool']
2929 2929 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts['tool'])))
2930 2930
2931 2931 with ui.configoverride(overrides, b'debugmergepatterns'):
2932 2932 hgmerge = encoding.environ.get(b"HGMERGE")
2933 2933 if hgmerge is not None:
2934 2934 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
2935 2935 uimerge = ui.config(b"ui", b"merge")
2936 2936 if uimerge:
2937 2937 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
2938 2938
2939 2939 ctx = scmutil.revsingle(repo, opts.get('rev'))
2940 2940 m = scmutil.match(ctx, pats, pycompat.byteskwargs(opts))
2941 2941 changedelete = opts['changedelete']
2942 2942 for path in ctx.walk(m):
2943 2943 fctx = ctx[path]
2944 2944 with ui.silent(
2945 2945 error=True
2946 2946 ) if not ui.debugflag else util.nullcontextmanager():
2947 2947 tool, toolpath = filemerge._picktool(
2948 2948 repo,
2949 2949 ui,
2950 2950 path,
2951 2951 fctx.isbinary(),
2952 2952 b'l' in fctx.flags(),
2953 2953 changedelete,
2954 2954 )
2955 2955 ui.write(b'%s = %s\n' % (path, tool))
2956 2956
2957 2957
2958 2958 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2959 2959 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2960 2960 """access the pushkey key/value protocol
2961 2961
2962 2962 With two args, list the keys in the given namespace.
2963 2963
2964 2964 With five args, set a key to new if it currently is set to old.
2965 2965 Reports success or failure.
2966 2966 """
2967 2967
2968 2968 target = hg.peer(ui, {}, repopath)
2969 2969 try:
2970 2970 if keyinfo:
2971 2971 key, old, new = keyinfo
2972 2972 with target.commandexecutor() as e:
2973 2973 r = e.callcommand(
2974 2974 b'pushkey',
2975 2975 {
2976 2976 b'namespace': namespace,
2977 2977 b'key': key,
2978 2978 b'old': old,
2979 2979 b'new': new,
2980 2980 },
2981 2981 ).result()
2982 2982
2983 2983 ui.status(pycompat.bytestr(r) + b'\n')
2984 2984 return not r
2985 2985 else:
2986 2986 for k, v in sorted(target.listkeys(namespace).items()):
2987 2987 ui.write(
2988 2988 b"%s\t%s\n"
2989 2989 % (stringutil.escapestr(k), stringutil.escapestr(v))
2990 2990 )
2991 2991 finally:
2992 2992 target.close()
2993 2993
2994 2994
2995 2995 @command(b'debugpvec', [], _(b'A B'))
2996 2996 def debugpvec(ui, repo, a, b=None):
2997 2997 ca = scmutil.revsingle(repo, a)
2998 2998 cb = scmutil.revsingle(repo, b)
2999 2999 pa = pvec.ctxpvec(ca)
3000 3000 pb = pvec.ctxpvec(cb)
3001 3001 if pa == pb:
3002 3002 rel = b"="
3003 3003 elif pa > pb:
3004 3004 rel = b">"
3005 3005 elif pa < pb:
3006 3006 rel = b"<"
3007 3007 elif pa | pb:
3008 3008 rel = b"|"
3009 3009 ui.write(_(b"a: %s\n") % pa)
3010 3010 ui.write(_(b"b: %s\n") % pb)
3011 3011 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3012 3012 ui.write(
3013 3013 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3014 3014 % (
3015 3015 abs(pa._depth - pb._depth),
3016 3016 pvec._hamming(pa._vec, pb._vec),
3017 3017 pa.distance(pb),
3018 3018 rel,
3019 3019 )
3020 3020 )
3021 3021
3022 3022
3023 3023 @command(
3024 3024 b'debugrebuilddirstate|debugrebuildstate',
3025 3025 [
3026 3026 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3027 3027 (
3028 3028 b'',
3029 3029 b'minimal',
3030 3030 None,
3031 3031 _(
3032 3032 b'only rebuild files that are inconsistent with '
3033 3033 b'the working copy parent'
3034 3034 ),
3035 3035 ),
3036 3036 ],
3037 3037 _(b'[-r REV]'),
3038 3038 )
3039 3039 def debugrebuilddirstate(ui, repo, rev, **opts):
3040 3040 """rebuild the dirstate as it would look like for the given revision
3041 3041
3042 3042 If no revision is specified the first current parent will be used.
3043 3043
3044 3044 The dirstate will be set to the files of the given revision.
3045 3045 The actual working directory content or existing dirstate
3046 3046 information such as adds or removes is not considered.
3047 3047
3048 3048 ``minimal`` will only rebuild the dirstate status for files that claim to be
3049 3049 tracked but are not in the parent manifest, or that exist in the parent
3050 3050 manifest but are not in the dirstate. It will not change adds, removes, or
3051 3051 modified files that are in the working copy parent.
3052 3052
3053 3053 One use of this command is to make the next :hg:`status` invocation
3054 3054 check the actual file content.
3055 3055 """
3056 3056 ctx = scmutil.revsingle(repo, rev)
3057 3057 with repo.wlock():
3058 3058 if repo.currenttransaction() is not None:
3059 3059 msg = b'rebuild the dirstate outside of a transaction'
3060 3060 raise error.ProgrammingError(msg)
3061 3061 dirstate = repo.dirstate
3062 3062 changedfiles = None
3063 3063 # See command doc for what minimal does.
3064 3064 if opts.get('minimal'):
3065 3065 manifestfiles = set(ctx.manifest().keys())
3066 3066 dirstatefiles = set(dirstate)
3067 3067 manifestonly = manifestfiles - dirstatefiles
3068 3068 dsonly = dirstatefiles - manifestfiles
3069 3069 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3070 3070 changedfiles = manifestonly | dsnotadded
3071 3071
3072 3072 with dirstate.changing_parents(repo):
3073 3073 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3074 3074
3075 3075
3076 3076 @command(
3077 3077 b'debugrebuildfncache',
3078 3078 [
3079 3079 (
3080 3080 b'',
3081 3081 b'only-data',
3082 3082 False,
3083 3083 _(b'only look for wrong .d files (much faster)'),
3084 3084 )
3085 3085 ],
3086 3086 b'',
3087 3087 )
3088 3088 def debugrebuildfncache(ui, repo, **opts):
3089 3089 """rebuild the fncache file"""
3090 3090 repair.rebuildfncache(ui, repo, opts.get("only_data"))
3091 3091
3092 3092
3093 3093 @command(
3094 3094 b'debugrename',
3095 3095 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3096 3096 _(b'[-r REV] [FILE]...'),
3097 3097 )
3098 3098 def debugrename(ui, repo, *pats, **opts):
3099 3099 """dump rename information"""
3100 3100
3101 3101 ctx = scmutil.revsingle(repo, opts.get('rev'))
3102 3102 m = scmutil.match(ctx, pats, pycompat.byteskwargs(opts))
3103 3103 for abs in ctx.walk(m):
3104 3104 fctx = ctx[abs]
3105 3105 o = fctx.filelog().renamed(fctx.filenode())
3106 3106 rel = repo.pathto(abs)
3107 3107 if o:
3108 3108 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3109 3109 else:
3110 3110 ui.write(_(b"%s not renamed\n") % rel)
3111 3111
3112 3112
3113 3113 @command(b'debugrequires|debugrequirements', [], b'')
3114 3114 def debugrequirements(ui, repo):
3115 3115 """print the current repo requirements"""
3116 3116 for r in sorted(repo.requirements):
3117 3117 ui.write(b"%s\n" % r)
3118 3118
3119 3119
3120 3120 @command(
3121 3121 b'debugrevlog',
3122 3122 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3123 3123 _(b'-c|-m|FILE'),
3124 3124 optionalrepo=True,
3125 3125 )
3126 3126 def debugrevlog(ui, repo, file_=None, **opts):
3127 3127 """show data and statistics about a revlog"""
3128 3128 r = cmdutil.openrevlog(
3129 3129 repo, b'debugrevlog', file_, pycompat.byteskwargs(opts)
3130 3130 )
3131 3131
3132 3132 if opts.get("dump"):
3133 3133 revlog_debug.dump(ui, r)
3134 3134 else:
3135 3135 revlog_debug.debug_revlog(ui, r)
3136 3136 return 0
3137 3137
3138 3138
3139 3139 @command(
3140 3140 b'debugrevlogindex',
3141 3141 cmdutil.debugrevlogopts
3142 3142 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3143 3143 _(b'[-f FORMAT] -c|-m|FILE'),
3144 3144 optionalrepo=True,
3145 3145 )
3146 3146 def debugrevlogindex(ui, repo, file_=None, **opts):
3147 3147 """dump the contents of a revlog index"""
3148 3148 r = cmdutil.openrevlog(
3149 3149 repo, b'debugrevlogindex', file_, pycompat.byteskwargs(opts)
3150 3150 )
3151 3151 format = opts.get('format', 0)
3152 3152 if format not in (0, 1):
3153 3153 raise error.Abort(_(b"unknown format %d") % format)
3154 3154
3155 3155 if ui.debugflag:
3156 3156 shortfn = hex
3157 3157 else:
3158 3158 shortfn = short
3159 3159
3160 3160 # There might not be anything in r, so have a sane default
3161 3161 idlen = 12
3162 3162 for i in r:
3163 3163 idlen = len(shortfn(r.node(i)))
3164 3164 break
3165 3165
3166 3166 if format == 0:
3167 3167 if ui.verbose:
3168 3168 ui.writenoi18n(
3169 3169 b" rev offset length linkrev %s %s p2\n"
3170 3170 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3171 3171 )
3172 3172 else:
3173 3173 ui.writenoi18n(
3174 3174 b" rev linkrev %s %s p2\n"
3175 3175 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3176 3176 )
3177 3177 elif format == 1:
3178 3178 if ui.verbose:
3179 3179 ui.writenoi18n(
3180 3180 (
3181 3181 b" rev flag offset length size link p1"
3182 3182 b" p2 %s\n"
3183 3183 )
3184 3184 % b"nodeid".rjust(idlen)
3185 3185 )
3186 3186 else:
3187 3187 ui.writenoi18n(
3188 3188 b" rev flag size link p1 p2 %s\n"
3189 3189 % b"nodeid".rjust(idlen)
3190 3190 )
3191 3191
3192 3192 for i in r:
3193 3193 node = r.node(i)
3194 3194 if format == 0:
3195 3195 try:
3196 3196 pp = r.parents(node)
3197 3197 except Exception:
3198 3198 pp = [repo.nullid, repo.nullid]
3199 3199 if ui.verbose:
3200 3200 ui.write(
3201 3201 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3202 3202 % (
3203 3203 i,
3204 3204 r.start(i),
3205 3205 r.length(i),
3206 3206 r.linkrev(i),
3207 3207 shortfn(node),
3208 3208 shortfn(pp[0]),
3209 3209 shortfn(pp[1]),
3210 3210 )
3211 3211 )
3212 3212 else:
3213 3213 ui.write(
3214 3214 b"% 6d % 7d %s %s %s\n"
3215 3215 % (
3216 3216 i,
3217 3217 r.linkrev(i),
3218 3218 shortfn(node),
3219 3219 shortfn(pp[0]),
3220 3220 shortfn(pp[1]),
3221 3221 )
3222 3222 )
3223 3223 elif format == 1:
3224 3224 pr = r.parentrevs(i)
3225 3225 if ui.verbose:
3226 3226 ui.write(
3227 3227 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3228 3228 % (
3229 3229 i,
3230 3230 r.flags(i),
3231 3231 r.start(i),
3232 3232 r.length(i),
3233 3233 r.rawsize(i),
3234 3234 r.linkrev(i),
3235 3235 pr[0],
3236 3236 pr[1],
3237 3237 shortfn(node),
3238 3238 )
3239 3239 )
3240 3240 else:
3241 3241 ui.write(
3242 3242 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3243 3243 % (
3244 3244 i,
3245 3245 r.flags(i),
3246 3246 r.rawsize(i),
3247 3247 r.linkrev(i),
3248 3248 pr[0],
3249 3249 pr[1],
3250 3250 shortfn(node),
3251 3251 )
3252 3252 )
3253 3253
3254 3254
3255 3255 @command(
3256 3256 b'debugrevspec',
3257 3257 [
3258 3258 (
3259 3259 b'',
3260 3260 b'optimize',
3261 3261 None,
3262 3262 _(b'print parsed tree after optimizing (DEPRECATED)'),
3263 3263 ),
3264 3264 (
3265 3265 b'',
3266 3266 b'show-revs',
3267 3267 True,
3268 3268 _(b'print list of result revisions (default)'),
3269 3269 ),
3270 3270 (
3271 3271 b's',
3272 3272 b'show-set',
3273 3273 None,
3274 3274 _(b'print internal representation of result set'),
3275 3275 ),
3276 3276 (
3277 3277 b'p',
3278 3278 b'show-stage',
3279 3279 [],
3280 3280 _(b'print parsed tree at the given stage'),
3281 3281 _(b'NAME'),
3282 3282 ),
3283 3283 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3284 3284 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3285 3285 ],
3286 3286 b'REVSPEC',
3287 3287 )
3288 3288 def debugrevspec(ui, repo, expr, **opts):
3289 3289 """parse and apply a revision specification
3290 3290
3291 3291 Use -p/--show-stage option to print the parsed tree at the given stages.
3292 3292 Use -p all to print tree at every stage.
3293 3293
3294 3294 Use --no-show-revs option with -s or -p to print only the set
3295 3295 representation or the parsed tree respectively.
3296 3296
3297 3297 Use --verify-optimized to compare the optimized result with the unoptimized
3298 3298 one. Returns 1 if the optimized result differs.
3299 3299 """
3300 3300 aliases = ui.configitems(b'revsetalias')
3301 3301 stages = [
3302 3302 (b'parsed', lambda tree: tree),
3303 3303 (
3304 3304 b'expanded',
3305 3305 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3306 3306 ),
3307 3307 (b'concatenated', revsetlang.foldconcat),
3308 3308 (b'analyzed', revsetlang.analyze),
3309 3309 (b'optimized', revsetlang.optimize),
3310 3310 ]
3311 3311 if opts['no_optimized']:
3312 3312 stages = stages[:-1]
3313 3313 if opts['verify_optimized'] and opts['no_optimized']:
3314 3314 raise error.Abort(
3315 3315 _(b'cannot use --verify-optimized with --no-optimized')
3316 3316 )
3317 3317 stagenames = {n for n, f in stages}
3318 3318
3319 3319 showalways = set()
3320 3320 showchanged = set()
3321 3321 if ui.verbose and not opts['show_stage']:
3322 3322 # show parsed tree by --verbose (deprecated)
3323 3323 showalways.add(b'parsed')
3324 3324 showchanged.update([b'expanded', b'concatenated'])
3325 3325 if opts['optimize']:
3326 3326 showalways.add(b'optimized')
3327 3327 if opts['show_stage'] and opts['optimize']:
3328 3328 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3329 3329 if opts['show_stage'] == [b'all']:
3330 3330 showalways.update(stagenames)
3331 3331 else:
3332 3332 for n in opts['show_stage']:
3333 3333 if n not in stagenames:
3334 3334 raise error.Abort(_(b'invalid stage name: %s') % n)
3335 3335 showalways.update(opts['show_stage'])
3336 3336
3337 3337 treebystage = {}
3338 3338 printedtree = None
3339 3339 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3340 3340 for n, f in stages:
3341 3341 treebystage[n] = tree = f(tree)
3342 3342 if n in showalways or (n in showchanged and tree != printedtree):
3343 3343 if opts['show_stage'] or n != b'parsed':
3344 3344 ui.write(b"* %s:\n" % n)
3345 3345 ui.write(revsetlang.prettyformat(tree), b"\n")
3346 3346 printedtree = tree
3347 3347
3348 3348 if opts['verify_optimized']:
3349 3349 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3350 3350 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3351 3351 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
3352 3352 ui.writenoi18n(
3353 3353 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3354 3354 )
3355 3355 ui.writenoi18n(
3356 3356 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3357 3357 )
3358 3358 arevs = list(arevs)
3359 3359 brevs = list(brevs)
3360 3360 if arevs == brevs:
3361 3361 return 0
3362 3362 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3363 3363 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3364 3364 sm = difflib.SequenceMatcher(None, arevs, brevs)
3365 3365 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3366 3366 if tag in ('delete', 'replace'):
3367 3367 for c in arevs[alo:ahi]:
3368 3368 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3369 3369 if tag in ('insert', 'replace'):
3370 3370 for c in brevs[blo:bhi]:
3371 3371 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3372 3372 if tag == 'equal':
3373 3373 for c in arevs[alo:ahi]:
3374 3374 ui.write(b' %d\n' % c)
3375 3375 return 1
3376 3376
3377 3377 func = revset.makematcher(tree)
3378 3378 revs = func(repo)
3379 3379 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
3380 3380 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3381 3381 if not opts['show_revs']:
3382 3382 return
3383 3383 for c in revs:
3384 3384 ui.write(b"%d\n" % c)
3385 3385
3386 3386
3387 3387 @command(
3388 3388 b'debugserve',
3389 3389 [
3390 3390 (
3391 3391 b'',
3392 3392 b'sshstdio',
3393 3393 False,
3394 3394 _(b'run an SSH server bound to process handles'),
3395 3395 ),
3396 3396 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3397 3397 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3398 3398 ],
3399 3399 b'',
3400 3400 )
3401 3401 def debugserve(ui, repo, **opts):
3402 3402 """run a server with advanced settings
3403 3403
3404 3404 This command is similar to :hg:`serve`. It exists partially as a
3405 3405 workaround to the fact that ``hg serve --stdio`` must have specific
3406 3406 arguments for security reasons.
3407 3407 """
3408 3408 if not opts['sshstdio']:
3409 3409 raise error.Abort(_(b'only --sshstdio is currently supported'))
3410 3410
3411 3411 logfh = None
3412 3412
3413 3413 if opts['logiofd'] and opts['logiofile']:
3414 3414 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3415 3415
3416 3416 if opts['logiofd']:
3417 3417 # Ideally we would be line buffered. But line buffering in binary
3418 3418 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3419 3419 # buffering could have performance impacts. But since this isn't
3420 3420 # performance critical code, it should be fine.
3421 3421 try:
3422 3422 logfh = os.fdopen(int(opts['logiofd']), 'ab', 0)
3423 3423 except OSError as e:
3424 3424 if e.errno != errno.ESPIPE:
3425 3425 raise
3426 3426 # can't seek a pipe, so `ab` mode fails on py3
3427 3427 logfh = os.fdopen(int(opts['logiofd']), 'wb', 0)
3428 3428 elif opts['logiofile']:
3429 3429 logfh = open(opts['logiofile'], b'ab', 0)
3430 3430
3431 3431 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3432 3432 s.serve_forever()
3433 3433
3434 3434
3435 3435 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3436 3436 def debugsetparents(ui, repo, rev1, rev2=None):
3437 3437 """manually set the parents of the current working directory (DANGEROUS)
3438 3438
3439 3439 This command is not what you are looking for and should not be used. Using
3440 3440 this command will most certainly results in slight corruption of the file
3441 3441 level histories withing your repository. DO NOT USE THIS COMMAND.
3442 3442
3443 3443 The command update the p1 and p2 field in the dirstate, and not touching
3444 3444 anything else. This useful for writing repository conversion tools, but
3445 3445 should be used with extreme care. For example, neither the working
3446 3446 directory nor the dirstate is updated, so file status may be incorrect
3447 3447 after running this command. Only used if you are one of the few people that
3448 3448 deeply unstand both conversion tools and file level histories. If you are
3449 3449 reading this help, you are not one of this people (most of them sailed west
3450 3450 from Mithlond anyway.
3451 3451
3452 3452 So one last time DO NOT USE THIS COMMAND.
3453 3453
3454 3454 Returns 0 on success.
3455 3455 """
3456 3456
3457 3457 node1 = scmutil.revsingle(repo, rev1).node()
3458 3458 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3459 3459
3460 3460 with repo.wlock():
3461 3461 repo.setparents(node1, node2)
3462 3462
3463 3463
3464 3464 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3465 3465 def debugsidedata(ui, repo, file_, rev=None, **opts):
3466 3466 """dump the side data for a cl/manifest/file revision
3467 3467
3468 3468 Use --verbose to dump the sidedata content."""
3469 3469 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
3470 3470 if rev is not None:
3471 3471 raise error.InputError(
3472 3472 _(b'cannot specify a revision with other arguments')
3473 3473 )
3474 3474 file_, rev = None, file_
3475 3475 elif rev is None:
3476 3476 raise error.InputError(_(b'please specify a revision'))
3477 3477 r = cmdutil.openstorage(
3478 3478 repo, b'debugdata', file_, pycompat.byteskwargs(opts)
3479 3479 )
3480 3480 r = getattr(r, '_revlog', r)
3481 3481 try:
3482 3482 sidedata = r.sidedata(r.lookup(rev))
3483 3483 except KeyError:
3484 3484 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3485 3485 if sidedata:
3486 3486 sidedata = list(sidedata.items())
3487 3487 sidedata.sort()
3488 3488 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3489 3489 for key, value in sidedata:
3490 3490 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3491 3491 if ui.verbose:
3492 3492 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3493 3493
3494 3494
3495 3495 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3496 3496 def debugssl(ui, repo, source=None, **opts):
3497 3497 """test a secure connection to a server
3498 3498
3499 3499 This builds the certificate chain for the server on Windows, installing the
3500 3500 missing intermediates and trusted root via Windows Update if necessary. It
3501 3501 does nothing on other platforms.
3502 3502
3503 3503 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3504 3504 that server is used. See :hg:`help urls` for more information.
3505 3505
3506 3506 If the update succeeds, retry the original operation. Otherwise, the cause
3507 3507 of the SSL error is likely another issue.
3508 3508 """
3509 3509 if not pycompat.iswindows:
3510 3510 raise error.Abort(
3511 3511 _(b'certificate chain building is only possible on Windows')
3512 3512 )
3513 3513
3514 3514 if not source:
3515 3515 if not repo:
3516 3516 raise error.Abort(
3517 3517 _(
3518 3518 b"there is no Mercurial repository here, and no "
3519 3519 b"server specified"
3520 3520 )
3521 3521 )
3522 3522 source = b"default"
3523 3523
3524 3524 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3525 3525 url = path.url
3526 3526
3527 3527 defaultport = {b'https': 443, b'ssh': 22}
3528 3528 if url.scheme in defaultport:
3529 3529 try:
3530 3530 addr = (url.host, int(url.port or defaultport[url.scheme]))
3531 3531 except ValueError:
3532 3532 raise error.Abort(_(b"malformed port number in URL"))
3533 3533 else:
3534 3534 raise error.Abort(_(b"only https and ssh connections are supported"))
3535 3535
3536 3536 from . import win32
3537 3537
3538 3538 s = ssl.wrap_socket(
3539 3539 socket.socket(),
3540 3540 ssl_version=ssl.PROTOCOL_TLS,
3541 3541 cert_reqs=ssl.CERT_NONE,
3542 3542 ca_certs=None,
3543 3543 )
3544 3544
3545 3545 try:
3546 3546 s.connect(addr)
3547 3547 cert = s.getpeercert(True)
3548 3548
3549 3549 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3550 3550
3551 3551 complete = win32.checkcertificatechain(cert, build=False)
3552 3552
3553 3553 if not complete:
3554 3554 ui.status(_(b'certificate chain is incomplete, updating... '))
3555 3555
3556 3556 if not win32.checkcertificatechain(cert):
3557 3557 ui.status(_(b'failed.\n'))
3558 3558 else:
3559 3559 ui.status(_(b'done.\n'))
3560 3560 else:
3561 3561 ui.status(_(b'full certificate chain is available\n'))
3562 3562 finally:
3563 3563 s.close()
3564 3564
3565 3565
3566 3566 @command(
3567 3567 b'debug::stable-tail-sort',
3568 3568 [
3569 3569 (
3570 3570 b'T',
3571 3571 b'template',
3572 3572 b'{rev}\n',
3573 3573 _(b'display with template'),
3574 3574 _(b'TEMPLATE'),
3575 3575 ),
3576 3576 ],
3577 3577 b'REV',
3578 3578 )
3579 3579 def debug_stable_tail_sort(ui, repo, revspec, template, **opts):
3580 3580 """display the stable-tail sort of the ancestors of a given node"""
3581 3581 rev = logcmdutil.revsingle(repo, revspec).rev()
3582 3582 cl = repo.changelog
3583 3583
3584 3584 displayer = logcmdutil.maketemplater(ui, repo, template)
3585 3585 sorted_revs = stabletailsort._stable_tail_sort_naive(cl, rev)
3586 3586 for ancestor_rev in sorted_revs:
3587 3587 displayer.show(repo[ancestor_rev])
3588 3588
3589 3589
3590 3590 @command(
3591 3591 b'debug::stable-tail-sort-leaps',
3592 3592 [
3593 3593 (
3594 3594 b'T',
3595 3595 b'template',
3596 3596 b'{rev}',
3597 3597 _(b'display with template'),
3598 3598 _(b'TEMPLATE'),
3599 3599 ),
3600 3600 (b's', b'specific', False, _(b'restrict to specific leaps')),
3601 3601 ],
3602 3602 b'REV',
3603 3603 )
3604 3604 def debug_stable_tail_sort_leaps(ui, repo, rspec, template, specific, **opts):
3605 3605 """display the leaps in the stable-tail sort of a node, one per line"""
3606 3606 rev = logcmdutil.revsingle(repo, rspec).rev()
3607 3607
3608 3608 if specific:
3609 3609 get_leaps = stabletailsort._find_specific_leaps_naive
3610 3610 else:
3611 3611 get_leaps = stabletailsort._find_all_leaps_naive
3612 3612
3613 3613 displayer = logcmdutil.maketemplater(ui, repo, template)
3614 3614 for source, target in get_leaps(repo.changelog, rev):
3615 3615 displayer.show(repo[source])
3616 3616 displayer.show(repo[target])
3617 3617 ui.write(b'\n')
3618 3618
3619 3619
3620 3620 @command(
3621 3621 b"debugbackupbundle",
3622 3622 [
3623 3623 (
3624 3624 b"",
3625 3625 b"recover",
3626 3626 b"",
3627 3627 b"brings the specified changeset back into the repository",
3628 3628 )
3629 3629 ]
3630 3630 + cmdutil.logopts,
3631 3631 _(b"hg debugbackupbundle [--recover HASH]"),
3632 3632 )
3633 3633 def debugbackupbundle(ui, repo, *pats, **opts):
3634 3634 """lists the changesets available in backup bundles
3635 3635
3636 3636 Without any arguments, this command prints a list of the changesets in each
3637 3637 backup bundle.
3638 3638
3639 3639 --recover takes a changeset hash and unbundles the first bundle that
3640 3640 contains that hash, which puts that changeset back in your repository.
3641 3641
3642 3642 --verbose will print the entire commit message and the bundle path for that
3643 3643 backup.
3644 3644 """
3645 3645 backups = list(
3646 3646 filter(
3647 3647 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3648 3648 )
3649 3649 )
3650 3650 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3651 3651
3652 3652 opts["bundle"] = b""
3653 3653 opts["force"] = None
3654 3654 limit = logcmdutil.getlimit(pycompat.byteskwargs(opts))
3655 3655
3656 3656 def display(other, chlist, displayer):
3657 3657 if opts.get("newest_first"):
3658 3658 chlist.reverse()
3659 3659 count = 0
3660 3660 for n in chlist:
3661 3661 if limit is not None and count >= limit:
3662 3662 break
3663 3663 parents = [
3664 3664 True for p in other.changelog.parents(n) if p != repo.nullid
3665 3665 ]
3666 3666 if opts.get("no_merges") and len(parents) == 2:
3667 3667 continue
3668 3668 count += 1
3669 3669 displayer.show(other[n])
3670 3670
3671 3671 recovernode = opts.get("recover")
3672 3672 if recovernode:
3673 3673 if scmutil.isrevsymbol(repo, recovernode):
3674 3674 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3675 3675 return
3676 3676 elif backups:
3677 3677 msg = _(
3678 3678 b"Recover changesets using: hg debugbackupbundle --recover "
3679 3679 b"<changeset hash>\n\nAvailable backup changesets:"
3680 3680 )
3681 3681 ui.status(msg, label=b"status.removed")
3682 3682 else:
3683 3683 ui.status(_(b"no backup changesets found\n"))
3684 3684 return
3685 3685
3686 3686 for backup in backups:
3687 3687 # Much of this is copied from the hg incoming logic
3688 3688 source = os.path.relpath(backup, encoding.getcwd())
3689 3689 path = urlutil.get_unique_pull_path_obj(
3690 3690 b'debugbackupbundle',
3691 3691 ui,
3692 3692 source,
3693 3693 )
3694 3694 try:
3695 3695 other = hg.peer(repo, pycompat.byteskwargs(opts), path)
3696 3696 except error.LookupError as ex:
3697 3697 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3698 3698 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3699 3699 ui.warn(msg, hint=hint)
3700 3700 continue
3701 3701 branches = (path.branch, opts.get('branch', []))
3702 3702 revs, checkout = hg.addbranchrevs(
3703 3703 repo, other, branches, opts.get("rev")
3704 3704 )
3705 3705
3706 3706 if revs:
3707 3707 revs = [other.lookup(rev) for rev in revs]
3708 3708
3709 3709 with ui.silent():
3710 3710 try:
3711 3711 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3712 3712 ui, repo, other, revs, opts["bundle"], opts["force"]
3713 3713 )
3714 3714 except error.LookupError:
3715 3715 continue
3716 3716
3717 3717 try:
3718 3718 if not chlist:
3719 3719 continue
3720 3720 if recovernode:
3721 3721 with repo.lock(), repo.transaction(b"unbundle") as tr:
3722 3722 if scmutil.isrevsymbol(other, recovernode):
3723 3723 ui.status(_(b"Unbundling %s\n") % (recovernode))
3724 3724 f = hg.openpath(ui, path.loc)
3725 3725 gen = exchange.readbundle(ui, f, path.loc)
3726 3726 if isinstance(gen, bundle2.unbundle20):
3727 3727 bundle2.applybundle(
3728 3728 repo,
3729 3729 gen,
3730 3730 tr,
3731 3731 source=b"unbundle",
3732 3732 url=b"bundle:" + path.loc,
3733 3733 )
3734 3734 else:
3735 3735 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3736 3736 break
3737 3737 else:
3738 3738 backupdate = encoding.strtolocal(
3739 3739 time.strftime(
3740 3740 "%a %H:%M, %Y-%m-%d",
3741 3741 time.localtime(os.path.getmtime(path.loc)),
3742 3742 )
3743 3743 )
3744 3744 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3745 3745 if ui.verbose:
3746 3746 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3747 3747 else:
3748 3748 opts[
3749 3749 "template"
3750 3750 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3751 3751 displayer = logcmdutil.changesetdisplayer(
3752 3752 ui, other, pycompat.byteskwargs(opts), False
3753 3753 )
3754 3754 display(other, chlist, displayer)
3755 3755 displayer.close()
3756 3756 finally:
3757 3757 cleanupfn()
3758 3758
3759 3759
3760 3760 @command(
3761 3761 b'debugsub',
3762 3762 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3763 3763 _(b'[-r REV] [REV]'),
3764 3764 )
3765 3765 def debugsub(ui, repo, rev=None):
3766 3766 ctx = scmutil.revsingle(repo, rev, None)
3767 3767 for k, v in sorted(ctx.substate.items()):
3768 3768 ui.writenoi18n(b'path %s\n' % k)
3769 3769 ui.writenoi18n(b' source %s\n' % v[0])
3770 3770 ui.writenoi18n(b' revision %s\n' % v[1])
3771 3771
3772 3772
3773 3773 @command(
3774 3774 b'debugshell',
3775 3775 [
3776 3776 (
3777 3777 b'c',
3778 3778 b'command',
3779 3779 b'',
3780 3780 _(b'program passed in as a string'),
3781 3781 _(b'COMMAND'),
3782 3782 )
3783 3783 ],
3784 3784 _(b'[-c COMMAND]'),
3785 3785 optionalrepo=True,
3786 3786 )
3787 3787 def debugshell(ui, repo, **opts):
3788 3788 """run an interactive Python interpreter
3789 3789
3790 3790 The local namespace is provided with a reference to the ui and
3791 3791 the repo instance (if available).
3792 3792 """
3793 3793 import code
3794 3794
3795 3795 imported_objects = {
3796 3796 'ui': ui,
3797 3797 'repo': repo,
3798 3798 }
3799 3799
3800 3800 # py2exe disables initialization of the site module, which is responsible
3801 3801 # for arranging for ``quit()`` to exit the interpreter. Manually initialize
3802 3802 # the stuff that site normally does here, so that the interpreter can be
3803 3803 # quit in a consistent manner, whether run with pyoxidizer, exewrapper.c,
3804 3804 # py.exe, or py2exe.
3805 3805 if getattr(sys, "frozen", None) == 'console_exe':
3806 3806 try:
3807 3807 import site
3808 3808
3809 3809 site.setcopyright()
3810 3810 site.sethelper()
3811 3811 site.setquit()
3812 3812 except ImportError:
3813 3813 site = None # Keep PyCharm happy
3814 3814
3815 3815 command = opts.get('command')
3816 3816 if command:
3817 3817 compiled = code.compile_command(encoding.strfromlocal(command))
3818 3818 code.InteractiveInterpreter(locals=imported_objects).runcode(compiled)
3819 3819 return
3820 3820
3821 3821 code.interact(local=imported_objects)
3822 3822
3823 3823
3824 3824 @command(
3825 3825 b'debug-revlog-stats',
3826 3826 [
3827 3827 (b'c', b'changelog', None, _(b'Display changelog statistics')),
3828 3828 (b'm', b'manifest', None, _(b'Display manifest statistics')),
3829 3829 (b'f', b'filelogs', None, _(b'Display filelogs statistics')),
3830 3830 ]
3831 3831 + cmdutil.formatteropts,
3832 3832 )
3833 3833 def debug_revlog_stats(ui, repo, **opts):
3834 3834 """display statistics about revlogs in the store"""
3835 3835 changelog = opts["changelog"]
3836 3836 manifest = opts["manifest"]
3837 3837 filelogs = opts["filelogs"]
3838 3838
3839 3839 if changelog is None and manifest is None and filelogs is None:
3840 3840 changelog = True
3841 3841 manifest = True
3842 3842 filelogs = True
3843 3843
3844 3844 repo = repo.unfiltered()
3845 3845 fm = ui.formatter(b'debug-revlog-stats', pycompat.byteskwargs(opts))
3846 3846 revlog_debug.debug_revlog_stats(repo, fm, changelog, manifest, filelogs)
3847 3847 fm.end()
3848 3848
3849 3849
3850 3850 @command(
3851 3851 b'debugsuccessorssets',
3852 3852 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3853 3853 _(b'[REV]'),
3854 3854 )
3855 3855 def debugsuccessorssets(ui, repo, *revs, **opts):
3856 3856 """show set of successors for revision
3857 3857
3858 3858 A successors set of changeset A is a consistent group of revisions that
3859 3859 succeed A. It contains non-obsolete changesets only unless closests
3860 3860 successors set is set.
3861 3861
3862 3862 In most cases a changeset A has a single successors set containing a single
3863 3863 successor (changeset A replaced by A').
3864 3864
3865 3865 A changeset that is made obsolete with no successors are called "pruned".
3866 3866 Such changesets have no successors sets at all.
3867 3867
3868 3868 A changeset that has been "split" will have a successors set containing
3869 3869 more than one successor.
3870 3870
3871 3871 A changeset that has been rewritten in multiple different ways is called
3872 3872 "divergent". Such changesets have multiple successor sets (each of which
3873 3873 may also be split, i.e. have multiple successors).
3874 3874
3875 3875 Results are displayed as follows::
3876 3876
3877 3877 <rev1>
3878 3878 <successors-1A>
3879 3879 <rev2>
3880 3880 <successors-2A>
3881 3881 <successors-2B1> <successors-2B2> <successors-2B3>
3882 3882
3883 3883 Here rev2 has two possible (i.e. divergent) successors sets. The first
3884 3884 holds one element, whereas the second holds three (i.e. the changeset has
3885 3885 been split).
3886 3886 """
3887 3887 # passed to successorssets caching computation from one call to another
3888 3888 cache = {}
3889 3889 ctx2str = bytes
3890 3890 node2str = short
3891 3891 for rev in logcmdutil.revrange(repo, revs):
3892 3892 ctx = repo[rev]
3893 3893 ui.write(b'%s\n' % ctx2str(ctx))
3894 3894 for succsset in obsutil.successorssets(
3895 3895 repo, ctx.node(), closest=opts['closest'], cache=cache
3896 3896 ):
3897 3897 if succsset:
3898 3898 ui.write(b' ')
3899 3899 ui.write(node2str(succsset[0]))
3900 3900 for node in succsset[1:]:
3901 3901 ui.write(b' ')
3902 3902 ui.write(node2str(node))
3903 3903 ui.write(b'\n')
3904 3904
3905 3905
3906 3906 @command(b'debugtagscache', [])
3907 3907 def debugtagscache(ui, repo):
3908 3908 """display the contents of .hg/cache/hgtagsfnodes1"""
3909 3909 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3910 3910 flog = repo.file(b'.hgtags')
3911 3911 for r in repo:
3912 3912 node = repo[r].node()
3913 3913 tagsnode = cache.getfnode(node, computemissing=False)
3914 3914 if tagsnode:
3915 3915 tagsnodedisplay = hex(tagsnode)
3916 3916 if not flog.hasnode(tagsnode):
3917 3917 tagsnodedisplay += b' (unknown node)'
3918 3918 elif tagsnode is None:
3919 3919 tagsnodedisplay = b'missing'
3920 3920 else:
3921 3921 tagsnodedisplay = b'invalid'
3922 3922
3923 3923 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3924 3924
3925 3925
3926 3926 @command(
3927 3927 b'debugtemplate',
3928 3928 [
3929 3929 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3930 3930 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3931 3931 ],
3932 3932 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3933 3933 optionalrepo=True,
3934 3934 )
3935 3935 def debugtemplate(ui, repo, tmpl, **opts):
3936 3936 """parse and apply a template
3937 3937
3938 3938 If -r/--rev is given, the template is processed as a log template and
3939 3939 applied to the given changesets. Otherwise, it is processed as a generic
3940 3940 template.
3941 3941
3942 3942 Use --verbose to print the parsed tree.
3943 3943 """
3944 3944 revs = None
3945 3945 if opts['rev']:
3946 3946 if repo is None:
3947 3947 raise error.RepoError(
3948 3948 _(b'there is no Mercurial repository here (.hg not found)')
3949 3949 )
3950 3950 revs = logcmdutil.revrange(repo, opts['rev'])
3951 3951
3952 3952 props = {}
3953 3953 for d in opts['define']:
3954 3954 try:
3955 3955 k, v = (e.strip() for e in d.split(b'=', 1))
3956 3956 if not k or k == b'ui':
3957 3957 raise ValueError
3958 3958 props[k] = v
3959 3959 except ValueError:
3960 3960 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3961 3961
3962 3962 if ui.verbose:
3963 3963 aliases = ui.configitems(b'templatealias')
3964 3964 tree = templater.parse(tmpl)
3965 3965 ui.note(templater.prettyformat(tree), b'\n')
3966 3966 newtree = templater.expandaliases(tree, aliases)
3967 3967 if newtree != tree:
3968 3968 ui.notenoi18n(
3969 3969 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3970 3970 )
3971 3971
3972 3972 if revs is None:
3973 3973 tres = formatter.templateresources(ui, repo)
3974 3974 t = formatter.maketemplater(ui, tmpl, resources=tres)
3975 3975 if ui.verbose:
3976 3976 kwds, funcs = t.symbolsuseddefault()
3977 3977 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3978 3978 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3979 3979 ui.write(t.renderdefault(props))
3980 3980 else:
3981 3981 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3982 3982 if ui.verbose:
3983 3983 kwds, funcs = displayer.t.symbolsuseddefault()
3984 3984 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3985 3985 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3986 3986 for r in revs:
3987 3987 displayer.show(repo[r], **pycompat.strkwargs(props))
3988 3988 displayer.close()
3989 3989
3990 3990
3991 3991 @command(
3992 3992 b'debuguigetpass',
3993 3993 [
3994 3994 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3995 3995 ],
3996 3996 _(b'[-p TEXT]'),
3997 3997 norepo=True,
3998 3998 )
3999 3999 def debuguigetpass(ui, prompt=b''):
4000 4000 """show prompt to type password"""
4001 4001 r = ui.getpass(prompt)
4002 4002 if r is None:
4003 4003 r = b"<default response>"
4004 4004 ui.writenoi18n(b'response: %s\n' % r)
4005 4005
4006 4006
4007 4007 @command(
4008 4008 b'debuguiprompt',
4009 4009 [
4010 4010 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
4011 4011 ],
4012 4012 _(b'[-p TEXT]'),
4013 4013 norepo=True,
4014 4014 )
4015 4015 def debuguiprompt(ui, prompt=b''):
4016 4016 """show plain prompt"""
4017 4017 r = ui.prompt(prompt)
4018 4018 ui.writenoi18n(b'response: %s\n' % r)
4019 4019
4020 4020
4021 4021 @command(b'debugupdatecaches', [])
4022 4022 def debugupdatecaches(ui, repo, *pats, **opts):
4023 4023 """warm all known caches in the repository"""
4024 4024 with repo.wlock(), repo.lock():
4025 4025 repo.updatecaches(caches=repository.CACHES_ALL)
4026 4026
4027 4027
4028 4028 @command(
4029 4029 b'debugupgraderepo',
4030 4030 [
4031 4031 (
4032 4032 b'o',
4033 4033 b'optimize',
4034 4034 [],
4035 4035 _(b'extra optimization to perform'),
4036 4036 _(b'NAME'),
4037 4037 ),
4038 4038 (b'', b'run', False, _(b'performs an upgrade')),
4039 4039 (b'', b'backup', True, _(b'keep the old repository content around')),
4040 4040 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4041 4041 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4042 4042 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4043 4043 ],
4044 4044 )
4045 4045 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4046 4046 """upgrade a repository to use different features
4047 4047
4048 4048 If no arguments are specified, the repository is evaluated for upgrade
4049 4049 and a list of problems and potential optimizations is printed.
4050 4050
4051 4051 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4052 4052 can be influenced via additional arguments. More details will be provided
4053 4053 by the command output when run without ``--run``.
4054 4054
4055 4055 During the upgrade, the repository will be locked and no writes will be
4056 4056 allowed.
4057 4057
4058 4058 At the end of the upgrade, the repository may not be readable while new
4059 4059 repository data is swapped in. This window will be as long as it takes to
4060 4060 rename some directories inside the ``.hg`` directory. On most machines, this
4061 4061 should complete almost instantaneously and the chances of a consumer being
4062 4062 unable to access the repository should be low.
4063 4063
4064 4064 By default, all revlogs will be upgraded. You can restrict this using flags
4065 4065 such as `--manifest`:
4066 4066
4067 4067 * `--manifest`: only optimize the manifest
4068 4068 * `--no-manifest`: optimize all revlog but the manifest
4069 4069 * `--changelog`: optimize the changelog only
4070 4070 * `--no-changelog --no-manifest`: optimize filelogs only
4071 4071 * `--filelogs`: optimize the filelogs only
4072 4072 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4073 4073 """
4074 4074 return upgrade.upgraderepo(
4075 4075 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4076 4076 )
4077 4077
4078 4078
4079 4079 @command(
4080 4080 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4081 4081 )
4082 4082 def debugwalk(ui, repo, *pats, **opts):
4083 4083 """show how files match on given patterns"""
4084 4084 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
4085 4085 if ui.verbose:
4086 4086 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4087 4087 items = list(repo[None].walk(m))
4088 4088 if not items:
4089 4089 return
4090 4090 f = lambda fn: fn
4091 4091 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4092 4092 f = lambda fn: util.normpath(fn)
4093 4093 fmt = b'f %%-%ds %%-%ds %%s' % (
4094 4094 max([len(abs) for abs in items]),
4095 4095 max([len(repo.pathto(abs)) for abs in items]),
4096 4096 )
4097 4097 for abs in items:
4098 4098 line = fmt % (
4099 4099 abs,
4100 4100 f(repo.pathto(abs)),
4101 4101 m.exact(abs) and b'exact' or b'',
4102 4102 )
4103 4103 ui.write(b"%s\n" % line.rstrip())
4104 4104
4105 4105
4106 4106 @command(b'debugwhyunstable', [], _(b'REV'))
4107 4107 def debugwhyunstable(ui, repo, rev):
4108 4108 """explain instabilities of a changeset"""
4109 4109 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4110 4110 dnodes = b''
4111 4111 if entry.get(b'divergentnodes'):
4112 4112 dnodes = (
4113 4113 b' '.join(
4114 4114 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4115 4115 for ctx in entry[b'divergentnodes']
4116 4116 )
4117 4117 + b' '
4118 4118 )
4119 4119 ui.write(
4120 4120 b'%s: %s%s %s\n'
4121 4121 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4122 4122 )
4123 4123
4124 4124
4125 4125 @command(
4126 4126 b'debugwireargs',
4127 4127 [
4128 4128 (b'', b'three', b'', b'three'),
4129 4129 (b'', b'four', b'', b'four'),
4130 4130 (b'', b'five', b'', b'five'),
4131 4131 ]
4132 4132 + cmdutil.remoteopts,
4133 4133 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4134 4134 norepo=True,
4135 4135 )
4136 4136 def debugwireargs(ui, repopath, *vals, **opts):
4137 4137 repo = hg.peer(ui, pycompat.byteskwargs(opts), repopath)
4138 4138 try:
4139 4139 for opt in cmdutil.remoteopts:
4140 4140 del opts[pycompat.sysstr(opt[1])]
4141 4141 args = {}
4142 4142 for k, v in opts.items():
4143 4143 if v:
4144 4144 args[k] = v
4145 4145
4146 4146 # run twice to check that we don't mess up the stream for the next command
4147 4147 res1 = repo.debugwireargs(*vals, **args)
4148 4148 res2 = repo.debugwireargs(*vals, **args)
4149 4149 ui.write(b"%s\n" % res1)
4150 4150 if res1 != res2:
4151 4151 ui.warn(b"%s\n" % res2)
4152 4152 finally:
4153 4153 repo.close()
4154 4154
4155 4155
4156 4156 def _parsewirelangblocks(fh):
4157 4157 activeaction = None
4158 4158 blocklines = []
4159 4159 lastindent = 0
4160 4160
4161 4161 for line in fh:
4162 4162 line = line.rstrip()
4163 4163 if not line:
4164 4164 continue
4165 4165
4166 4166 if line.startswith(b'#'):
4167 4167 continue
4168 4168
4169 4169 if not line.startswith(b' '):
4170 4170 # New block. Flush previous one.
4171 4171 if activeaction:
4172 4172 yield activeaction, blocklines
4173 4173
4174 4174 activeaction = line
4175 4175 blocklines = []
4176 4176 lastindent = 0
4177 4177 continue
4178 4178
4179 4179 # Else we start with an indent.
4180 4180
4181 4181 if not activeaction:
4182 4182 raise error.Abort(_(b'indented line outside of block'))
4183 4183
4184 4184 indent = len(line) - len(line.lstrip())
4185 4185
4186 4186 # If this line is indented more than the last line, concatenate it.
4187 4187 if indent > lastindent and blocklines:
4188 4188 blocklines[-1] += line.lstrip()
4189 4189 else:
4190 4190 blocklines.append(line)
4191 4191 lastindent = indent
4192 4192
4193 4193 # Flush last block.
4194 4194 if activeaction:
4195 4195 yield activeaction, blocklines
4196 4196
4197 4197
4198 4198 @command(
4199 4199 b'debugwireproto',
4200 4200 [
4201 4201 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4202 4202 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4203 4203 (
4204 4204 b'',
4205 4205 b'noreadstderr',
4206 4206 False,
4207 4207 _(b'do not read from stderr of the remote'),
4208 4208 ),
4209 4209 (
4210 4210 b'',
4211 4211 b'nologhandshake',
4212 4212 False,
4213 4213 _(b'do not log I/O related to the peer handshake'),
4214 4214 ),
4215 4215 ]
4216 4216 + cmdutil.remoteopts,
4217 4217 _(b'[PATH]'),
4218 4218 optionalrepo=True,
4219 4219 )
4220 4220 def debugwireproto(ui, repo, path=None, **opts):
4221 4221 """send wire protocol commands to a server
4222 4222
4223 4223 This command can be used to issue wire protocol commands to remote
4224 4224 peers and to debug the raw data being exchanged.
4225 4225
4226 4226 ``--localssh`` will start an SSH server against the current repository
4227 4227 and connect to that. By default, the connection will perform a handshake
4228 4228 and establish an appropriate peer instance.
4229 4229
4230 4230 ``--peer`` can be used to bypass the handshake protocol and construct a
4231 4231 peer instance using the specified class type. Valid values are ``raw``,
4232 4232 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4233 4233 don't support higher-level command actions.
4234 4234
4235 4235 ``--noreadstderr`` can be used to disable automatic reading from stderr
4236 4236 of the peer (for SSH connections only). Disabling automatic reading of
4237 4237 stderr is useful for making output more deterministic.
4238 4238
4239 4239 Commands are issued via a mini language which is specified via stdin.
4240 4240 The language consists of individual actions to perform. An action is
4241 4241 defined by a block. A block is defined as a line with no leading
4242 4242 space followed by 0 or more lines with leading space. Blocks are
4243 4243 effectively a high-level command with additional metadata.
4244 4244
4245 4245 Lines beginning with ``#`` are ignored.
4246 4246
4247 4247 The following sections denote available actions.
4248 4248
4249 4249 raw
4250 4250 ---
4251 4251
4252 4252 Send raw data to the server.
4253 4253
4254 4254 The block payload contains the raw data to send as one atomic send
4255 4255 operation. The data may not actually be delivered in a single system
4256 4256 call: it depends on the abilities of the transport being used.
4257 4257
4258 4258 Each line in the block is de-indented and concatenated. Then, that
4259 4259 value is evaluated as a Python b'' literal. This allows the use of
4260 4260 backslash escaping, etc.
4261 4261
4262 4262 raw+
4263 4263 ----
4264 4264
4265 4265 Behaves like ``raw`` except flushes output afterwards.
4266 4266
4267 4267 command <X>
4268 4268 -----------
4269 4269
4270 4270 Send a request to run a named command, whose name follows the ``command``
4271 4271 string.
4272 4272
4273 4273 Arguments to the command are defined as lines in this block. The format of
4274 4274 each line is ``<key> <value>``. e.g.::
4275 4275
4276 4276 command listkeys
4277 4277 namespace bookmarks
4278 4278
4279 4279 If the value begins with ``eval:``, it will be interpreted as a Python
4280 4280 literal expression. Otherwise values are interpreted as Python b'' literals.
4281 4281 This allows sending complex types and encoding special byte sequences via
4282 4282 backslash escaping.
4283 4283
4284 4284 The following arguments have special meaning:
4285 4285
4286 4286 ``PUSHFILE``
4287 4287 When defined, the *push* mechanism of the peer will be used instead
4288 4288 of the static request-response mechanism and the content of the
4289 4289 file specified in the value of this argument will be sent as the
4290 4290 command payload.
4291 4291
4292 4292 This can be used to submit a local bundle file to the remote.
4293 4293
4294 4294 batchbegin
4295 4295 ----------
4296 4296
4297 4297 Instruct the peer to begin a batched send.
4298 4298
4299 4299 All ``command`` blocks are queued for execution until the next
4300 4300 ``batchsubmit`` block.
4301 4301
4302 4302 batchsubmit
4303 4303 -----------
4304 4304
4305 4305 Submit previously queued ``command`` blocks as a batch request.
4306 4306
4307 4307 This action MUST be paired with a ``batchbegin`` action.
4308 4308
4309 4309 httprequest <method> <path>
4310 4310 ---------------------------
4311 4311
4312 4312 (HTTP peer only)
4313 4313
4314 4314 Send an HTTP request to the peer.
4315 4315
4316 4316 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4317 4317
4318 4318 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4319 4319 headers to add to the request. e.g. ``Accept: foo``.
4320 4320
4321 4321 The following arguments are special:
4322 4322
4323 4323 ``BODYFILE``
4324 4324 The content of the file defined as the value to this argument will be
4325 4325 transferred verbatim as the HTTP request body.
4326 4326
4327 4327 ``frame <type> <flags> <payload>``
4328 4328 Send a unified protocol frame as part of the request body.
4329 4329
4330 4330 All frames will be collected and sent as the body to the HTTP
4331 4331 request.
4332 4332
4333 4333 close
4334 4334 -----
4335 4335
4336 4336 Close the connection to the server.
4337 4337
4338 4338 flush
4339 4339 -----
4340 4340
4341 4341 Flush data written to the server.
4342 4342
4343 4343 readavailable
4344 4344 -------------
4345 4345
4346 4346 Close the write end of the connection and read all available data from
4347 4347 the server.
4348 4348
4349 4349 If the connection to the server encompasses multiple pipes, we poll both
4350 4350 pipes and read available data.
4351 4351
4352 4352 readline
4353 4353 --------
4354 4354
4355 4355 Read a line of output from the server. If there are multiple output
4356 4356 pipes, reads only the main pipe.
4357 4357
4358 4358 ereadline
4359 4359 ---------
4360 4360
4361 4361 Like ``readline``, but read from the stderr pipe, if available.
4362 4362
4363 4363 read <X>
4364 4364 --------
4365 4365
4366 4366 ``read()`` N bytes from the server's main output pipe.
4367 4367
4368 4368 eread <X>
4369 4369 ---------
4370 4370
4371 4371 ``read()`` N bytes from the server's stderr pipe, if available.
4372 4372
4373 4373 Specifying Unified Frame-Based Protocol Frames
4374 4374 ----------------------------------------------
4375 4375
4376 4376 It is possible to emit a *Unified Frame-Based Protocol* by using special
4377 4377 syntax.
4378 4378
4379 4379 A frame is composed as a type, flags, and payload. These can be parsed
4380 4380 from a string of the form:
4381 4381
4382 4382 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4383 4383
4384 4384 ``request-id`` and ``stream-id`` are integers defining the request and
4385 4385 stream identifiers.
4386 4386
4387 4387 ``type`` can be an integer value for the frame type or the string name
4388 4388 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4389 4389 ``command-name``.
4390 4390
4391 4391 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4392 4392 components. Each component (and there can be just one) can be an integer
4393 4393 or a flag name for stream flags or frame flags, respectively. Values are
4394 4394 resolved to integers and then bitwise OR'd together.
4395 4395
4396 4396 ``payload`` represents the raw frame payload. If it begins with
4397 4397 ``cbor:``, the following string is evaluated as Python code and the
4398 4398 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4399 4399 as a Python byte string literal.
4400 4400 """
4401 4401 if opts['localssh'] and not repo:
4402 4402 raise error.Abort(_(b'--localssh requires a repository'))
4403 4403
4404 4404 if opts['peer'] and opts['peer'] not in (
4405 4405 b'raw',
4406 4406 b'ssh1',
4407 4407 ):
4408 4408 raise error.Abort(
4409 4409 _(b'invalid value for --peer'),
4410 4410 hint=_(b'valid values are "raw" and "ssh1"'),
4411 4411 )
4412 4412
4413 4413 if path and opts['localssh']:
4414 4414 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4415 4415
4416 4416 if ui.interactive():
4417 4417 ui.write(_(b'(waiting for commands on stdin)\n'))
4418 4418
4419 4419 blocks = list(_parsewirelangblocks(ui.fin))
4420 4420
4421 4421 proc = None
4422 4422 stdin = None
4423 4423 stdout = None
4424 4424 stderr = None
4425 4425 opener = None
4426 4426
4427 4427 if opts['localssh']:
4428 4428 # We start the SSH server in its own process so there is process
4429 4429 # separation. This prevents a whole class of potential bugs around
4430 4430 # shared state from interfering with server operation.
4431 4431 args = procutil.hgcmd() + [
4432 4432 b'-R',
4433 4433 repo.root,
4434 4434 b'debugserve',
4435 4435 b'--sshstdio',
4436 4436 ]
4437 4437 proc = subprocess.Popen(
4438 4438 pycompat.rapply(procutil.tonativestr, args),
4439 4439 stdin=subprocess.PIPE,
4440 4440 stdout=subprocess.PIPE,
4441 4441 stderr=subprocess.PIPE,
4442 4442 bufsize=0,
4443 4443 )
4444 4444
4445 4445 stdin = proc.stdin
4446 4446 stdout = proc.stdout
4447 4447 stderr = proc.stderr
4448 4448
4449 4449 # We turn the pipes into observers so we can log I/O.
4450 4450 if ui.verbose or opts['peer'] == b'raw':
4451 4451 stdin = util.makeloggingfileobject(
4452 4452 ui, proc.stdin, b'i', logdata=True
4453 4453 )
4454 4454 stdout = util.makeloggingfileobject(
4455 4455 ui, proc.stdout, b'o', logdata=True
4456 4456 )
4457 4457 stderr = util.makeloggingfileobject(
4458 4458 ui, proc.stderr, b'e', logdata=True
4459 4459 )
4460 4460
4461 4461 # --localssh also implies the peer connection settings.
4462 4462
4463 4463 url = b'ssh://localserver'
4464 4464 autoreadstderr = not opts['noreadstderr']
4465 4465
4466 4466 if opts['peer'] == b'ssh1':
4467 4467 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4468 4468 peer = sshpeer.sshv1peer(
4469 4469 ui,
4470 4470 url,
4471 4471 proc,
4472 4472 stdin,
4473 4473 stdout,
4474 4474 stderr,
4475 4475 None,
4476 4476 autoreadstderr=autoreadstderr,
4477 4477 )
4478 4478 elif opts['peer'] == b'raw':
4479 4479 ui.write(_(b'using raw connection to peer\n'))
4480 4480 peer = None
4481 4481 else:
4482 4482 ui.write(_(b'creating ssh peer from handshake results\n'))
4483 4483 peer = sshpeer._make_peer(
4484 4484 ui,
4485 4485 url,
4486 4486 proc,
4487 4487 stdin,
4488 4488 stdout,
4489 4489 stderr,
4490 4490 autoreadstderr=autoreadstderr,
4491 4491 )
4492 4492
4493 4493 elif path:
4494 4494 # We bypass hg.peer() so we can proxy the sockets.
4495 4495 # TODO consider not doing this because we skip
4496 4496 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4497 4497 u = urlutil.url(path)
4498 4498 if u.scheme != b'http':
4499 4499 raise error.Abort(_(b'only http:// paths are currently supported'))
4500 4500
4501 4501 url, authinfo = u.authinfo()
4502 4502 openerargs = {
4503 4503 'useragent': b'Mercurial debugwireproto',
4504 4504 }
4505 4505
4506 4506 # Turn pipes/sockets into observers so we can log I/O.
4507 4507 if ui.verbose:
4508 4508 openerargs.update(
4509 4509 {
4510 4510 'loggingfh': ui,
4511 4511 'loggingname': b's',
4512 4512 'loggingopts': {
4513 4513 'logdata': True,
4514 4514 'logdataapis': False,
4515 4515 },
4516 4516 }
4517 4517 )
4518 4518
4519 4519 if ui.debugflag:
4520 4520 openerargs['loggingopts']['logdataapis'] = True
4521 4521
4522 4522 # Don't send default headers when in raw mode. This allows us to
4523 4523 # bypass most of the behavior of our URL handling code so we can
4524 4524 # have near complete control over what's sent on the wire.
4525 4525 if opts['peer'] == b'raw':
4526 4526 openerargs['sendaccept'] = False
4527 4527
4528 4528 opener = urlmod.opener(ui, authinfo, **openerargs)
4529 4529
4530 4530 if opts['peer'] == b'raw':
4531 4531 ui.write(_(b'using raw connection to peer\n'))
4532 4532 peer = None
4533 4533 elif opts['peer']:
4534 4534 raise error.Abort(
4535 4535 _(b'--peer %s not supported with HTTP peers') % opts['peer']
4536 4536 )
4537 4537 else:
4538 4538 peer_path = urlutil.try_path(ui, path)
4539 4539 peer = httppeer._make_peer(ui, peer_path, opener=opener)
4540 4540
4541 4541 # We /could/ populate stdin/stdout with sock.makefile()...
4542 4542 else:
4543 4543 raise error.Abort(_(b'unsupported connection configuration'))
4544 4544
4545 4545 batchedcommands = None
4546 4546
4547 4547 # Now perform actions based on the parsed wire language instructions.
4548 4548 for action, lines in blocks:
4549 4549 if action in (b'raw', b'raw+'):
4550 4550 if not stdin:
4551 4551 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4552 4552
4553 4553 # Concatenate the data together.
4554 4554 data = b''.join(l.lstrip() for l in lines)
4555 4555 data = stringutil.unescapestr(data)
4556 4556 stdin.write(data)
4557 4557
4558 4558 if action == b'raw+':
4559 4559 stdin.flush()
4560 4560 elif action == b'flush':
4561 4561 if not stdin:
4562 4562 raise error.Abort(_(b'cannot call flush on this peer'))
4563 4563 stdin.flush()
4564 4564 elif action.startswith(b'command'):
4565 4565 if not peer:
4566 4566 raise error.Abort(
4567 4567 _(
4568 4568 b'cannot send commands unless peer instance '
4569 4569 b'is available'
4570 4570 )
4571 4571 )
4572 4572
4573 4573 command = action.split(b' ', 1)[1]
4574 4574
4575 4575 args = {}
4576 4576 for line in lines:
4577 4577 # We need to allow empty values.
4578 4578 fields = line.lstrip().split(b' ', 1)
4579 4579 if len(fields) == 1:
4580 4580 key = fields[0]
4581 4581 value = b''
4582 4582 else:
4583 4583 key, value = fields
4584 4584
4585 4585 if value.startswith(b'eval:'):
4586 4586 value = stringutil.evalpythonliteral(value[5:])
4587 4587 else:
4588 4588 value = stringutil.unescapestr(value)
4589 4589
4590 4590 args[key] = value
4591 4591
4592 4592 if batchedcommands is not None:
4593 4593 batchedcommands.append((command, args))
4594 4594 continue
4595 4595
4596 4596 ui.status(_(b'sending %s command\n') % command)
4597 4597
4598 4598 if b'PUSHFILE' in args:
4599 4599 with open(args[b'PUSHFILE'], 'rb') as fh:
4600 4600 del args[b'PUSHFILE']
4601 4601 res, output = peer._callpush(
4602 4602 command, fh, **pycompat.strkwargs(args)
4603 4603 )
4604 4604 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4605 4605 ui.status(
4606 4606 _(b'remote output: %s\n') % stringutil.escapestr(output)
4607 4607 )
4608 4608 else:
4609 4609 with peer.commandexecutor() as e:
4610 4610 res = e.callcommand(command, args).result()
4611 4611
4612 4612 ui.status(
4613 4613 _(b'response: %s\n')
4614 4614 % stringutil.pprint(res, bprefix=True, indent=2)
4615 4615 )
4616 4616
4617 4617 elif action == b'batchbegin':
4618 4618 if batchedcommands is not None:
4619 4619 raise error.Abort(_(b'nested batchbegin not allowed'))
4620 4620
4621 4621 batchedcommands = []
4622 4622 elif action == b'batchsubmit':
4623 4623 # There is a batching API we could go through. But it would be
4624 4624 # difficult to normalize requests into function calls. It is easier
4625 4625 # to bypass this layer and normalize to commands + args.
4626 4626 ui.status(
4627 4627 _(b'sending batch with %d sub-commands\n')
4628 4628 % len(batchedcommands)
4629 4629 )
4630 4630 assert peer is not None
4631 4631 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4632 4632 ui.status(
4633 4633 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4634 4634 )
4635 4635
4636 4636 batchedcommands = None
4637 4637
4638 4638 elif action.startswith(b'httprequest '):
4639 4639 if not opener:
4640 4640 raise error.Abort(
4641 4641 _(b'cannot use httprequest without an HTTP peer')
4642 4642 )
4643 4643
4644 4644 request = action.split(b' ', 2)
4645 4645 if len(request) != 3:
4646 4646 raise error.Abort(
4647 4647 _(
4648 4648 b'invalid httprequest: expected format is '
4649 4649 b'"httprequest <method> <path>'
4650 4650 )
4651 4651 )
4652 4652
4653 4653 method, httppath = request[1:]
4654 4654 headers = {}
4655 4655 body = None
4656 4656 frames = []
4657 4657 for line in lines:
4658 4658 line = line.lstrip()
4659 4659 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4660 4660 if m:
4661 4661 # Headers need to use native strings.
4662 4662 key = pycompat.strurl(m.group(1))
4663 4663 value = pycompat.strurl(m.group(2))
4664 4664 headers[key] = value
4665 4665 continue
4666 4666
4667 4667 if line.startswith(b'BODYFILE '):
4668 4668 with open(line.split(b' ', 1), b'rb') as fh:
4669 4669 body = fh.read()
4670 4670 elif line.startswith(b'frame '):
4671 4671 frame = wireprotoframing.makeframefromhumanstring(
4672 4672 line[len(b'frame ') :]
4673 4673 )
4674 4674
4675 4675 frames.append(frame)
4676 4676 else:
4677 4677 raise error.Abort(
4678 4678 _(b'unknown argument to httprequest: %s') % line
4679 4679 )
4680 4680
4681 4681 url = path + httppath
4682 4682
4683 4683 if frames:
4684 4684 body = b''.join(bytes(f) for f in frames)
4685 4685
4686 4686 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4687 4687
4688 4688 # urllib.Request insists on using has_data() as a proxy for
4689 4689 # determining the request method. Override that to use our
4690 4690 # explicitly requested method.
4691 4691 req.get_method = lambda: pycompat.sysstr(method)
4692 4692
4693 4693 try:
4694 4694 res = opener.open(req)
4695 4695 body = res.read()
4696 4696 except util.urlerr.urlerror as e:
4697 4697 # read() method must be called, but only exists in Python 2
4698 4698 getattr(e, 'read', lambda: None)()
4699 4699 continue
4700 4700
4701 4701 ct = res.headers.get('Content-Type')
4702 4702 if ct == 'application/mercurial-cbor':
4703 4703 ui.write(
4704 4704 _(b'cbor> %s\n')
4705 4705 % stringutil.pprint(
4706 4706 cborutil.decodeall(body), bprefix=True, indent=2
4707 4707 )
4708 4708 )
4709 4709
4710 4710 elif action == b'close':
4711 4711 assert peer is not None
4712 4712 peer.close()
4713 4713 elif action == b'readavailable':
4714 4714 if not stdout or not stderr:
4715 4715 raise error.Abort(
4716 4716 _(b'readavailable not available on this peer')
4717 4717 )
4718 4718
4719 4719 stdin.close()
4720 4720 stdout.read()
4721 4721 stderr.read()
4722 4722
4723 4723 elif action == b'readline':
4724 4724 if not stdout:
4725 4725 raise error.Abort(_(b'readline not available on this peer'))
4726 4726 stdout.readline()
4727 4727 elif action == b'ereadline':
4728 4728 if not stderr:
4729 4729 raise error.Abort(_(b'ereadline not available on this peer'))
4730 4730 stderr.readline()
4731 4731 elif action.startswith(b'read '):
4732 4732 count = int(action.split(b' ', 1)[1])
4733 4733 if not stdout:
4734 4734 raise error.Abort(_(b'read not available on this peer'))
4735 4735 stdout.read(count)
4736 4736 elif action.startswith(b'eread '):
4737 4737 count = int(action.split(b' ', 1)[1])
4738 4738 if not stderr:
4739 4739 raise error.Abort(_(b'eread not available on this peer'))
4740 4740 stderr.read(count)
4741 4741 else:
4742 4742 raise error.Abort(_(b'unknown action: %s') % action)
4743 4743
4744 4744 if batchedcommands is not None:
4745 4745 raise error.Abort(_(b'unclosed "batchbegin" request'))
4746 4746
4747 4747 if peer:
4748 4748 peer.close()
4749 4749
4750 4750 if proc:
4751 4751 proc.kill()
@@ -1,41 +1,41 b''
1 1 #!/bin/bash
2 2 #
3 3 # Make sure to patch mercurial to create the delta against nullrev
4 4 #
5 5 # # Parent cdb85d0512b81031d4a7b30d6a5ddbe69ef1a876
6 6 #
7 7 # diff --git a/mercurial/revlogutils/deltas.py b/mercurial/revlogutils/deltas.py
8 8 # --- a/mercurial/revlogutils/deltas.py
9 9 # +++ b/mercurial/revlogutils/deltas.py
10 10 # @@ -1117,7 +1117,10 @@ class deltacomputer:
11 11 # candidaterevs = next(groups)
12 12 #
13 13 # if deltainfo is None:
14 14 # - deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev)
15 15 # + if revlog.delta_config.general_delta:
16 16 # + deltainfo = self._builddeltainfo(revinfo, nullrev, fh)
17 17 # + else:
18 18 # + deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev)
19 19
20 20
21 21 cd "`dirname \"$0\"`"
22 22 export HGRCPATH=
23 23 export HGMODULEPOLICY=py
24 24
25 25 rm -rf nullrev-diff
26 26 ../../hg init nullrev-diff --config format.revlog-compression=zlib
27 27 cd nullrev-diff
28 28 echo hi > a
29 29 ../../../hg commit -Am root-B
30 30 echo ho > a
31 31 ../../../hg commit -Am child-A
32 32 hg up null
33 33 echo ha > a
34 34 ../../../hg commit -Am root-A
35 ../../../hg debugdeltachain a
35 ../../../hg debugdeltachain a --all-info
36 36 rm -rf .hg/cache/ .hg/wcache/
37 37 cd ..
38 38
39 39 tar cf test-revlog-diff-relative-to-nullrev.tar nullrev-diff
40 40
41 41 rm -rf nullrev-diff
@@ -1,732 +1,818 b''
1 1 $ cat << EOF >> $HGRCPATH
2 2 > [ui]
3 3 > interactive=yes
4 4 > EOF
5 5
6 6 $ hg init debugrevlog
7 7 $ cd debugrevlog
8 8 $ echo a > a
9 9 $ hg ci -Am adda
10 10 adding a
11 11 $ hg rm .
12 12 removing a
13 13 $ hg ci -Am make-it-empty
14 14 $ hg revert --all -r 0
15 15 adding a
16 16 $ hg ci -Am make-it-full
17 17 #if reporevlogstore
18 18 $ hg debugrevlog -c
19 19 format : 1
20 20 flags : inline
21 21
22 22 revisions : 3
23 23 merges : 0 ( 0.00%)
24 24 normal : 3 (100.00%)
25 25 revisions : 3
26 26 empty : 0 ( 0.00%)
27 27 text : 0 (100.00%)
28 28 delta : 0 (100.00%)
29 29 snapshot : 3 (100.00%)
30 30 lvl-0 : 3 (100.00%)
31 31 deltas : 0 ( 0.00%)
32 32 revision size : 191
33 33 snapshot : 191 (100.00%)
34 34 lvl-0 : 191 (100.00%)
35 35 deltas : 0 ( 0.00%)
36 36
37 37 chunks : 3
38 38 0x75 (u) : 3 (100.00%)
39 39 chunks size : 191
40 40 0x75 (u) : 191 (100.00%)
41 41
42 42
43 43 total-stored-content: 188 bytes
44 44
45 45 avg chain length : 0
46 46 max chain length : 0
47 47 max chain reach : 67
48 48 compression ratio : 0
49 49
50 50 uncompressed data size (min/max/avg) : 57 / 66 / 62
51 51 full revision size (min/max/avg) : 58 / 67 / 63
52 52 inter-snapshot size (min/max/avg) : 0 / 0 / 0
53 53 delta size (min/max/avg) : 0 / 0 / 0
54 54 $ hg debugrevlog -m
55 55 format : 1
56 56 flags : inline, generaldelta
57 57
58 58 revisions : 3
59 59 merges : 0 ( 0.00%)
60 60 normal : 3 (100.00%)
61 61 revisions : 3
62 62 empty : 1 (33.33%)
63 63 text : 1 (100.00%)
64 64 delta : 0 ( 0.00%)
65 65 snapshot : 2 (66.67%)
66 66 lvl-0 : 2 (66.67%)
67 67 deltas : 0 ( 0.00%)
68 68 revision size : 88
69 69 snapshot : 88 (100.00%)
70 70 lvl-0 : 88 (100.00%)
71 71 deltas : 0 ( 0.00%)
72 72
73 73 chunks : 3
74 74 empty : 1 (33.33%)
75 75 0x75 (u) : 2 (66.67%)
76 76 chunks size : 88
77 77 empty : 0 ( 0.00%)
78 78 0x75 (u) : 88 (100.00%)
79 79
80 80
81 81 total-stored-content: 86 bytes
82 82
83 83 avg chain length : 0
84 84 max chain length : 0
85 85 max chain reach : 44
86 86 compression ratio : 0
87 87
88 88 uncompressed data size (min/max/avg) : 0 / 43 / 28
89 89 full revision size (min/max/avg) : 44 / 44 / 44
90 90 inter-snapshot size (min/max/avg) : 0 / 0 / 0
91 91 delta size (min/max/avg) : 0 / 0 / 0
92 92 $ hg debugrevlog a
93 93 format : 1
94 94 flags : inline, generaldelta
95 95
96 96 revisions : 1
97 97 merges : 0 ( 0.00%)
98 98 normal : 1 (100.00%)
99 99 revisions : 1
100 100 empty : 0 ( 0.00%)
101 101 text : 0 (100.00%)
102 102 delta : 0 (100.00%)
103 103 snapshot : 1 (100.00%)
104 104 lvl-0 : 1 (100.00%)
105 105 deltas : 0 ( 0.00%)
106 106 revision size : 3
107 107 snapshot : 3 (100.00%)
108 108 lvl-0 : 3 (100.00%)
109 109 deltas : 0 ( 0.00%)
110 110
111 111 chunks : 1
112 112 0x75 (u) : 1 (100.00%)
113 113 chunks size : 3
114 114 0x75 (u) : 3 (100.00%)
115 115
116 116
117 117 total-stored-content: 2 bytes
118 118
119 119 avg chain length : 0
120 120 max chain length : 0
121 121 max chain reach : 3
122 122 compression ratio : 0
123 123
124 124 uncompressed data size (min/max/avg) : 2 / 2 / 2
125 125 full revision size (min/max/avg) : 3 / 3 / 3
126 126 inter-snapshot size (min/max/avg) : 0 / 0 / 0
127 127 delta size (min/max/avg) : 0 / 0 / 0
128 128 #endif
129 129
130 130 Test debugindex, with and without the --verbose/--debug flag
131 131 $ hg debugrevlogindex a
132 132 rev linkrev nodeid p1 p2
133 133 0 0 b789fdd96dc2 000000000000 000000000000
134 134
135 135 #if no-reposimplestore
136 136 $ hg --verbose debugrevlogindex a
137 137 rev offset length linkrev nodeid p1 p2
138 138 0 0 3 0 b789fdd96dc2 000000000000 000000000000
139 139
140 140 $ hg --debug debugrevlogindex a
141 141 rev offset length linkrev nodeid p1 p2
142 142 0 0 3 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
143 143 #endif
144 144
145 145 $ hg debugrevlogindex -f 1 a
146 146 rev flag size link p1 p2 nodeid
147 147 0 0000 2 0 -1 -1 b789fdd96dc2
148 148
149 149 #if no-reposimplestore
150 150 $ hg --verbose debugrevlogindex -f 1 a
151 151 rev flag offset length size link p1 p2 nodeid
152 152 0 0000 0 3 2 0 -1 -1 b789fdd96dc2
153 153
154 154 $ hg --debug debugrevlogindex -f 1 a
155 155 rev flag offset length size link p1 p2 nodeid
156 156 0 0000 0 3 2 0 -1 -1 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
157 157 #endif
158 158
159 159 $ hg debugindex -c
160 160 rev linkrev nodeid p1-nodeid p2-nodeid
161 161 0 0 07f494440405 000000000000 000000000000
162 162 1 1 8cccb4b5fec2 07f494440405 000000000000
163 163 2 2 b1e228c512c5 8cccb4b5fec2 000000000000
164 164 $ hg debugindex -c --debug
165 165 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
166 166 0 -1 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 57 0 0 2 0 58 inline 0 0
167 167 1 -1 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a 0 07f4944404050f47db2e5c5071e0e84e7a27bba9 -1 0000000000000000000000000000000000000000 66 1 0 2 58 67 inline 0 0
168 168 2 -1 2 b1e228c512c5d7066d70562ed839c3323a62d6d2 1 8cccb4b5fec20cafeb99dd01c26d4dee8ea4388a -1 0000000000000000000000000000000000000000 65 2 0 2 125 66 inline 0 0
169 169 $ hg debugindex -m
170 170 rev linkrev nodeid p1-nodeid p2-nodeid
171 171 0 0 a0c8bcbbb45c 000000000000 000000000000
172 172 1 1 57faf8a737ae a0c8bcbbb45c 000000000000
173 173 2 2 a35b10320954 57faf8a737ae 000000000000
174 174 $ hg debugindex -m --debug
175 175 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
176 176 0 -1 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 43 0 0 2 0 44 inline 0 0
177 177 1 -1 1 57faf8a737ae7faf490582941a82319ba6529dca 0 a0c8bcbbb45c63b90b70ad007bf38961f64f2af0 -1 0000000000000000000000000000000000000000 0 1 0 2 44 0 inline 0 0
178 178 2 -1 2 a35b103209548032201c16c7688cb2657f037a38 1 57faf8a737ae7faf490582941a82319ba6529dca -1 0000000000000000000000000000000000000000 43 2 0 2 44 44 inline 0 0
179 179 $ hg debugindex a
180 180 rev linkrev nodeid p1-nodeid p2-nodeid
181 181 0 0 b789fdd96dc2 000000000000 000000000000
182 182 $ hg debugindex --debug a
183 183 rev rank linkrev nodeid p1-rev p1-nodeid p2-rev p2-nodeid full-size delta-base flags comp-mode data-offset chunk-size sd-comp-mode sidedata-offset sd-chunk-size
184 184 0 -1 0 b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3 -1 0000000000000000000000000000000000000000 -1 0000000000000000000000000000000000000000 2 0 0 2 0 3 inline 0 0
185 185
186 186 debugdelta chain basic output
187 187
188 188 #if reporevlogstore pure
189 189 $ hg debugindexstats
190 190 abort: debugindexstats only works with native code
191 191 [255]
192 192 #endif
193 193 #if reporevlogstore no-pure
194 194 $ hg debugindexstats
195 195 node trie capacity: 4
196 196 node trie count: 2
197 197 node trie depth: 1
198 198 node trie last rev scanned: -1 (no-rust !)
199 199 node trie last rev scanned: 3 (rust !)
200 200 node trie lookups: 4 (no-rust !)
201 201 node trie lookups: 2 (rust !)
202 202 node trie misses: 1
203 203 node trie splits: 1
204 204 revs in memory: 3
205 205 #endif
206 206
207 207 #if reporevlogstore no-pure
208 $ hg debugdeltachain -m
208 $ hg debugdeltachain -m --all-info
209 209 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
210 210 0 -1 -1 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
211 211 1 0 -1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
212 212 2 1 -1 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
213 213
214 214 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen}\n'
215 215 0 1 1
216 216 1 2 1
217 217 2 3 1
218 218
219 $ hg debugdeltachain -m -Tjson
219 $ hg debugdeltachain -m -Tjson --size-info
220 [
221 {
222 "chainid": 1,
223 "chainlen": 1,
224 "chainratio": 1.0232558139534884,
225 "chainsize": 44,
226 "compsize": 44,
227 "deltatype": "base",
228 "p1": -1,
229 "p2": -1,
230 "prevrev": -1,
231 "rev": 0,
232 "uncompsize": 43
233 },
234 {
235 "chainid": 2,
236 "chainlen": 1,
237 "chainratio": 0,
238 "chainsize": 0,
239 "compsize": 0,
240 "deltatype": "base",
241 "p1": 0,
242 "p2": -1,
243 "prevrev": -1,
244 "rev": 1,
245 "uncompsize": 0
246 },
247 {
248 "chainid": 3,
249 "chainlen": 1,
250 "chainratio": 1.0232558139534884,
251 "chainsize": 44,
252 "compsize": 44,
253 "deltatype": "base",
254 "p1": 1,
255 "p2": -1,
256 "prevrev": -1,
257 "rev": 2,
258 "uncompsize": 43
259 }
260 ]
261
262 $ hg debugdeltachain -m -Tjson --all-info
220 263 [
221 264 {
222 265 "chainid": 1,
223 266 "chainlen": 1,
224 267 "chainratio": 1.0232558139534884,
225 268 "chainsize": 44,
226 269 "compsize": 44,
227 270 "deltatype": "base",
228 271 "extradist": 0,
229 272 "extraratio": 0.0,
230 273 "largestblock": 44,
231 274 "lindist": 44,
232 275 "p1": -1,
233 276 "p2": -1,
234 277 "prevrev": -1,
235 278 "readdensity": 1.0,
236 279 "readsize": 44,
237 280 "rev": 0,
238 281 "srchunks": 1,
239 282 "uncompsize": 43
240 283 },
241 284 {
242 285 "chainid": 2,
243 286 "chainlen": 1,
244 287 "chainratio": 0,
245 288 "chainsize": 0,
246 289 "compsize": 0,
247 290 "deltatype": "base",
248 291 "extradist": 0,
249 292 "extraratio": 0,
250 293 "largestblock": 0,
251 294 "lindist": 0,
252 295 "p1": 0,
253 296 "p2": -1,
254 297 "prevrev": -1,
255 298 "readdensity": 1,
256 299 "readsize": 0,
257 300 "rev": 1,
258 301 "srchunks": 1,
259 302 "uncompsize": 0
260 303 },
261 304 {
262 305 "chainid": 3,
263 306 "chainlen": 1,
264 307 "chainratio": 1.0232558139534884,
265 308 "chainsize": 44,
266 309 "compsize": 44,
267 310 "deltatype": "base",
268 311 "extradist": 0,
269 312 "extraratio": 0.0,
270 313 "largestblock": 44,
271 314 "lindist": 44,
272 315 "p1": 1,
273 316 "p2": -1,
274 317 "prevrev": -1,
275 318 "readdensity": 1.0,
276 319 "readsize": 44,
277 320 "rev": 2,
278 321 "srchunks": 1,
279 322 "uncompsize": 43
280 323 }
281 324 ]
282 325
283 326 debugdelta chain with sparse read enabled
284 327
285 328 $ cat >> $HGRCPATH <<EOF
286 329 > [experimental]
287 330 > sparse-read = True
288 331 > EOF
289 $ hg debugdeltachain -m
332 $ hg debugdeltachain -m --all-info
290 333 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
291 334 0 -1 -1 1 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
292 335 1 0 -1 2 1 -1 base 0 0 0 0.00000 0 0 0.00000 0 0 1.00000 1
293 336 2 1 -1 3 1 -1 base 44 43 44 1.02326 44 0 0.00000 44 44 1.00000 1
294 337
295 $ hg debugdeltachain -m -T '{rev} {chainid} {chainlen} {readsize} {largestblock} {readdensity}\n'
338 $ hg debugdeltachain -m --sparse-info -T '{rev} {chainid} {chainlen} {readsize} {largestblock} {readdensity}\n'
296 339 0 1 1 44 44 1.0
297 340 1 2 1 0 0 1
298 341 2 3 1 44 44 1.0
299 342
300 $ hg debugdeltachain -m -Tjson
343 $ hg debugdeltachain -m -Tjson --sparse-info
344 [
345 {
346 "chainid": 1,
347 "chainlen": 1,
348 "deltatype": "base",
349 "largestblock": 44,
350 "p1": -1,
351 "p2": -1,
352 "prevrev": -1,
353 "readdensity": 1.0,
354 "readsize": 44,
355 "rev": 0,
356 "srchunks": 1
357 },
358 {
359 "chainid": 2,
360 "chainlen": 1,
361 "deltatype": "base",
362 "largestblock": 0,
363 "p1": 0,
364 "p2": -1,
365 "prevrev": -1,
366 "readdensity": 1,
367 "readsize": 0,
368 "rev": 1,
369 "srchunks": 1
370 },
371 {
372 "chainid": 3,
373 "chainlen": 1,
374 "deltatype": "base",
375 "largestblock": 44,
376 "p1": 1,
377 "p2": -1,
378 "prevrev": -1,
379 "readdensity": 1.0,
380 "readsize": 44,
381 "rev": 2,
382 "srchunks": 1
383 }
384 ]
385
386 $ hg debugdeltachain -m -Tjson --all-info
301 387 [
302 388 {
303 389 "chainid": 1,
304 390 "chainlen": 1,
305 391 "chainratio": 1.0232558139534884,
306 392 "chainsize": 44,
307 393 "compsize": 44,
308 394 "deltatype": "base",
309 395 "extradist": 0,
310 396 "extraratio": 0.0,
311 397 "largestblock": 44,
312 398 "lindist": 44,
313 399 "p1": -1,
314 400 "p2": -1,
315 401 "prevrev": -1,
316 402 "readdensity": 1.0,
317 403 "readsize": 44,
318 404 "rev": 0,
319 405 "srchunks": 1,
320 406 "uncompsize": 43
321 407 },
322 408 {
323 409 "chainid": 2,
324 410 "chainlen": 1,
325 411 "chainratio": 0,
326 412 "chainsize": 0,
327 413 "compsize": 0,
328 414 "deltatype": "base",
329 415 "extradist": 0,
330 416 "extraratio": 0,
331 417 "largestblock": 0,
332 418 "lindist": 0,
333 419 "p1": 0,
334 420 "p2": -1,
335 421 "prevrev": -1,
336 422 "readdensity": 1,
337 423 "readsize": 0,
338 424 "rev": 1,
339 425 "srchunks": 1,
340 426 "uncompsize": 0
341 427 },
342 428 {
343 429 "chainid": 3,
344 430 "chainlen": 1,
345 431 "chainratio": 1.0232558139534884,
346 432 "chainsize": 44,
347 433 "compsize": 44,
348 434 "deltatype": "base",
349 435 "extradist": 0,
350 436 "extraratio": 0.0,
351 437 "largestblock": 44,
352 438 "lindist": 44,
353 439 "p1": 1,
354 440 "p2": -1,
355 441 "prevrev": -1,
356 442 "readdensity": 1.0,
357 443 "readsize": 44,
358 444 "rev": 2,
359 445 "srchunks": 1,
360 446 "uncompsize": 43
361 447 }
362 448 ]
363 449
364 450 $ printf "This test checks things.\n" >> a
365 451 $ hg ci -m a
366 452 $ hg branch other
367 453 marked working directory as branch other
368 454 (branches are permanent and global, did you want a bookmark?)
369 455 $ for i in `$TESTDIR/seq.py 5`; do
370 456 > printf "shorter ${i}" >> a
371 457 > hg ci -m "a other:$i"
372 458 > hg up -q default
373 459 > printf "for the branch default we want longer chains: ${i}" >> a
374 460 > hg ci -m "a default:$i"
375 461 > hg up -q other
376 462 > done
377 $ hg debugdeltachain a -T '{rev} {srchunks}\n' \
463 $ hg debugdeltachain a -T '{rev} {srchunks}\n' --all-info\
378 464 > --config experimental.sparse-read.density-threshold=0.50 \
379 465 > --config experimental.sparse-read.min-gap-size=0
380 466 0 1
381 467 1 1
382 468 2 1
383 469 3 1
384 470 4 1
385 471 5 1
386 472 6 1
387 473 7 1
388 474 8 1
389 475 9 1
390 476 10 2 (no-zstd !)
391 477 10 1 (zstd !)
392 478 11 1
393 479 $ hg --config extensions.strip= strip --no-backup -r 1
394 480 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
395 481
396 482 Test max chain len
397 483 $ cat >> $HGRCPATH << EOF
398 484 > [format]
399 485 > maxchainlen=4
400 486 > EOF
401 487
402 488 $ printf "This test checks if maxchainlen config value is respected also it can serve as basic test for debugrevlog -d <file>.\n" >> a
403 489 $ hg ci -m a
404 490 $ printf "b\n" >> a
405 491 $ hg ci -m a
406 492 $ printf "c\n" >> a
407 493 $ hg ci -m a
408 494 $ printf "d\n" >> a
409 495 $ hg ci -m a
410 496 $ printf "e\n" >> a
411 497 $ hg ci -m a
412 498 $ printf "f\n" >> a
413 499 $ hg ci -m a
414 500 $ printf 'g\n' >> a
415 501 $ hg ci -m a
416 502 $ printf 'h\n' >> a
417 503 $ hg ci -m a
418 504
419 505 $ hg debugrevlog -d a
420 506 # rev p1rev p2rev start end deltastart base p1 p2 rawsize totalsize compression heads chainlen
421 507 0 -1 -1 0 ??? 0 0 0 0 ??? ???? ? 1 0 (glob)
422 508 1 0 -1 ??? ??? 0 0 0 0 ??? ???? ? 1 1 (glob)
423 509 2 1 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
424 510 3 2 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
425 511 4 3 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 4 (glob)
426 512 5 4 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 0 (glob)
427 513 6 5 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 1 (glob)
428 514 7 6 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 2 (glob)
429 515 8 7 -1 ??? ??? ??? ??? ??? 0 ??? ???? ? 1 3 (glob)
430 516 #endif
431 517
432 518 Test debuglocks command:
433 519
434 520 $ hg debuglocks
435 521 lock: free
436 522 wlock: free
437 523
438 524 * Test setting the lock
439 525
440 526 waitlock <file> will wait for file to be created. If it isn't in a reasonable
441 527 amount of time, displays error message and returns 1
442 528 $ waitlock() {
443 529 > start=`date +%s`
444 530 > timeout=5
445 531 > while [ \( ! -f $1 \) -a \( ! -L $1 \) ]; do
446 532 > now=`date +%s`
447 533 > if [ "`expr $now - $start`" -gt $timeout ]; then
448 534 > echo "timeout: $1 was not created in $timeout seconds"
449 535 > return 1
450 536 > fi
451 537 > sleep 0.1
452 538 > done
453 539 > }
454 540 $ dolock() {
455 541 > {
456 542 > waitlock .hg/unlock
457 543 > rm -f .hg/unlock
458 544 > echo y
459 545 > } | hg debuglocks "$@" > /dev/null
460 546 > }
461 547 $ dolock -s &
462 548 $ waitlock .hg/store/lock
463 549
464 550 $ hg debuglocks
465 551 lock: user *, process * (*s) (glob)
466 552 wlock: free
467 553 [1]
468 554 $ touch .hg/unlock
469 555 $ wait
470 556 $ [ -f .hg/store/lock ] || echo "There is no lock"
471 557 There is no lock
472 558
473 559 * Test setting the wlock
474 560
475 561 $ dolock -S &
476 562 $ waitlock .hg/wlock
477 563
478 564 $ hg debuglocks
479 565 lock: free
480 566 wlock: user *, process * (*s) (glob)
481 567 [1]
482 568 $ touch .hg/unlock
483 569 $ wait
484 570 $ [ -f .hg/wlock ] || echo "There is no wlock"
485 571 There is no wlock
486 572
487 573 * Test setting both locks
488 574
489 575 $ dolock -Ss &
490 576 $ waitlock .hg/wlock && waitlock .hg/store/lock
491 577
492 578 $ hg debuglocks
493 579 lock: user *, process * (*s) (glob)
494 580 wlock: user *, process * (*s) (glob)
495 581 [2]
496 582
497 583 * Test failing to set a lock
498 584
499 585 $ hg debuglocks -s
500 586 abort: lock is already held
501 587 [255]
502 588
503 589 $ hg debuglocks -S
504 590 abort: wlock is already held
505 591 [255]
506 592
507 593 $ touch .hg/unlock
508 594 $ wait
509 595
510 596 $ hg debuglocks
511 597 lock: free
512 598 wlock: free
513 599
514 600 * Test forcing the lock
515 601
516 602 $ dolock -s &
517 603 $ waitlock .hg/store/lock
518 604
519 605 $ hg debuglocks
520 606 lock: user *, process * (*s) (glob)
521 607 wlock: free
522 608 [1]
523 609
524 610 $ hg debuglocks -L
525 611
526 612 $ hg debuglocks
527 613 lock: free
528 614 wlock: free
529 615
530 616 $ touch .hg/unlock
531 617 $ wait
532 618
533 619 * Test forcing the wlock
534 620
535 621 $ dolock -S &
536 622 $ waitlock .hg/wlock
537 623
538 624 $ hg debuglocks
539 625 lock: free
540 626 wlock: user *, process * (*s) (glob)
541 627 [1]
542 628
543 629 $ hg debuglocks -W
544 630
545 631 $ hg debuglocks
546 632 lock: free
547 633 wlock: free
548 634
549 635 $ touch .hg/unlock
550 636 $ wait
551 637
552 638 Test WdirUnsupported exception
553 639
554 640 $ hg debugdata -c ffffffffffffffffffffffffffffffffffffffff
555 641 abort: working directory revision cannot be specified
556 642 [255]
557 643
558 644 Test cache warming command
559 645
560 646 $ rm -rf .hg/cache/
561 647 $ hg debugupdatecaches --debug
562 648 updating the branch cache
563 649 $ ls -r .hg/cache/*
564 650 .hg/cache/tags2-served
565 651 .hg/cache/tags2
566 652 .hg/cache/rbc-revs-v1
567 653 .hg/cache/rbc-names-v1
568 654 .hg/cache/hgtagsfnodes1
569 655 .hg/cache/branch2-visible-hidden
570 656 .hg/cache/branch2-visible
571 657 .hg/cache/branch2-served.hidden
572 658 .hg/cache/branch2-served
573 659 .hg/cache/branch2-immutable
574 660 .hg/cache/branch2-base
575 661
576 662 Test debugcolor
577 663
578 664 #if no-windows
579 665 $ hg debugcolor --style --color always | grep -E 'mode|style|log\.'
580 666 color mode: 'ansi'
581 667 available style:
582 668 \x1b[0;33mlog.changeset\x1b[0m: \x1b[0;33myellow\x1b[0m (esc)
583 669 #endif
584 670
585 671 $ hg debugcolor --style --color never
586 672 color mode: None
587 673 available style:
588 674
589 675 $ cd ..
590 676
591 677 Test internal debugstacktrace command
592 678
593 679 $ cat > debugstacktrace.py << EOF
594 680 > from mercurial import (
595 681 > util,
596 682 > )
597 683 > from mercurial.utils import (
598 684 > procutil,
599 685 > )
600 686 > def f():
601 687 > util.debugstacktrace(f=procutil.stdout)
602 688 > g()
603 689 > def g():
604 690 > util.dst(b'hello from g\\n', skip=1)
605 691 > h()
606 692 > def h():
607 693 > util.dst(b'hi ...\\nfrom h hidden in g', 1, depth=2)
608 694 > f()
609 695 > EOF
610 696 $ "$PYTHON" debugstacktrace.py
611 697 stacktrace at:
612 698 *debugstacktrace.py:15 in * (glob)
613 699 *debugstacktrace.py:8 in f (glob)
614 700 hello from g at:
615 701 *debugstacktrace.py:15 in * (glob)
616 702 *debugstacktrace.py:9 in f (glob)
617 703 hi ...
618 704 from h hidden in g at:
619 705 *debugstacktrace.py:9 in f (glob)
620 706 *debugstacktrace.py:12 in g (glob)
621 707
622 708 Test debugcapabilities command:
623 709
624 710 $ hg debugcapabilities ./debugrevlog/
625 711 Main capabilities:
626 712 branchmap
627 713 $USUAL_BUNDLE2_CAPS$
628 714 getbundle
629 715 known
630 716 lookup
631 717 pushkey
632 718 unbundle
633 719 Bundle2 capabilities:
634 720 HG20
635 721 bookmarks
636 722 changegroup
637 723 01
638 724 02
639 725 03
640 726 checkheads
641 727 related
642 728 digests
643 729 md5
644 730 sha1
645 731 sha512
646 732 error
647 733 abort
648 734 unsupportedcontent
649 735 pushraced
650 736 pushkey
651 737 hgtagsfnodes
652 738 listkeys
653 739 phases
654 740 heads
655 741 pushkey
656 742 remote-changegroup
657 743 http
658 744 https
659 745 stream
660 746 v2
661 747
662 748 Test debugpeer
663 749
664 750 $ hg debugpeer ssh://user@dummy/debugrevlog
665 751 url: ssh://user@dummy/debugrevlog
666 752 local: no
667 753 pushable: yes
668 754
669 755 #if rust
670 756
671 757 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
672 758 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
673 759 devel-peer-request: hello+between
674 760 devel-peer-request: pairs: 81 bytes
675 761 sending hello command
676 762 sending between command
677 763 remote: 473
678 764 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlog-compression-zstd,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
679 765 remote: 1
680 766 devel-peer-request: protocaps
681 767 devel-peer-request: caps: * bytes (glob)
682 768 sending protocaps command
683 769 url: ssh://user@dummy/debugrevlog
684 770 local: no
685 771 pushable: yes
686 772
687 773 #endif
688 774
689 775 #if no-rust zstd
690 776
691 777 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
692 778 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
693 779 devel-peer-request: hello+between
694 780 devel-peer-request: pairs: 81 bytes
695 781 sending hello command
696 782 sending between command
697 783 remote: 473
698 784 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlog-compression-zstd,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
699 785 remote: 1
700 786 devel-peer-request: protocaps
701 787 devel-peer-request: caps: * bytes (glob)
702 788 sending protocaps command
703 789 url: ssh://user@dummy/debugrevlog
704 790 local: no
705 791 pushable: yes
706 792
707 793 #endif
708 794
709 795 #if no-rust no-zstd
710 796
711 797 $ hg --debug debugpeer ssh://user@dummy/debugrevlog
712 798 running .* ".*[/\\]dummyssh" ['"]user@dummy['"] ['"]hg -R debugrevlog serve --stdio['"] (re)
713 799 devel-peer-request: hello+between
714 800 devel-peer-request: pairs: 81 bytes
715 801 sending hello command
716 802 sending between command
717 803 remote: 449
718 804 remote: capabilities: batch branchmap $USUAL_BUNDLE2_CAPS$ changegroupsubset getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1,sparserevlog unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
719 805 remote: 1
720 806 devel-peer-request: protocaps
721 807 devel-peer-request: caps: * bytes (glob)
722 808 sending protocaps command
723 809 url: ssh://user@dummy/debugrevlog
724 810 local: no
725 811 pushable: yes
726 812
727 813 #endif
728 814
729 815 Test debugshell
730 816
731 817 $ hg debugshell -c 'ui.write(b"%s\n" % ui.username())'
732 818 test
@@ -1,406 +1,406 b''
1 1 #require no-reposimplestore
2 2
3 3 Check whether size of generaldelta revlog is not bigger than its
4 4 regular equivalent. Test would fail if generaldelta was naive
5 5 implementation of parentdelta: third manifest revision would be fully
6 6 inserted due to big distance from its paren revision (zero).
7 7
8 8 $ cat << EOF >> $HGRCPATH
9 9 > [format]
10 10 > sparse-revlog = no
11 11 > EOF
12 12
13 13 $ hg init repo --config format.generaldelta=no --config format.usegeneraldelta=no
14 14 $ cd repo
15 15 $ echo foo > foo
16 16 $ echo bar > bar
17 17 $ echo baz > baz
18 18 $ hg commit -q -Am boo
19 19 $ hg clone --pull . ../gdrepo -q --config format.generaldelta=yes
20 20 $ for r in 1 2 3; do
21 21 > echo $r > foo
22 22 > hg commit -q -m $r
23 23 > hg up -q -r 0
24 24 > hg pull . -q -r $r -R ../gdrepo
25 25 > done
26 26
27 27 $ cd ..
28 28 >>> import os
29 29 >>> regsize = os.stat("repo/.hg/store/00manifest.i").st_size
30 30 >>> gdsize = os.stat("gdrepo/.hg/store/00manifest.i").st_size
31 31 >>> if regsize < gdsize:
32 32 ... print('generaldata increased size of manifest')
33 33
34 34 Verify rev reordering doesnt create invalid bundles (issue4462)
35 35 This requires a commit tree that when pulled will reorder manifest revs such
36 36 that the second manifest to create a file rev will be ordered before the first
37 37 manifest to create that file rev. We also need to do a partial pull to ensure
38 38 reordering happens. At the end we verify the linkrev points at the earliest
39 39 commit.
40 40
41 41 $ hg init server --config format.generaldelta=True
42 42 $ cd server
43 43 $ touch a
44 44 $ hg commit -Aqm a
45 45 $ echo x > x
46 46 $ echo y > y
47 47 $ hg commit -Aqm xy
48 48 $ hg up -q '.^'
49 49 $ echo x > x
50 50 $ echo z > z
51 51 $ hg commit -Aqm xz
52 52 $ hg up -q 1
53 53 $ echo b > b
54 54 $ hg commit -Aqm b
55 55 $ hg merge -q 2
56 56 $ hg commit -Aqm merge
57 57 $ echo c > c
58 58 $ hg commit -Aqm c
59 59 $ hg log -G -T '{rev} {shortest(node)} {desc}'
60 60 @ 5 ebb8 c
61 61 |
62 62 o 4 baf7 merge
63 63 |\
64 64 | o 3 a129 b
65 65 | |
66 66 o | 2 958c xz
67 67 | |
68 68 | o 1 f00c xy
69 69 |/
70 70 o 0 3903 a
71 71
72 72 $ cd ..
73 73 $ hg init client --config format.generaldelta=false --config format.usegeneraldelta=false
74 74 $ cd client
75 75 $ hg pull -q ../server -r 4
76 76 $ hg debugdeltachain x
77 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
78 0 -1 -1 1 1 -1 base 3 2 3 1.50000 3 0 0.00000
77 rev p1 p2 chain# chainlen prev delta
78 0 -1 -1 1 1 -1 base
79 79
80 80 $ cd ..
81 81
82 82 Test "usegeneraldelta" config
83 83 (repo are general delta, but incoming bundle are not re-deltafied)
84 84
85 85 delta coming from the server base delta server are not recompressed.
86 86 (also include the aggressive version for comparison)
87 87
88 88 $ hg clone repo --pull --config format.usegeneraldelta=1 usegd
89 89 requesting all changes
90 90 adding changesets
91 91 adding manifests
92 92 adding file changes
93 93 added 4 changesets with 6 changes to 3 files (+2 heads)
94 94 new changesets 0ea3fcf9d01d:bba78d330d9c
95 95 updating to branch default
96 96 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 97 $ hg clone repo --pull --config format.generaldelta=1 full
98 98 requesting all changes
99 99 adding changesets
100 100 adding manifests
101 101 adding file changes
102 102 added 4 changesets with 6 changes to 3 files (+2 heads)
103 103 new changesets 0ea3fcf9d01d:bba78d330d9c
104 104 updating to branch default
105 105 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 106 $ hg -R repo debugdeltachain -m
107 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
108 0 -1 -1 1 1 -1 base 10? 135 10? 0.7???? 10? 0 0.00000 (glob)
109 1 0 -1 1 2 0 prev 57 135 1?? 1.????? 16? 0 0.00000 (glob)
110 2 0 -1 1 3 1 prev 57 135 2?? 1.6???? 2?? 0 0.00000 (glob)
111 3 0 -1 2 1 -1 base 104 135 104 0.77037 104 0 0.00000
107 rev p1 p2 chain# chainlen prev delta
108 0 -1 -1 1 1 -1 base
109 1 0 -1 1 2 0 prev
110 2 0 -1 1 3 1 prev
111 3 0 -1 2 1 -1 base
112 112 $ hg -R usegd debugdeltachain -m
113 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
114 0 -1 -1 1 1 -1 base 10? 135 10? 0.7???? 10? 0 0.00000 (glob)
115 1 0 -1 1 2 0 p1 57 135 16? 1.????? 16? 0 0.00000 (glob)
116 2 0 -1 1 3 1 prev 57 135 2?? 1.6???? 2?? 0 0.00000 (glob)
117 3 0 -1 1 2 0 p1 57 135 16? 1.????? 27? 114 0.????? (glob)
113 rev p1 p2 chain# chainlen prev delta
114 0 -1 -1 1 1 -1 base
115 1 0 -1 1 2 0 p1
116 2 0 -1 1 3 1 prev
117 3 0 -1 1 2 0 p1
118 118 $ hg -R full debugdeltachain -m
119 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
120 0 -1 -1 1 1 -1 base 10? 135 10? 0.7???? 10? 0 0.00000 (glob)
121 1 0 -1 1 2 0 p1 57 135 16? 1.????? 16? 0 0.00000 (glob)
122 2 0 -1 1 2 0 p1 57 135 16? 1.????? 2?? 57 0.3???? (glob)
123 3 0 -1 1 2 0 p1 57 135 16? 1.????? 27? 114 0.????? (glob)
119 rev p1 p2 chain# chainlen prev delta
120 0 -1 -1 1 1 -1 base
121 1 0 -1 1 2 0 p1
122 2 0 -1 1 2 0 p1
123 3 0 -1 1 2 0 p1
124 124
125 125 Test revlog.optimize-delta-parent-choice
126 126
127 127 $ hg init --config format.generaldelta=1 aggressive
128 128 $ cd aggressive
129 129 $ cat << EOF >> .hg/hgrc
130 130 > [format]
131 131 > generaldelta = 1
132 132 > EOF
133 133 $ touch a b c d e
134 134 $ hg commit -Aqm side1
135 135 $ hg up -q null
136 136 $ touch x y
137 137 $ hg commit -Aqm side2
138 138
139 139 - Verify non-aggressive merge uses p1 (commit 1) as delta parent
140 140 $ hg merge -q 0
141 141 $ hg commit -q -m merge
142 142 $ hg debugdeltachain -m
143 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
144 0 -1 -1 1 1 -1 base ?? 215 ?? 0.????? ?? 0 0.00000 (glob)
145 1 -1 -1 1 2 0 prev ?? 86 1?? 1.????? 1?? 0 0.00000 (glob)
146 2 1 0 1 2 0 p2 ?? 301 1?? 0.4???? ??? ?? 0.5???? (glob)
143 rev p1 p2 chain# chainlen prev delta
144 0 -1 -1 1 1 -1 base
145 1 -1 -1 1 2 0 prev
146 2 1 0 1 2 0 p2
147 147
148 148 $ hg strip -q -r . --config extensions.strip=
149 149
150 150 - Verify aggressive merge uses p2 (commit 0) as delta parent
151 151 $ hg up -q -C 1
152 152 $ hg merge -q 0
153 153 $ hg commit -q -m merge --config storage.revlog.optimize-delta-parent-choice=yes
154 154 $ hg debugdeltachain -m
155 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
156 0 -1 -1 1 1 -1 base ?? 215 ?? 0.????? ?? 0 0.00000 (glob)
157 1 -1 -1 1 2 0 prev ?? 86 1?? 1.????? 1?? 0 0.00000 (glob)
158 2 1 0 1 2 0 p2 ?? 301 1?? 0.4???? ??? ?? 0.5???? (glob)
155 rev p1 p2 chain# chainlen prev delta
156 0 -1 -1 1 1 -1 base
157 1 -1 -1 1 2 0 prev
158 2 1 0 1 2 0 p2
159 159
160 160 Test that strip bundle use bundle2
161 161 $ hg --config extensions.strip= strip .
162 162 0 files updated, 0 files merged, 5 files removed, 0 files unresolved
163 163 saved backup bundle to $TESTTMP/aggressive/.hg/strip-backup/1c5d4dc9a8b8-6c68e60c-backup.hg
164 164 $ hg debugbundle .hg/strip-backup/*
165 165 Stream params: {Compression: BZ}
166 166 changegroup -- {nbchanges: 1, version: 03} (mandatory: True)
167 167 1c5d4dc9a8b8d6e1750966d343e94db665e7a1e9
168 168 cache:rev-branch-cache -- {} (mandatory: False)
169 169 phase-heads -- {} (mandatory: True)
170 170 1c5d4dc9a8b8d6e1750966d343e94db665e7a1e9 draft
171 171
172 172 $ cd ..
173 173
174 174 test maxdeltachainspan
175 175
176 176 $ hg init source-repo
177 177 $ cd source-repo
178 178 $ hg debugbuilddag --new-file '.+5:brancha$.+11:branchb$.+30:branchc<brancha+2<branchb+2'
179 179 # add an empty revision somewhere
180 180 $ hg up tip
181 181 14 files updated, 0 files merged, 0 files removed, 0 files unresolved
182 182 $ hg rm .
183 183 removing nf10
184 184 removing nf11
185 185 removing nf12
186 186 removing nf13
187 187 removing nf14
188 188 removing nf15
189 189 removing nf16
190 190 removing nf17
191 191 removing nf51
192 192 removing nf52
193 193 removing nf6
194 194 removing nf7
195 195 removing nf8
196 196 removing nf9
197 197 $ hg commit -m 'empty all'
198 198 $ hg revert --all --rev 'p1(.)'
199 199 adding nf10
200 200 adding nf11
201 201 adding nf12
202 202 adding nf13
203 203 adding nf14
204 204 adding nf15
205 205 adding nf16
206 206 adding nf17
207 207 adding nf51
208 208 adding nf52
209 209 adding nf6
210 210 adding nf7
211 211 adding nf8
212 212 adding nf9
213 213 $ hg commit -m 'restore all'
214 214 $ hg up null
215 215 0 files updated, 0 files merged, 14 files removed, 0 files unresolved
216 216 $
217 217 $ cd ..
218 $ hg -R source-repo debugdeltachain -m
218 $ hg -R source-repo debugdeltachain -m --all-info
219 219 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
220 220 0 -1 -1 1 1 -1 base 46 45 46 1.02222 46 0 0.00000
221 221 1 0 -1 1 2 0 p1 57 90 103 1.14444 103 0 0.00000
222 222 2 1 -1 1 3 1 p1 57 135 160 1.18519 160 0 0.00000
223 223 3 2 -1 1 4 2 p1 57 180 217 1.20556 217 0 0.00000
224 224 4 3 -1 1 5 3 p1 57 225 274 1.21778 274 0 0.00000
225 225 5 4 -1 1 6 4 p1 57 270 331 1.22593 331 0 0.00000
226 226 6 -1 -1 2 1 -1 base 46 45 46 1.02222 46 0 0.00000
227 227 7 6 -1 2 2 6 p1 57 90 103 1.14444 103 0 0.00000
228 228 8 7 -1 2 3 7 p1 57 135 160 1.18519 160 0 0.00000
229 229 9 8 -1 2 4 8 p1 57 180 217 1.20556 217 0 0.00000
230 230 10 9 -1 2 5 9 p1 58 226 275 1.21681 275 0 0.00000
231 231 11 10 -1 2 6 10 p1 58 272 333 1.22426 333 0 0.00000
232 232 12 11 -1 2 7 11 p1 58 318 391 1.22956 391 0 0.00000
233 233 13 12 -1 2 8 12 p1 58 364 449 1.23352 449 0 0.00000
234 234 14 13 -1 2 9 13 p1 58 410 507 1.23659 507 0 0.00000
235 235 15 14 -1 2 10 14 p1 58 456 565 1.23904 565 0 0.00000
236 236 16 15 -1 2 11 15 p1 58 502 623 1.24104 623 0 0.00000
237 237 17 16 -1 2 12 16 p1 58 548 681 1.24270 681 0 0.00000
238 238 18 -1 -1 3 1 -1 base 47 46 47 1.02174 47 0 0.00000
239 239 19 18 -1 3 2 18 p1 58 92 105 1.14130 105 0 0.00000
240 240 20 19 -1 3 3 19 p1 58 138 163 1.18116 163 0 0.00000
241 241 21 20 -1 3 4 20 p1 58 184 221 1.20109 221 0 0.00000
242 242 22 21 -1 3 5 21 p1 58 230 279 1.21304 279 0 0.00000
243 243 23 22 -1 3 6 22 p1 58 276 337 1.22101 337 0 0.00000
244 244 24 23 -1 3 7 23 p1 58 322 395 1.22671 395 0 0.00000
245 245 25 24 -1 3 8 24 p1 58 368 453 1.23098 453 0 0.00000
246 246 26 25 -1 3 9 25 p1 58 414 511 1.23430 511 0 0.00000
247 247 27 26 -1 3 10 26 p1 58 460 569 1.23696 569 0 0.00000
248 248 28 27 -1 3 11 27 p1 58 506 627 1.23913 627 0 0.00000
249 249 29 28 -1 3 12 28 p1 58 552 685 1.24094 685 0 0.00000
250 250 30 29 -1 3 13 29 p1 58 598 743 1.24247 743 0 0.00000
251 251 31 30 -1 3 14 30 p1 58 644 801 1.24379 801 0 0.00000
252 252 32 31 -1 3 15 31 p1 58 690 859 1.24493 859 0 0.00000
253 253 33 32 -1 3 16 32 p1 58 736 917 1.24592 917 0 0.00000
254 254 34 33 -1 3 17 33 p1 58 782 975 1.24680 975 0 0.00000
255 255 35 34 -1 3 18 34 p1 58 828 1033 1.24758 1033 0 0.00000
256 256 36 35 -1 3 19 35 p1 58 874 1091 1.24828 1091 0 0.00000
257 257 37 36 -1 3 20 36 p1 58 920 1149 1.24891 1149 0 0.00000
258 258 38 37 -1 3 21 37 p1 58 966 1207 1.24948 1207 0 0.00000
259 259 39 38 -1 3 22 38 p1 58 1012 1265 1.25000 1265 0 0.00000
260 260 40 39 -1 3 23 39 p1 58 1058 1323 1.25047 1323 0 0.00000
261 261 41 40 -1 3 24 40 p1 58 1104 1381 1.25091 1381 0 0.00000
262 262 42 41 -1 3 25 41 p1 58 1150 1439 1.25130 1439 0 0.00000
263 263 43 42 -1 3 26 42 p1 58 1196 1497 1.25167 1497 0 0.00000
264 264 44 43 -1 3 27 43 p1 58 1242 1555 1.25201 1555 0 0.00000
265 265 45 44 -1 3 28 44 p1 58 1288 1613 1.25233 1613 0 0.00000
266 266 46 45 -1 3 29 45 p1 58 1334 1671 1.25262 1671 0 0.00000
267 267 47 46 -1 3 30 46 p1 58 1380 1729 1.25290 1729 0 0.00000
268 268 48 47 -1 3 31 47 p1 58 1426 1787 1.25316 1787 0 0.00000
269 269 49 5 -1 4 1 -1 base ??? 316 ??? 0.6???? ??? 0 0.00000 (glob)
270 270 50 49 -1 4 2 49 p1 58 362 2?? 0.7???? 2?? 0 0.00000 (glob)
271 271 51 17 -1 4 3 50 prev 3?? 5?? 6?? 1.0???? 6?? 0 0.00000 (glob)
272 272 52 51 -1 4 4 51 p1 58 640 6?? 1.0???? 6?? 0 0.00000 (glob)
273 273 53 52 -1 5 1 -1 base 0 0 0 0.00000 0 0 0.00000
274 274 54 53 -1 6 1 -1 base 3?? 640 3?? 0.5???? 3?? 0 0.00000 (glob)
275 275 $ hg clone --pull source-repo --config experimental.maxdeltachainspan=2800 relax-chain --config format.generaldelta=yes
276 276 requesting all changes
277 277 adding changesets
278 278 adding manifests
279 279 adding file changes
280 280 added 55 changesets with 53 changes to 53 files (+2 heads)
281 281 new changesets 61246295ee1e:c930ac4a5b32
282 282 updating to branch default
283 283 14 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 $ hg -R relax-chain debugdeltachain -m
284 $ hg -R relax-chain debugdeltachain -m --all-info
285 285 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
286 286 0 -1 -1 1 1 -1 base 46 45 46 1.02222 46 0 0.00000
287 287 1 0 -1 1 2 0 p1 57 90 103 1.14444 103 0 0.00000
288 288 2 1 -1 1 3 1 p1 57 135 160 1.18519 160 0 0.00000
289 289 3 2 -1 1 4 2 p1 57 180 217 1.20556 217 0 0.00000
290 290 4 3 -1 1 5 3 p1 57 225 274 1.21778 274 0 0.00000
291 291 5 4 -1 1 6 4 p1 57 270 331 1.22593 331 0 0.00000
292 292 6 -1 -1 2 1 -1 base 46 45 46 1.02222 46 0 0.00000
293 293 7 6 -1 2 2 6 p1 57 90 103 1.14444 103 0 0.00000
294 294 8 7 -1 2 3 7 p1 57 135 160 1.18519 160 0 0.00000
295 295 9 8 -1 2 4 8 p1 57 180 217 1.20556 217 0 0.00000
296 296 10 9 -1 2 5 9 p1 58 226 275 1.21681 275 0 0.00000
297 297 11 10 -1 2 6 10 p1 58 272 333 1.22426 333 0 0.00000
298 298 12 11 -1 2 7 11 p1 58 318 391 1.22956 391 0 0.00000
299 299 13 12 -1 2 8 12 p1 58 364 449 1.23352 449 0 0.00000
300 300 14 13 -1 2 9 13 p1 58 410 507 1.23659 507 0 0.00000
301 301 15 14 -1 2 10 14 p1 58 456 565 1.23904 565 0 0.00000
302 302 16 15 -1 2 11 15 p1 58 502 623 1.24104 623 0 0.00000
303 303 17 16 -1 2 12 16 p1 58 548 681 1.24270 681 0 0.00000
304 304 18 -1 -1 3 1 -1 base 47 46 47 1.02174 47 0 0.00000
305 305 19 18 -1 3 2 18 p1 58 92 105 1.14130 105 0 0.00000
306 306 20 19 -1 3 3 19 p1 58 138 163 1.18116 163 0 0.00000
307 307 21 20 -1 3 4 20 p1 58 184 221 1.20109 221 0 0.00000
308 308 22 21 -1 3 5 21 p1 58 230 279 1.21304 279 0 0.00000
309 309 23 22 -1 3 6 22 p1 58 276 337 1.22101 337 0 0.00000
310 310 24 23 -1 3 7 23 p1 58 322 395 1.22671 395 0 0.00000
311 311 25 24 -1 3 8 24 p1 58 368 453 1.23098 453 0 0.00000
312 312 26 25 -1 3 9 25 p1 58 414 511 1.23430 511 0 0.00000
313 313 27 26 -1 3 10 26 p1 58 460 569 1.23696 569 0 0.00000
314 314 28 27 -1 3 11 27 p1 58 506 627 1.23913 627 0 0.00000
315 315 29 28 -1 3 12 28 p1 58 552 685 1.24094 685 0 0.00000
316 316 30 29 -1 3 13 29 p1 58 598 743 1.24247 743 0 0.00000
317 317 31 30 -1 3 14 30 p1 58 644 801 1.24379 801 0 0.00000
318 318 32 31 -1 3 15 31 p1 58 690 859 1.24493 859 0 0.00000
319 319 33 32 -1 3 16 32 p1 58 736 917 1.24592 917 0 0.00000
320 320 34 33 -1 3 17 33 p1 58 782 975 1.24680 975 0 0.00000
321 321 35 34 -1 3 18 34 p1 58 828 1033 1.24758 1033 0 0.00000
322 322 36 35 -1 3 19 35 p1 58 874 1091 1.24828 1091 0 0.00000
323 323 37 36 -1 3 20 36 p1 58 920 1149 1.24891 1149 0 0.00000
324 324 38 37 -1 3 21 37 p1 58 966 1207 1.24948 1207 0 0.00000
325 325 39 38 -1 3 22 38 p1 58 1012 1265 1.25000 1265 0 0.00000
326 326 40 39 -1 3 23 39 p1 58 1058 1323 1.25047 1323 0 0.00000
327 327 41 40 -1 3 24 40 p1 58 1104 1381 1.25091 1381 0 0.00000
328 328 42 41 -1 3 25 41 p1 58 1150 1439 1.25130 1439 0 0.00000
329 329 43 42 -1 3 26 42 p1 58 1196 1497 1.25167 1497 0 0.00000
330 330 44 43 -1 3 27 43 p1 58 1242 1555 1.25201 1555 0 0.00000
331 331 45 44 -1 3 28 44 p1 58 1288 1613 1.25233 1613 0 0.00000
332 332 46 45 -1 3 29 45 p1 58 1334 1671 1.25262 1671 0 0.00000
333 333 47 46 -1 3 30 46 p1 58 1380 1729 1.25290 1729 0 0.00000
334 334 48 47 -1 3 31 47 p1 58 1426 1787 1.25316 1787 0 0.00000
335 335 49 5 -1 4 1 -1 base ??? 316 ??? 0.6???? ??? 0 0.00000 (glob)
336 336 50 49 -1 4 2 49 p1 58 362 2?? 0.7???? 2?? 0 0.00000 (glob)
337 337 51 17 -1 2 13 17 p1 58 594 739 1.24411 278? 20?? 2.7???? (glob)
338 338 52 51 -1 5 1 -1 base 3?? 640 3?? 0.5???? 3?? 0 0.00000 (glob)
339 339 53 52 -1 6 1 -1 base 0 0 0 0.00000 0 0 0.00000
340 340 54 53 -1 7 1 -1 base 3?? 640 3?? 0.5???? 3?? 0 0.00000 (glob)
341 341 $ hg clone --pull source-repo --config experimental.maxdeltachainspan=0 noconst-chain --config format.usegeneraldelta=yes --config storage.revlog.reuse-external-delta-parent=no
342 342 requesting all changes
343 343 adding changesets
344 344 adding manifests
345 345 adding file changes
346 346 added 55 changesets with 53 changes to 53 files (+2 heads)
347 347 new changesets 61246295ee1e:c930ac4a5b32
348 348 updating to branch default
349 349 14 files updated, 0 files merged, 0 files removed, 0 files unresolved
350 $ hg -R noconst-chain debugdeltachain -m
350 $ hg -R noconst-chain debugdeltachain -m --all-info
351 351 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
352 352 0 -1 -1 1 1 -1 base 46 45 46 1.02222 46 0 0.00000
353 353 1 0 -1 1 2 0 p1 57 90 103 1.14444 103 0 0.00000
354 354 2 1 -1 1 3 1 p1 57 135 160 1.18519 160 0 0.00000
355 355 3 2 -1 1 4 2 p1 57 180 217 1.20556 217 0 0.00000
356 356 4 3 -1 1 5 3 p1 57 225 274 1.21778 274 0 0.00000
357 357 5 4 -1 1 6 4 p1 57 270 331 1.22593 331 0 0.00000
358 358 6 -1 -1 2 1 -1 base 46 45 46 1.02222 46 0 0.00000
359 359 7 6 -1 2 2 6 p1 57 90 103 1.14444 103 0 0.00000
360 360 8 7 -1 2 3 7 p1 57 135 160 1.18519 160 0 0.00000
361 361 9 8 -1 2 4 8 p1 57 180 217 1.20556 217 0 0.00000
362 362 10 9 -1 2 5 9 p1 58 226 275 1.21681 275 0 0.00000
363 363 11 10 -1 2 6 10 p1 58 272 333 1.22426 333 0 0.00000
364 364 12 11 -1 2 7 11 p1 58 318 391 1.22956 391 0 0.00000
365 365 13 12 -1 2 8 12 p1 58 364 449 1.23352 449 0 0.00000
366 366 14 13 -1 2 9 13 p1 58 410 507 1.23659 507 0 0.00000
367 367 15 14 -1 2 10 14 p1 58 456 565 1.23904 565 0 0.00000
368 368 16 15 -1 2 11 15 p1 58 502 623 1.24104 623 0 0.00000
369 369 17 16 -1 2 12 16 p1 58 548 681 1.24270 681 0 0.00000
370 370 18 -1 -1 3 1 -1 base 47 46 47 1.02174 47 0 0.00000
371 371 19 18 -1 3 2 18 p1 58 92 105 1.14130 105 0 0.00000
372 372 20 19 -1 3 3 19 p1 58 138 163 1.18116 163 0 0.00000
373 373 21 20 -1 3 4 20 p1 58 184 221 1.20109 221 0 0.00000
374 374 22 21 -1 3 5 21 p1 58 230 279 1.21304 279 0 0.00000
375 375 23 22 -1 3 6 22 p1 58 276 337 1.22101 337 0 0.00000
376 376 24 23 -1 3 7 23 p1 58 322 395 1.22671 395 0 0.00000
377 377 25 24 -1 3 8 24 p1 58 368 453 1.23098 453 0 0.00000
378 378 26 25 -1 3 9 25 p1 58 414 511 1.23430 511 0 0.00000
379 379 27 26 -1 3 10 26 p1 58 460 569 1.23696 569 0 0.00000
380 380 28 27 -1 3 11 27 p1 58 506 627 1.23913 627 0 0.00000
381 381 29 28 -1 3 12 28 p1 58 552 685 1.24094 685 0 0.00000
382 382 30 29 -1 3 13 29 p1 58 598 743 1.24247 743 0 0.00000
383 383 31 30 -1 3 14 30 p1 58 644 801 1.24379 801 0 0.00000
384 384 32 31 -1 3 15 31 p1 58 690 859 1.24493 859 0 0.00000
385 385 33 32 -1 3 16 32 p1 58 736 917 1.24592 917 0 0.00000
386 386 34 33 -1 3 17 33 p1 58 782 975 1.24680 975 0 0.00000
387 387 35 34 -1 3 18 34 p1 58 828 1033 1.24758 1033 0 0.00000
388 388 36 35 -1 3 19 35 p1 58 874 1091 1.24828 1091 0 0.00000
389 389 37 36 -1 3 20 36 p1 58 920 1149 1.24891 1149 0 0.00000
390 390 38 37 -1 3 21 37 p1 58 966 1207 1.24948 1207 0 0.00000
391 391 39 38 -1 3 22 38 p1 58 1012 1265 1.25000 1265 0 0.00000
392 392 40 39 -1 3 23 39 p1 58 1058 1323 1.25047 1323 0 0.00000
393 393 41 40 -1 3 24 40 p1 58 1104 1381 1.25091 1381 0 0.00000
394 394 42 41 -1 3 25 41 p1 58 1150 1439 1.25130 1439 0 0.00000
395 395 43 42 -1 3 26 42 p1 58 1196 1497 1.25167 1497 0 0.00000
396 396 44 43 -1 3 27 43 p1 58 1242 1555 1.25201 1555 0 0.00000
397 397 45 44 -1 3 28 44 p1 58 1288 1613 1.25233 1613 0 0.00000
398 398 46 45 -1 3 29 45 p1 58 1334 1671 1.25262 1671 0 0.00000
399 399 47 46 -1 3 30 46 p1 58 1380 1729 1.25290 1729 0 0.00000
400 400 48 47 -1 3 31 47 p1 58 1426 1787 1.25316 1787 0 0.00000
401 401 49 5 -1 1 7 5 p1 58 316 389 1.23101 2857 2468 6.34447
402 402 50 49 -1 1 8 49 p1 58 362 447 1.23481 2915 2468 5.52125
403 403 51 17 -1 2 13 17 p1 58 594 739 1.24411 2642 1903 2.57510
404 404 52 51 -1 2 14 51 p1 58 640 797 1.24531 2700 1903 2.38770
405 405 53 52 -1 4 1 -1 base 0 0 0 0.00000 0 0 0.00000
406 406 54 53 -1 5 1 -1 base 3?? 640 3?? 0.5???? 3?? 0 0.00000 (glob)
@@ -1,220 +1,220 b''
1 1 revlog.parseindex must be able to parse the index file even if
2 2 an index entry is split between two 64k blocks. The ideal test
3 3 would be to create an index file with inline data where
4 4 64k < size < 64k + 64 (64k is the size of the read buffer, 64 is
5 5 the size of an index entry) and with an index entry starting right
6 6 before the 64k block boundary, and try to read it.
7 7 We approximate that by reducing the read buffer to 1 byte.
8 8
9 9 $ hg init a
10 10 $ cd a
11 11 $ echo abc > foo
12 12 $ hg add foo
13 13 $ hg commit -m 'add foo'
14 14 $ echo >> foo
15 15 $ hg commit -m 'change foo'
16 16 $ hg log -r 0:
17 17 changeset: 0:7c31755bf9b5
18 18 user: test
19 19 date: Thu Jan 01 00:00:00 1970 +0000
20 20 summary: add foo
21 21
22 22 changeset: 1:26333235a41c
23 23 tag: tip
24 24 user: test
25 25 date: Thu Jan 01 00:00:00 1970 +0000
26 26 summary: change foo
27 27
28 28 $ cat >> test.py << EOF
29 29 > from mercurial import changelog, node, pycompat, vfs
30 30 >
31 31 > class singlebyteread(object):
32 32 > def __init__(self, real):
33 33 > self.real = real
34 34 >
35 35 > def read(self, size=-1):
36 36 > if size == 65536:
37 37 > size = 1
38 38 > return self.real.read(size)
39 39 >
40 40 > def __getattr__(self, key):
41 41 > return getattr(self.real, key)
42 42 >
43 43 > def __enter__(self):
44 44 > self.real.__enter__()
45 45 > return self
46 46 >
47 47 > def __exit__(self, *args, **kwargs):
48 48 > return self.real.__exit__(*args, **kwargs)
49 49 >
50 50 > def opener(*args):
51 51 > o = vfs.vfs(*args)
52 52 > def wrapper(*a, **kwargs):
53 53 > f = o(*a, **kwargs)
54 54 > return singlebyteread(f)
55 55 > wrapper.options = o.options
56 56 > return wrapper
57 57 >
58 58 > cl = changelog.changelog(opener(b'.hg/store'))
59 59 > print(len(cl), 'revisions:')
60 60 > for r in cl:
61 61 > print(pycompat.sysstr(node.short(cl.node(r))))
62 62 > EOF
63 63 $ "$PYTHON" test.py
64 64 2 revisions:
65 65 7c31755bf9b5
66 66 26333235a41c
67 67
68 68 $ cd ..
69 69
70 70 #if no-pure
71 71
72 72 Test SEGV caused by bad revision passed to reachableroots() (issue4775):
73 73
74 74 $ cd a
75 75
76 76 $ "$PYTHON" <<EOF
77 77 > from mercurial import changelog, vfs
78 78 > cl = changelog.changelog(vfs.vfs(b'.hg/store'))
79 79 > print('good heads:')
80 80 > for head in [0, len(cl) - 1, -1]:
81 81 > print('%s: %r' % (head, cl.reachableroots(0, [head], [0])))
82 82 > print('bad heads:')
83 83 > for head in [len(cl), 10000, -2, -10000, None]:
84 84 > print('%s:' % head, end=' ')
85 85 > try:
86 86 > cl.reachableroots(0, [head], [0])
87 87 > print('uncaught buffer overflow?')
88 88 > except (IndexError, TypeError) as inst:
89 89 > print(inst)
90 90 > print('good roots:')
91 91 > for root in [0, len(cl) - 1, -1]:
92 92 > print('%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root])))
93 93 > print('out-of-range roots are ignored:')
94 94 > for root in [len(cl), 10000, -2, -10000]:
95 95 > print('%s: %r' % (root, cl.reachableroots(root, [len(cl) - 1], [root])))
96 96 > print('bad roots:')
97 97 > for root in [None]:
98 98 > print('%s:' % root, end=' ')
99 99 > try:
100 100 > cl.reachableroots(root, [len(cl) - 1], [root])
101 101 > print('uncaught error?')
102 102 > except TypeError as inst:
103 103 > print(inst)
104 104 > EOF
105 105 good heads:
106 106 0: [0]
107 107 1: [0]
108 108 -1: []
109 109 bad heads:
110 110 2: head out of range
111 111 10000: head out of range
112 112 -2: head out of range
113 113 -10000: head out of range
114 114 None: (an integer is required( .got type NoneType.)?|'NoneType' object cannot be interpreted as an integer) (re)
115 115 good roots:
116 116 0: [0]
117 117 1: [1]
118 118 -1: [-1]
119 119 out-of-range roots are ignored:
120 120 2: []
121 121 10000: []
122 122 -2: []
123 123 -10000: []
124 124 bad roots:
125 125 None: (an integer is required( .got type NoneType.)?|'NoneType' object cannot be interpreted as an integer) (re)
126 126
127 127 $ cd ..
128 128
129 129 Test corrupted p1/p2 fields that could cause SEGV at parsers.c:
130 130
131 131 $ mkdir invalidparent
132 132 $ cd invalidparent
133 133
134 134 $ hg clone --pull -q --config phases.publish=False ../a limit --config format.sparse-revlog=no
135 135 $ hg clone --pull -q --config phases.publish=False ../a neglimit --config format.sparse-revlog=no
136 136 $ hg clone --pull -q --config phases.publish=False ../a segv --config format.sparse-revlog=no
137 137 $ rm -R limit/.hg/cache neglimit/.hg/cache segv/.hg/cache
138 138
139 139 $ "$PYTHON" <<EOF
140 140 > data = open("limit/.hg/store/00changelog.i", "rb").read()
141 141 > poisons = [
142 142 > (b'limit', b'\0\0\0\x02'),
143 143 > (b'neglimit', b'\xff\xff\xff\xfe'),
144 144 > (b'segv', b'\0\x01\0\0'),
145 145 > ]
146 146 > for n, p in poisons:
147 147 > # corrupt p1 at rev0 and p2 at rev1
148 148 > d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
149 149 > open(n + b"/.hg/store/00changelog.i", "wb").write(d)
150 150 > EOF
151 151
152 152 $ hg -R limit debugrevlogindex -f1 -c
153 153 rev flag size link p1 p2 nodeid
154 154 0 0000 62 0 2 -1 7c31755bf9b5
155 155 1 0000 65 1 0 2 26333235a41c
156 156
157 157 $ hg -R limit debugdeltachain -c
158 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
159 0 2 -1 1 1 -1 base 63 62 63 1.01613 63 0 0.00000
160 1 0 2 2 1 -1 base 66 65 66 1.01538 66 0 0.00000
158 rev p1 p2 chain# chainlen prev delta
159 0 2 -1 1 1 -1 base
160 1 0 2 2 1 -1 base
161 161
162 162 $ hg -R neglimit debugrevlogindex -f1 -c
163 163 rev flag size link p1 p2 nodeid
164 164 0 0000 62 0 -2 -1 7c31755bf9b5
165 165 1 0000 65 1 0 -2 26333235a41c
166 166
167 167 $ hg -R segv debugrevlogindex -f1 -c
168 168 rev flag size link p1 p2 nodeid
169 169 0 0000 62 0 65536 -1 7c31755bf9b5
170 170 1 0000 65 1 0 65536 26333235a41c
171 171
172 172 $ hg -R segv debugdeltachain -c
173 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio
174 0 65536 -1 1 1 -1 base 63 62 63 1.01613 63 0 0.00000
175 1 0 65536 2 1 -1 base 66 65 66 1.01538 66 0 0.00000
173 rev p1 p2 chain# chainlen prev delta
174 0 65536 -1 1 1 -1 base
175 1 0 65536 2 1 -1 base
176 176
177 177 $ cat <<EOF > test.py
178 178 > import sys
179 179 > from mercurial import changelog, pycompat, vfs
180 180 > cl = changelog.changelog(vfs.vfs(pycompat.fsencode(sys.argv[1])))
181 181 > n0, n1 = cl.node(0), cl.node(1)
182 182 > ops = [
183 183 > ('reachableroots',
184 184 > lambda: cl.index.reachableroots2(0, [1], [0], False)),
185 185 > ('compute_phases_map_sets', lambda: cl.computephases({1: {cl.node(0)}})),
186 186 > ('index_headrevs', lambda: cl.headrevs()),
187 187 > ('find_gca_candidates', lambda: cl.commonancestorsheads(n0, n1)),
188 188 > ('find_deepest', lambda: cl.ancestor(n0, n1)),
189 189 > ]
190 190 > for l, f in ops:
191 191 > print(l + ':', end=' ')
192 192 > try:
193 193 > f()
194 194 > print('uncaught buffer overflow?')
195 195 > except ValueError as inst:
196 196 > print(inst)
197 197 > EOF
198 198
199 199 $ "$PYTHON" test.py limit/.hg/store
200 200 reachableroots: parent out of range
201 201 compute_phases_map_sets: parent out of range
202 202 index_headrevs: parent out of range
203 203 find_gca_candidates: parent out of range
204 204 find_deepest: parent out of range
205 205 $ "$PYTHON" test.py neglimit/.hg/store
206 206 reachableroots: parent out of range
207 207 compute_phases_map_sets: parent out of range
208 208 index_headrevs: parent out of range
209 209 find_gca_candidates: parent out of range
210 210 find_deepest: parent out of range
211 211 $ "$PYTHON" test.py segv/.hg/store
212 212 reachableroots: parent out of range
213 213 compute_phases_map_sets: parent out of range
214 214 index_headrevs: parent out of range
215 215 find_gca_candidates: parent out of range
216 216 find_deepest: parent out of range
217 217
218 218 $ cd ..
219 219
220 220 #endif
@@ -1,89 +1,89 b''
1 1 $ hg init empty-repo
2 2 $ cd empty-repo
3 3
4 4 Flags on revlog version 0 are rejected
5 5
6 6 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
7 7 ... fh.write(b'\x00\x01\x00\x00') and None
8 8
9 9 $ hg log
10 10 abort: unknown flags (0x01) in version 0 revlog 00changelog
11 11 [50]
12 12
13 13 Unknown flags on revlog version 1 are rejected
14 14
15 15 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
16 16 ... fh.write(b'\x00\x04\x00\x01') and None
17 17
18 18 $ hg log
19 19 abort: unknown flags (0x04) in version 1 revlog 00changelog
20 20 [50]
21 21
22 22 Unknown version is rejected
23 23
24 24 >>> with open('.hg/store/00changelog.i', 'wb') as fh:
25 25 ... fh.write(b'\x00\x00\xbe\xef') and None
26 26
27 27 $ hg log
28 28 abort: unknown version (48879) in revlog 00changelog
29 29 [50]
30 30
31 31 $ cd ..
32 32
33 33 Test for CVE-2016-3630
34 34
35 35 $ mkdir test2; cd test2
36 36 $ hg init
37 37
38 38 >>> import codecs
39 39 >>> open("a.i", "wb").write(codecs.decode(codecs.decode(
40 40 ... b"""eJxjYGZgZIAAYQYGxhgom+k/FMx8YKx9ZUaKSOyqo4cnuKb8mbqHV5cBCVTMWb1Cwqkhe4Gsg9AD
41 41 ... Joa3dYtcYYYBAQ8Qr4OqZAYRICPTSr5WKd/42rV36d+8/VmrNpv7NP1jQAXrQE4BqQUARngwVA==""",
42 42 ... "base64"), "zlib")) and None
43 43
44 44 $ hg debugrevlogindex a.i
45 45 rev linkrev nodeid p1 p2
46 46 0 2 99e0332bd498 000000000000 000000000000
47 47 1 3 6674f57a23d8 99e0332bd498 000000000000
48 48
49 49 >>> from mercurial.revlogutils.constants import KIND_OTHER
50 50 >>> from mercurial import revlog, vfs
51 51 >>> tvfs = vfs.vfs(b'.')
52 52 >>> tvfs.options = {b'revlogv1': True}
53 53 >>> rl = revlog.revlog(tvfs, target=(KIND_OTHER, b'test'), radix=b'a')
54 54 >>> rl.revision(1)
55 55 mpatchError(*'patch cannot be decoded'*) (glob)
56 56
57 57 $ cd ..
58 58
59 59
60 60 Regression test for support for the old repos with strange diff encoding.
61 61 Apparently it used to be possible (maybe it's still possible, but we don't know how)
62 62 to create commits whose diffs are encoded relative to a nullrev.
63 63 This test checks that a repo with that encoding can still be read.
64 64
65 65 This is what we did to produce the repo in test-revlog-diff-relative-to-nullrev.tar:
66 66
67 67 - tweak the code in mercurial/revlogutils/deltas.py to produce such "trivial" deltas:
68 68 > if deltainfo is None:
69 69 > - deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev)
70 70 > + deltainfo = self._builddeltainfo(revinfo, nullrev, fh)
71 71 - hg init
72 72 - echo hi > a
73 73 - hg commit -Am_
74 74 - remove some cache files
75 75
76 76 $ tar -xf - < "$TESTDIR"/bundles/test-revlog-diff-relative-to-nullrev.tar
77 77 $ cd nullrev-diff
78 78 $ hg debugdeltachain a
79 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
80 0 -1 -1 1 2 -1 p1 15 3 15 5.00000 15 0 0.00000 15 15 1.00000 1
81 1 0 -1 1 2 -1 p2 15 3 15 5.00000 30 15 1.00000 30 30 0.50000 1
82 2 -1 -1 1 2 -1 p1 15 3 15 5.00000 45 30 2.00000 45 45 0.33333 1
79 rev p1 p2 chain# chainlen prev delta
80 0 -1 -1 1 2 -1 p1
81 1 0 -1 1 2 -1 p2
82 2 -1 -1 1 2 -1 p1
83 83 $ hg cat --config rhg.cat=true -r 0 a
84 84 hi
85 85 $ hg cat --config rhg.cat=true -r 1 a
86 86 ho
87 87 $ hg cat --config rhg.cat=true -r 2 a
88 88 ha
89 89 $ cd ..
@@ -1,326 +1,326 b''
1 1 ====================================
2 2 Test delta choice with sparse revlog
3 3 ====================================
4 4
5 5 Sparse-revlog usually shows the most gain on Manifest. However, it is simpler
6 6 to general an appropriate file, so we test with a single file instead. The
7 7 goal is to observe intermediate snapshot being created.
8 8
9 9 We need a large enough file. Part of the content needs to be replaced
10 10 repeatedly while some of it changes rarely.
11 11
12 12 $ bundlepath="$TESTDIR/artifacts/cache/big-file-churn.hg"
13 13
14 14 $ expectedhash=`cat "$bundlepath".md5`
15 15
16 16 #if slow
17 17
18 18 $ if [ ! -f "$bundlepath" ]; then
19 19 > "$TESTDIR"/artifacts/scripts/generate-churning-bundle.py > /dev/null
20 20 > fi
21 21
22 22 #else
23 23
24 24 $ if [ ! -f "$bundlepath" ]; then
25 25 > echo 'skipped: missing artifact, run "'"$TESTDIR"'/artifacts/scripts/generate-churning-bundle.py"'
26 26 > exit 80
27 27 > fi
28 28
29 29 #endif
30 30
31 31 $ currenthash=`f -M "$bundlepath" | cut -d = -f 2`
32 32 $ if [ "$currenthash" != "$expectedhash" ]; then
33 33 > echo 'skipped: outdated artifact, md5 "'"$currenthash"'" expected "'"$expectedhash"'" run "'"$TESTDIR"'/artifacts/scripts/generate-churning-bundle.py"'
34 34 > exit 80
35 35 > fi
36 36
37 37 $ cat >> $HGRCPATH << EOF
38 38 > [format]
39 39 > sparse-revlog = yes
40 40 > maxchainlen = 15
41 41 > [storage]
42 42 > revlog.optimize-delta-parent-choice = yes
43 43 > revlog.reuse-external-delta = no
44 44 > EOF
45 45 $ hg init sparse-repo
46 46 $ cd sparse-repo
47 47 $ hg unbundle $bundlepath
48 48 adding changesets
49 49 adding manifests
50 50 adding file changes
51 51 added 5001 changesets with 5001 changes to 1 files (+89 heads)
52 52 new changesets 9706f5af64f4:d9032adc8114 (5001 drafts)
53 53 (run 'hg heads' to see heads, 'hg merge' to merge)
54 54 $ hg up
55 55 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 56 updated to "d9032adc8114: commit #5000"
57 57 89 other heads for branch "default"
58 58
59 59 $ hg log --stat -r 0:3
60 60 changeset: 0:9706f5af64f4
61 61 user: test
62 62 date: Thu Jan 01 00:00:00 1970 +0000
63 63 summary: initial commit
64 64
65 65 SPARSE-REVLOG-TEST-FILE | 10500 ++++++++++++++++++++++++++++++++++++++++++++++
66 66 1 files changed, 10500 insertions(+), 0 deletions(-)
67 67
68 68 changeset: 1:724907deaa5e
69 69 user: test
70 70 date: Thu Jan 01 00:00:00 1970 +0000
71 71 summary: commit #1
72 72
73 73 SPARSE-REVLOG-TEST-FILE | 1068 +++++++++++++++++++++++-----------------------
74 74 1 files changed, 534 insertions(+), 534 deletions(-)
75 75
76 76 changeset: 2:62c41bce3e5d
77 77 user: test
78 78 date: Thu Jan 01 00:00:00 1970 +0000
79 79 summary: commit #2
80 80
81 81 SPARSE-REVLOG-TEST-FILE | 1068 +++++++++++++++++++++++-----------------------
82 82 1 files changed, 534 insertions(+), 534 deletions(-)
83 83
84 84 changeset: 3:348a9cbd6959
85 85 user: test
86 86 date: Thu Jan 01 00:00:00 1970 +0000
87 87 summary: commit #3
88 88
89 89 SPARSE-REVLOG-TEST-FILE | 1068 +++++++++++++++++++++++-----------------------
90 90 1 files changed, 534 insertions(+), 534 deletions(-)
91 91
92 92
93 93 $ f -s .hg/store/data/*.d
94 94 .hg/store/data/_s_p_a_r_s_e-_r_e_v_l_o_g-_t_e_s_t-_f_i_l_e.d: size=58616973
95 95 $ hg debugrevlog *
96 96 format : 1
97 97 flags : generaldelta
98 98
99 99 revisions : 5001
100 100 merges : 625 (12.50%)
101 101 normal : 4376 (87.50%)
102 102 revisions : 5001
103 103 empty : 0 ( 0.00%)
104 104 text : 0 (100.00%)
105 105 delta : 0 (100.00%)
106 106 snapshot : 383 ( 7.66%)
107 107 lvl-0 : 3 ( 0.06%)
108 108 lvl-1 : 18 ( 0.36%) non-ancestor-bases: 9 (50.00%)
109 109 lvl-2 : 62 ( 1.24%) non-ancestor-bases: 58 (93.55%)
110 110 lvl-3 : 108 ( 2.16%) non-ancestor-bases: 108 (100.00%)
111 111 lvl-4 : 191 ( 3.82%) non-ancestor-bases: 180 (94.24%)
112 112 lvl-5 : 1 ( 0.02%) non-ancestor-bases: 1 (100.00%)
113 113 deltas : 4618 (92.34%)
114 114 revision size : 58616973
115 115 snapshot : 9247844 (15.78%)
116 116 lvl-0 : 539532 ( 0.92%)
117 117 lvl-1 : 1467743 ( 2.50%)
118 118 lvl-2 : 1873820 ( 3.20%)
119 119 lvl-3 : 2326874 ( 3.97%)
120 120 lvl-4 : 3029118 ( 5.17%)
121 121 lvl-5 : 10757 ( 0.02%)
122 122 deltas : 49369129 (84.22%)
123 123
124 124 chunks : 5001
125 125 0x28 : 5001 (100.00%)
126 126 chunks size : 58616973
127 127 0x28 : 58616973 (100.00%)
128 128
129 129
130 130 total-stored-content: 1 732 705 361 bytes
131 131
132 132 avg chain length : 9
133 133 max chain length : 15
134 134 max chain reach : 27366701
135 135 compression ratio : 29
136 136
137 137 uncompressed data size (min/max/avg) : 346468 / 346472 / 346471
138 138 full revision size (min/max/avg) : 179288 / 180786 / 179844
139 139 inter-snapshot size (min/max/avg) : 10757 / 169507 / 22916
140 140 level-1 (min/max/avg) : 13905 / 169507 / 81541
141 141 level-2 (min/max/avg) : 10887 / 83873 / 30222
142 142 level-3 (min/max/avg) : 10911 / 43047 / 21545
143 143 level-4 (min/max/avg) : 10838 / 21390 / 15859
144 144 level-5 (min/max/avg) : 10757 / 10757 / 10757
145 145 delta size (min/max/avg) : 9672 / 108072 / 10690
146 146
147 147 deltas against prev : 3906 (84.58%)
148 148 where prev = p1 : 3906 (100.00%)
149 149 where prev = p2 : 0 ( 0.00%)
150 150 other-ancestor : 0 ( 0.00%)
151 151 unrelated : 0 ( 0.00%)
152 152 deltas against p1 : 649 (14.05%)
153 153 deltas against p2 : 63 ( 1.36%)
154 154 deltas against ancs : 0 ( 0.00%)
155 155 deltas against other : 0 ( 0.00%)
156 156
157 157
158 158 Test `debug-delta-find`
159 159 -----------------------
160 160
161 161 $ ls -1
162 162 SPARSE-REVLOG-TEST-FILE
163 163 $ hg debugdeltachain SPARSE-REVLOG-TEST-FILE | grep snap | tail -1
164 4971 4970 -1 3 5 4930 snap 19179 346472 427596 1.23414 15994877 15567281 36.40652 427596 179288 1.00000 5
164 4971 4970 -1 3 5 4930 snap
165 165 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971
166 166 DBG-DELTAS-SEARCH: SEARCH rev=4971
167 167 DBG-DELTAS-SEARCH: ROUND #1 - 1 candidates - search-down
168 168 DBG-DELTAS-SEARCH: CANDIDATE: rev=4962
169 169 DBG-DELTAS-SEARCH: type=snapshot-4
170 170 DBG-DELTAS-SEARCH: size=18296
171 171 DBG-DELTAS-SEARCH: base=4930
172 172 DBG-DELTAS-SEARCH: uncompressed-delta-size=30377
173 173 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
174 174 DBG-DELTAS-SEARCH: DELTA: length=16872 (BAD)
175 175 DBG-DELTAS-SEARCH: ROUND #2 - 1 candidates - search-down
176 176 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
177 177 DBG-DELTAS-SEARCH: type=snapshot-3
178 178 DBG-DELTAS-SEARCH: size=39228
179 179 DBG-DELTAS-SEARCH: base=4799
180 180 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
181 181 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
182 182 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
183 183 DBG-DELTAS-SEARCH: ROUND #3 - 1 candidates - refine-down
184 184 DBG-DELTAS-SEARCH: CONTENDER: rev=4930 - length=19179
185 185 DBG-DELTAS-SEARCH: CANDIDATE: rev=4799
186 186 DBG-DELTAS-SEARCH: type=snapshot-2
187 187 DBG-DELTAS-SEARCH: size=50213
188 188 DBG-DELTAS-SEARCH: base=4623
189 189 DBG-DELTAS-SEARCH: uncompressed-delta-size=82661
190 190 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
191 191 DBG-DELTAS-SEARCH: DELTA: length=49132 (BAD)
192 192 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=0 - search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
193 193
194 194 $ cat << EOF >>.hg/hgrc
195 195 > [storage]
196 196 > revlog.optimize-delta-parent-choice = no
197 197 > revlog.reuse-external-delta = yes
198 198 > EOF
199 199
200 200 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971 --quiet
201 201 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=0 - search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
202 202 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971 --source full
203 203 DBG-DELTAS-SEARCH: SEARCH rev=4971
204 204 DBG-DELTAS-SEARCH: ROUND #1 - 1 candidates - search-down
205 205 DBG-DELTAS-SEARCH: CANDIDATE: rev=4962
206 206 DBG-DELTAS-SEARCH: type=snapshot-4
207 207 DBG-DELTAS-SEARCH: size=18296
208 208 DBG-DELTAS-SEARCH: base=4930
209 209 DBG-DELTAS-SEARCH: uncompressed-delta-size=30377
210 210 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
211 211 DBG-DELTAS-SEARCH: DELTA: length=16872 (BAD)
212 212 DBG-DELTAS-SEARCH: ROUND #2 - 1 candidates - search-down
213 213 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
214 214 DBG-DELTAS-SEARCH: type=snapshot-3
215 215 DBG-DELTAS-SEARCH: size=39228
216 216 DBG-DELTAS-SEARCH: base=4799
217 217 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
218 218 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
219 219 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
220 220 DBG-DELTAS-SEARCH: ROUND #3 - 1 candidates - refine-down
221 221 DBG-DELTAS-SEARCH: CONTENDER: rev=4930 - length=19179
222 222 DBG-DELTAS-SEARCH: CANDIDATE: rev=4799
223 223 DBG-DELTAS-SEARCH: type=snapshot-2
224 224 DBG-DELTAS-SEARCH: size=50213
225 225 DBG-DELTAS-SEARCH: base=4623
226 226 DBG-DELTAS-SEARCH: uncompressed-delta-size=82661
227 227 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
228 228 DBG-DELTAS-SEARCH: DELTA: length=49132 (BAD)
229 229 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=0 - search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
230 230 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971 --source storage
231 231 DBG-DELTAS-SEARCH: SEARCH rev=4971
232 232 DBG-DELTAS-SEARCH: ROUND #1 - 1 candidates - cached-delta
233 233 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
234 234 DBG-DELTAS-SEARCH: type=snapshot-3
235 235 DBG-DELTAS-SEARCH: size=39228
236 236 DBG-DELTAS-SEARCH: base=4799
237 237 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
238 238 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
239 239 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
240 240 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=1 - search-rounds=1 try-count=1 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
241 241 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971 --source p1
242 242 DBG-DELTAS-SEARCH: SEARCH rev=4971
243 243 DBG-DELTAS-SEARCH: ROUND #1 - 1 candidates - search-down
244 244 DBG-DELTAS-SEARCH: CANDIDATE: rev=4962
245 245 DBG-DELTAS-SEARCH: type=snapshot-4
246 246 DBG-DELTAS-SEARCH: size=18296
247 247 DBG-DELTAS-SEARCH: base=4930
248 248 DBG-DELTAS-SEARCH: uncompressed-delta-size=30377
249 249 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
250 250 DBG-DELTAS-SEARCH: DELTA: length=16872 (BAD)
251 251 DBG-DELTAS-SEARCH: ROUND #2 - 1 candidates - search-down
252 252 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
253 253 DBG-DELTAS-SEARCH: type=snapshot-3
254 254 DBG-DELTAS-SEARCH: size=39228
255 255 DBG-DELTAS-SEARCH: base=4799
256 256 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
257 257 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
258 258 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
259 259 DBG-DELTAS-SEARCH: ROUND #3 - 1 candidates - refine-down
260 260 DBG-DELTAS-SEARCH: CONTENDER: rev=4930 - length=19179
261 261 DBG-DELTAS-SEARCH: CANDIDATE: rev=4799
262 262 DBG-DELTAS-SEARCH: type=snapshot-2
263 263 DBG-DELTAS-SEARCH: size=50213
264 264 DBG-DELTAS-SEARCH: base=4623
265 265 DBG-DELTAS-SEARCH: uncompressed-delta-size=82661
266 266 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
267 267 DBG-DELTAS-SEARCH: DELTA: length=49132 (BAD)
268 268 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=0 - search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
269 269 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971 --source p2
270 270 DBG-DELTAS-SEARCH: SEARCH rev=4971
271 271 DBG-DELTAS-SEARCH: ROUND #1 - 1 candidates - search-down
272 272 DBG-DELTAS-SEARCH: CANDIDATE: rev=4962
273 273 DBG-DELTAS-SEARCH: type=snapshot-4
274 274 DBG-DELTAS-SEARCH: size=18296
275 275 DBG-DELTAS-SEARCH: base=4930
276 276 DBG-DELTAS-SEARCH: uncompressed-delta-size=30377
277 277 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
278 278 DBG-DELTAS-SEARCH: DELTA: length=16872 (BAD)
279 279 DBG-DELTAS-SEARCH: ROUND #2 - 1 candidates - search-down
280 280 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
281 281 DBG-DELTAS-SEARCH: type=snapshot-3
282 282 DBG-DELTAS-SEARCH: size=39228
283 283 DBG-DELTAS-SEARCH: base=4799
284 284 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
285 285 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
286 286 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
287 287 DBG-DELTAS-SEARCH: ROUND #3 - 1 candidates - refine-down
288 288 DBG-DELTAS-SEARCH: CONTENDER: rev=4930 - length=19179
289 289 DBG-DELTAS-SEARCH: CANDIDATE: rev=4799
290 290 DBG-DELTAS-SEARCH: type=snapshot-2
291 291 DBG-DELTAS-SEARCH: size=50213
292 292 DBG-DELTAS-SEARCH: base=4623
293 293 DBG-DELTAS-SEARCH: uncompressed-delta-size=82661
294 294 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
295 295 DBG-DELTAS-SEARCH: DELTA: length=49132 (BAD)
296 296 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=0 - search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
297 297 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971 --source prev
298 298 DBG-DELTAS-SEARCH: SEARCH rev=4971
299 299 DBG-DELTAS-SEARCH: ROUND #1 - 1 candidates - search-down
300 300 DBG-DELTAS-SEARCH: CANDIDATE: rev=4962
301 301 DBG-DELTAS-SEARCH: type=snapshot-4
302 302 DBG-DELTAS-SEARCH: size=18296
303 303 DBG-DELTAS-SEARCH: base=4930
304 304 DBG-DELTAS-SEARCH: uncompressed-delta-size=30377
305 305 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
306 306 DBG-DELTAS-SEARCH: DELTA: length=16872 (BAD)
307 307 DBG-DELTAS-SEARCH: ROUND #2 - 1 candidates - search-down
308 308 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
309 309 DBG-DELTAS-SEARCH: type=snapshot-3
310 310 DBG-DELTAS-SEARCH: size=39228
311 311 DBG-DELTAS-SEARCH: base=4799
312 312 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
313 313 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
314 314 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
315 315 DBG-DELTAS-SEARCH: ROUND #3 - 1 candidates - refine-down
316 316 DBG-DELTAS-SEARCH: CONTENDER: rev=4930 - length=19179
317 317 DBG-DELTAS-SEARCH: CANDIDATE: rev=4799
318 318 DBG-DELTAS-SEARCH: type=snapshot-2
319 319 DBG-DELTAS-SEARCH: size=50213
320 320 DBG-DELTAS-SEARCH: base=4623
321 321 DBG-DELTAS-SEARCH: uncompressed-delta-size=82661
322 322 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
323 323 DBG-DELTAS-SEARCH: DELTA: length=49132 (BAD)
324 324 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: delta-base=4930 is-cached=0 - search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
325 325
326 326 $ cd ..
@@ -1,2103 +1,2103 b''
1 1 #require no-reposimplestore
2 2
3 3 $ cat >> $HGRCPATH << EOF
4 4 > [extensions]
5 5 > share =
6 6 > [format]
7 7 > # stabilize test accross variant
8 8 > revlog-compression=zlib
9 9 > [storage]
10 10 > dirstate-v2.slow-path=allow
11 11 > EOF
12 12
13 13 store and revlogv1 are required in source
14 14
15 15 $ hg --config format.usestore=false init no-store
16 16 $ hg -R no-store debugupgraderepo
17 17 abort: cannot upgrade repository; requirement missing: store
18 18 [255]
19 19
20 20 $ hg init no-revlogv1
21 21 $ cat > no-revlogv1/.hg/requires << EOF
22 22 > dotencode
23 23 > fncache
24 24 > generaldelta
25 25 > store
26 26 > EOF
27 27
28 28 $ hg -R no-revlogv1 debugupgraderepo
29 29 abort: cannot upgrade repository; missing a revlog version
30 30 [255]
31 31
32 32 Cannot upgrade shared repositories
33 33
34 34 $ hg init share-parent
35 35 $ hg -R share-parent debugbuilddag -n .+9
36 36 $ hg -R share-parent up tip
37 37 10 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 38 $ hg -q share share-parent share-child
39 39
40 40 $ hg -R share-child debugupgraderepo --config format.sparse-revlog=no
41 41 abort: cannot use these actions on a share repository: sparserevlog
42 42 (upgrade the main repository directly)
43 43 [255]
44 44
45 45 Unless the action is compatible with share
46 46
47 47 $ hg -R share-child debugupgraderepo --config format.use-dirstate-v2=yes --quiet
48 48 requirements
49 49 preserved: * (glob)
50 50 added: dirstate-v2
51 51
52 52 no revlogs to process
53 53
54 54
55 55 $ hg -R share-child debugupgraderepo --config format.use-dirstate-v2=yes --quiet --run
56 56 upgrade will perform the following actions:
57 57
58 58 requirements
59 59 preserved: * (glob)
60 60 added: dirstate-v2
61 61
62 62 no revlogs to process
63 63
64 64 $ hg debugformat -R share-child | grep dirstate-v2
65 65 dirstate-v2: yes
66 66 $ hg debugformat -R share-parent | grep dirstate-v2
67 67 dirstate-v2: no
68 68 $ hg status --all -R share-child
69 69 C nf0
70 70 C nf1
71 71 C nf2
72 72 C nf3
73 73 C nf4
74 74 C nf5
75 75 C nf6
76 76 C nf7
77 77 C nf8
78 78 C nf9
79 79 $ hg log -l 3 -R share-child
80 80 changeset: 9:0059eb38e4a4
81 81 tag: tip
82 82 user: debugbuilddag
83 83 date: Thu Jan 01 00:00:09 1970 +0000
84 84 summary: r9
85 85
86 86 changeset: 8:4d5be70c8130
87 87 user: debugbuilddag
88 88 date: Thu Jan 01 00:00:08 1970 +0000
89 89 summary: r8
90 90
91 91 changeset: 7:e60bfe72517e
92 92 user: debugbuilddag
93 93 date: Thu Jan 01 00:00:07 1970 +0000
94 94 summary: r7
95 95
96 96 $ hg status --all -R share-parent
97 97 C nf0
98 98 C nf1
99 99 C nf2
100 100 C nf3
101 101 C nf4
102 102 C nf5
103 103 C nf6
104 104 C nf7
105 105 C nf8
106 106 C nf9
107 107 $ hg log -l 3 -R share-parent
108 108 changeset: 9:0059eb38e4a4
109 109 tag: tip
110 110 user: debugbuilddag
111 111 date: Thu Jan 01 00:00:09 1970 +0000
112 112 summary: r9
113 113
114 114 changeset: 8:4d5be70c8130
115 115 user: debugbuilddag
116 116 date: Thu Jan 01 00:00:08 1970 +0000
117 117 summary: r8
118 118
119 119 changeset: 7:e60bfe72517e
120 120 user: debugbuilddag
121 121 date: Thu Jan 01 00:00:07 1970 +0000
122 122 summary: r7
123 123
124 124
125 125 $ hg -R share-child debugupgraderepo --config format.use-dirstate-v2=no --quiet --run
126 126 upgrade will perform the following actions:
127 127
128 128 requirements
129 129 preserved: * (glob)
130 130 removed: dirstate-v2
131 131
132 132 no revlogs to process
133 133
134 134 $ hg debugformat -R share-child | grep dirstate-v2
135 135 dirstate-v2: no
136 136 $ hg debugformat -R share-parent | grep dirstate-v2
137 137 dirstate-v2: no
138 138 $ hg status --all -R share-child
139 139 C nf0
140 140 C nf1
141 141 C nf2
142 142 C nf3
143 143 C nf4
144 144 C nf5
145 145 C nf6
146 146 C nf7
147 147 C nf8
148 148 C nf9
149 149 $ hg log -l 3 -R share-child
150 150 changeset: 9:0059eb38e4a4
151 151 tag: tip
152 152 user: debugbuilddag
153 153 date: Thu Jan 01 00:00:09 1970 +0000
154 154 summary: r9
155 155
156 156 changeset: 8:4d5be70c8130
157 157 user: debugbuilddag
158 158 date: Thu Jan 01 00:00:08 1970 +0000
159 159 summary: r8
160 160
161 161 changeset: 7:e60bfe72517e
162 162 user: debugbuilddag
163 163 date: Thu Jan 01 00:00:07 1970 +0000
164 164 summary: r7
165 165
166 166 $ hg status --all -R share-parent
167 167 C nf0
168 168 C nf1
169 169 C nf2
170 170 C nf3
171 171 C nf4
172 172 C nf5
173 173 C nf6
174 174 C nf7
175 175 C nf8
176 176 C nf9
177 177 $ hg log -l 3 -R share-parent
178 178 changeset: 9:0059eb38e4a4
179 179 tag: tip
180 180 user: debugbuilddag
181 181 date: Thu Jan 01 00:00:09 1970 +0000
182 182 summary: r9
183 183
184 184 changeset: 8:4d5be70c8130
185 185 user: debugbuilddag
186 186 date: Thu Jan 01 00:00:08 1970 +0000
187 187 summary: r8
188 188
189 189 changeset: 7:e60bfe72517e
190 190 user: debugbuilddag
191 191 date: Thu Jan 01 00:00:07 1970 +0000
192 192 summary: r7
193 193
194 194
195 195 Do not yet support downgrading treemanifest repos
196 196
197 197 $ hg --config experimental.treemanifest=true init treemanifest
198 198 $ hg -R treemanifest debugupgraderepo
199 199 abort: cannot upgrade repository; requirement would be removed: treemanifest
200 200 [255]
201 201
202 202 Cannot add treemanifest requirement during upgrade
203 203
204 204 $ hg init disallowaddedreq
205 205 $ hg -R disallowaddedreq --config experimental.treemanifest=true debugupgraderepo
206 206 abort: cannot upgrade repository; do not support adding requirement: treemanifest
207 207 [255]
208 208
209 209 An upgrade of a repository created with recommended settings only suggests optimizations
210 210
211 211 $ hg init empty
212 212 $ cd empty
213 213 $ hg debugformat
214 214 format-variant repo
215 215 fncache: yes
216 216 dirstate-v2: no
217 217 tracked-hint: no
218 218 dotencode: yes
219 219 generaldelta: yes
220 220 share-safe: yes
221 221 sparserevlog: yes
222 222 persistent-nodemap: no (no-rust !)
223 223 persistent-nodemap: yes (rust !)
224 224 copies-sdc: no
225 225 revlog-v2: no
226 226 changelog-v2: no
227 227 plain-cl-delta: yes
228 228 compression: zlib
229 229 compression-level: default
230 230 $ hg debugformat --verbose
231 231 format-variant repo config default
232 232 fncache: yes yes yes
233 233 dirstate-v2: no no no
234 234 tracked-hint: no no no
235 235 dotencode: yes yes yes
236 236 generaldelta: yes yes yes
237 237 share-safe: yes yes yes
238 238 sparserevlog: yes yes yes
239 239 persistent-nodemap: no no no (no-rust !)
240 240 persistent-nodemap: yes yes no (rust !)
241 241 copies-sdc: no no no
242 242 revlog-v2: no no no
243 243 changelog-v2: no no no
244 244 plain-cl-delta: yes yes yes
245 245 compression: zlib zlib zlib (no-zstd !)
246 246 compression: zlib zlib zstd (zstd !)
247 247 compression-level: default default default
248 248 $ hg debugformat --verbose --config format.usefncache=no
249 249 format-variant repo config default
250 250 fncache: yes no yes
251 251 dirstate-v2: no no no
252 252 tracked-hint: no no no
253 253 dotencode: yes no yes
254 254 generaldelta: yes yes yes
255 255 share-safe: yes yes yes
256 256 sparserevlog: yes yes yes
257 257 persistent-nodemap: no no no (no-rust !)
258 258 persistent-nodemap: yes yes no (rust !)
259 259 copies-sdc: no no no
260 260 revlog-v2: no no no
261 261 changelog-v2: no no no
262 262 plain-cl-delta: yes yes yes
263 263 compression: zlib zlib zlib (no-zstd !)
264 264 compression: zlib zlib zstd (zstd !)
265 265 compression-level: default default default
266 266 $ hg debugformat --verbose --config format.usefncache=no --color=debug
267 267 format-variant repo config default
268 268 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
269 269 [formatvariant.name.uptodate|dirstate-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
270 270 [formatvariant.name.uptodate|tracked-hint: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
271 271 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| yes][formatvariant.config.special| no][formatvariant.default| yes]
272 272 [formatvariant.name.uptodate|generaldelta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
273 273 [formatvariant.name.uptodate|share-safe: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
274 274 [formatvariant.name.uptodate|sparserevlog: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
275 275 [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] (no-rust !)
276 276 [formatvariant.name.mismatchdefault|persistent-nodemap:][formatvariant.repo.mismatchdefault| yes][formatvariant.config.special| yes][formatvariant.default| no] (rust !)
277 277 [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
278 278 [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
279 279 [formatvariant.name.uptodate|changelog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
280 280 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
281 281 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib] (no-zstd !)
282 282 [formatvariant.name.mismatchdefault|compression: ][formatvariant.repo.mismatchdefault| zlib][formatvariant.config.special| zlib][formatvariant.default| zstd] (zstd !)
283 283 [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
284 284 $ hg debugformat -Tjson
285 285 [
286 286 {
287 287 "config": true,
288 288 "default": true,
289 289 "name": "fncache",
290 290 "repo": true
291 291 },
292 292 {
293 293 "config": false,
294 294 "default": false,
295 295 "name": "dirstate-v2",
296 296 "repo": false
297 297 },
298 298 {
299 299 "config": false,
300 300 "default": false,
301 301 "name": "tracked-hint",
302 302 "repo": false
303 303 },
304 304 {
305 305 "config": true,
306 306 "default": true,
307 307 "name": "dotencode",
308 308 "repo": true
309 309 },
310 310 {
311 311 "config": true,
312 312 "default": true,
313 313 "name": "generaldelta",
314 314 "repo": true
315 315 },
316 316 {
317 317 "config": true,
318 318 "default": true,
319 319 "name": "share-safe",
320 320 "repo": true
321 321 },
322 322 {
323 323 "config": true,
324 324 "default": true,
325 325 "name": "sparserevlog",
326 326 "repo": true
327 327 },
328 328 {
329 329 "config": false, (no-rust !)
330 330 "config": true, (rust !)
331 331 "default": false,
332 332 "name": "persistent-nodemap",
333 333 "repo": false (no-rust !)
334 334 "repo": true (rust !)
335 335 },
336 336 {
337 337 "config": false,
338 338 "default": false,
339 339 "name": "copies-sdc",
340 340 "repo": false
341 341 },
342 342 {
343 343 "config": false,
344 344 "default": false,
345 345 "name": "revlog-v2",
346 346 "repo": false
347 347 },
348 348 {
349 349 "config": false,
350 350 "default": false,
351 351 "name": "changelog-v2",
352 352 "repo": false
353 353 },
354 354 {
355 355 "config": true,
356 356 "default": true,
357 357 "name": "plain-cl-delta",
358 358 "repo": true
359 359 },
360 360 {
361 361 "config": "zlib",
362 362 "default": "zlib", (no-zstd !)
363 363 "default": "zstd", (zstd !)
364 364 "name": "compression",
365 365 "repo": "zlib"
366 366 },
367 367 {
368 368 "config": "default",
369 369 "default": "default",
370 370 "name": "compression-level",
371 371 "repo": "default"
372 372 }
373 373 ]
374 374 $ hg debugupgraderepo
375 375 (no format upgrades found in existing repository)
376 376 performing an upgrade with "--run" will make the following changes:
377 377
378 378 requirements
379 379 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
380 380 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
381 381
382 382 no revlogs to process
383 383
384 384 additional optimizations are available by specifying "--optimize <name>":
385 385
386 386 re-delta-parent
387 387 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
388 388
389 389 re-delta-multibase
390 390 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
391 391
392 392 re-delta-all
393 393 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
394 394
395 395 re-delta-fulladd
396 396 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
397 397
398 398
399 399 $ hg debugupgraderepo --quiet
400 400 requirements
401 401 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
402 402 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
403 403
404 404 no revlogs to process
405 405
406 406
407 407 --optimize can be used to add optimizations
408 408
409 409 $ hg debugupgrade --optimize 're-delta-parent'
410 410 (no format upgrades found in existing repository)
411 411 performing an upgrade with "--run" will make the following changes:
412 412
413 413 requirements
414 414 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
415 415 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
416 416
417 417 optimisations: re-delta-parent
418 418
419 419 re-delta-parent
420 420 deltas within internal storage will choose a new base revision if needed
421 421
422 422 processed revlogs:
423 423 - all-filelogs
424 424 - changelog
425 425 - manifest
426 426
427 427 additional optimizations are available by specifying "--optimize <name>":
428 428
429 429 re-delta-multibase
430 430 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
431 431
432 432 re-delta-all
433 433 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
434 434
435 435 re-delta-fulladd
436 436 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
437 437
438 438
439 439 modern form of the option
440 440
441 441 $ hg debugupgrade --optimize re-delta-parent
442 442 (no format upgrades found in existing repository)
443 443 performing an upgrade with "--run" will make the following changes:
444 444
445 445 requirements
446 446 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
447 447 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
448 448
449 449 optimisations: re-delta-parent
450 450
451 451 re-delta-parent
452 452 deltas within internal storage will choose a new base revision if needed
453 453
454 454 processed revlogs:
455 455 - all-filelogs
456 456 - changelog
457 457 - manifest
458 458
459 459 additional optimizations are available by specifying "--optimize <name>":
460 460
461 461 re-delta-multibase
462 462 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
463 463
464 464 re-delta-all
465 465 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
466 466
467 467 re-delta-fulladd
468 468 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
469 469
470 470
471 471 $ hg debugupgrade --optimize re-delta-parent --quiet
472 472 requirements
473 473 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
474 474 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
475 475
476 476 optimisations: re-delta-parent
477 477
478 478 processed revlogs:
479 479 - all-filelogs
480 480 - changelog
481 481 - manifest
482 482
483 483
484 484 passing multiple optimization:
485 485
486 486 $ hg debugupgrade --optimize re-delta-parent --optimize re-delta-multibase --quiet
487 487 requirements
488 488 preserved: * (glob)
489 489
490 490 optimisations: re-delta-multibase, re-delta-parent
491 491
492 492 processed revlogs:
493 493 - all-filelogs
494 494 - changelog
495 495 - manifest
496 496
497 497
498 498 unknown optimization:
499 499
500 500 $ hg debugupgrade --optimize foobar
501 501 abort: unknown optimization action requested: foobar
502 502 (run without arguments to see valid optimizations)
503 503 [255]
504 504
505 505 Various sub-optimal detections work
506 506
507 507 $ cat > .hg/requires << EOF
508 508 > revlogv1
509 509 > store
510 510 > EOF
511 511
512 512 $ hg debugformat
513 513 format-variant repo
514 514 fncache: no
515 515 dirstate-v2: no
516 516 tracked-hint: no
517 517 dotencode: no
518 518 generaldelta: no
519 519 share-safe: no
520 520 sparserevlog: no
521 521 persistent-nodemap: no
522 522 copies-sdc: no
523 523 revlog-v2: no
524 524 changelog-v2: no
525 525 plain-cl-delta: yes
526 526 compression: zlib
527 527 compression-level: default
528 528 $ hg debugformat --verbose
529 529 format-variant repo config default
530 530 fncache: no yes yes
531 531 dirstate-v2: no no no
532 532 tracked-hint: no no no
533 533 dotencode: no yes yes
534 534 generaldelta: no yes yes
535 535 share-safe: no yes yes
536 536 sparserevlog: no yes yes
537 537 persistent-nodemap: no no no (no-rust !)
538 538 persistent-nodemap: no yes no (rust !)
539 539 copies-sdc: no no no
540 540 revlog-v2: no no no
541 541 changelog-v2: no no no
542 542 plain-cl-delta: yes yes yes
543 543 compression: zlib zlib zlib (no-zstd !)
544 544 compression: zlib zlib zstd (zstd !)
545 545 compression-level: default default default
546 546 $ hg debugformat --verbose --config format.usegeneraldelta=no
547 547 format-variant repo config default
548 548 fncache: no yes yes
549 549 dirstate-v2: no no no
550 550 tracked-hint: no no no
551 551 dotencode: no yes yes
552 552 generaldelta: no no yes
553 553 share-safe: no yes yes
554 554 sparserevlog: no no yes
555 555 persistent-nodemap: no no no (no-rust !)
556 556 persistent-nodemap: no yes no (rust !)
557 557 copies-sdc: no no no
558 558 revlog-v2: no no no
559 559 changelog-v2: no no no
560 560 plain-cl-delta: yes yes yes
561 561 compression: zlib zlib zlib (no-zstd !)
562 562 compression: zlib zlib zstd (zstd !)
563 563 compression-level: default default default
564 564 $ hg debugformat --verbose --config format.usegeneraldelta=no --color=debug
565 565 format-variant repo config default
566 566 [formatvariant.name.mismatchconfig|fncache: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
567 567 [formatvariant.name.uptodate|dirstate-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
568 568 [formatvariant.name.uptodate|tracked-hint: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
569 569 [formatvariant.name.mismatchconfig|dotencode: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
570 570 [formatvariant.name.mismatchdefault|generaldelta: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
571 571 [formatvariant.name.mismatchconfig|share-safe: ][formatvariant.repo.mismatchconfig| no][formatvariant.config.default| yes][formatvariant.default| yes]
572 572 [formatvariant.name.mismatchdefault|sparserevlog: ][formatvariant.repo.mismatchdefault| no][formatvariant.config.special| no][formatvariant.default| yes]
573 573 [formatvariant.name.uptodate|persistent-nodemap:][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no] (no-rust !)
574 574 [formatvariant.name.mismatchconfig|persistent-nodemap:][formatvariant.repo.mismatchconfig| no][formatvariant.config.special| yes][formatvariant.default| no] (rust !)
575 575 [formatvariant.name.uptodate|copies-sdc: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
576 576 [formatvariant.name.uptodate|revlog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
577 577 [formatvariant.name.uptodate|changelog-v2: ][formatvariant.repo.uptodate| no][formatvariant.config.default| no][formatvariant.default| no]
578 578 [formatvariant.name.uptodate|plain-cl-delta: ][formatvariant.repo.uptodate| yes][formatvariant.config.default| yes][formatvariant.default| yes]
579 579 [formatvariant.name.uptodate|compression: ][formatvariant.repo.uptodate| zlib][formatvariant.config.default| zlib][formatvariant.default| zlib] (no-zstd !)
580 580 [formatvariant.name.mismatchdefault|compression: ][formatvariant.repo.mismatchdefault| zlib][formatvariant.config.special| zlib][formatvariant.default| zstd] (zstd !)
581 581 [formatvariant.name.uptodate|compression-level: ][formatvariant.repo.uptodate| default][formatvariant.config.default| default][formatvariant.default| default]
582 582 $ hg debugupgraderepo
583 583 note: selecting all-filelogs for processing to change: dotencode
584 584 note: selecting all-manifestlogs for processing to change: dotencode
585 585 note: selecting changelog for processing to change: dotencode
586 586
587 587 repository lacks features recommended by current config options:
588 588
589 589 fncache
590 590 long and reserved filenames may not work correctly; repository performance is sub-optimal
591 591
592 592 dotencode
593 593 storage of filenames beginning with a period or space may not work correctly
594 594
595 595 generaldelta
596 596 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
597 597
598 598 share-safe
599 599 old shared repositories do not share source repository requirements and config. This leads to various problems when the source repository format is upgraded or some new extensions are enabled.
600 600
601 601 sparserevlog
602 602 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
603 603
604 604 persistent-nodemap (rust !)
605 605 persist the node -> rev mapping on disk to speedup lookup (rust !)
606 606 (rust !)
607 607
608 608 performing an upgrade with "--run" will make the following changes:
609 609
610 610 requirements
611 611 preserved: revlogv1, store
612 612 added: dotencode, fncache, generaldelta, share-safe, sparserevlog (no-rust !)
613 613 added: dotencode, fncache, generaldelta, persistent-nodemap, share-safe, sparserevlog (rust !)
614 614
615 615 fncache
616 616 repository will be more resilient to storing certain paths and performance of certain operations should be improved
617 617
618 618 dotencode
619 619 repository will be better able to store files beginning with a space or period
620 620
621 621 generaldelta
622 622 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
623 623
624 624 share-safe
625 625 Upgrades a repository to share-safe format so that future shares of this repository share its requirements and configs.
626 626
627 627 sparserevlog
628 628 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
629 629
630 630 persistent-nodemap (rust !)
631 631 Speedup revision lookup by node id. (rust !)
632 632 (rust !)
633 633 processed revlogs:
634 634 - all-filelogs
635 635 - changelog
636 636 - manifest
637 637
638 638 additional optimizations are available by specifying "--optimize <name>":
639 639
640 640 re-delta-parent
641 641 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
642 642
643 643 re-delta-multibase
644 644 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
645 645
646 646 re-delta-all
647 647 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
648 648
649 649 re-delta-fulladd
650 650 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
651 651
652 652 $ hg debugupgraderepo --quiet
653 653 requirements
654 654 preserved: revlogv1, store
655 655 added: dotencode, fncache, generaldelta, share-safe, sparserevlog (no-rust !)
656 656 added: dotencode, fncache, generaldelta, persistent-nodemap, share-safe, sparserevlog (rust !)
657 657
658 658 processed revlogs:
659 659 - all-filelogs
660 660 - changelog
661 661 - manifest
662 662
663 663
664 664 $ hg --config format.dotencode=false debugupgraderepo
665 665 note: selecting all-filelogs for processing to change: fncache
666 666 note: selecting all-manifestlogs for processing to change: fncache
667 667 note: selecting changelog for processing to change: fncache
668 668
669 669 repository lacks features recommended by current config options:
670 670
671 671 fncache
672 672 long and reserved filenames may not work correctly; repository performance is sub-optimal
673 673
674 674 generaldelta
675 675 deltas within internal storage are unable to choose optimal revisions; repository is larger and slower than it could be; interaction with other repositories may require extra network and CPU resources, making "hg push" and "hg pull" slower
676 676
677 677 share-safe
678 678 old shared repositories do not share source repository requirements and config. This leads to various problems when the source repository format is upgraded or some new extensions are enabled.
679 679
680 680 sparserevlog
681 681 in order to limit disk reading and memory usage on older version, the span of a delta chain from its root to its end is limited, whatever the relevant data in this span. This can severly limit Mercurial ability to build good chain of delta resulting is much more storage space being taken and limit reusability of on disk delta during exchange.
682 682
683 683 persistent-nodemap (rust !)
684 684 persist the node -> rev mapping on disk to speedup lookup (rust !)
685 685 (rust !)
686 686 repository lacks features used by the default config options:
687 687
688 688 dotencode
689 689 storage of filenames beginning with a period or space may not work correctly
690 690
691 691
692 692 performing an upgrade with "--run" will make the following changes:
693 693
694 694 requirements
695 695 preserved: revlogv1, store
696 696 added: fncache, generaldelta, share-safe, sparserevlog (no-rust !)
697 697 added: fncache, generaldelta, persistent-nodemap, share-safe, sparserevlog (rust !)
698 698
699 699 fncache
700 700 repository will be more resilient to storing certain paths and performance of certain operations should be improved
701 701
702 702 generaldelta
703 703 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
704 704
705 705 share-safe
706 706 Upgrades a repository to share-safe format so that future shares of this repository share its requirements and configs.
707 707
708 708 sparserevlog
709 709 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
710 710
711 711 persistent-nodemap (rust !)
712 712 Speedup revision lookup by node id. (rust !)
713 713 (rust !)
714 714 processed revlogs:
715 715 - all-filelogs
716 716 - changelog
717 717 - manifest
718 718
719 719 additional optimizations are available by specifying "--optimize <name>":
720 720
721 721 re-delta-parent
722 722 deltas within internal storage will be recalculated to choose an optimal base revision where this was not already done; the size of the repository may shrink and various operations may become faster; the first time this optimization is performed could slow down upgrade execution considerably; subsequent invocations should not run noticeably slower
723 723
724 724 re-delta-multibase
725 725 deltas within internal storage will be recalculated against multiple base revision and the smallest difference will be used; the size of the repository may shrink significantly when there are many merges; this optimization will slow down execution in proportion to the number of merges in the repository and the amount of files in the repository; this slow down should not be significant unless there are tens of thousands of files and thousands of merges
726 726
727 727 re-delta-all
728 728 deltas within internal storage will always be recalculated without reusing prior deltas; this will likely make execution run several times slower; this optimization is typically not needed
729 729
730 730 re-delta-fulladd
731 731 every revision will be re-added as if it was new content. It will go through the full storage mechanism giving extensions a chance to process it (eg. lfs). This is similar to "re-delta-all" but even slower since more logic is involved.
732 732
733 733
734 734 $ cd ..
735 735
736 736 Upgrading a repository that is already modern essentially no-ops
737 737
738 738 $ hg init modern
739 739 $ hg -R modern debugupgraderepo --run
740 740 nothing to do
741 741
742 742 Upgrading a repository to generaldelta works
743 743
744 744 $ hg --config format.usegeneraldelta=false init upgradegd
745 745 $ cd upgradegd
746 746 $ touch f0
747 747 $ hg -q commit -A -m initial
748 748 $ mkdir FooBarDirectory.d
749 749 $ touch FooBarDirectory.d/f1
750 750 $ hg -q commit -A -m 'add f1'
751 751 $ hg -q up -r 0
752 752 >>> import random
753 753 >>> random.seed(0) # have a reproducible content
754 754 >>> with open("f2", "wb") as f:
755 755 ... for i in range(100000):
756 756 ... f.write(b"%d\n" % random.randint(1000000000, 9999999999)) and None
757 757 $ hg -q commit -A -m 'add f2'
758 758
759 759 make sure we have a .d file
760 760
761 761 $ ls -d .hg/store/data/*
762 762 .hg/store/data/_foo_bar_directory.d.hg
763 763 .hg/store/data/f0.i
764 764 .hg/store/data/f2.d
765 765 .hg/store/data/f2.i
766 766
767 767 $ hg debugupgraderepo --run --config format.sparse-revlog=false
768 768 note: selecting all-filelogs for processing to change: generaldelta
769 769 note: selecting all-manifestlogs for processing to change: generaldelta
770 770 note: selecting changelog for processing to change: generaldelta
771 771
772 772 upgrade will perform the following actions:
773 773
774 774 requirements
775 775 preserved: dotencode, fncache, revlogv1, share-safe, store (no-rust !)
776 776 preserved: dotencode, fncache, persistent-nodemap, revlogv1, share-safe, store (rust !)
777 777 added: generaldelta
778 778
779 779 generaldelta
780 780 repository storage will be able to create optimal deltas; new repository data will be smaller and read times should decrease; interacting with other repositories using this storage model should require less network and CPU resources, making "hg push" and "hg pull" faster
781 781
782 782 processed revlogs:
783 783 - all-filelogs
784 784 - changelog
785 785 - manifest
786 786
787 787 beginning upgrade...
788 788 repository locked and read-only
789 789 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
790 790 (it is safe to interrupt this process any time before data migration completes)
791 791 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
792 792 migrating 519 KB in store; 1.05 MB tracked data
793 793 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
794 794 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
795 795 migrating 1 manifests containing 3 revisions (384 bytes in store; 238 bytes tracked data)
796 796 finished migrating 3 manifest revisions across 1 manifests; change in size: -17 bytes
797 797 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
798 798 finished migrating 3 changelog revisions; change in size: 0 bytes
799 799 finished migrating 9 total revisions; total change in store size: -17 bytes
800 800 copying phaseroots
801 801 copying requires
802 802 data fully upgraded in a temporary repository
803 803 marking source repository as being upgraded; clients will be unable to read from repository
804 804 starting in-place swap of repository data
805 805 replaced files will be backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
806 806 replacing store...
807 807 store replacement complete; repository was inconsistent for *s (glob)
808 808 finalizing requirements file and making repository readable again
809 809 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
810 810 copy of old repository backed up at $TESTTMP/upgradegd/.hg/upgradebackup.* (glob)
811 811 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
812 812
813 813 Original requirements backed up
814 814
815 815 $ cat .hg/upgradebackup.*/requires
816 816 share-safe
817 817 $ cat .hg/upgradebackup.*/store/requires
818 818 dotencode
819 819 fncache
820 820 persistent-nodemap (rust !)
821 821 revlogv1
822 822 store
823 823 upgradeinprogress
824 824
825 825 generaldelta added to original requirements files
826 826
827 827 $ hg debugrequires
828 828 dotencode
829 829 fncache
830 830 generaldelta
831 831 persistent-nodemap (rust !)
832 832 revlogv1
833 833 share-safe
834 834 store
835 835
836 836 store directory has files we expect
837 837
838 838 $ ls .hg/store
839 839 00changelog.i
840 840 00manifest.i
841 841 data
842 842 data-s
843 843 fncache
844 844 phaseroots
845 845 requires
846 846 undo
847 847 undo.backupfiles
848 848
849 849 manifest should be generaldelta
850 850
851 851 $ hg debugrevlog -m | grep flags
852 852 flags : inline, generaldelta
853 853
854 854 verify should be happy
855 855
856 856 $ hg verify -q
857 857
858 858 old store should be backed up
859 859
860 860 $ ls -d .hg/upgradebackup.*/
861 861 .hg/upgradebackup.*/ (glob)
862 862 $ ls .hg/upgradebackup.*/store
863 863 00changelog.i
864 864 00manifest.i
865 865 data
866 866 data-s
867 867 fncache
868 868 phaseroots
869 869 requires
870 870 undo
871 871 undo.backup.fncache.bck
872 872 undo.backupfiles
873 873
874 874 unless --no-backup is passed
875 875
876 876 $ rm -rf .hg/upgradebackup.*/
877 877 $ hg debugupgraderepo --run --no-backup
878 878 note: selecting all-filelogs for processing to change: sparserevlog
879 879 note: selecting all-manifestlogs for processing to change: sparserevlog
880 880 note: selecting changelog for processing to change: sparserevlog
881 881
882 882 upgrade will perform the following actions:
883 883
884 884 requirements
885 885 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
886 886 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
887 887 added: sparserevlog
888 888
889 889 sparserevlog
890 890 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
891 891
892 892 processed revlogs:
893 893 - all-filelogs
894 894 - changelog
895 895 - manifest
896 896
897 897 beginning upgrade...
898 898 repository locked and read-only
899 899 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
900 900 (it is safe to interrupt this process any time before data migration completes)
901 901 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
902 902 migrating 519 KB in store; 1.05 MB tracked data
903 903 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
904 904 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
905 905 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
906 906 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
907 907 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
908 908 finished migrating 3 changelog revisions; change in size: 0 bytes
909 909 finished migrating 9 total revisions; total change in store size: 0 bytes
910 910 copying phaseroots
911 911 copying requires
912 912 data fully upgraded in a temporary repository
913 913 marking source repository as being upgraded; clients will be unable to read from repository
914 914 starting in-place swap of repository data
915 915 replacing store...
916 916 store replacement complete; repository was inconsistent for * (glob)
917 917 finalizing requirements file and making repository readable again
918 918 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
919 919 $ ls -1 .hg/ | grep upgradebackup
920 920 [1]
921 921
922 922 We can restrict optimization to some revlog:
923 923
924 924 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
925 925 upgrade will perform the following actions:
926 926
927 927 requirements
928 928 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
929 929 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
930 930
931 931 optimisations: re-delta-parent
932 932
933 933 re-delta-parent
934 934 deltas within internal storage will choose a new base revision if needed
935 935
936 936 processed revlogs:
937 937 - manifest
938 938
939 939 beginning upgrade...
940 940 repository locked and read-only
941 941 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
942 942 (it is safe to interrupt this process any time before data migration completes)
943 943 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
944 944 migrating 519 KB in store; 1.05 MB tracked data
945 945 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
946 946 blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions
947 947 blindly copying data/f0.i containing 1 revisions
948 948 blindly copying data/f2.i containing 1 revisions
949 949 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
950 950 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
951 951 cloning 3 revisions from 00manifest.i
952 952 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
953 953 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
954 954 blindly copying 00changelog.i containing 3 revisions
955 955 finished migrating 3 changelog revisions; change in size: 0 bytes
956 956 finished migrating 9 total revisions; total change in store size: 0 bytes
957 957 copying phaseroots
958 958 copying requires
959 959 data fully upgraded in a temporary repository
960 960 marking source repository as being upgraded; clients will be unable to read from repository
961 961 starting in-place swap of repository data
962 962 replacing store...
963 963 store replacement complete; repository was inconsistent for *s (glob)
964 964 finalizing requirements file and making repository readable again
965 965 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
966 966
967 967 Check that the repo still works fine
968 968
969 969 $ hg log -G --stat
970 970 @ changeset: 2:fca376863211
971 971 | tag: tip
972 972 | parent: 0:ba592bf28da2
973 973 | user: test
974 974 | date: Thu Jan 01 00:00:00 1970 +0000
975 975 | summary: add f2
976 976 |
977 977 | f2 | 100000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
978 978 | 1 files changed, 100000 insertions(+), 0 deletions(-)
979 979 |
980 980 | o changeset: 1:2029ce2354e2
981 981 |/ user: test
982 982 | date: Thu Jan 01 00:00:00 1970 +0000
983 983 | summary: add f1
984 984 |
985 985 |
986 986 o changeset: 0:ba592bf28da2
987 987 user: test
988 988 date: Thu Jan 01 00:00:00 1970 +0000
989 989 summary: initial
990 990
991 991
992 992
993 993 $ hg verify -q
994 994
995 995 Check we can select negatively
996 996
997 997 $ hg debugupgrade --optimize re-delta-parent --run --no-manifest --no-backup --debug --traceback
998 998 upgrade will perform the following actions:
999 999
1000 1000 requirements
1001 1001 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1002 1002 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1003 1003
1004 1004 optimisations: re-delta-parent
1005 1005
1006 1006 re-delta-parent
1007 1007 deltas within internal storage will choose a new base revision if needed
1008 1008
1009 1009 processed revlogs:
1010 1010 - all-filelogs
1011 1011 - changelog
1012 1012
1013 1013 beginning upgrade...
1014 1014 repository locked and read-only
1015 1015 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1016 1016 (it is safe to interrupt this process any time before data migration completes)
1017 1017 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1018 1018 migrating 519 KB in store; 1.05 MB tracked data
1019 1019 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
1020 1020 cloning 1 revisions from data/FooBarDirectory.d/f1.i
1021 1021 cloning 1 revisions from data/f0.i
1022 1022 cloning 1 revisions from data/f2.i
1023 1023 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
1024 1024 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
1025 1025 blindly copying 00manifest.i containing 3 revisions
1026 1026 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1027 1027 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
1028 1028 cloning 3 revisions from 00changelog.i
1029 1029 finished migrating 3 changelog revisions; change in size: 0 bytes
1030 1030 finished migrating 9 total revisions; total change in store size: 0 bytes
1031 1031 copying phaseroots
1032 1032 copying requires
1033 1033 data fully upgraded in a temporary repository
1034 1034 marking source repository as being upgraded; clients will be unable to read from repository
1035 1035 starting in-place swap of repository data
1036 1036 replacing store...
1037 1037 store replacement complete; repository was inconsistent for *s (glob)
1038 1038 finalizing requirements file and making repository readable again
1039 1039 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1040 1040 $ hg verify -q
1041 1041
1042 1042 Check that we can select changelog only
1043 1043
1044 1044 $ hg debugupgrade --optimize re-delta-parent --run --changelog --no-backup --debug --traceback
1045 1045 upgrade will perform the following actions:
1046 1046
1047 1047 requirements
1048 1048 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1049 1049 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1050 1050
1051 1051 optimisations: re-delta-parent
1052 1052
1053 1053 re-delta-parent
1054 1054 deltas within internal storage will choose a new base revision if needed
1055 1055
1056 1056 processed revlogs:
1057 1057 - changelog
1058 1058
1059 1059 beginning upgrade...
1060 1060 repository locked and read-only
1061 1061 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1062 1062 (it is safe to interrupt this process any time before data migration completes)
1063 1063 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1064 1064 migrating 519 KB in store; 1.05 MB tracked data
1065 1065 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
1066 1066 blindly copying data/FooBarDirectory.d/f1.i containing 1 revisions
1067 1067 blindly copying data/f0.i containing 1 revisions
1068 1068 blindly copying data/f2.i containing 1 revisions
1069 1069 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
1070 1070 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
1071 1071 blindly copying 00manifest.i containing 3 revisions
1072 1072 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1073 1073 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
1074 1074 cloning 3 revisions from 00changelog.i
1075 1075 finished migrating 3 changelog revisions; change in size: 0 bytes
1076 1076 finished migrating 9 total revisions; total change in store size: 0 bytes
1077 1077 copying phaseroots
1078 1078 copying requires
1079 1079 data fully upgraded in a temporary repository
1080 1080 marking source repository as being upgraded; clients will be unable to read from repository
1081 1081 starting in-place swap of repository data
1082 1082 replacing store...
1083 1083 store replacement complete; repository was inconsistent for *s (glob)
1084 1084 finalizing requirements file and making repository readable again
1085 1085 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1086 1086 $ hg verify -q
1087 1087
1088 1088 Check that we can select filelog only
1089 1089
1090 1090 $ hg debugupgrade --optimize re-delta-parent --run --no-changelog --no-manifest --no-backup --debug --traceback
1091 1091 upgrade will perform the following actions:
1092 1092
1093 1093 requirements
1094 1094 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1095 1095 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1096 1096
1097 1097 optimisations: re-delta-parent
1098 1098
1099 1099 re-delta-parent
1100 1100 deltas within internal storage will choose a new base revision if needed
1101 1101
1102 1102 processed revlogs:
1103 1103 - all-filelogs
1104 1104
1105 1105 beginning upgrade...
1106 1106 repository locked and read-only
1107 1107 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1108 1108 (it is safe to interrupt this process any time before data migration completes)
1109 1109 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1110 1110 migrating 519 KB in store; 1.05 MB tracked data
1111 1111 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
1112 1112 cloning 1 revisions from data/FooBarDirectory.d/f1.i
1113 1113 cloning 1 revisions from data/f0.i
1114 1114 cloning 1 revisions from data/f2.i
1115 1115 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
1116 1116 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
1117 1117 blindly copying 00manifest.i containing 3 revisions
1118 1118 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1119 1119 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
1120 1120 blindly copying 00changelog.i containing 3 revisions
1121 1121 finished migrating 3 changelog revisions; change in size: 0 bytes
1122 1122 finished migrating 9 total revisions; total change in store size: 0 bytes
1123 1123 copying phaseroots
1124 1124 copying requires
1125 1125 data fully upgraded in a temporary repository
1126 1126 marking source repository as being upgraded; clients will be unable to read from repository
1127 1127 starting in-place swap of repository data
1128 1128 replacing store...
1129 1129 store replacement complete; repository was inconsistent for *s (glob)
1130 1130 finalizing requirements file and making repository readable again
1131 1131 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1132 1132 $ hg verify -q
1133 1133
1134 1134
1135 1135 Check you can't skip revlog clone during important format downgrade
1136 1136
1137 1137 $ echo "[format]" > .hg/hgrc
1138 1138 $ echo "sparse-revlog=no" >> .hg/hgrc
1139 1139 $ hg debugupgrade --optimize re-delta-parent --no-manifest --no-backup --quiet
1140 1140 warning: ignoring --no-manifest, as upgrade is changing: sparserevlog
1141 1141
1142 1142 requirements
1143 1143 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
1144 1144 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
1145 1145 removed: sparserevlog
1146 1146
1147 1147 optimisations: re-delta-parent
1148 1148
1149 1149 processed revlogs:
1150 1150 - all-filelogs
1151 1151 - changelog
1152 1152 - manifest
1153 1153
1154 1154 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
1155 1155 note: selecting all-filelogs for processing to change: sparserevlog
1156 1156 note: selecting changelog for processing to change: sparserevlog
1157 1157
1158 1158 upgrade will perform the following actions:
1159 1159
1160 1160 requirements
1161 1161 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
1162 1162 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
1163 1163 removed: sparserevlog
1164 1164
1165 1165 optimisations: re-delta-parent
1166 1166
1167 1167 re-delta-parent
1168 1168 deltas within internal storage will choose a new base revision if needed
1169 1169
1170 1170 processed revlogs:
1171 1171 - all-filelogs
1172 1172 - changelog
1173 1173 - manifest
1174 1174
1175 1175 beginning upgrade...
1176 1176 repository locked and read-only
1177 1177 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1178 1178 (it is safe to interrupt this process any time before data migration completes)
1179 1179 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1180 1180 migrating 519 KB in store; 1.05 MB tracked data
1181 1181 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
1182 1182 cloning 1 revisions from data/FooBarDirectory.d/f1.i
1183 1183 cloning 1 revisions from data/f0.i
1184 1184 cloning 1 revisions from data/f2.i
1185 1185 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
1186 1186 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
1187 1187 cloning 3 revisions from 00manifest.i
1188 1188 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1189 1189 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
1190 1190 cloning 3 revisions from 00changelog.i
1191 1191 finished migrating 3 changelog revisions; change in size: 0 bytes
1192 1192 finished migrating 9 total revisions; total change in store size: 0 bytes
1193 1193 copying phaseroots
1194 1194 copying requires
1195 1195 data fully upgraded in a temporary repository
1196 1196 marking source repository as being upgraded; clients will be unable to read from repository
1197 1197 starting in-place swap of repository data
1198 1198 replacing store...
1199 1199 store replacement complete; repository was inconsistent for *s (glob)
1200 1200 finalizing requirements file and making repository readable again
1201 1201 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1202 1202 $ hg verify -q
1203 1203
1204 1204 Check you can't skip revlog clone during important format upgrade
1205 1205
1206 1206 $ echo "sparse-revlog=yes" >> .hg/hgrc
1207 1207 $ hg debugupgrade --optimize re-delta-parent --run --manifest --no-backup --debug --traceback
1208 1208 note: selecting all-filelogs for processing to change: sparserevlog
1209 1209 note: selecting changelog for processing to change: sparserevlog
1210 1210
1211 1211 upgrade will perform the following actions:
1212 1212
1213 1213 requirements
1214 1214 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
1215 1215 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
1216 1216 added: sparserevlog
1217 1217
1218 1218 optimisations: re-delta-parent
1219 1219
1220 1220 sparserevlog
1221 1221 Revlog supports delta chain with more unused data between payload. These gaps will be skipped at read time. This allows for better delta chains, making a better compression and faster exchange with server.
1222 1222
1223 1223 re-delta-parent
1224 1224 deltas within internal storage will choose a new base revision if needed
1225 1225
1226 1226 processed revlogs:
1227 1227 - all-filelogs
1228 1228 - changelog
1229 1229 - manifest
1230 1230
1231 1231 beginning upgrade...
1232 1232 repository locked and read-only
1233 1233 creating temporary repository to stage upgraded data: $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1234 1234 (it is safe to interrupt this process any time before data migration completes)
1235 1235 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1236 1236 migrating 519 KB in store; 1.05 MB tracked data
1237 1237 migrating 3 filelogs containing 3 revisions (518 KB in store; 1.05 MB tracked data)
1238 1238 cloning 1 revisions from data/FooBarDirectory.d/f1.i
1239 1239 cloning 1 revisions from data/f0.i
1240 1240 cloning 1 revisions from data/f2.i
1241 1241 finished migrating 3 filelog revisions across 3 filelogs; change in size: 0 bytes
1242 1242 migrating 1 manifests containing 3 revisions (367 bytes in store; 238 bytes tracked data)
1243 1243 cloning 3 revisions from 00manifest.i
1244 1244 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1245 1245 migrating changelog containing 3 revisions (394 bytes in store; 199 bytes tracked data)
1246 1246 cloning 3 revisions from 00changelog.i
1247 1247 finished migrating 3 changelog revisions; change in size: 0 bytes
1248 1248 finished migrating 9 total revisions; total change in store size: 0 bytes
1249 1249 copying phaseroots
1250 1250 copying requires
1251 1251 data fully upgraded in a temporary repository
1252 1252 marking source repository as being upgraded; clients will be unable to read from repository
1253 1253 starting in-place swap of repository data
1254 1254 replacing store...
1255 1255 store replacement complete; repository was inconsistent for *s (glob)
1256 1256 finalizing requirements file and making repository readable again
1257 1257 removing temporary repository $TESTTMP/upgradegd/.hg/upgrade.* (glob)
1258 1258 $ hg verify -q
1259 1259
1260 1260 $ cd ..
1261 1261
1262 1262 store files with special filenames aren't encoded during copy
1263 1263
1264 1264 $ hg init store-filenames
1265 1265 $ cd store-filenames
1266 1266 $ touch foo
1267 1267 $ hg -q commit -A -m initial
1268 1268 $ touch .hg/store/.XX_special_filename
1269 1269
1270 1270 $ hg debugupgraderepo --run
1271 1271 nothing to do
1272 1272 $ hg debugupgraderepo --run --optimize 're-delta-fulladd'
1273 1273 upgrade will perform the following actions:
1274 1274
1275 1275 requirements
1276 1276 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1277 1277 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1278 1278
1279 1279 optimisations: re-delta-fulladd
1280 1280
1281 1281 re-delta-fulladd
1282 1282 each revision will be added as new content to the internal storage; this will likely drastically slow down execution time, but some extensions might need it
1283 1283
1284 1284 processed revlogs:
1285 1285 - all-filelogs
1286 1286 - changelog
1287 1287 - manifest
1288 1288
1289 1289 beginning upgrade...
1290 1290 repository locked and read-only
1291 1291 creating temporary repository to stage upgraded data: $TESTTMP/store-filenames/.hg/upgrade.* (glob)
1292 1292 (it is safe to interrupt this process any time before data migration completes)
1293 1293 migrating 3 total revisions (1 in filelogs, 1 in manifests, 1 in changelog)
1294 1294 migrating 301 bytes in store; 107 bytes tracked data
1295 1295 migrating 1 filelogs containing 1 revisions (64 bytes in store; 0 bytes tracked data)
1296 1296 finished migrating 1 filelog revisions across 1 filelogs; change in size: 0 bytes
1297 1297 migrating 1 manifests containing 1 revisions (110 bytes in store; 45 bytes tracked data)
1298 1298 finished migrating 1 manifest revisions across 1 manifests; change in size: 0 bytes
1299 1299 migrating changelog containing 1 revisions (127 bytes in store; 62 bytes tracked data)
1300 1300 finished migrating 1 changelog revisions; change in size: 0 bytes
1301 1301 finished migrating 3 total revisions; total change in store size: 0 bytes
1302 1302 copying .XX_special_filename
1303 1303 copying phaseroots
1304 1304 copying requires
1305 1305 data fully upgraded in a temporary repository
1306 1306 marking source repository as being upgraded; clients will be unable to read from repository
1307 1307 starting in-place swap of repository data
1308 1308 replaced files will be backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
1309 1309 replacing store...
1310 1310 store replacement complete; repository was inconsistent for *s (glob)
1311 1311 finalizing requirements file and making repository readable again
1312 1312 removing temporary repository $TESTTMP/store-filenames/.hg/upgrade.* (glob)
1313 1313 copy of old repository backed up at $TESTTMP/store-filenames/.hg/upgradebackup.* (glob)
1314 1314 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
1315 1315
1316 1316 fncache is valid after upgrade
1317 1317
1318 1318 $ hg debugrebuildfncache
1319 1319 fncache already up to date
1320 1320
1321 1321 $ cd ..
1322 1322
1323 1323 Check upgrading a large file repository
1324 1324 ---------------------------------------
1325 1325
1326 1326 $ hg init largefilesrepo
1327 1327 $ cat << EOF >> largefilesrepo/.hg/hgrc
1328 1328 > [extensions]
1329 1329 > largefiles =
1330 1330 > EOF
1331 1331
1332 1332 $ cd largefilesrepo
1333 1333 $ touch foo
1334 1334 $ hg add --large foo
1335 1335 $ hg -q commit -m initial
1336 1336 $ hg debugrequires
1337 1337 dotencode
1338 1338 fncache
1339 1339 generaldelta
1340 1340 largefiles
1341 1341 persistent-nodemap (rust !)
1342 1342 revlogv1
1343 1343 share-safe
1344 1344 sparserevlog
1345 1345 store
1346 1346
1347 1347 $ hg debugupgraderepo --run
1348 1348 nothing to do
1349 1349 $ hg debugrequires
1350 1350 dotencode
1351 1351 fncache
1352 1352 generaldelta
1353 1353 largefiles
1354 1354 persistent-nodemap (rust !)
1355 1355 revlogv1
1356 1356 share-safe
1357 1357 sparserevlog
1358 1358 store
1359 1359
1360 1360 $ cat << EOF >> .hg/hgrc
1361 1361 > [extensions]
1362 1362 > lfs =
1363 1363 > [lfs]
1364 1364 > threshold = 10
1365 1365 > EOF
1366 1366 $ echo '123456789012345' > lfs.bin
1367 1367 $ hg ci -Am 'lfs.bin'
1368 1368 adding lfs.bin
1369 1369 $ hg debugrequires | grep lfs
1370 1370 lfs
1371 1371 $ find .hg/store/lfs -type f
1372 1372 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1373 1373
1374 1374 $ hg debugupgraderepo --run
1375 1375 nothing to do
1376 1376
1377 1377 $ hg debugrequires | grep lfs
1378 1378 lfs
1379 1379 $ find .hg/store/lfs -type f
1380 1380 .hg/store/lfs/objects/d0/beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1381 1381 $ hg verify -q
1382 1382 $ hg debugdata lfs.bin 0
1383 1383 version https://git-lfs.github.com/spec/v1
1384 1384 oid sha256:d0beab232adff5ba365880366ad30b1edb85c4c5372442b5d2fe27adc96d653f
1385 1385 size 16
1386 1386 x-is-binary 0
1387 1387
1388 1388 $ cd ..
1389 1389
1390 1390 repository config is taken in account
1391 1391 -------------------------------------
1392 1392
1393 1393 $ cat << EOF >> $HGRCPATH
1394 1394 > [format]
1395 1395 > maxchainlen = 1
1396 1396 > EOF
1397 1397
1398 1398 $ hg init localconfig
1399 1399 $ cd localconfig
1400 1400 $ cat << EOF > file
1401 1401 > some content
1402 1402 > with some length
1403 1403 > to make sure we get a delta
1404 1404 > after changes
1405 1405 > very long
1406 1406 > very long
1407 1407 > very long
1408 1408 > very long
1409 1409 > very long
1410 1410 > very long
1411 1411 > very long
1412 1412 > very long
1413 1413 > very long
1414 1414 > very long
1415 1415 > very long
1416 1416 > EOF
1417 1417 $ hg -q commit -A -m A
1418 1418 $ echo "new line" >> file
1419 1419 $ hg -q commit -m B
1420 1420 $ echo "new line" >> file
1421 1421 $ hg -q commit -m C
1422 1422
1423 1423 $ cat << EOF >> .hg/hgrc
1424 1424 > [format]
1425 1425 > maxchainlen = 9001
1426 1426 > EOF
1427 1427 $ hg config format
1428 1428 format.revlog-compression=$BUNDLE2_COMPRESSIONS$
1429 1429 format.maxchainlen=9001
1430 $ hg debugdeltachain file
1430 $ hg debugdeltachain file --all-info
1431 1431 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
1432 1432 0 -1 -1 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
1433 1433 1 0 -1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
1434 1434 2 1 -1 1 2 0 snap 30 200 107 0.53500 128 21 0.19626 128 128 0.83594 1
1435 1435
1436 1436 $ hg debugupgraderepo --run --optimize 're-delta-all'
1437 1437 upgrade will perform the following actions:
1438 1438
1439 1439 requirements
1440 1440 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1441 1441 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1442 1442
1443 1443 optimisations: re-delta-all
1444 1444
1445 1445 re-delta-all
1446 1446 deltas within internal storage will be fully recomputed; this will likely drastically slow down execution time
1447 1447
1448 1448 processed revlogs:
1449 1449 - all-filelogs
1450 1450 - changelog
1451 1451 - manifest
1452 1452
1453 1453 beginning upgrade...
1454 1454 repository locked and read-only
1455 1455 creating temporary repository to stage upgraded data: $TESTTMP/localconfig/.hg/upgrade.* (glob)
1456 1456 (it is safe to interrupt this process any time before data migration completes)
1457 1457 migrating 9 total revisions (3 in filelogs, 3 in manifests, 3 in changelog)
1458 1458 migrating 1019 bytes in store; 882 bytes tracked data
1459 1459 migrating 1 filelogs containing 3 revisions (320 bytes in store; 573 bytes tracked data)
1460 1460 finished migrating 3 filelog revisions across 1 filelogs; change in size: -9 bytes
1461 1461 migrating 1 manifests containing 3 revisions (333 bytes in store; 138 bytes tracked data)
1462 1462 finished migrating 3 manifest revisions across 1 manifests; change in size: 0 bytes
1463 1463 migrating changelog containing 3 revisions (366 bytes in store; 171 bytes tracked data)
1464 1464 finished migrating 3 changelog revisions; change in size: 0 bytes
1465 1465 finished migrating 9 total revisions; total change in store size: -9 bytes
1466 1466 copying phaseroots
1467 1467 copying requires
1468 1468 data fully upgraded in a temporary repository
1469 1469 marking source repository as being upgraded; clients will be unable to read from repository
1470 1470 starting in-place swap of repository data
1471 1471 replaced files will be backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
1472 1472 replacing store...
1473 1473 store replacement complete; repository was inconsistent for *s (glob)
1474 1474 finalizing requirements file and making repository readable again
1475 1475 removing temporary repository $TESTTMP/localconfig/.hg/upgrade.* (glob)
1476 1476 copy of old repository backed up at $TESTTMP/localconfig/.hg/upgradebackup.* (glob)
1477 1477 the old repository will not be deleted; remove it to free up disk space once the upgraded repository is verified
1478 $ hg debugdeltachain file
1478 $ hg debugdeltachain file --all-info
1479 1479 rev p1 p2 chain# chainlen prev delta size rawsize chainsize ratio lindist extradist extraratio readsize largestblk rddensity srchunks
1480 1480 0 -1 -1 1 1 -1 base 77 182 77 0.42308 77 0 0.00000 77 77 1.00000 1
1481 1481 1 0 -1 1 2 0 p1 21 191 98 0.51309 98 0 0.00000 98 98 1.00000 1
1482 1482 2 1 -1 1 3 1 p1 21 200 119 0.59500 119 0 0.00000 119 119 1.00000 1
1483 1483 $ cd ..
1484 1484
1485 1485 $ cat << EOF >> $HGRCPATH
1486 1486 > [format]
1487 1487 > maxchainlen = 9001
1488 1488 > EOF
1489 1489
1490 1490 Check upgrading a sparse-revlog repository
1491 1491 ---------------------------------------
1492 1492
1493 1493 $ hg init sparserevlogrepo --config format.sparse-revlog=no
1494 1494 $ cd sparserevlogrepo
1495 1495 $ touch foo
1496 1496 $ hg add foo
1497 1497 $ hg -q commit -m "foo"
1498 1498 $ hg debugrequires
1499 1499 dotencode
1500 1500 fncache
1501 1501 generaldelta
1502 1502 persistent-nodemap (rust !)
1503 1503 revlogv1
1504 1504 share-safe
1505 1505 store
1506 1506
1507 1507 Check that we can add the sparse-revlog format requirement
1508 1508 $ hg --config format.sparse-revlog=yes debugupgraderepo --run --quiet
1509 1509 upgrade will perform the following actions:
1510 1510
1511 1511 requirements
1512 1512 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
1513 1513 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
1514 1514 added: sparserevlog
1515 1515
1516 1516 processed revlogs:
1517 1517 - all-filelogs
1518 1518 - changelog
1519 1519 - manifest
1520 1520
1521 1521 $ hg debugrequires
1522 1522 dotencode
1523 1523 fncache
1524 1524 generaldelta
1525 1525 persistent-nodemap (rust !)
1526 1526 revlogv1
1527 1527 share-safe
1528 1528 sparserevlog
1529 1529 store
1530 1530
1531 1531 Check that we can remove the sparse-revlog format requirement
1532 1532 $ hg --config format.sparse-revlog=no debugupgraderepo --run --quiet
1533 1533 upgrade will perform the following actions:
1534 1534
1535 1535 requirements
1536 1536 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
1537 1537 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
1538 1538 removed: sparserevlog
1539 1539
1540 1540 processed revlogs:
1541 1541 - all-filelogs
1542 1542 - changelog
1543 1543 - manifest
1544 1544
1545 1545 $ hg debugrequires
1546 1546 dotencode
1547 1547 fncache
1548 1548 generaldelta
1549 1549 persistent-nodemap (rust !)
1550 1550 revlogv1
1551 1551 share-safe
1552 1552 store
1553 1553
1554 1554 #if zstd
1555 1555
1556 1556 Check upgrading to a zstd revlog
1557 1557 --------------------------------
1558 1558
1559 1559 upgrade
1560 1560
1561 1561 $ hg --config format.revlog-compression=zstd debugupgraderepo --run --no-backup --quiet
1562 1562 upgrade will perform the following actions:
1563 1563
1564 1564 requirements
1565 1565 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, store (no-rust !)
1566 1566 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, store (rust !)
1567 1567 added: revlog-compression-zstd, sparserevlog
1568 1568
1569 1569 processed revlogs:
1570 1570 - all-filelogs
1571 1571 - changelog
1572 1572 - manifest
1573 1573
1574 1574 $ hg debugformat -v
1575 1575 format-variant repo config default
1576 1576 fncache: yes yes yes
1577 1577 dirstate-v2: no no no
1578 1578 tracked-hint: no no no
1579 1579 dotencode: yes yes yes
1580 1580 generaldelta: yes yes yes
1581 1581 share-safe: yes yes yes
1582 1582 sparserevlog: yes yes yes
1583 1583 persistent-nodemap: no no no (no-rust !)
1584 1584 persistent-nodemap: yes yes no (rust !)
1585 1585 copies-sdc: no no no
1586 1586 revlog-v2: no no no
1587 1587 changelog-v2: no no no
1588 1588 plain-cl-delta: yes yes yes
1589 1589 compression: zlib zlib zlib (no-zstd !)
1590 1590 compression: zstd zlib zstd (zstd !)
1591 1591 compression-level: default default default
1592 1592 $ hg debugrequires
1593 1593 dotencode
1594 1594 fncache
1595 1595 generaldelta
1596 1596 persistent-nodemap (rust !)
1597 1597 revlog-compression-zstd
1598 1598 revlogv1
1599 1599 share-safe
1600 1600 sparserevlog
1601 1601 store
1602 1602
1603 1603 downgrade
1604 1604
1605 1605 $ hg debugupgraderepo --run --no-backup --quiet
1606 1606 upgrade will perform the following actions:
1607 1607
1608 1608 requirements
1609 1609 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1610 1610 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1611 1611 removed: revlog-compression-zstd
1612 1612
1613 1613 processed revlogs:
1614 1614 - all-filelogs
1615 1615 - changelog
1616 1616 - manifest
1617 1617
1618 1618 $ hg debugformat -v
1619 1619 format-variant repo config default
1620 1620 fncache: yes yes yes
1621 1621 dirstate-v2: no no no
1622 1622 tracked-hint: no no no
1623 1623 dotencode: yes yes yes
1624 1624 generaldelta: yes yes yes
1625 1625 share-safe: yes yes yes
1626 1626 sparserevlog: yes yes yes
1627 1627 persistent-nodemap: no no no (no-rust !)
1628 1628 persistent-nodemap: yes yes no (rust !)
1629 1629 copies-sdc: no no no
1630 1630 revlog-v2: no no no
1631 1631 changelog-v2: no no no
1632 1632 plain-cl-delta: yes yes yes
1633 1633 compression: zlib zlib zlib (no-zstd !)
1634 1634 compression: zlib zlib zstd (zstd !)
1635 1635 compression-level: default default default
1636 1636 $ hg debugrequires
1637 1637 dotencode
1638 1638 fncache
1639 1639 generaldelta
1640 1640 persistent-nodemap (rust !)
1641 1641 revlogv1
1642 1642 share-safe
1643 1643 sparserevlog
1644 1644 store
1645 1645
1646 1646 upgrade from hgrc
1647 1647
1648 1648 $ cat >> .hg/hgrc << EOF
1649 1649 > [format]
1650 1650 > revlog-compression=zstd
1651 1651 > EOF
1652 1652 $ hg debugupgraderepo --run --no-backup --quiet
1653 1653 upgrade will perform the following actions:
1654 1654
1655 1655 requirements
1656 1656 preserved: dotencode, fncache, generaldelta, revlogv1, share-safe, sparserevlog, store (no-rust !)
1657 1657 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlogv1, share-safe, sparserevlog, store (rust !)
1658 1658 added: revlog-compression-zstd
1659 1659
1660 1660 processed revlogs:
1661 1661 - all-filelogs
1662 1662 - changelog
1663 1663 - manifest
1664 1664
1665 1665 $ hg debugformat -v
1666 1666 format-variant repo config default
1667 1667 fncache: yes yes yes
1668 1668 dirstate-v2: no no no
1669 1669 tracked-hint: no no no
1670 1670 dotencode: yes yes yes
1671 1671 generaldelta: yes yes yes
1672 1672 share-safe: yes yes yes
1673 1673 sparserevlog: yes yes yes
1674 1674 persistent-nodemap: no no no (no-rust !)
1675 1675 persistent-nodemap: yes yes no (rust !)
1676 1676 copies-sdc: no no no
1677 1677 revlog-v2: no no no
1678 1678 changelog-v2: no no no
1679 1679 plain-cl-delta: yes yes yes
1680 1680 compression: zlib zlib zlib (no-zstd !)
1681 1681 compression: zstd zstd zstd (zstd !)
1682 1682 compression-level: default default default
1683 1683 $ hg debugrequires
1684 1684 dotencode
1685 1685 fncache
1686 1686 generaldelta
1687 1687 persistent-nodemap (rust !)
1688 1688 revlog-compression-zstd
1689 1689 revlogv1
1690 1690 share-safe
1691 1691 sparserevlog
1692 1692 store
1693 1693
1694 1694 #endif
1695 1695
1696 1696 Check upgrading to a revlog format supporting sidedata
1697 1697 ------------------------------------------------------
1698 1698
1699 1699 upgrade
1700 1700
1701 1701 $ hg debugsidedata -c 0
1702 1702 $ hg --config experimental.revlogv2=enable-unstable-format-and-corrupt-my-data debugupgraderepo --run --no-backup --config "extensions.sidedata=$TESTDIR/testlib/ext-sidedata.py" --quiet
1703 1703 upgrade will perform the following actions:
1704 1704
1705 1705 requirements
1706 1706 preserved: dotencode, fncache, generaldelta, share-safe, store (no-zstd !)
1707 1707 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, share-safe, sparserevlog, store (zstd no-rust !)
1708 1708 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, share-safe, sparserevlog, store (rust !)
1709 1709 removed: revlogv1
1710 1710 added: exp-revlogv2.2 (zstd !)
1711 1711 added: exp-revlogv2.2, sparserevlog (no-zstd !)
1712 1712
1713 1713 processed revlogs:
1714 1714 - all-filelogs
1715 1715 - changelog
1716 1716 - manifest
1717 1717
1718 1718 $ hg debugformat -v
1719 1719 format-variant repo config default
1720 1720 fncache: yes yes yes
1721 1721 dirstate-v2: no no no
1722 1722 tracked-hint: no no no
1723 1723 dotencode: yes yes yes
1724 1724 generaldelta: yes yes yes
1725 1725 share-safe: yes yes yes
1726 1726 sparserevlog: yes yes yes
1727 1727 persistent-nodemap: no no no (no-rust !)
1728 1728 persistent-nodemap: yes yes no (rust !)
1729 1729 copies-sdc: no no no
1730 1730 revlog-v2: yes no no
1731 1731 changelog-v2: no no no
1732 1732 plain-cl-delta: yes yes yes
1733 1733 compression: zlib zlib zlib (no-zstd !)
1734 1734 compression: zstd zstd zstd (zstd !)
1735 1735 compression-level: default default default
1736 1736 $ hg debugrequires
1737 1737 dotencode
1738 1738 exp-revlogv2.2
1739 1739 fncache
1740 1740 generaldelta
1741 1741 persistent-nodemap (rust !)
1742 1742 revlog-compression-zstd (zstd !)
1743 1743 share-safe
1744 1744 sparserevlog
1745 1745 store
1746 1746 $ hg debugsidedata -c 0
1747 1747 2 sidedata entries
1748 1748 entry-0001 size 4
1749 1749 entry-0002 size 32
1750 1750
1751 1751 downgrade
1752 1752
1753 1753 $ hg debugupgraderepo --config experimental.revlogv2=no --run --no-backup --quiet
1754 1754 upgrade will perform the following actions:
1755 1755
1756 1756 requirements
1757 1757 preserved: dotencode, fncache, generaldelta, share-safe, sparserevlog, store (no-zstd !)
1758 1758 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, share-safe, sparserevlog, store (zstd no-rust !)
1759 1759 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, share-safe, sparserevlog, store (rust !)
1760 1760 removed: exp-revlogv2.2
1761 1761 added: revlogv1
1762 1762
1763 1763 processed revlogs:
1764 1764 - all-filelogs
1765 1765 - changelog
1766 1766 - manifest
1767 1767
1768 1768 $ hg debugformat -v
1769 1769 format-variant repo config default
1770 1770 fncache: yes yes yes
1771 1771 dirstate-v2: no no no
1772 1772 tracked-hint: no no no
1773 1773 dotencode: yes yes yes
1774 1774 generaldelta: yes yes yes
1775 1775 share-safe: yes yes yes
1776 1776 sparserevlog: yes yes yes
1777 1777 persistent-nodemap: no no no (no-rust !)
1778 1778 persistent-nodemap: yes yes no (rust !)
1779 1779 copies-sdc: no no no
1780 1780 revlog-v2: no no no
1781 1781 changelog-v2: no no no
1782 1782 plain-cl-delta: yes yes yes
1783 1783 compression: zlib zlib zlib (no-zstd !)
1784 1784 compression: zstd zstd zstd (zstd !)
1785 1785 compression-level: default default default
1786 1786 $ hg debugrequires
1787 1787 dotencode
1788 1788 fncache
1789 1789 generaldelta
1790 1790 persistent-nodemap (rust !)
1791 1791 revlog-compression-zstd (zstd !)
1792 1792 revlogv1
1793 1793 share-safe
1794 1794 sparserevlog
1795 1795 store
1796 1796 $ hg debugsidedata -c 0
1797 1797
1798 1798 upgrade from hgrc
1799 1799
1800 1800 $ cat >> .hg/hgrc << EOF
1801 1801 > [experimental]
1802 1802 > revlogv2=enable-unstable-format-and-corrupt-my-data
1803 1803 > EOF
1804 1804 $ hg debugupgraderepo --run --no-backup --quiet
1805 1805 upgrade will perform the following actions:
1806 1806
1807 1807 requirements
1808 1808 preserved: dotencode, fncache, generaldelta, share-safe, sparserevlog, store (no-zstd !)
1809 1809 preserved: dotencode, fncache, generaldelta, revlog-compression-zstd, share-safe, sparserevlog, store (zstd no-rust !)
1810 1810 preserved: dotencode, fncache, generaldelta, persistent-nodemap, revlog-compression-zstd, share-safe, sparserevlog, store (rust !)
1811 1811 removed: revlogv1
1812 1812 added: exp-revlogv2.2
1813 1813
1814 1814 processed revlogs:
1815 1815 - all-filelogs
1816 1816 - changelog
1817 1817 - manifest
1818 1818
1819 1819 $ hg debugformat -v
1820 1820 format-variant repo config default
1821 1821 fncache: yes yes yes
1822 1822 dirstate-v2: no no no
1823 1823 tracked-hint: no no no
1824 1824 dotencode: yes yes yes
1825 1825 generaldelta: yes yes yes
1826 1826 share-safe: yes yes yes
1827 1827 sparserevlog: yes yes yes
1828 1828 persistent-nodemap: no no no (no-rust !)
1829 1829 persistent-nodemap: yes yes no (rust !)
1830 1830 copies-sdc: no no no
1831 1831 revlog-v2: yes yes no
1832 1832 changelog-v2: no no no
1833 1833 plain-cl-delta: yes yes yes
1834 1834 compression: zlib zlib zlib (no-zstd !)
1835 1835 compression: zstd zstd zstd (zstd !)
1836 1836 compression-level: default default default
1837 1837 $ hg debugrequires
1838 1838 dotencode
1839 1839 exp-revlogv2.2
1840 1840 fncache
1841 1841 generaldelta
1842 1842 persistent-nodemap (rust !)
1843 1843 revlog-compression-zstd (zstd !)
1844 1844 share-safe
1845 1845 sparserevlog
1846 1846 store
1847 1847 $ hg debugsidedata -c 0
1848 1848
1849 1849 Demonstrate that nothing to perform upgrade will still run all the way through
1850 1850
1851 1851 $ hg debugupgraderepo --run
1852 1852 nothing to do
1853 1853
1854 1854 #if no-rust
1855 1855
1856 1856 $ cat << EOF >> $HGRCPATH
1857 1857 > [storage]
1858 1858 > dirstate-v2.slow-path = allow
1859 1859 > EOF
1860 1860
1861 1861 #endif
1862 1862
1863 1863 Upgrade to dirstate-v2
1864 1864
1865 1865 $ hg debugformat -v --config format.use-dirstate-v2=1 | grep dirstate-v2
1866 1866 dirstate-v2: no yes no
1867 1867 $ hg debugupgraderepo --config format.use-dirstate-v2=1 --run
1868 1868 upgrade will perform the following actions:
1869 1869
1870 1870 requirements
1871 1871 preserved: * (glob)
1872 1872 added: dirstate-v2
1873 1873
1874 1874 dirstate-v2
1875 1875 "hg status" will be faster
1876 1876
1877 1877 no revlogs to process
1878 1878
1879 1879 beginning upgrade...
1880 1880 repository locked and read-only
1881 1881 creating temporary repository to stage upgraded data: $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob)
1882 1882 (it is safe to interrupt this process any time before data migration completes)
1883 1883 upgrading to dirstate-v2 from v1
1884 1884 replaced files will be backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
1885 1885 removing temporary repository $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob)
1886 1886 $ ls .hg/upgradebackup.*/dirstate
1887 1887 .hg/upgradebackup.*/dirstate (glob)
1888 1888 $ hg debugformat -v | grep dirstate-v2
1889 1889 dirstate-v2: yes no no
1890 1890 $ hg status
1891 1891 $ dd bs=12 count=1 if=.hg/dirstate 2> /dev/null
1892 1892 dirstate-v2
1893 1893
1894 1894 Downgrade from dirstate-v2
1895 1895
1896 1896 $ hg debugupgraderepo --run
1897 1897 upgrade will perform the following actions:
1898 1898
1899 1899 requirements
1900 1900 preserved: * (glob)
1901 1901 removed: dirstate-v2
1902 1902
1903 1903 no revlogs to process
1904 1904
1905 1905 beginning upgrade...
1906 1906 repository locked and read-only
1907 1907 creating temporary repository to stage upgraded data: $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob)
1908 1908 (it is safe to interrupt this process any time before data migration completes)
1909 1909 downgrading from dirstate-v2 to v1
1910 1910 replaced files will be backed up at $TESTTMP/sparserevlogrepo/.hg/upgradebackup.* (glob)
1911 1911 removing temporary repository $TESTTMP/sparserevlogrepo/.hg/upgrade.* (glob)
1912 1912 $ hg debugformat -v | grep dirstate-v2
1913 1913 dirstate-v2: no no no
1914 1914 $ hg status
1915 1915
1916 1916 $ cd ..
1917 1917
1918 1918 dirstate-v2: upgrade and downgrade from and empty repository:
1919 1919 -------------------------------------------------------------
1920 1920
1921 1921 $ hg init --config format.use-dirstate-v2=no dirstate-v2-empty
1922 1922 $ cd dirstate-v2-empty
1923 1923 $ hg debugformat | grep dirstate-v2
1924 1924 dirstate-v2: no
1925 1925
1926 1926 upgrade
1927 1927
1928 1928 $ hg debugupgraderepo --run --config format.use-dirstate-v2=yes
1929 1929 upgrade will perform the following actions:
1930 1930
1931 1931 requirements
1932 1932 preserved: * (glob)
1933 1933 added: dirstate-v2
1934 1934
1935 1935 dirstate-v2
1936 1936 "hg status" will be faster
1937 1937
1938 1938 no revlogs to process
1939 1939
1940 1940 beginning upgrade...
1941 1941 repository locked and read-only
1942 1942 creating temporary repository to stage upgraded data: $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob)
1943 1943 (it is safe to interrupt this process any time before data migration completes)
1944 1944 upgrading to dirstate-v2 from v1
1945 1945 replaced files will be backed up at $TESTTMP/dirstate-v2-empty/.hg/upgradebackup.* (glob)
1946 1946 removing temporary repository $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob)
1947 1947 $ hg debugformat | grep dirstate-v2
1948 1948 dirstate-v2: yes
1949 1949
1950 1950 downgrade
1951 1951
1952 1952 $ hg debugupgraderepo --run --config format.use-dirstate-v2=no
1953 1953 upgrade will perform the following actions:
1954 1954
1955 1955 requirements
1956 1956 preserved: * (glob)
1957 1957 removed: dirstate-v2
1958 1958
1959 1959 no revlogs to process
1960 1960
1961 1961 beginning upgrade...
1962 1962 repository locked and read-only
1963 1963 creating temporary repository to stage upgraded data: $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob)
1964 1964 (it is safe to interrupt this process any time before data migration completes)
1965 1965 downgrading from dirstate-v2 to v1
1966 1966 replaced files will be backed up at $TESTTMP/dirstate-v2-empty/.hg/upgradebackup.* (glob)
1967 1967 removing temporary repository $TESTTMP/dirstate-v2-empty/.hg/upgrade.* (glob)
1968 1968 $ hg debugformat | grep dirstate-v2
1969 1969 dirstate-v2: no
1970 1970
1971 1971 $ cd ..
1972 1972
1973 1973 Test automatic upgrade/downgrade
1974 1974 ================================
1975 1975
1976 1976
1977 1977 For dirstate v2
1978 1978 ---------------
1979 1979
1980 1980 create an initial repository
1981 1981
1982 1982 $ hg init auto-upgrade \
1983 1983 > --config format.use-dirstate-v2=no \
1984 1984 > --config format.use-dirstate-tracked-hint=yes \
1985 1985 > --config format.use-share-safe=no
1986 1986 $ hg debugbuilddag -R auto-upgrade --new-file .+5
1987 1987 $ hg -R auto-upgrade update
1988 1988 6 files updated, 0 files merged, 0 files removed, 0 files unresolved
1989 1989 $ hg debugformat -R auto-upgrade | grep dirstate-v2
1990 1990 dirstate-v2: no
1991 1991
1992 1992 upgrade it to dirstate-v2 automatically
1993 1993
1994 1994 $ hg status -R auto-upgrade \
1995 1995 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
1996 1996 > --config format.use-dirstate-v2=yes
1997 1997 automatically upgrading repository to the `dirstate-v2` feature
1998 1998 (see `hg help config.format.use-dirstate-v2` for details)
1999 1999 $ hg debugformat -R auto-upgrade | grep dirstate-v2
2000 2000 dirstate-v2: yes
2001 2001
2002 2002 downgrade it from dirstate-v2 automatically
2003 2003
2004 2004 $ hg status -R auto-upgrade \
2005 2005 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
2006 2006 > --config format.use-dirstate-v2=no
2007 2007 automatically downgrading repository from the `dirstate-v2` feature
2008 2008 (see `hg help config.format.use-dirstate-v2` for details)
2009 2009 $ hg debugformat -R auto-upgrade | grep dirstate-v2
2010 2010 dirstate-v2: no
2011 2011
2012 2012
2013 2013 For multiple change at the same time
2014 2014 ------------------------------------
2015 2015
2016 2016 $ hg debugformat -R auto-upgrade | grep -E '(dirstate-v2|tracked|share-safe)'
2017 2017 dirstate-v2: no
2018 2018 tracked-hint: yes
2019 2019 share-safe: no
2020 2020
2021 2021 $ hg status -R auto-upgrade \
2022 2022 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
2023 2023 > --config format.use-dirstate-v2=yes \
2024 2024 > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories=yes \
2025 2025 > --config format.use-dirstate-tracked-hint=no\
2026 2026 > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories=yes \
2027 2027 > --config format.use-share-safe=yes
2028 2028 automatically upgrading repository to the `dirstate-v2` feature
2029 2029 (see `hg help config.format.use-dirstate-v2` for details)
2030 2030 automatically upgrading repository to the `share-safe` feature
2031 2031 (see `hg help config.format.use-share-safe` for details)
2032 2032 automatically downgrading repository from the `tracked-hint` feature
2033 2033 (see `hg help config.format.use-dirstate-tracked-hint` for details)
2034 2034 $ hg debugformat -R auto-upgrade | grep -E '(dirstate-v2|tracked|share-safe)'
2035 2035 dirstate-v2: yes
2036 2036 tracked-hint: no
2037 2037 share-safe: yes
2038 2038
2039 2039 Quiet upgrade and downgrade
2040 2040 ---------------------------
2041 2041
2042 2042
2043 2043 $ hg debugformat -R auto-upgrade | grep -E '(dirstate-v2|tracked|share-safe)'
2044 2044 dirstate-v2: yes
2045 2045 tracked-hint: no
2046 2046 share-safe: yes
2047 2047 $ hg status -R auto-upgrade \
2048 2048 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
2049 2049 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet=yes \
2050 2050 > --config format.use-dirstate-v2=no \
2051 2051 > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories=yes \
2052 2052 > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet=yes \
2053 2053 > --config format.use-dirstate-tracked-hint=yes \
2054 2054 > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories=yes \
2055 2055 > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet=yes \
2056 2056 > --config format.use-share-safe=no
2057 2057
2058 2058 $ hg debugformat -R auto-upgrade | grep -E '(dirstate-v2|tracked|share-safe)'
2059 2059 dirstate-v2: no
2060 2060 tracked-hint: yes
2061 2061 share-safe: no
2062 2062
2063 2063 $ hg status -R auto-upgrade \
2064 2064 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
2065 2065 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet=yes \
2066 2066 > --config format.use-dirstate-v2=yes \
2067 2067 > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories=yes \
2068 2068 > --config format.use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet=yes \
2069 2069 > --config format.use-dirstate-tracked-hint=no\
2070 2070 > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories=yes \
2071 2071 > --config format.use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet=yes \
2072 2072 > --config format.use-share-safe=yes
2073 2073 $ hg debugformat -R auto-upgrade | grep -E '(dirstate-v2|tracked|share-safe)'
2074 2074 dirstate-v2: yes
2075 2075 tracked-hint: no
2076 2076 share-safe: yes
2077 2077
2078 2078 Attempting Auto-upgrade on a read-only repository
2079 2079 -------------------------------------------------
2080 2080
2081 2081 $ chmod -R a-w auto-upgrade
2082 2082
2083 2083 $ hg status -R auto-upgrade \
2084 2084 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
2085 2085 > --config format.use-dirstate-v2=no
2086 2086 $ hg debugformat -R auto-upgrade | grep dirstate-v2
2087 2087 dirstate-v2: yes
2088 2088
2089 2089 $ chmod -R u+w auto-upgrade
2090 2090
2091 2091 Attempting Auto-upgrade on a locked repository
2092 2092 ----------------------------------------------
2093 2093
2094 2094 $ hg -R auto-upgrade debuglock --set-lock --quiet &
2095 2095 $ echo $! >> $DAEMON_PIDS
2096 2096 $ $RUNTESTDIR/testlib/wait-on-file 10 auto-upgrade/.hg/store/lock
2097 2097 $ hg status -R auto-upgrade \
2098 2098 > --config format.use-dirstate-v2.automatic-upgrade-of-mismatching-repositories=yes \
2099 2099 > --config format.use-dirstate-v2=no
2100 2100 $ hg debugformat -R auto-upgrade | grep dirstate-v2
2101 2101 dirstate-v2: yes
2102 2102
2103 2103 $ killdaemons.py
General Comments 0
You need to be logged in to leave comments. Login now