mercurial/debugcommands.py
changeset 43077 687b865b95ad
parent 43076 2372284d9457
child 43080 86e4daa2d54c
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
    93 release = lockmod.release
    93 release = lockmod.release
    94 
    94 
    95 command = registrar.command()
    95 command = registrar.command()
    96 
    96 
    97 
    97 
    98 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
    98 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
    99 def debugancestor(ui, repo, *args):
    99 def debugancestor(ui, repo, *args):
   100     """find the ancestor revision of two revisions in a given index"""
   100     """find the ancestor revision of two revisions in a given index"""
   101     if len(args) == 3:
   101     if len(args) == 3:
   102         index, rev1, rev2 = args
   102         index, rev1, rev2 = args
   103         r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
   103         r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
   104         lookup = r.lookup
   104         lookup = r.lookup
   105     elif len(args) == 2:
   105     elif len(args) == 2:
   106         if not repo:
   106         if not repo:
   107             raise error.Abort(
   107             raise error.Abort(
   108                 _('there is no Mercurial repository here ' '(.hg not found)')
   108                 _(b'there is no Mercurial repository here ' b'(.hg not found)')
   109             )
   109             )
   110         rev1, rev2 = args
   110         rev1, rev2 = args
   111         r = repo.changelog
   111         r = repo.changelog
   112         lookup = repo.lookup
   112         lookup = repo.lookup
   113     else:
   113     else:
   114         raise error.Abort(_('either two or three arguments required'))
   114         raise error.Abort(_(b'either two or three arguments required'))
   115     a = r.ancestor(lookup(rev1), lookup(rev2))
   115     a = r.ancestor(lookup(rev1), lookup(rev2))
   116     ui.write('%d:%s\n' % (r.rev(a), hex(a)))
   116     ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
   117 
   117 
   118 
   118 
   119 @command('debugapplystreamclonebundle', [], 'FILE')
   119 @command(b'debugapplystreamclonebundle', [], b'FILE')
   120 def debugapplystreamclonebundle(ui, repo, fname):
   120 def debugapplystreamclonebundle(ui, repo, fname):
   121     """apply a stream clone bundle file"""
   121     """apply a stream clone bundle file"""
   122     f = hg.openpath(ui, fname)
   122     f = hg.openpath(ui, fname)
   123     gen = exchange.readbundle(ui, f, fname)
   123     gen = exchange.readbundle(ui, f, fname)
   124     gen.apply(repo)
   124     gen.apply(repo)
   125 
   125 
   126 
   126 
   127 @command(
   127 @command(
   128     'debugbuilddag',
   128     b'debugbuilddag',
   129     [
   129     [
   130         ('m', 'mergeable-file', None, _('add single file mergeable changes')),
       
   131         (
   130         (
   132             'o',
   131             b'm',
   133             'overwritten-file',
   132             b'mergeable-file',
   134             None,
   133             None,
   135             _('add single file all revs overwrite'),
   134             _(b'add single file mergeable changes'),
   136         ),
   135         ),
   137         ('n', 'new-file', None, _('add new file at each rev')),
   136         (
       
   137             b'o',
       
   138             b'overwritten-file',
       
   139             None,
       
   140             _(b'add single file all revs overwrite'),
       
   141         ),
       
   142         (b'n', b'new-file', None, _(b'add new file at each rev')),
   138     ],
   143     ],
   139     _('[OPTION]... [TEXT]'),
   144     _(b'[OPTION]... [TEXT]'),
   140 )
   145 )
   141 def debugbuilddag(
   146 def debugbuilddag(
   142     ui,
   147     ui,
   143     repo,
   148     repo,
   144     text=None,
   149     text=None,
   177     All string valued-elements are either strictly alphanumeric, or must
   182     All string valued-elements are either strictly alphanumeric, or must
   178     be enclosed in double quotes ("..."), with "\\" as escape character.
   183     be enclosed in double quotes ("..."), with "\\" as escape character.
   179     """
   184     """
   180 
   185 
   181     if text is None:
   186     if text is None:
   182         ui.status(_("reading DAG from stdin\n"))
   187         ui.status(_(b"reading DAG from stdin\n"))
   183         text = ui.fin.read()
   188         text = ui.fin.read()
   184 
   189 
   185     cl = repo.changelog
   190     cl = repo.changelog
   186     if len(cl) > 0:
   191     if len(cl) > 0:
   187         raise error.Abort(_('repository is not empty'))
   192         raise error.Abort(_(b'repository is not empty'))
   188 
   193 
   189     # determine number of revs in DAG
   194     # determine number of revs in DAG
   190     total = 0
   195     total = 0
   191     for type, data in dagparser.parsedag(text):
   196     for type, data in dagparser.parsedag(text):
   192         if type == 'n':
   197         if type == b'n':
   193             total += 1
   198             total += 1
   194 
   199 
   195     if mergeable_file:
   200     if mergeable_file:
   196         linesperrev = 2
   201         linesperrev = 2
   197         # make a file with k lines per rev
   202         # make a file with k lines per rev
   198         initialmergedlines = [
   203         initialmergedlines = [
   199             '%d' % i for i in pycompat.xrange(0, total * linesperrev)
   204             b'%d' % i for i in pycompat.xrange(0, total * linesperrev)
   200         ]
   205         ]
   201         initialmergedlines.append("")
   206         initialmergedlines.append(b"")
   202 
   207 
   203     tags = []
   208     tags = []
   204     progress = ui.makeprogress(_('building'), unit=_('revisions'), total=total)
   209     progress = ui.makeprogress(
   205     with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
   210         _(b'building'), unit=_(b'revisions'), total=total
       
   211     )
       
   212     with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
   206         at = -1
   213         at = -1
   207         atbranch = 'default'
   214         atbranch = b'default'
   208         nodeids = []
   215         nodeids = []
   209         id = 0
   216         id = 0
   210         progress.update(id)
   217         progress.update(id)
   211         for type, data in dagparser.parsedag(text):
   218         for type, data in dagparser.parsedag(text):
   212             if type == 'n':
   219             if type == b'n':
   213                 ui.note(('node %s\n' % pycompat.bytestr(data)))
   220                 ui.note((b'node %s\n' % pycompat.bytestr(data)))
   214                 id, ps = data
   221                 id, ps = data
   215 
   222 
   216                 files = []
   223                 files = []
   217                 filecontent = {}
   224                 filecontent = {}
   218 
   225 
   219                 p2 = None
   226                 p2 = None
   220                 if mergeable_file:
   227                 if mergeable_file:
   221                     fn = "mf"
   228                     fn = b"mf"
   222                     p1 = repo[ps[0]]
   229                     p1 = repo[ps[0]]
   223                     if len(ps) > 1:
   230                     if len(ps) > 1:
   224                         p2 = repo[ps[1]]
   231                         p2 = repo[ps[1]]
   225                         pa = p1.ancestor(p2)
   232                         pa = p1.ancestor(p2)
   226                         base, local, other = [
   233                         base, local, other = [
   227                             x[fn].data() for x in (pa, p1, p2)
   234                             x[fn].data() for x in (pa, p1, p2)
   228                         ]
   235                         ]
   229                         m3 = simplemerge.Merge3Text(base, local, other)
   236                         m3 = simplemerge.Merge3Text(base, local, other)
   230                         ml = [l.strip() for l in m3.merge_lines()]
   237                         ml = [l.strip() for l in m3.merge_lines()]
   231                         ml.append("")
   238                         ml.append(b"")
   232                     elif at > 0:
   239                     elif at > 0:
   233                         ml = p1[fn].data().split("\n")
   240                         ml = p1[fn].data().split(b"\n")
   234                     else:
   241                     else:
   235                         ml = initialmergedlines
   242                         ml = initialmergedlines
   236                     ml[id * linesperrev] += " r%i" % id
   243                     ml[id * linesperrev] += b" r%i" % id
   237                     mergedtext = "\n".join(ml)
   244                     mergedtext = b"\n".join(ml)
   238                     files.append(fn)
   245                     files.append(fn)
   239                     filecontent[fn] = mergedtext
   246                     filecontent[fn] = mergedtext
   240 
   247 
   241                 if overwritten_file:
   248                 if overwritten_file:
   242                     fn = "of"
   249                     fn = b"of"
   243                     files.append(fn)
   250                     files.append(fn)
   244                     filecontent[fn] = "r%i\n" % id
   251                     filecontent[fn] = b"r%i\n" % id
   245 
   252 
   246                 if new_file:
   253                 if new_file:
   247                     fn = "nf%i" % id
   254                     fn = b"nf%i" % id
   248                     files.append(fn)
   255                     files.append(fn)
   249                     filecontent[fn] = "r%i\n" % id
   256                     filecontent[fn] = b"r%i\n" % id
   250                     if len(ps) > 1:
   257                     if len(ps) > 1:
   251                         if not p2:
   258                         if not p2:
   252                             p2 = repo[ps[1]]
   259                             p2 = repo[ps[1]]
   253                         for fn in p2:
   260                         for fn in p2:
   254                             if fn.startswith("nf"):
   261                             if fn.startswith(b"nf"):
   255                                 files.append(fn)
   262                                 files.append(fn)
   256                                 filecontent[fn] = p2[fn].data()
   263                                 filecontent[fn] = p2[fn].data()
   257 
   264 
   258                 def fctxfn(repo, cx, path):
   265                 def fctxfn(repo, cx, path):
   259                     if path in filecontent:
   266                     if path in filecontent:
   269                 else:
   276                 else:
   270                     pars = [nodeids[p] for p in ps]
   277                     pars = [nodeids[p] for p in ps]
   271                 cx = context.memctx(
   278                 cx = context.memctx(
   272                     repo,
   279                     repo,
   273                     pars,
   280                     pars,
   274                     "r%i" % id,
   281                     b"r%i" % id,
   275                     files,
   282                     files,
   276                     fctxfn,
   283                     fctxfn,
   277                     date=(id, 0),
   284                     date=(id, 0),
   278                     user="debugbuilddag",
   285                     user=b"debugbuilddag",
   279                     extra={'branch': atbranch},
   286                     extra={b'branch': atbranch},
   280                 )
   287                 )
   281                 nodeid = repo.commitctx(cx)
   288                 nodeid = repo.commitctx(cx)
   282                 nodeids.append(nodeid)
   289                 nodeids.append(nodeid)
   283                 at = id
   290                 at = id
   284             elif type == 'l':
   291             elif type == b'l':
   285                 id, name = data
   292                 id, name = data
   286                 ui.note(('tag %s\n' % name))
   293                 ui.note((b'tag %s\n' % name))
   287                 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
   294                 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
   288             elif type == 'a':
   295             elif type == b'a':
   289                 ui.note(('branch %s\n' % data))
   296                 ui.note((b'branch %s\n' % data))
   290                 atbranch = data
   297                 atbranch = data
   291             progress.update(id)
   298             progress.update(id)
   292 
   299 
   293         if tags:
   300         if tags:
   294             repo.vfs.write("localtags", "".join(tags))
   301             repo.vfs.write(b"localtags", b"".join(tags))
   295 
   302 
   296 
   303 
   297 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
   304 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
   298     indent_string = ' ' * indent
   305     indent_string = b' ' * indent
   299     if all:
   306     if all:
   300         ui.write(
   307         ui.write(
   301             "%sformat: id, p1, p2, cset, delta base, len(delta)\n"
   308             b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
   302             % indent_string
   309             % indent_string
   303         )
   310         )
   304 
   311 
   305         def showchunks(named):
   312         def showchunks(named):
   306             ui.write("\n%s%s\n" % (indent_string, named))
   313             ui.write(b"\n%s%s\n" % (indent_string, named))
   307             for deltadata in gen.deltaiter():
   314             for deltadata in gen.deltaiter():
   308                 node, p1, p2, cs, deltabase, delta, flags = deltadata
   315                 node, p1, p2, cs, deltabase, delta, flags = deltadata
   309                 ui.write(
   316                 ui.write(
   310                     "%s%s %s %s %s %s %d\n"
   317                     b"%s%s %s %s %s %s %d\n"
   311                     % (
   318                     % (
   312                         indent_string,
   319                         indent_string,
   313                         hex(node),
   320                         hex(node),
   314                         hex(p1),
   321                         hex(p1),
   315                         hex(p2),
   322                         hex(p2),
   318                         len(delta),
   325                         len(delta),
   319                     )
   326                     )
   320                 )
   327                 )
   321 
   328 
   322         chunkdata = gen.changelogheader()
   329         chunkdata = gen.changelogheader()
   323         showchunks("changelog")
   330         showchunks(b"changelog")
   324         chunkdata = gen.manifestheader()
   331         chunkdata = gen.manifestheader()
   325         showchunks("manifest")
   332         showchunks(b"manifest")
   326         for chunkdata in iter(gen.filelogheader, {}):
   333         for chunkdata in iter(gen.filelogheader, {}):
   327             fname = chunkdata['filename']
   334             fname = chunkdata[b'filename']
   328             showchunks(fname)
   335             showchunks(fname)
   329     else:
   336     else:
   330         if isinstance(gen, bundle2.unbundle20):
   337         if isinstance(gen, bundle2.unbundle20):
   331             raise error.Abort(_('use debugbundle2 for this file'))
   338             raise error.Abort(_(b'use debugbundle2 for this file'))
   332         chunkdata = gen.changelogheader()
   339         chunkdata = gen.changelogheader()
   333         for deltadata in gen.deltaiter():
   340         for deltadata in gen.deltaiter():
   334             node, p1, p2, cs, deltabase, delta, flags = deltadata
   341             node, p1, p2, cs, deltabase, delta, flags = deltadata
   335             ui.write("%s%s\n" % (indent_string, hex(node)))
   342             ui.write(b"%s%s\n" % (indent_string, hex(node)))
   336 
   343 
   337 
   344 
   338 def _debugobsmarkers(ui, part, indent=0, **opts):
   345 def _debugobsmarkers(ui, part, indent=0, **opts):
   339     """display version and markers contained in 'data'"""
   346     """display version and markers contained in 'data'"""
   340     opts = pycompat.byteskwargs(opts)
   347     opts = pycompat.byteskwargs(opts)
   341     data = part.read()
   348     data = part.read()
   342     indent_string = ' ' * indent
   349     indent_string = b' ' * indent
   343     try:
   350     try:
   344         version, markers = obsolete._readmarkers(data)
   351         version, markers = obsolete._readmarkers(data)
   345     except error.UnknownVersion as exc:
   352     except error.UnknownVersion as exc:
   346         msg = "%sunsupported version: %s (%d bytes)\n"
   353         msg = b"%sunsupported version: %s (%d bytes)\n"
   347         msg %= indent_string, exc.version, len(data)
   354         msg %= indent_string, exc.version, len(data)
   348         ui.write(msg)
   355         ui.write(msg)
   349     else:
   356     else:
   350         msg = "%sversion: %d (%d bytes)\n"
   357         msg = b"%sversion: %d (%d bytes)\n"
   351         msg %= indent_string, version, len(data)
   358         msg %= indent_string, version, len(data)
   352         ui.write(msg)
   359         ui.write(msg)
   353         fm = ui.formatter('debugobsolete', opts)
   360         fm = ui.formatter(b'debugobsolete', opts)
   354         for rawmarker in sorted(markers):
   361         for rawmarker in sorted(markers):
   355             m = obsutil.marker(None, rawmarker)
   362             m = obsutil.marker(None, rawmarker)
   356             fm.startitem()
   363             fm.startitem()
   357             fm.plain(indent_string)
   364             fm.plain(indent_string)
   358             cmdutil.showmarker(fm, m)
   365             cmdutil.showmarker(fm, m)
   359         fm.end()
   366         fm.end()
   360 
   367 
   361 
   368 
   362 def _debugphaseheads(ui, data, indent=0):
   369 def _debugphaseheads(ui, data, indent=0):
   363     """display version and markers contained in 'data'"""
   370     """display version and markers contained in 'data'"""
   364     indent_string = ' ' * indent
   371     indent_string = b' ' * indent
   365     headsbyphase = phases.binarydecode(data)
   372     headsbyphase = phases.binarydecode(data)
   366     for phase in phases.allphases:
   373     for phase in phases.allphases:
   367         for head in headsbyphase[phase]:
   374         for head in headsbyphase[phase]:
   368             ui.write(indent_string)
   375             ui.write(indent_string)
   369             ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
   376             ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
   370 
   377 
   371 
   378 
   372 def _quasirepr(thing):
   379 def _quasirepr(thing):
   373     if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
   380     if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
   374         return '{%s}' % (
   381         return b'{%s}' % (
   375             b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
   382             b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
   376         )
   383         )
   377     return pycompat.bytestr(repr(thing))
   384     return pycompat.bytestr(repr(thing))
   378 
   385 
   379 
   386 
   380 def _debugbundle2(ui, gen, all=None, **opts):
   387 def _debugbundle2(ui, gen, all=None, **opts):
   381     """lists the contents of a bundle2"""
   388     """lists the contents of a bundle2"""
   382     if not isinstance(gen, bundle2.unbundle20):
   389     if not isinstance(gen, bundle2.unbundle20):
   383         raise error.Abort(_('not a bundle2 file'))
   390         raise error.Abort(_(b'not a bundle2 file'))
   384     ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
   391     ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
   385     parttypes = opts.get(r'part_type', [])
   392     parttypes = opts.get(r'part_type', [])
   386     for part in gen.iterparts():
   393     for part in gen.iterparts():
   387         if parttypes and part.type not in parttypes:
   394         if parttypes and part.type not in parttypes:
   388             continue
   395             continue
   389         msg = '%s -- %s (mandatory: %r)\n'
   396         msg = b'%s -- %s (mandatory: %r)\n'
   390         ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
   397         ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
   391         if part.type == 'changegroup':
   398         if part.type == b'changegroup':
   392             version = part.params.get('version', '01')
   399             version = part.params.get(b'version', b'01')
   393             cg = changegroup.getunbundler(version, part, 'UN')
   400             cg = changegroup.getunbundler(version, part, b'UN')
   394             if not ui.quiet:
   401             if not ui.quiet:
   395                 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
   402                 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
   396         if part.type == 'obsmarkers':
   403         if part.type == b'obsmarkers':
   397             if not ui.quiet:
   404             if not ui.quiet:
   398                 _debugobsmarkers(ui, part, indent=4, **opts)
   405                 _debugobsmarkers(ui, part, indent=4, **opts)
   399         if part.type == 'phase-heads':
   406         if part.type == b'phase-heads':
   400             if not ui.quiet:
   407             if not ui.quiet:
   401                 _debugphaseheads(ui, part, indent=4)
   408                 _debugphaseheads(ui, part, indent=4)
   402 
   409 
   403 
   410 
   404 @command(
   411 @command(
   405     'debugbundle',
   412     b'debugbundle',
   406     [
   413     [
   407         ('a', 'all', None, _('show all details')),
   414         (b'a', b'all', None, _(b'show all details')),
   408         ('', 'part-type', [], _('show only the named part type')),
   415         (b'', b'part-type', [], _(b'show only the named part type')),
   409         ('', 'spec', None, _('print the bundlespec of the bundle')),
   416         (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
   410     ],
   417     ],
   411     _('FILE'),
   418     _(b'FILE'),
   412     norepo=True,
   419     norepo=True,
   413 )
   420 )
   414 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
   421 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
   415     """lists the contents of a bundle"""
   422     """lists the contents of a bundle"""
   416     with hg.openpath(ui, bundlepath) as f:
   423     with hg.openpath(ui, bundlepath) as f:
   417         if spec:
   424         if spec:
   418             spec = exchange.getbundlespec(ui, f)
   425             spec = exchange.getbundlespec(ui, f)
   419             ui.write('%s\n' % spec)
   426             ui.write(b'%s\n' % spec)
   420             return
   427             return
   421 
   428 
   422         gen = exchange.readbundle(ui, f, bundlepath)
   429         gen = exchange.readbundle(ui, f, bundlepath)
   423         if isinstance(gen, bundle2.unbundle20):
   430         if isinstance(gen, bundle2.unbundle20):
   424             return _debugbundle2(ui, gen, all=all, **opts)
   431             return _debugbundle2(ui, gen, all=all, **opts)
   425         _debugchangegroup(ui, gen, all=all, **opts)
   432         _debugchangegroup(ui, gen, all=all, **opts)
   426 
   433 
   427 
   434 
   428 @command('debugcapabilities', [], _('PATH'), norepo=True)
   435 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
   429 def debugcapabilities(ui, path, **opts):
   436 def debugcapabilities(ui, path, **opts):
   430     """lists the capabilities of a remote peer"""
   437     """lists the capabilities of a remote peer"""
   431     opts = pycompat.byteskwargs(opts)
   438     opts = pycompat.byteskwargs(opts)
   432     peer = hg.peer(ui, opts, path)
   439     peer = hg.peer(ui, opts, path)
   433     caps = peer.capabilities()
   440     caps = peer.capabilities()
   434     ui.write('Main capabilities:\n')
   441     ui.write(b'Main capabilities:\n')
   435     for c in sorted(caps):
   442     for c in sorted(caps):
   436         ui.write('  %s\n' % c)
   443         ui.write(b'  %s\n' % c)
   437     b2caps = bundle2.bundle2caps(peer)
   444     b2caps = bundle2.bundle2caps(peer)
   438     if b2caps:
   445     if b2caps:
   439         ui.write('Bundle2 capabilities:\n')
   446         ui.write(b'Bundle2 capabilities:\n')
   440         for key, values in sorted(b2caps.iteritems()):
   447         for key, values in sorted(b2caps.iteritems()):
   441             ui.write('  %s\n' % key)
   448             ui.write(b'  %s\n' % key)
   442             for v in values:
   449             for v in values:
   443                 ui.write('    %s\n' % v)
   450                 ui.write(b'    %s\n' % v)
   444 
   451 
   445 
   452 
   446 @command('debugcheckstate', [], '')
   453 @command(b'debugcheckstate', [], b'')
   447 def debugcheckstate(ui, repo):
   454 def debugcheckstate(ui, repo):
   448     """validate the correctness of the current dirstate"""
   455     """validate the correctness of the current dirstate"""
   449     parent1, parent2 = repo.dirstate.parents()
   456     parent1, parent2 = repo.dirstate.parents()
   450     m1 = repo[parent1].manifest()
   457     m1 = repo[parent1].manifest()
   451     m2 = repo[parent2].manifest()
   458     m2 = repo[parent2].manifest()
   452     errors = 0
   459     errors = 0
   453     for f in repo.dirstate:
   460     for f in repo.dirstate:
   454         state = repo.dirstate[f]
   461         state = repo.dirstate[f]
   455         if state in "nr" and f not in m1:
   462         if state in b"nr" and f not in m1:
   456             ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
   463             ui.warn(_(b"%s in state %s, but not in manifest1\n") % (f, state))
   457             errors += 1
   464             errors += 1
   458         if state in "a" and f in m1:
   465         if state in b"a" and f in m1:
   459             ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
   466             ui.warn(_(b"%s in state %s, but also in manifest1\n") % (f, state))
   460             errors += 1
   467             errors += 1
   461         if state in "m" and f not in m1 and f not in m2:
   468         if state in b"m" and f not in m1 and f not in m2:
   462             ui.warn(
   469             ui.warn(
   463                 _("%s in state %s, but not in either manifest\n") % (f, state)
   470                 _(b"%s in state %s, but not in either manifest\n") % (f, state)
   464             )
   471             )
   465             errors += 1
   472             errors += 1
   466     for f in m1:
   473     for f in m1:
   467         state = repo.dirstate[f]
   474         state = repo.dirstate[f]
   468         if state not in "nrm":
   475         if state not in b"nrm":
   469             ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
   476             ui.warn(_(b"%s in manifest1, but listed as state %s") % (f, state))
   470             errors += 1
   477             errors += 1
   471     if errors:
   478     if errors:
   472         error = _(".hg/dirstate inconsistent with current parent's manifest")
   479         error = _(b".hg/dirstate inconsistent with current parent's manifest")
   473         raise error.Abort(error)
   480         raise error.Abort(error)
   474 
   481 
   475 
   482 
   476 @command(
   483 @command(
   477     'debugcolor',
   484     b'debugcolor',
   478     [('', 'style', None, _('show all configured styles'))],
   485     [(b'', b'style', None, _(b'show all configured styles'))],
   479     'hg debugcolor',
   486     b'hg debugcolor',
   480 )
   487 )
   481 def debugcolor(ui, repo, **opts):
   488 def debugcolor(ui, repo, **opts):
   482     """show available color, effects or style"""
   489     """show available color, effects or style"""
   483     ui.write('color mode: %s\n' % stringutil.pprint(ui._colormode))
   490     ui.write(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
   484     if opts.get(r'style'):
   491     if opts.get(r'style'):
   485         return _debugdisplaystyle(ui)
   492         return _debugdisplaystyle(ui)
   486     else:
   493     else:
   487         return _debugdisplaycolor(ui)
   494         return _debugdisplaycolor(ui)
   488 
   495 
   491     ui = ui.copy()
   498     ui = ui.copy()
   492     ui._styles.clear()
   499     ui._styles.clear()
   493     for effect in color._activeeffects(ui).keys():
   500     for effect in color._activeeffects(ui).keys():
   494         ui._styles[effect] = effect
   501         ui._styles[effect] = effect
   495     if ui._terminfoparams:
   502     if ui._terminfoparams:
   496         for k, v in ui.configitems('color'):
   503         for k, v in ui.configitems(b'color'):
   497             if k.startswith('color.'):
   504             if k.startswith(b'color.'):
   498                 ui._styles[k] = k[6:]
   505                 ui._styles[k] = k[6:]
   499             elif k.startswith('terminfo.'):
   506             elif k.startswith(b'terminfo.'):
   500                 ui._styles[k] = k[9:]
   507                 ui._styles[k] = k[9:]
   501     ui.write(_('available colors:\n'))
   508     ui.write(_(b'available colors:\n'))
   502     # sort label with a '_' after the other to group '_background' entry.
   509     # sort label with a '_' after the other to group '_background' entry.
   503     items = sorted(ui._styles.items(), key=lambda i: ('_' in i[0], i[0], i[1]))
   510     items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
   504     for colorname, label in items:
   511     for colorname, label in items:
   505         ui.write('%s\n' % colorname, label=label)
   512         ui.write(b'%s\n' % colorname, label=label)
   506 
   513 
   507 
   514 
   508 def _debugdisplaystyle(ui):
   515 def _debugdisplaystyle(ui):
   509     ui.write(_('available style:\n'))
   516     ui.write(_(b'available style:\n'))
   510     if not ui._styles:
   517     if not ui._styles:
   511         return
   518         return
   512     width = max(len(s) for s in ui._styles)
   519     width = max(len(s) for s in ui._styles)
   513     for label, effects in sorted(ui._styles.items()):
   520     for label, effects in sorted(ui._styles.items()):
   514         ui.write('%s' % label, label=label)
   521         ui.write(b'%s' % label, label=label)
   515         if effects:
   522         if effects:
   516             # 50
   523             # 50
   517             ui.write(': ')
   524             ui.write(b': ')
   518             ui.write(' ' * (max(0, width - len(label))))
   525             ui.write(b' ' * (max(0, width - len(label))))
   519             ui.write(', '.join(ui.label(e, e) for e in effects.split()))
   526             ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
   520         ui.write('\n')
   527         ui.write(b'\n')
   521 
   528 
   522 
   529 
   523 @command('debugcreatestreamclonebundle', [], 'FILE')
   530 @command(b'debugcreatestreamclonebundle', [], b'FILE')
   524 def debugcreatestreamclonebundle(ui, repo, fname):
   531 def debugcreatestreamclonebundle(ui, repo, fname):
   525     """create a stream clone bundle file
   532     """create a stream clone bundle file
   526 
   533 
   527     Stream bundles are special bundles that are essentially archives of
   534     Stream bundles are special bundles that are essentially archives of
   528     revlog files. They are commonly used for cloning very quickly.
   535     revlog files. They are commonly used for cloning very quickly.
   530     # TODO we may want to turn this into an abort when this functionality
   537     # TODO we may want to turn this into an abort when this functionality
   531     # is moved into `hg bundle`.
   538     # is moved into `hg bundle`.
   532     if phases.hassecret(repo):
   539     if phases.hassecret(repo):
   533         ui.warn(
   540         ui.warn(
   534             _(
   541             _(
   535                 '(warning: stream clone bundle will contain secret '
   542                 b'(warning: stream clone bundle will contain secret '
   536                 'revisions)\n'
   543                 b'revisions)\n'
   537             )
   544             )
   538         )
   545         )
   539 
   546 
   540     requirements, gen = streamclone.generatebundlev1(repo)
   547     requirements, gen = streamclone.generatebundlev1(repo)
   541     changegroup.writechunks(ui, gen, fname)
   548     changegroup.writechunks(ui, gen, fname)
   542 
   549 
   543     ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
   550     ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
   544 
   551 
   545 
   552 
   546 @command(
   553 @command(
   547     'debugdag',
   554     b'debugdag',
   548     [
   555     [
   549         ('t', 'tags', None, _('use tags as labels')),
   556         (b't', b'tags', None, _(b'use tags as labels')),
   550         ('b', 'branches', None, _('annotate with branch names')),
   557         (b'b', b'branches', None, _(b'annotate with branch names')),
   551         ('', 'dots', None, _('use dots for runs')),
   558         (b'', b'dots', None, _(b'use dots for runs')),
   552         ('s', 'spaces', None, _('separate elements by spaces')),
   559         (b's', b'spaces', None, _(b'separate elements by spaces')),
   553     ],
   560     ],
   554     _('[OPTION]... [FILE [REV]...]'),
   561     _(b'[OPTION]... [FILE [REV]...]'),
   555     optionalrepo=True,
   562     optionalrepo=True,
   556 )
   563 )
   557 def debugdag(ui, repo, file_=None, *revs, **opts):
   564 def debugdag(ui, repo, file_=None, *revs, **opts):
   558     """format the changelog or an index DAG as a concise textual description
   565     """format the changelog or an index DAG as a concise textual description
   559 
   566 
   568         rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
   575         rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
   569         revs = set((int(r) for r in revs))
   576         revs = set((int(r) for r in revs))
   570 
   577 
   571         def events():
   578         def events():
   572             for r in rlog:
   579             for r in rlog:
   573                 yield 'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
   580                 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
   574                 if r in revs:
   581                 if r in revs:
   575                     yield 'l', (r, "r%i" % r)
   582                     yield b'l', (r, b"r%i" % r)
   576 
   583 
   577     elif repo:
   584     elif repo:
   578         cl = repo.changelog
   585         cl = repo.changelog
   579         tags = opts.get(r'tags')
   586         tags = opts.get(r'tags')
   580         branches = opts.get(r'branches')
   587         branches = opts.get(r'branches')
   582             labels = {}
   589             labels = {}
   583             for l, n in repo.tags().items():
   590             for l, n in repo.tags().items():
   584                 labels.setdefault(cl.rev(n), []).append(l)
   591                 labels.setdefault(cl.rev(n), []).append(l)
   585 
   592 
   586         def events():
   593         def events():
   587             b = "default"
   594             b = b"default"
   588             for r in cl:
   595             for r in cl:
   589                 if branches:
   596                 if branches:
   590                     newb = cl.read(cl.node(r))[5]['branch']
   597                     newb = cl.read(cl.node(r))[5][b'branch']
   591                     if newb != b:
   598                     if newb != b:
   592                         yield 'a', newb
   599                         yield b'a', newb
   593                         b = newb
   600                         b = newb
   594                 yield 'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
   601                 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
   595                 if tags:
   602                 if tags:
   596                     ls = labels.get(r)
   603                     ls = labels.get(r)
   597                     if ls:
   604                     if ls:
   598                         for l in ls:
   605                         for l in ls:
   599                             yield 'l', (r, l)
   606                             yield b'l', (r, l)
   600 
   607 
   601     else:
   608     else:
   602         raise error.Abort(_('need repo for changelog dag'))
   609         raise error.Abort(_(b'need repo for changelog dag'))
   603 
   610 
   604     for line in dagparser.dagtextlines(
   611     for line in dagparser.dagtextlines(
   605         events(),
   612         events(),
   606         addspaces=spaces,
   613         addspaces=spaces,
   607         wraplabels=True,
   614         wraplabels=True,
   609         wrapnonlinear=dots,
   616         wrapnonlinear=dots,
   610         usedots=dots,
   617         usedots=dots,
   611         maxlinewidth=70,
   618         maxlinewidth=70,
   612     ):
   619     ):
   613         ui.write(line)
   620         ui.write(line)
   614         ui.write("\n")
   621         ui.write(b"\n")
   615 
   622 
   616 
   623 
   617 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
   624 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
   618 def debugdata(ui, repo, file_, rev=None, **opts):
   625 def debugdata(ui, repo, file_, rev=None, **opts):
   619     """dump the contents of a data file revision"""
   626     """dump the contents of a data file revision"""
   620     opts = pycompat.byteskwargs(opts)
   627     opts = pycompat.byteskwargs(opts)
   621     if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
   628     if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
   622         if rev is not None:
   629         if rev is not None:
   623             raise error.CommandError('debugdata', _('invalid arguments'))
   630             raise error.CommandError(b'debugdata', _(b'invalid arguments'))
   624         file_, rev = None, file_
   631         file_, rev = None, file_
   625     elif rev is None:
   632     elif rev is None:
   626         raise error.CommandError('debugdata', _('invalid arguments'))
   633         raise error.CommandError(b'debugdata', _(b'invalid arguments'))
   627     r = cmdutil.openstorage(repo, 'debugdata', file_, opts)
   634     r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
   628     try:
   635     try:
   629         ui.write(r.rawdata(r.lookup(rev)))
   636         ui.write(r.rawdata(r.lookup(rev)))
   630     except KeyError:
   637     except KeyError:
   631         raise error.Abort(_('invalid revision identifier %s') % rev)
   638         raise error.Abort(_(b'invalid revision identifier %s') % rev)
   632 
   639 
   633 
   640 
   634 @command(
   641 @command(
   635     'debugdate',
   642     b'debugdate',
   636     [('e', 'extended', None, _('try extended date formats'))],
   643     [(b'e', b'extended', None, _(b'try extended date formats'))],
   637     _('[-e] DATE [RANGE]'),
   644     _(b'[-e] DATE [RANGE]'),
   638     norepo=True,
   645     norepo=True,
   639     optionalrepo=True,
   646     optionalrepo=True,
   640 )
   647 )
   641 def debugdate(ui, date, range=None, **opts):
   648 def debugdate(ui, date, range=None, **opts):
   642     """parse and display a date"""
   649     """parse and display a date"""
   643     if opts[r"extended"]:
   650     if opts[r"extended"]:
   644         d = dateutil.parsedate(date, util.extendeddateformats)
   651         d = dateutil.parsedate(date, util.extendeddateformats)
   645     else:
   652     else:
   646         d = dateutil.parsedate(date)
   653         d = dateutil.parsedate(date)
   647     ui.write("internal: %d %d\n" % d)
   654     ui.write(b"internal: %d %d\n" % d)
   648     ui.write("standard: %s\n" % dateutil.datestr(d))
   655     ui.write(b"standard: %s\n" % dateutil.datestr(d))
   649     if range:
   656     if range:
   650         m = dateutil.matchdate(range)
   657         m = dateutil.matchdate(range)
   651         ui.write("match: %s\n" % m(d[0]))
   658         ui.write(b"match: %s\n" % m(d[0]))
   652 
   659 
   653 
   660 
   654 @command(
   661 @command(
   655     'debugdeltachain',
   662     b'debugdeltachain',
   656     cmdutil.debugrevlogopts + cmdutil.formatteropts,
   663     cmdutil.debugrevlogopts + cmdutil.formatteropts,
   657     _('-c|-m|FILE'),
   664     _(b'-c|-m|FILE'),
   658     optionalrepo=True,
   665     optionalrepo=True,
   659 )
   666 )
   660 def debugdeltachain(ui, repo, file_=None, **opts):
   667 def debugdeltachain(ui, repo, file_=None, **opts):
   661     """dump information about delta chains in a revlog
   668     """dump information about delta chains in a revlog
   662 
   669 
   691     :``srchunks``:  in how many data hunks the whole revision would be read
   698     :``srchunks``:  in how many data hunks the whole revision would be read
   692 
   699 
   693     The sparse read can be enabled with experimental.sparse-read = True
   700     The sparse read can be enabled with experimental.sparse-read = True
   694     """
   701     """
   695     opts = pycompat.byteskwargs(opts)
   702     opts = pycompat.byteskwargs(opts)
   696     r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
   703     r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
   697     index = r.index
   704     index = r.index
   698     start = r.start
   705     start = r.start
   699     length = r.length
   706     length = r.length
   700     generaldelta = r.version & revlog.FLAG_GENERALDELTA
   707     generaldelta = r.version & revlog.FLAG_GENERALDELTA
   701     withsparseread = getattr(r, '_withsparseread', False)
   708     withsparseread = getattr(r, '_withsparseread', False)
   706         uncompsize = e[2]
   713         uncompsize = e[2]
   707         chainsize = 0
   714         chainsize = 0
   708 
   715 
   709         if generaldelta:
   716         if generaldelta:
   710             if e[3] == e[5]:
   717             if e[3] == e[5]:
   711                 deltatype = 'p1'
   718                 deltatype = b'p1'
   712             elif e[3] == e[6]:
   719             elif e[3] == e[6]:
   713                 deltatype = 'p2'
   720                 deltatype = b'p2'
   714             elif e[3] == rev - 1:
   721             elif e[3] == rev - 1:
   715                 deltatype = 'prev'
   722                 deltatype = b'prev'
   716             elif e[3] == rev:
   723             elif e[3] == rev:
   717                 deltatype = 'base'
   724                 deltatype = b'base'
   718             else:
   725             else:
   719                 deltatype = 'other'
   726                 deltatype = b'other'
   720         else:
   727         else:
   721             if e[3] == rev:
   728             if e[3] == rev:
   722                 deltatype = 'base'
   729                 deltatype = b'base'
   723             else:
   730             else:
   724                 deltatype = 'prev'
   731                 deltatype = b'prev'
   725 
   732 
   726         chain = r._deltachain(rev)[0]
   733         chain = r._deltachain(rev)[0]
   727         for iterrev in chain:
   734         for iterrev in chain:
   728             e = index[iterrev]
   735             e = index[iterrev]
   729             chainsize += e[1]
   736             chainsize += e[1]
   730 
   737 
   731         return compsize, uncompsize, deltatype, chain, chainsize
   738         return compsize, uncompsize, deltatype, chain, chainsize
   732 
   739 
   733     fm = ui.formatter('debugdeltachain', opts)
   740     fm = ui.formatter(b'debugdeltachain', opts)
   734 
   741 
   735     fm.plain(
   742     fm.plain(
   736         '    rev  chain# chainlen     prev   delta       '
   743         b'    rev  chain# chainlen     prev   delta       '
   737         'size    rawsize  chainsize     ratio   lindist extradist '
   744         b'size    rawsize  chainsize     ratio   lindist extradist '
   738         'extraratio'
   745         b'extraratio'
   739     )
   746     )
   740     if withsparseread:
   747     if withsparseread:
   741         fm.plain('   readsize largestblk rddensity srchunks')
   748         fm.plain(b'   readsize largestblk rddensity srchunks')
   742     fm.plain('\n')
   749     fm.plain(b'\n')
   743 
   750 
   744     chainbases = {}
   751     chainbases = {}
   745     for rev in r:
   752     for rev in r:
   746         comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
   753         comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
   747         chainbase = chain[0]
   754         chainbase = chain[0]
   765         else:
   772         else:
   766             extraratio = extradist
   773             extraratio = extradist
   767 
   774 
   768         fm.startitem()
   775         fm.startitem()
   769         fm.write(
   776         fm.write(
   770             'rev chainid chainlen prevrev deltatype compsize '
   777             b'rev chainid chainlen prevrev deltatype compsize '
   771             'uncompsize chainsize chainratio lindist extradist '
   778             b'uncompsize chainsize chainratio lindist extradist '
   772             'extraratio',
   779             b'extraratio',
   773             '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
   780             b'%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
   774             rev,
   781             rev,
   775             chainid,
   782             chainid,
   776             len(chain),
   783             len(chain),
   777             prevrev,
   784             prevrev,
   778             deltatype,
   785             deltatype,
   814                 readdensity = float(chainsize) / float(readsize)
   821                 readdensity = float(chainsize) / float(readsize)
   815             else:
   822             else:
   816                 readdensity = 1
   823                 readdensity = 1
   817 
   824 
   818             fm.write(
   825             fm.write(
   819                 'readsize largestblock readdensity srchunks',
   826                 b'readsize largestblock readdensity srchunks',
   820                 ' %10d %10d %9.5f %8d',
   827                 b' %10d %10d %9.5f %8d',
   821                 readsize,
   828                 readsize,
   822                 largestblock,
   829                 largestblock,
   823                 readdensity,
   830                 readdensity,
   824                 srchunks,
   831                 srchunks,
   825                 readsize=readsize,
   832                 readsize=readsize,
   826                 largestblock=largestblock,
   833                 largestblock=largestblock,
   827                 readdensity=readdensity,
   834                 readdensity=readdensity,
   828                 srchunks=srchunks,
   835                 srchunks=srchunks,
   829             )
   836             )
   830 
   837 
   831         fm.plain('\n')
   838         fm.plain(b'\n')
   832 
   839 
   833     fm.end()
   840     fm.end()
   834 
   841 
   835 
   842 
   836 @command(
   843 @command(
   837     'debugdirstate|debugstate',
   844     b'debugdirstate|debugstate',
   838     [
   845     [
   839         ('', 'nodates', None, _('do not display the saved mtime (DEPRECATED)')),
   846         (
   840         ('', 'dates', True, _('display the saved mtime')),
   847             b'',
   841         ('', 'datesort', None, _('sort by saved mtime')),
   848             b'nodates',
       
   849             None,
       
   850             _(b'do not display the saved mtime (DEPRECATED)'),
       
   851         ),
       
   852         (b'', b'dates', True, _(b'display the saved mtime')),
       
   853         (b'', b'datesort', None, _(b'sort by saved mtime')),
   842     ],
   854     ],
   843     _('[OPTION]...'),
   855     _(b'[OPTION]...'),
   844 )
   856 )
   845 def debugstate(ui, repo, **opts):
   857 def debugstate(ui, repo, **opts):
   846     """show the contents of the current dirstate"""
   858     """show the contents of the current dirstate"""
   847 
   859 
   848     nodates = not opts[r'dates']
   860     nodates = not opts[r'dates']
   854         keyfunc = lambda x: (x[1][3], x[0])  # sort by mtime, then by filename
   866         keyfunc = lambda x: (x[1][3], x[0])  # sort by mtime, then by filename
   855     else:
   867     else:
   856         keyfunc = None  # sort by filename
   868         keyfunc = None  # sort by filename
   857     for file_, ent in sorted(repo.dirstate.iteritems(), key=keyfunc):
   869     for file_, ent in sorted(repo.dirstate.iteritems(), key=keyfunc):
   858         if ent[3] == -1:
   870         if ent[3] == -1:
   859             timestr = 'unset               '
   871             timestr = b'unset               '
   860         elif nodates:
   872         elif nodates:
   861             timestr = 'set                 '
   873             timestr = b'set                 '
   862         else:
   874         else:
   863             timestr = time.strftime(
   875             timestr = time.strftime(
   864                 r"%Y-%m-%d %H:%M:%S ", time.localtime(ent[3])
   876                 r"%Y-%m-%d %H:%M:%S ", time.localtime(ent[3])
   865             )
   877             )
   866             timestr = encoding.strtolocal(timestr)
   878             timestr = encoding.strtolocal(timestr)
   867         if ent[1] & 0o20000:
   879         if ent[1] & 0o20000:
   868             mode = 'lnk'
   880             mode = b'lnk'
   869         else:
   881         else:
   870             mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
   882             mode = b'%3o' % (ent[1] & 0o777 & ~util.umask)
   871         ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
   883         ui.write(b"%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
   872     for f in repo.dirstate.copies():
   884     for f in repo.dirstate.copies():
   873         ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
   885         ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
   874 
   886 
   875 
   887 
   876 @command(
   888 @command(
   877     'debugdiscovery',
   889     b'debugdiscovery',
   878     [
   890     [
   879         ('', 'old', None, _('use old-style discovery')),
   891         (b'', b'old', None, _(b'use old-style discovery')),
   880         (
   892         (
   881             '',
   893             b'',
   882             'nonheads',
   894             b'nonheads',
   883             None,
   895             None,
   884             _('use old-style discovery with non-heads included'),
   896             _(b'use old-style discovery with non-heads included'),
   885         ),
   897         ),
   886         ('', 'rev', [], 'restrict discovery to this set of revs'),
   898         (b'', b'rev', [], b'restrict discovery to this set of revs'),
   887         ('', 'seed', '12323', 'specify the random seed use for discovery'),
   899         (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
   888     ]
   900     ]
   889     + cmdutil.remoteopts,
   901     + cmdutil.remoteopts,
   890     _('[--rev REV] [OTHER]'),
   902     _(b'[--rev REV] [OTHER]'),
   891 )
   903 )
   892 def debugdiscovery(ui, repo, remoteurl="default", **opts):
   904 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
   893     """runs the changeset discovery protocol in isolation"""
   905     """runs the changeset discovery protocol in isolation"""
   894     opts = pycompat.byteskwargs(opts)
   906     opts = pycompat.byteskwargs(opts)
   895     remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
   907     remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
   896     remote = hg.peer(repo, opts, remoteurl)
   908     remote = hg.peer(repo, opts, remoteurl)
   897     ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
   909     ui.status(_(b'comparing with %s\n') % util.hidepassword(remoteurl))
   898 
   910 
   899     # make sure tests are repeatable
   911     # make sure tests are repeatable
   900     random.seed(int(opts['seed']))
   912     random.seed(int(opts[b'seed']))
   901 
   913 
   902     if opts.get('old'):
   914     if opts.get(b'old'):
   903 
   915 
   904         def doit(pushedrevs, remoteheads, remote=remote):
   916         def doit(pushedrevs, remoteheads, remote=remote):
   905             if not util.safehasattr(remote, 'branches'):
   917             if not util.safehasattr(remote, b'branches'):
   906                 # enable in-client legacy support
   918                 # enable in-client legacy support
   907                 remote = localrepo.locallegacypeer(remote.local())
   919                 remote = localrepo.locallegacypeer(remote.local())
   908             common, _in, hds = treediscovery.findcommonincoming(
   920             common, _in, hds = treediscovery.findcommonincoming(
   909                 repo, remote, force=True
   921                 repo, remote, force=True
   910             )
   922             )
   911             common = set(common)
   923             common = set(common)
   912             if not opts.get('nonheads'):
   924             if not opts.get(b'nonheads'):
   913                 ui.write(
   925                 ui.write(
   914                     "unpruned common: %s\n"
   926                     b"unpruned common: %s\n"
   915                     % " ".join(sorted(short(n) for n in common))
   927                     % b" ".join(sorted(short(n) for n in common))
   916                 )
   928                 )
   917 
   929 
   918                 clnode = repo.changelog.node
   930                 clnode = repo.changelog.node
   919                 common = repo.revs('heads(::%ln)', common)
   931                 common = repo.revs(b'heads(::%ln)', common)
   920                 common = {clnode(r) for r in common}
   932                 common = {clnode(r) for r in common}
   921             return common, hds
   933             return common, hds
   922 
   934 
   923     else:
   935     else:
   924 
   936 
   931                 ui, repo, remote, ancestorsof=nodes
   943                 ui, repo, remote, ancestorsof=nodes
   932             )
   944             )
   933             return common, hds
   945             return common, hds
   934 
   946 
   935     remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
   947     remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
   936     localrevs = opts['rev']
   948     localrevs = opts[b'rev']
   937     with util.timedcm('debug-discovery') as t:
   949     with util.timedcm(b'debug-discovery') as t:
   938         common, hds = doit(localrevs, remoterevs)
   950         common, hds = doit(localrevs, remoterevs)
   939 
   951 
   940     # compute all statistics
   952     # compute all statistics
   941     common = set(common)
   953     common = set(common)
   942     rheads = set(hds)
   954     rheads = set(hds)
   943     lheads = set(repo.heads())
   955     lheads = set(repo.heads())
   944 
   956 
   945     data = {}
   957     data = {}
   946     data['elapsed'] = t.elapsed
   958     data[b'elapsed'] = t.elapsed
   947     data['nb-common'] = len(common)
   959     data[b'nb-common'] = len(common)
   948     data['nb-common-local'] = len(common & lheads)
   960     data[b'nb-common-local'] = len(common & lheads)
   949     data['nb-common-remote'] = len(common & rheads)
   961     data[b'nb-common-remote'] = len(common & rheads)
   950     data['nb-common-both'] = len(common & rheads & lheads)
   962     data[b'nb-common-both'] = len(common & rheads & lheads)
   951     data['nb-local'] = len(lheads)
   963     data[b'nb-local'] = len(lheads)
   952     data['nb-local-missing'] = data['nb-local'] - data['nb-common-local']
   964     data[b'nb-local-missing'] = data[b'nb-local'] - data[b'nb-common-local']
   953     data['nb-remote'] = len(rheads)
   965     data[b'nb-remote'] = len(rheads)
   954     data['nb-remote-unknown'] = data['nb-remote'] - data['nb-common-remote']
   966     data[b'nb-remote-unknown'] = data[b'nb-remote'] - data[b'nb-common-remote']
   955     data['nb-revs'] = len(repo.revs('all()'))
   967     data[b'nb-revs'] = len(repo.revs(b'all()'))
   956     data['nb-revs-common'] = len(repo.revs('::%ln', common))
   968     data[b'nb-revs-common'] = len(repo.revs(b'::%ln', common))
   957     data['nb-revs-missing'] = data['nb-revs'] - data['nb-revs-common']
   969     data[b'nb-revs-missing'] = data[b'nb-revs'] - data[b'nb-revs-common']
   958 
   970 
   959     # display discovery summary
   971     # display discovery summary
   960     ui.write("elapsed time:  %(elapsed)f seconds\n" % data)
   972     ui.write(b"elapsed time:  %(elapsed)f seconds\n" % data)
   961     ui.write("heads summary:\n")
   973     ui.write(b"heads summary:\n")
   962     ui.write("  total common heads:  %(nb-common)9d\n" % data)
   974     ui.write(b"  total common heads:  %(nb-common)9d\n" % data)
   963     ui.write("    also local heads:  %(nb-common-local)9d\n" % data)
   975     ui.write(b"    also local heads:  %(nb-common-local)9d\n" % data)
   964     ui.write("    also remote heads: %(nb-common-remote)9d\n" % data)
   976     ui.write(b"    also remote heads: %(nb-common-remote)9d\n" % data)
   965     ui.write("    both:              %(nb-common-both)9d\n" % data)
   977     ui.write(b"    both:              %(nb-common-both)9d\n" % data)
   966     ui.write("  local heads:         %(nb-local)9d\n" % data)
   978     ui.write(b"  local heads:         %(nb-local)9d\n" % data)
   967     ui.write("    common:            %(nb-common-local)9d\n" % data)
   979     ui.write(b"    common:            %(nb-common-local)9d\n" % data)
   968     ui.write("    missing:           %(nb-local-missing)9d\n" % data)
   980     ui.write(b"    missing:           %(nb-local-missing)9d\n" % data)
   969     ui.write("  remote heads:        %(nb-remote)9d\n" % data)
   981     ui.write(b"  remote heads:        %(nb-remote)9d\n" % data)
   970     ui.write("    common:            %(nb-common-remote)9d\n" % data)
   982     ui.write(b"    common:            %(nb-common-remote)9d\n" % data)
   971     ui.write("    unknown:           %(nb-remote-unknown)9d\n" % data)
   983     ui.write(b"    unknown:           %(nb-remote-unknown)9d\n" % data)
   972     ui.write("local changesets:      %(nb-revs)9d\n" % data)
   984     ui.write(b"local changesets:      %(nb-revs)9d\n" % data)
   973     ui.write("  common:              %(nb-revs-common)9d\n" % data)
   985     ui.write(b"  common:              %(nb-revs-common)9d\n" % data)
   974     ui.write("  missing:             %(nb-revs-missing)9d\n" % data)
   986     ui.write(b"  missing:             %(nb-revs-missing)9d\n" % data)
   975 
   987 
   976     if ui.verbose:
   988     if ui.verbose:
   977         ui.write(
   989         ui.write(
   978             "common heads: %s\n" % " ".join(sorted(short(n) for n in common))
   990             b"common heads: %s\n" % b" ".join(sorted(short(n) for n in common))
   979         )
   991         )
   980 
   992 
   981 
   993 
   982 _chunksize = 4 << 10
   994 _chunksize = 4 << 10
   983 
   995 
   984 
   996 
   985 @command('debugdownload', [('o', 'output', '', _('path')),], optionalrepo=True)
   997 @command(
       
   998     b'debugdownload', [(b'o', b'output', b'', _(b'path')),], optionalrepo=True
       
   999 )
   986 def debugdownload(ui, repo, url, output=None, **opts):
  1000 def debugdownload(ui, repo, url, output=None, **opts):
   987     """download a resource using Mercurial logic and config
  1001     """download a resource using Mercurial logic and config
   988     """
  1002     """
   989     fh = urlmod.open(ui, url, output)
  1003     fh = urlmod.open(ui, url, output)
   990 
  1004 
   991     dest = ui
  1005     dest = ui
   992     if output:
  1006     if output:
   993         dest = open(output, "wb", _chunksize)
  1007         dest = open(output, b"wb", _chunksize)
   994     try:
  1008     try:
   995         data = fh.read(_chunksize)
  1009         data = fh.read(_chunksize)
   996         while data:
  1010         while data:
   997             dest.write(data)
  1011             dest.write(data)
   998             data = fh.read(_chunksize)
  1012             data = fh.read(_chunksize)
   999     finally:
  1013     finally:
  1000         if output:
  1014         if output:
  1001             dest.close()
  1015             dest.close()
  1002 
  1016 
  1003 
  1017 
  1004 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
  1018 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
  1005 def debugextensions(ui, repo, **opts):
  1019 def debugextensions(ui, repo, **opts):
  1006     '''show information about active extensions'''
  1020     '''show information about active extensions'''
  1007     opts = pycompat.byteskwargs(opts)
  1021     opts = pycompat.byteskwargs(opts)
  1008     exts = extensions.extensions(ui)
  1022     exts = extensions.extensions(ui)
  1009     hgver = util.version()
  1023     hgver = util.version()
  1010     fm = ui.formatter('debugextensions', opts)
  1024     fm = ui.formatter(b'debugextensions', opts)
  1011     for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
  1025     for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
  1012         isinternal = extensions.ismoduleinternal(extmod)
  1026         isinternal = extensions.ismoduleinternal(extmod)
  1013         extsource = pycompat.fsencode(extmod.__file__)
  1027         extsource = pycompat.fsencode(extmod.__file__)
  1014         if isinternal:
  1028         if isinternal:
  1015             exttestedwith = []  # never expose magic string to users
  1029             exttestedwith = []  # never expose magic string to users
  1016         else:
  1030         else:
  1017             exttestedwith = getattr(extmod, 'testedwith', '').split()
  1031             exttestedwith = getattr(extmod, 'testedwith', b'').split()
  1018         extbuglink = getattr(extmod, 'buglink', None)
  1032         extbuglink = getattr(extmod, 'buglink', None)
  1019 
  1033 
  1020         fm.startitem()
  1034         fm.startitem()
  1021 
  1035 
  1022         if ui.quiet or ui.verbose:
  1036         if ui.quiet or ui.verbose:
  1023             fm.write('name', '%s\n', extname)
  1037             fm.write(b'name', b'%s\n', extname)
  1024         else:
  1038         else:
  1025             fm.write('name', '%s', extname)
  1039             fm.write(b'name', b'%s', extname)
  1026             if isinternal or hgver in exttestedwith:
  1040             if isinternal or hgver in exttestedwith:
  1027                 fm.plain('\n')
  1041                 fm.plain(b'\n')
  1028             elif not exttestedwith:
  1042             elif not exttestedwith:
  1029                 fm.plain(_(' (untested!)\n'))
  1043                 fm.plain(_(b' (untested!)\n'))
  1030             else:
  1044             else:
  1031                 lasttestedversion = exttestedwith[-1]
  1045                 lasttestedversion = exttestedwith[-1]
  1032                 fm.plain(' (%s!)\n' % lasttestedversion)
  1046                 fm.plain(b' (%s!)\n' % lasttestedversion)
  1033 
  1047 
  1034         fm.condwrite(
  1048         fm.condwrite(
  1035             ui.verbose and extsource,
  1049             ui.verbose and extsource,
  1036             'source',
  1050             b'source',
  1037             _('  location: %s\n'),
  1051             _(b'  location: %s\n'),
  1038             extsource or "",
  1052             extsource or b"",
  1039         )
  1053         )
  1040 
  1054 
  1041         if ui.verbose:
  1055         if ui.verbose:
  1042             fm.plain(_('  bundled: %s\n') % ['no', 'yes'][isinternal])
  1056             fm.plain(_(b'  bundled: %s\n') % [b'no', b'yes'][isinternal])
  1043         fm.data(bundled=isinternal)
  1057         fm.data(bundled=isinternal)
  1044 
  1058 
  1045         fm.condwrite(
  1059         fm.condwrite(
  1046             ui.verbose and exttestedwith,
  1060             ui.verbose and exttestedwith,
  1047             'testedwith',
  1061             b'testedwith',
  1048             _('  tested with: %s\n'),
  1062             _(b'  tested with: %s\n'),
  1049             fm.formatlist(exttestedwith, name='ver'),
  1063             fm.formatlist(exttestedwith, name=b'ver'),
  1050         )
  1064         )
  1051 
  1065 
  1052         fm.condwrite(
  1066         fm.condwrite(
  1053             ui.verbose and extbuglink,
  1067             ui.verbose and extbuglink,
  1054             'buglink',
  1068             b'buglink',
  1055             _('  bug reporting: %s\n'),
  1069             _(b'  bug reporting: %s\n'),
  1056             extbuglink or "",
  1070             extbuglink or b"",
  1057         )
  1071         )
  1058 
  1072 
  1059     fm.end()
  1073     fm.end()
  1060 
  1074 
  1061 
  1075 
  1062 @command(
  1076 @command(
  1063     'debugfileset',
  1077     b'debugfileset',
  1064     [
  1078     [
  1065         ('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
       
  1066         (
  1079         (
  1067             '',
  1080             b'r',
  1068             'all-files',
  1081             b'rev',
  1069             False,
  1082             b'',
  1070             _('test files from all revisions and working directory'),
  1083             _(b'apply the filespec on this revision'),
       
  1084             _(b'REV'),
  1071         ),
  1085         ),
  1072         (
  1086         (
  1073             's',
  1087             b'',
  1074             'show-matcher',
  1088             b'all-files',
  1075             None,
  1089             False,
  1076             _('print internal representation of matcher'),
  1090             _(b'test files from all revisions and working directory'),
  1077         ),
  1091         ),
  1078         (
  1092         (
  1079             'p',
  1093             b's',
  1080             'show-stage',
  1094             b'show-matcher',
       
  1095             None,
       
  1096             _(b'print internal representation of matcher'),
       
  1097         ),
       
  1098         (
       
  1099             b'p',
       
  1100             b'show-stage',
  1081             [],
  1101             [],
  1082             _('print parsed tree at the given stage'),
  1102             _(b'print parsed tree at the given stage'),
  1083             _('NAME'),
  1103             _(b'NAME'),
  1084         ),
  1104         ),
  1085     ],
  1105     ],
  1086     _('[-r REV] [--all-files] [OPTION]... FILESPEC'),
  1106     _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
  1087 )
  1107 )
  1088 def debugfileset(ui, repo, expr, **opts):
  1108 def debugfileset(ui, repo, expr, **opts):
  1089     '''parse and apply a fileset specification'''
  1109     '''parse and apply a fileset specification'''
  1090     from . import fileset
  1110     from . import fileset
  1091 
  1111 
  1092     fileset.symbols  # force import of fileset so we have predicates to optimize
  1112     fileset.symbols  # force import of fileset so we have predicates to optimize
  1093     opts = pycompat.byteskwargs(opts)
  1113     opts = pycompat.byteskwargs(opts)
  1094     ctx = scmutil.revsingle(repo, opts.get('rev'), None)
  1114     ctx = scmutil.revsingle(repo, opts.get(b'rev'), None)
  1095 
  1115 
  1096     stages = [
  1116     stages = [
  1097         ('parsed', pycompat.identity),
  1117         (b'parsed', pycompat.identity),
  1098         ('analyzed', filesetlang.analyze),
  1118         (b'analyzed', filesetlang.analyze),
  1099         ('optimized', filesetlang.optimize),
  1119         (b'optimized', filesetlang.optimize),
  1100     ]
  1120     ]
  1101     stagenames = set(n for n, f in stages)
  1121     stagenames = set(n for n, f in stages)
  1102 
  1122 
  1103     showalways = set()
  1123     showalways = set()
  1104     if ui.verbose and not opts['show_stage']:
  1124     if ui.verbose and not opts[b'show_stage']:
  1105         # show parsed tree by --verbose (deprecated)
  1125         # show parsed tree by --verbose (deprecated)
  1106         showalways.add('parsed')
  1126         showalways.add(b'parsed')
  1107     if opts['show_stage'] == ['all']:
  1127     if opts[b'show_stage'] == [b'all']:
  1108         showalways.update(stagenames)
  1128         showalways.update(stagenames)
  1109     else:
  1129     else:
  1110         for n in opts['show_stage']:
  1130         for n in opts[b'show_stage']:
  1111             if n not in stagenames:
  1131             if n not in stagenames:
  1112                 raise error.Abort(_('invalid stage name: %s') % n)
  1132                 raise error.Abort(_(b'invalid stage name: %s') % n)
  1113         showalways.update(opts['show_stage'])
  1133         showalways.update(opts[b'show_stage'])
  1114 
  1134 
  1115     tree = filesetlang.parse(expr)
  1135     tree = filesetlang.parse(expr)
  1116     for n, f in stages:
  1136     for n, f in stages:
  1117         tree = f(tree)
  1137         tree = f(tree)
  1118         if n in showalways:
  1138         if n in showalways:
  1119             if opts['show_stage'] or n != 'parsed':
  1139             if opts[b'show_stage'] or n != b'parsed':
  1120                 ui.write("* %s:\n" % n)
  1140                 ui.write(b"* %s:\n" % n)
  1121             ui.write(filesetlang.prettyformat(tree), "\n")
  1141             ui.write(filesetlang.prettyformat(tree), b"\n")
  1122 
  1142 
  1123     files = set()
  1143     files = set()
  1124     if opts['all_files']:
  1144     if opts[b'all_files']:
  1125         for r in repo:
  1145         for r in repo:
  1126             c = repo[r]
  1146             c = repo[r]
  1127             files.update(c.files())
  1147             files.update(c.files())
  1128             files.update(c.substate)
  1148             files.update(c.substate)
  1129     if opts['all_files'] or ctx.rev() is None:
  1149     if opts[b'all_files'] or ctx.rev() is None:
  1130         wctx = repo[None]
  1150         wctx = repo[None]
  1131         files.update(
  1151         files.update(
  1132             repo.dirstate.walk(
  1152             repo.dirstate.walk(
  1133                 scmutil.matchall(repo),
  1153                 scmutil.matchall(repo),
  1134                 subrepos=list(wctx.substate),
  1154                 subrepos=list(wctx.substate),
  1140     else:
  1160     else:
  1141         files.update(ctx.files())
  1161         files.update(ctx.files())
  1142         files.update(ctx.substate)
  1162         files.update(ctx.substate)
  1143 
  1163 
  1144     m = ctx.matchfileset(expr)
  1164     m = ctx.matchfileset(expr)
  1145     if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
  1165     if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
  1146         ui.write('* matcher:\n', stringutil.prettyrepr(m), '\n')
  1166         ui.write(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
  1147     for f in sorted(files):
  1167     for f in sorted(files):
  1148         if not m(f):
  1168         if not m(f):
  1149             continue
  1169             continue
  1150         ui.write("%s\n" % f)
  1170         ui.write(b"%s\n" % f)
  1151 
  1171 
  1152 
  1172 
  1153 @command('debugformat', [] + cmdutil.formatteropts)
  1173 @command(b'debugformat', [] + cmdutil.formatteropts)
  1154 def debugformat(ui, repo, **opts):
  1174 def debugformat(ui, repo, **opts):
  1155     """display format information about the current repository
  1175     """display format information about the current repository
  1156 
  1176 
  1157     Use --verbose to get extra information about current config value and
  1177     Use --verbose to get extra information about current config value and
  1158     Mercurial default."""
  1178     Mercurial default."""
  1159     opts = pycompat.byteskwargs(opts)
  1179     opts = pycompat.byteskwargs(opts)
  1160     maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
  1180     maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
  1161     maxvariantlength = max(len('format-variant'), maxvariantlength)
  1181     maxvariantlength = max(len(b'format-variant'), maxvariantlength)
  1162 
  1182 
  1163     def makeformatname(name):
  1183     def makeformatname(name):
  1164         return '%s:' + (' ' * (maxvariantlength - len(name)))
  1184         return b'%s:' + (b' ' * (maxvariantlength - len(name)))
  1165 
  1185 
  1166     fm = ui.formatter('debugformat', opts)
  1186     fm = ui.formatter(b'debugformat', opts)
  1167     if fm.isplain():
  1187     if fm.isplain():
  1168 
  1188 
  1169         def formatvalue(value):
  1189         def formatvalue(value):
  1170             if util.safehasattr(value, 'startswith'):
  1190             if util.safehasattr(value, b'startswith'):
  1171                 return value
  1191                 return value
  1172             if value:
  1192             if value:
  1173                 return 'yes'
  1193                 return b'yes'
  1174             else:
  1194             else:
  1175                 return 'no'
  1195                 return b'no'
  1176 
  1196 
  1177     else:
  1197     else:
  1178         formatvalue = pycompat.identity
  1198         formatvalue = pycompat.identity
  1179 
  1199 
  1180     fm.plain('format-variant')
  1200     fm.plain(b'format-variant')
  1181     fm.plain(' ' * (maxvariantlength - len('format-variant')))
  1201     fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
  1182     fm.plain(' repo')
  1202     fm.plain(b' repo')
  1183     if ui.verbose:
  1203     if ui.verbose:
  1184         fm.plain(' config default')
  1204         fm.plain(b' config default')
  1185     fm.plain('\n')
  1205     fm.plain(b'\n')
  1186     for fv in upgrade.allformatvariant:
  1206     for fv in upgrade.allformatvariant:
  1187         fm.startitem()
  1207         fm.startitem()
  1188         repovalue = fv.fromrepo(repo)
  1208         repovalue = fv.fromrepo(repo)
  1189         configvalue = fv.fromconfig(repo)
  1209         configvalue = fv.fromconfig(repo)
  1190 
  1210 
  1191         if repovalue != configvalue:
  1211         if repovalue != configvalue:
  1192             namelabel = 'formatvariant.name.mismatchconfig'
  1212             namelabel = b'formatvariant.name.mismatchconfig'
  1193             repolabel = 'formatvariant.repo.mismatchconfig'
  1213             repolabel = b'formatvariant.repo.mismatchconfig'
  1194         elif repovalue != fv.default:
  1214         elif repovalue != fv.default:
  1195             namelabel = 'formatvariant.name.mismatchdefault'
  1215             namelabel = b'formatvariant.name.mismatchdefault'
  1196             repolabel = 'formatvariant.repo.mismatchdefault'
  1216             repolabel = b'formatvariant.repo.mismatchdefault'
  1197         else:
  1217         else:
  1198             namelabel = 'formatvariant.name.uptodate'
  1218             namelabel = b'formatvariant.name.uptodate'
  1199             repolabel = 'formatvariant.repo.uptodate'
  1219             repolabel = b'formatvariant.repo.uptodate'
  1200 
  1220 
  1201         fm.write('name', makeformatname(fv.name), fv.name, label=namelabel)
  1221         fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
  1202         fm.write('repo', ' %3s', formatvalue(repovalue), label=repolabel)
  1222         fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
  1203         if fv.default != configvalue:
  1223         if fv.default != configvalue:
  1204             configlabel = 'formatvariant.config.special'
  1224             configlabel = b'formatvariant.config.special'
  1205         else:
  1225         else:
  1206             configlabel = 'formatvariant.config.default'
  1226             configlabel = b'formatvariant.config.default'
  1207         fm.condwrite(
  1227         fm.condwrite(
  1208             ui.verbose,
  1228             ui.verbose,
  1209             'config',
  1229             b'config',
  1210             ' %6s',
  1230             b' %6s',
  1211             formatvalue(configvalue),
  1231             formatvalue(configvalue),
  1212             label=configlabel,
  1232             label=configlabel,
  1213         )
  1233         )
  1214         fm.condwrite(
  1234         fm.condwrite(
  1215             ui.verbose,
  1235             ui.verbose,
  1216             'default',
  1236             b'default',
  1217             ' %7s',
  1237             b' %7s',
  1218             formatvalue(fv.default),
  1238             formatvalue(fv.default),
  1219             label='formatvariant.default',
  1239             label=b'formatvariant.default',
  1220         )
  1240         )
  1221         fm.plain('\n')
  1241         fm.plain(b'\n')
  1222     fm.end()
  1242     fm.end()
  1223 
  1243 
  1224 
  1244 
  1225 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
  1245 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
  1226 def debugfsinfo(ui, path="."):
  1246 def debugfsinfo(ui, path=b"."):
  1227     """show information detected about current filesystem"""
  1247     """show information detected about current filesystem"""
  1228     ui.write('path: %s\n' % path)
  1248     ui.write(b'path: %s\n' % path)
  1229     ui.write('mounted on: %s\n' % (util.getfsmountpoint(path) or '(unknown)'))
  1249     ui.write(b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)'))
  1230     ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
  1250     ui.write(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
  1231     ui.write('fstype: %s\n' % (util.getfstype(path) or '(unknown)'))
  1251     ui.write(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
  1232     ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
  1252     ui.write(b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no'))
  1233     ui.write('hardlink: %s\n' % (util.checknlink(path) and 'yes' or 'no'))
  1253     ui.write(b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no'))
  1234     casesensitive = '(unknown)'
  1254     casesensitive = b'(unknown)'
  1235     try:
  1255     try:
  1236         with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
  1256         with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
  1237             casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
  1257             casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
  1238     except OSError:
  1258     except OSError:
  1239         pass
  1259         pass
  1240     ui.write('case-sensitive: %s\n' % casesensitive)
  1260     ui.write(b'case-sensitive: %s\n' % casesensitive)
  1241 
  1261 
  1242 
  1262 
  1243 @command(
  1263 @command(
  1244     'debuggetbundle',
  1264     b'debuggetbundle',
  1245     [
  1265     [
  1246         ('H', 'head', [], _('id of head node'), _('ID')),
  1266         (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
  1247         ('C', 'common', [], _('id of common node'), _('ID')),
  1267         (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
  1248         ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
  1268         (
       
  1269             b't',
       
  1270             b'type',
       
  1271             b'bzip2',
       
  1272             _(b'bundle compression type to use'),
       
  1273             _(b'TYPE'),
       
  1274         ),
  1249     ],
  1275     ],
  1250     _('REPO FILE [-H|-C ID]...'),
  1276     _(b'REPO FILE [-H|-C ID]...'),
  1251     norepo=True,
  1277     norepo=True,
  1252 )
  1278 )
  1253 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
  1279 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
  1254     """retrieves a bundle from a repo
  1280     """retrieves a bundle from a repo
  1255 
  1281 
  1256     Every ID must be a full-length hex node id string. Saves the bundle to the
  1282     Every ID must be a full-length hex node id string. Saves the bundle to the
  1257     given file.
  1283     given file.
  1258     """
  1284     """
  1259     opts = pycompat.byteskwargs(opts)
  1285     opts = pycompat.byteskwargs(opts)
  1260     repo = hg.peer(ui, opts, repopath)
  1286     repo = hg.peer(ui, opts, repopath)
  1261     if not repo.capable('getbundle'):
  1287     if not repo.capable(b'getbundle'):
  1262         raise error.Abort("getbundle() not supported by target repository")
  1288         raise error.Abort(b"getbundle() not supported by target repository")
  1263     args = {}
  1289     args = {}
  1264     if common:
  1290     if common:
  1265         args[r'common'] = [bin(s) for s in common]
  1291         args[r'common'] = [bin(s) for s in common]
  1266     if head:
  1292     if head:
  1267         args[r'heads'] = [bin(s) for s in head]
  1293         args[r'heads'] = [bin(s) for s in head]
  1268     # TODO: get desired bundlecaps from command line.
  1294     # TODO: get desired bundlecaps from command line.
  1269     args[r'bundlecaps'] = None
  1295     args[r'bundlecaps'] = None
  1270     bundle = repo.getbundle('debug', **args)
  1296     bundle = repo.getbundle(b'debug', **args)
  1271 
  1297 
  1272     bundletype = opts.get('type', 'bzip2').lower()
  1298     bundletype = opts.get(b'type', b'bzip2').lower()
  1273     btypes = {
  1299     btypes = {
  1274         'none': 'HG10UN',
  1300         b'none': b'HG10UN',
  1275         'bzip2': 'HG10BZ',
  1301         b'bzip2': b'HG10BZ',
  1276         'gzip': 'HG10GZ',
  1302         b'gzip': b'HG10GZ',
  1277         'bundle2': 'HG20',
  1303         b'bundle2': b'HG20',
  1278     }
  1304     }
  1279     bundletype = btypes.get(bundletype)
  1305     bundletype = btypes.get(bundletype)
  1280     if bundletype not in bundle2.bundletypes:
  1306     if bundletype not in bundle2.bundletypes:
  1281         raise error.Abort(_('unknown bundle type specified with --type'))
  1307         raise error.Abort(_(b'unknown bundle type specified with --type'))
  1282     bundle2.writebundle(ui, bundle, bundlepath, bundletype)
  1308     bundle2.writebundle(ui, bundle, bundlepath, bundletype)
  1283 
  1309 
  1284 
  1310 
  1285 @command('debugignore', [], '[FILE]')
  1311 @command(b'debugignore', [], b'[FILE]')
  1286 def debugignore(ui, repo, *files, **opts):
  1312 def debugignore(ui, repo, *files, **opts):
  1287     """display the combined ignore pattern and information about ignored files
  1313     """display the combined ignore pattern and information about ignored files
  1288 
  1314 
  1289     With no argument display the combined ignore pattern.
  1315     With no argument display the combined ignore pattern.
  1290 
  1316 
  1292     if so, show the ignore rule (file and line number) that matched it.
  1318     if so, show the ignore rule (file and line number) that matched it.
  1293     """
  1319     """
  1294     ignore = repo.dirstate._ignore
  1320     ignore = repo.dirstate._ignore
  1295     if not files:
  1321     if not files:
  1296         # Show all the patterns
  1322         # Show all the patterns
  1297         ui.write("%s\n" % pycompat.byterepr(ignore))
  1323         ui.write(b"%s\n" % pycompat.byterepr(ignore))
  1298     else:
  1324     else:
  1299         m = scmutil.match(repo[None], pats=files)
  1325         m = scmutil.match(repo[None], pats=files)
  1300         uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
  1326         uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
  1301         for f in m.files():
  1327         for f in m.files():
  1302             nf = util.normpath(f)
  1328             nf = util.normpath(f)
  1303             ignored = None
  1329             ignored = None
  1304             ignoredata = None
  1330             ignoredata = None
  1305             if nf != '.':
  1331             if nf != b'.':
  1306                 if ignore(nf):
  1332                 if ignore(nf):
  1307                     ignored = nf
  1333                     ignored = nf
  1308                     ignoredata = repo.dirstate._ignorefileandline(nf)
  1334                     ignoredata = repo.dirstate._ignorefileandline(nf)
  1309                 else:
  1335                 else:
  1310                     for p in util.finddirs(nf):
  1336                     for p in util.finddirs(nf):
  1312                             ignored = p
  1338                             ignored = p
  1313                             ignoredata = repo.dirstate._ignorefileandline(p)
  1339                             ignoredata = repo.dirstate._ignorefileandline(p)
  1314                             break
  1340                             break
  1315             if ignored:
  1341             if ignored:
  1316                 if ignored == nf:
  1342                 if ignored == nf:
  1317                     ui.write(_("%s is ignored\n") % uipathfn(f))
  1343                     ui.write(_(b"%s is ignored\n") % uipathfn(f))
  1318                 else:
  1344                 else:
  1319                     ui.write(
  1345                     ui.write(
  1320                         _(
  1346                         _(
  1321                             "%s is ignored because of "
  1347                             b"%s is ignored because of "
  1322                             "containing directory %s\n"
  1348                             b"containing directory %s\n"
  1323                         )
  1349                         )
  1324                         % (uipathfn(f), ignored)
  1350                         % (uipathfn(f), ignored)
  1325                     )
  1351                     )
  1326                 ignorefile, lineno, line = ignoredata
  1352                 ignorefile, lineno, line = ignoredata
  1327                 ui.write(
  1353                 ui.write(
  1328                     _("(ignore rule in %s, line %d: '%s')\n")
  1354                     _(b"(ignore rule in %s, line %d: '%s')\n")
  1329                     % (ignorefile, lineno, line)
  1355                     % (ignorefile, lineno, line)
  1330                 )
  1356                 )
  1331             else:
  1357             else:
  1332                 ui.write(_("%s is not ignored\n") % uipathfn(f))
  1358                 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
  1333 
  1359 
  1334 
  1360 
  1335 @command(
  1361 @command(
  1336     'debugindex',
  1362     b'debugindex',
  1337     cmdutil.debugrevlogopts + cmdutil.formatteropts,
  1363     cmdutil.debugrevlogopts + cmdutil.formatteropts,
  1338     _('-c|-m|FILE'),
  1364     _(b'-c|-m|FILE'),
  1339 )
  1365 )
  1340 def debugindex(ui, repo, file_=None, **opts):
  1366 def debugindex(ui, repo, file_=None, **opts):
  1341     """dump index data for a storage primitive"""
  1367     """dump index data for a storage primitive"""
  1342     opts = pycompat.byteskwargs(opts)
  1368     opts = pycompat.byteskwargs(opts)
  1343     store = cmdutil.openstorage(repo, 'debugindex', file_, opts)
  1369     store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
  1344 
  1370 
  1345     if ui.debugflag:
  1371     if ui.debugflag:
  1346         shortfn = hex
  1372         shortfn = hex
  1347     else:
  1373     else:
  1348         shortfn = short
  1374         shortfn = short
  1350     idlen = 12
  1376     idlen = 12
  1351     for i in store:
  1377     for i in store:
  1352         idlen = len(shortfn(store.node(i)))
  1378         idlen = len(shortfn(store.node(i)))
  1353         break
  1379         break
  1354 
  1380 
  1355     fm = ui.formatter('debugindex', opts)
  1381     fm = ui.formatter(b'debugindex', opts)
  1356     fm.plain(
  1382     fm.plain(
  1357         b'   rev linkrev %s %s p2\n'
  1383         b'   rev linkrev %s %s p2\n'
  1358         % (b'nodeid'.ljust(idlen), b'p1'.ljust(idlen))
  1384         % (b'nodeid'.ljust(idlen), b'p1'.ljust(idlen))
  1359     )
  1385     )
  1360 
  1386 
  1362         node = store.node(rev)
  1388         node = store.node(rev)
  1363         parents = store.parents(node)
  1389         parents = store.parents(node)
  1364 
  1390 
  1365         fm.startitem()
  1391         fm.startitem()
  1366         fm.write(b'rev', b'%6d ', rev)
  1392         fm.write(b'rev', b'%6d ', rev)
  1367         fm.write(b'linkrev', '%7d ', store.linkrev(rev))
  1393         fm.write(b'linkrev', b'%7d ', store.linkrev(rev))
  1368         fm.write(b'node', '%s ', shortfn(node))
  1394         fm.write(b'node', b'%s ', shortfn(node))
  1369         fm.write(b'p1', '%s ', shortfn(parents[0]))
  1395         fm.write(b'p1', b'%s ', shortfn(parents[0]))
  1370         fm.write(b'p2', '%s', shortfn(parents[1]))
  1396         fm.write(b'p2', b'%s', shortfn(parents[1]))
  1371         fm.plain(b'\n')
  1397         fm.plain(b'\n')
  1372 
  1398 
  1373     fm.end()
  1399     fm.end()
  1374 
  1400 
  1375 
  1401 
  1376 @command(
  1402 @command(
  1377     'debugindexdot', cmdutil.debugrevlogopts, _('-c|-m|FILE'), optionalrepo=True
  1403     b'debugindexdot',
       
  1404     cmdutil.debugrevlogopts,
       
  1405     _(b'-c|-m|FILE'),
       
  1406     optionalrepo=True,
  1378 )
  1407 )
  1379 def debugindexdot(ui, repo, file_=None, **opts):
  1408 def debugindexdot(ui, repo, file_=None, **opts):
  1380     """dump an index DAG as a graphviz dot file"""
  1409     """dump an index DAG as a graphviz dot file"""
  1381     opts = pycompat.byteskwargs(opts)
  1410     opts = pycompat.byteskwargs(opts)
  1382     r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts)
  1411     r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
  1383     ui.write("digraph G {\n")
  1412     ui.write(b"digraph G {\n")
  1384     for i in r:
  1413     for i in r:
  1385         node = r.node(i)
  1414         node = r.node(i)
  1386         pp = r.parents(node)
  1415         pp = r.parents(node)
  1387         ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
  1416         ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
  1388         if pp[1] != nullid:
  1417         if pp[1] != nullid:
  1389             ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
  1418             ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
  1390     ui.write("}\n")
  1419     ui.write(b"}\n")
  1391 
  1420 
  1392 
  1421 
  1393 @command('debugindexstats', [])
  1422 @command(b'debugindexstats', [])
  1394 def debugindexstats(ui, repo):
  1423 def debugindexstats(ui, repo):
  1395     """show stats related to the changelog index"""
  1424     """show stats related to the changelog index"""
  1396     repo.changelog.shortest(nullid, 1)
  1425     repo.changelog.shortest(nullid, 1)
  1397     index = repo.changelog.index
  1426     index = repo.changelog.index
  1398     if not util.safehasattr(index, 'stats'):
  1427     if not util.safehasattr(index, b'stats'):
  1399         raise error.Abort(_('debugindexstats only works with native code'))
  1428         raise error.Abort(_(b'debugindexstats only works with native code'))
  1400     for k, v in sorted(index.stats().items()):
  1429     for k, v in sorted(index.stats().items()):
  1401         ui.write('%s: %d\n' % (k, v))
  1430         ui.write(b'%s: %d\n' % (k, v))
  1402 
  1431 
  1403 
  1432 
  1404 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
  1433 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
  1405 def debuginstall(ui, **opts):
  1434 def debuginstall(ui, **opts):
  1406     '''test Mercurial installation
  1435     '''test Mercurial installation
  1407 
  1436 
  1408     Returns 0 on success.
  1437     Returns 0 on success.
  1409     '''
  1438     '''
  1410     opts = pycompat.byteskwargs(opts)
  1439     opts = pycompat.byteskwargs(opts)
  1411 
  1440 
  1412     problems = 0
  1441     problems = 0
  1413 
  1442 
  1414     fm = ui.formatter('debuginstall', opts)
  1443     fm = ui.formatter(b'debuginstall', opts)
  1415     fm.startitem()
  1444     fm.startitem()
  1416 
  1445 
  1417     # encoding
  1446     # encoding
  1418     fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
  1447     fm.write(b'encoding', _(b"checking encoding (%s)...\n"), encoding.encoding)
  1419     err = None
  1448     err = None
  1420     try:
  1449     try:
  1421         codecs.lookup(pycompat.sysstr(encoding.encoding))
  1450         codecs.lookup(pycompat.sysstr(encoding.encoding))
  1422     except LookupError as inst:
  1451     except LookupError as inst:
  1423         err = stringutil.forcebytestr(inst)
  1452         err = stringutil.forcebytestr(inst)
  1424         problems += 1
  1453         problems += 1
  1425     fm.condwrite(
  1454     fm.condwrite(
  1426         err,
  1455         err,
  1427         'encodingerror',
  1456         b'encodingerror',
  1428         _(" %s\n" " (check that your locale is properly set)\n"),
  1457         _(b" %s\n" b" (check that your locale is properly set)\n"),
  1429         err,
  1458         err,
  1430     )
  1459     )
  1431 
  1460 
  1432     # Python
  1461     # Python
  1433     fm.write(
  1462     fm.write(
  1434         'pythonexe',
  1463         b'pythonexe',
  1435         _("checking Python executable (%s)\n"),
  1464         _(b"checking Python executable (%s)\n"),
  1436         pycompat.sysexecutable or _("unknown"),
  1465         pycompat.sysexecutable or _(b"unknown"),
  1437     )
  1466     )
  1438     fm.write(
  1467     fm.write(
  1439         'pythonver',
  1468         b'pythonver',
  1440         _("checking Python version (%s)\n"),
  1469         _(b"checking Python version (%s)\n"),
  1441         ("%d.%d.%d" % sys.version_info[:3]),
  1470         (b"%d.%d.%d" % sys.version_info[:3]),
  1442     )
  1471     )
  1443     fm.write(
  1472     fm.write(
  1444         'pythonlib',
  1473         b'pythonlib',
  1445         _("checking Python lib (%s)...\n"),
  1474         _(b"checking Python lib (%s)...\n"),
  1446         os.path.dirname(pycompat.fsencode(os.__file__)),
  1475         os.path.dirname(pycompat.fsencode(os.__file__)),
  1447     )
  1476     )
  1448 
  1477 
  1449     security = set(sslutil.supportedprotocols)
  1478     security = set(sslutil.supportedprotocols)
  1450     if sslutil.hassni:
  1479     if sslutil.hassni:
  1451         security.add('sni')
  1480         security.add(b'sni')
  1452 
  1481 
  1453     fm.write(
  1482     fm.write(
  1454         'pythonsecurity',
  1483         b'pythonsecurity',
  1455         _("checking Python security support (%s)\n"),
  1484         _(b"checking Python security support (%s)\n"),
  1456         fm.formatlist(sorted(security), name='protocol', fmt='%s', sep=','),
  1485         fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
  1457     )
  1486     )
  1458 
  1487 
  1459     # These are warnings, not errors. So don't increment problem count. This
  1488     # These are warnings, not errors. So don't increment problem count. This
  1460     # may change in the future.
  1489     # may change in the future.
  1461     if 'tls1.2' not in security:
  1490     if b'tls1.2' not in security:
  1462         fm.plain(
  1491         fm.plain(
  1463             _(
  1492             _(
  1464                 '  TLS 1.2 not supported by Python install; '
  1493                 b'  TLS 1.2 not supported by Python install; '
  1465                 'network connections lack modern security\n'
  1494                 b'network connections lack modern security\n'
  1466             )
  1495             )
  1467         )
  1496         )
  1468     if 'sni' not in security:
  1497     if b'sni' not in security:
  1469         fm.plain(
  1498         fm.plain(
  1470             _(
  1499             _(
  1471                 '  SNI not supported by Python install; may have '
  1500                 b'  SNI not supported by Python install; may have '
  1472                 'connectivity issues with some servers\n'
  1501                 b'connectivity issues with some servers\n'
  1473             )
  1502             )
  1474         )
  1503         )
  1475 
  1504 
  1476     # TODO print CA cert info
  1505     # TODO print CA cert info
  1477 
  1506 
  1478     # hg version
  1507     # hg version
  1479     hgver = util.version()
  1508     hgver = util.version()
  1480     fm.write(
  1509     fm.write(
  1481         'hgver', _("checking Mercurial version (%s)\n"), hgver.split('+')[0]
  1510         b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
  1482     )
  1511     )
  1483     fm.write(
  1512     fm.write(
  1484         'hgverextra',
  1513         b'hgverextra',
  1485         _("checking Mercurial custom build (%s)\n"),
  1514         _(b"checking Mercurial custom build (%s)\n"),
  1486         '+'.join(hgver.split('+')[1:]),
  1515         b'+'.join(hgver.split(b'+')[1:]),
  1487     )
  1516     )
  1488 
  1517 
  1489     # compiled modules
  1518     # compiled modules
  1490     fm.write(
  1519     fm.write(
  1491         'hgmodulepolicy', _("checking module policy (%s)\n"), policy.policy
  1520         b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
  1492     )
  1521     )
  1493     fm.write(
  1522     fm.write(
  1494         'hgmodules',
  1523         b'hgmodules',
  1495         _("checking installed modules (%s)...\n"),
  1524         _(b"checking installed modules (%s)...\n"),
  1496         os.path.dirname(pycompat.fsencode(__file__)),
  1525         os.path.dirname(pycompat.fsencode(__file__)),
  1497     )
  1526     )
  1498 
  1527 
  1499     rustandc = policy.policy in ('rust+c', 'rust+c-allow')
  1528     rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
  1500     rustext = rustandc  # for now, that's the only case
  1529     rustext = rustandc  # for now, that's the only case
  1501     cext = policy.policy in ('c', 'allow') or rustandc
  1530     cext = policy.policy in (b'c', b'allow') or rustandc
  1502     nopure = cext or rustext
  1531     nopure = cext or rustext
  1503     if nopure:
  1532     if nopure:
  1504         err = None
  1533         err = None
  1505         try:
  1534         try:
  1506             if cext:
  1535             if cext:
  1521 
  1550 
  1522                 dir(ancestor), dir(dirstate)  # quiet pyflakes
  1551                 dir(ancestor), dir(dirstate)  # quiet pyflakes
  1523         except Exception as inst:
  1552         except Exception as inst:
  1524             err = stringutil.forcebytestr(inst)
  1553             err = stringutil.forcebytestr(inst)
  1525             problems += 1
  1554             problems += 1
  1526         fm.condwrite(err, 'extensionserror', " %s\n", err)
  1555         fm.condwrite(err, b'extensionserror', b" %s\n", err)
  1527 
  1556 
  1528     compengines = util.compengines._engines.values()
  1557     compengines = util.compengines._engines.values()
  1529     fm.write(
  1558     fm.write(
  1530         'compengines',
  1559         b'compengines',
  1531         _('checking registered compression engines (%s)\n'),
  1560         _(b'checking registered compression engines (%s)\n'),
  1532         fm.formatlist(
  1561         fm.formatlist(
  1533             sorted(e.name() for e in compengines),
  1562             sorted(e.name() for e in compengines),
  1534             name='compengine',
  1563             name=b'compengine',
  1535             fmt='%s',
  1564             fmt=b'%s',
  1536             sep=', ',
  1565             sep=b', ',
  1537         ),
  1566         ),
  1538     )
  1567     )
  1539     fm.write(
  1568     fm.write(
  1540         'compenginesavail',
  1569         b'compenginesavail',
  1541         _('checking available compression engines ' '(%s)\n'),
  1570         _(b'checking available compression engines ' b'(%s)\n'),
  1542         fm.formatlist(
  1571         fm.formatlist(
  1543             sorted(e.name() for e in compengines if e.available()),
  1572             sorted(e.name() for e in compengines if e.available()),
  1544             name='compengine',
  1573             name=b'compengine',
  1545             fmt='%s',
  1574             fmt=b'%s',
  1546             sep=', ',
  1575             sep=b', ',
  1547         ),
  1576         ),
  1548     )
  1577     )
  1549     wirecompengines = compression.compengines.supportedwireengines(
  1578     wirecompengines = compression.compengines.supportedwireengines(
  1550         compression.SERVERROLE
  1579         compression.SERVERROLE
  1551     )
  1580     )
  1552     fm.write(
  1581     fm.write(
  1553         'compenginesserver',
  1582         b'compenginesserver',
  1554         _('checking available compression engines ' 'for wire protocol (%s)\n'),
  1583         _(
       
  1584             b'checking available compression engines '
       
  1585             b'for wire protocol (%s)\n'
       
  1586         ),
  1555         fm.formatlist(
  1587         fm.formatlist(
  1556             [e.name() for e in wirecompengines if e.wireprotosupport()],
  1588             [e.name() for e in wirecompengines if e.wireprotosupport()],
  1557             name='compengine',
  1589             name=b'compengine',
  1558             fmt='%s',
  1590             fmt=b'%s',
  1559             sep=', ',
  1591             sep=b', ',
  1560         ),
  1592         ),
  1561     )
  1593     )
  1562     re2 = 'missing'
  1594     re2 = b'missing'
  1563     if util._re2:
  1595     if util._re2:
  1564         re2 = 'available'
  1596         re2 = b'available'
  1565     fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
  1597     fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
  1566     fm.data(re2=bool(util._re2))
  1598     fm.data(re2=bool(util._re2))
  1567 
  1599 
  1568     # templates
  1600     # templates
  1569     p = templater.templatepaths()
  1601     p = templater.templatepaths()
  1570     fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
  1602     fm.write(b'templatedirs', b'checking templates (%s)...\n', b' '.join(p))
  1571     fm.condwrite(not p, '', _(" no template directories found\n"))
  1603     fm.condwrite(not p, b'', _(b" no template directories found\n"))
  1572     if p:
  1604     if p:
  1573         m = templater.templatepath("map-cmdline.default")
  1605         m = templater.templatepath(b"map-cmdline.default")
  1574         if m:
  1606         if m:
  1575             # template found, check if it is working
  1607             # template found, check if it is working
  1576             err = None
  1608             err = None
  1577             try:
  1609             try:
  1578                 templater.templater.frommapfile(m)
  1610                 templater.templater.frommapfile(m)
  1579             except Exception as inst:
  1611             except Exception as inst:
  1580                 err = stringutil.forcebytestr(inst)
  1612                 err = stringutil.forcebytestr(inst)
  1581                 p = None
  1613                 p = None
  1582             fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
  1614             fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
  1583         else:
  1615         else:
  1584             p = None
  1616             p = None
  1585         fm.condwrite(
  1617         fm.condwrite(
  1586             p, 'defaulttemplate', _("checking default template (%s)\n"), m
  1618             p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
  1587         )
  1619         )
  1588         fm.condwrite(
  1620         fm.condwrite(
  1589             not m,
  1621             not m,
  1590             'defaulttemplatenotfound',
  1622             b'defaulttemplatenotfound',
  1591             _(" template '%s' not found\n"),
  1623             _(b" template '%s' not found\n"),
  1592             "default",
  1624             b"default",
  1593         )
  1625         )
  1594     if not p:
  1626     if not p:
  1595         problems += 1
  1627         problems += 1
  1596     fm.condwrite(
  1628     fm.condwrite(
  1597         not p, '', _(" (templates seem to have been installed incorrectly)\n")
  1629         not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
  1598     )
  1630     )
  1599 
  1631 
  1600     # editor
  1632     # editor
  1601     editor = ui.geteditor()
  1633     editor = ui.geteditor()
  1602     editor = util.expandpath(editor)
  1634     editor = util.expandpath(editor)
  1603     editorbin = procutil.shellsplit(editor)[0]
  1635     editorbin = procutil.shellsplit(editor)[0]
  1604     fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
  1636     fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
  1605     cmdpath = procutil.findexe(editorbin)
  1637     cmdpath = procutil.findexe(editorbin)
  1606     fm.condwrite(
  1638     fm.condwrite(
  1607         not cmdpath and editor == 'vi',
  1639         not cmdpath and editor == b'vi',
  1608         'vinotfound',
  1640         b'vinotfound',
  1609         _(
  1641         _(
  1610             " No commit editor set and can't find %s in PATH\n"
  1642             b" No commit editor set and can't find %s in PATH\n"
  1611             " (specify a commit editor in your configuration"
  1643             b" (specify a commit editor in your configuration"
  1612             " file)\n"
  1644             b" file)\n"
  1613         ),
  1645         ),
  1614         not cmdpath and editor == 'vi' and editorbin,
  1646         not cmdpath and editor == b'vi' and editorbin,
  1615     )
  1647     )
  1616     fm.condwrite(
  1648     fm.condwrite(
  1617         not cmdpath and editor != 'vi',
  1649         not cmdpath and editor != b'vi',
  1618         'editornotfound',
  1650         b'editornotfound',
  1619         _(
  1651         _(
  1620             " Can't find editor '%s' in PATH\n"
  1652             b" Can't find editor '%s' in PATH\n"
  1621             " (specify a commit editor in your configuration"
  1653             b" (specify a commit editor in your configuration"
  1622             " file)\n"
  1654             b" file)\n"
  1623         ),
  1655         ),
  1624         not cmdpath and editorbin,
  1656         not cmdpath and editorbin,
  1625     )
  1657     )
  1626     if not cmdpath and editor != 'vi':
  1658     if not cmdpath and editor != b'vi':
  1627         problems += 1
  1659         problems += 1
  1628 
  1660 
  1629     # check username
  1661     # check username
  1630     username = None
  1662     username = None
  1631     err = None
  1663     err = None
  1633         username = ui.username()
  1665         username = ui.username()
  1634     except error.Abort as e:
  1666     except error.Abort as e:
  1635         err = stringutil.forcebytestr(e)
  1667         err = stringutil.forcebytestr(e)
  1636         problems += 1
  1668         problems += 1
  1637 
  1669 
  1638     fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
  1670     fm.condwrite(
       
  1671         username, b'username', _(b"checking username (%s)\n"), username
       
  1672     )
  1639     fm.condwrite(
  1673     fm.condwrite(
  1640         err,
  1674         err,
  1641         'usernameerror',
  1675         b'usernameerror',
  1642         _(
  1676         _(
  1643             "checking username...\n %s\n"
  1677             b"checking username...\n %s\n"
  1644             " (specify a username in your configuration file)\n"
  1678             b" (specify a username in your configuration file)\n"
  1645         ),
  1679         ),
  1646         err,
  1680         err,
  1647     )
  1681     )
  1648 
  1682 
  1649     for name, mod in extensions.extensions():
  1683     for name, mod in extensions.extensions():
  1650         handler = getattr(mod, 'debuginstall', None)
  1684         handler = getattr(mod, 'debuginstall', None)
  1651         if handler is not None:
  1685         if handler is not None:
  1652             problems += handler(ui, fm)
  1686             problems += handler(ui, fm)
  1653 
  1687 
  1654     fm.condwrite(not problems, '', _("no problems detected\n"))
  1688     fm.condwrite(not problems, b'', _(b"no problems detected\n"))
  1655     if not problems:
  1689     if not problems:
  1656         fm.data(problems=problems)
  1690         fm.data(problems=problems)
  1657     fm.condwrite(
  1691     fm.condwrite(
  1658         problems,
  1692         problems,
  1659         'problems',
  1693         b'problems',
  1660         _("%d problems detected," " please check your install!\n"),
  1694         _(b"%d problems detected," b" please check your install!\n"),
  1661         problems,
  1695         problems,
  1662     )
  1696     )
  1663     fm.end()
  1697     fm.end()
  1664 
  1698 
  1665     return problems
  1699     return problems
  1666 
  1700 
  1667 
  1701 
  1668 @command('debugknown', [], _('REPO ID...'), norepo=True)
  1702 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
  1669 def debugknown(ui, repopath, *ids, **opts):
  1703 def debugknown(ui, repopath, *ids, **opts):
  1670     """test whether node ids are known to a repo
  1704     """test whether node ids are known to a repo
  1671 
  1705 
  1672     Every ID must be a full-length hex node id string. Returns a list of 0s
  1706     Every ID must be a full-length hex node id string. Returns a list of 0s
  1673     and 1s indicating unknown/known.
  1707     and 1s indicating unknown/known.
  1674     """
  1708     """
  1675     opts = pycompat.byteskwargs(opts)
  1709     opts = pycompat.byteskwargs(opts)
  1676     repo = hg.peer(ui, opts, repopath)
  1710     repo = hg.peer(ui, opts, repopath)
  1677     if not repo.capable('known'):
  1711     if not repo.capable(b'known'):
  1678         raise error.Abort("known() not supported by target repository")
  1712         raise error.Abort(b"known() not supported by target repository")
  1679     flags = repo.known([bin(s) for s in ids])
  1713     flags = repo.known([bin(s) for s in ids])
  1680     ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
  1714     ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
  1681 
  1715 
  1682 
  1716 
  1683 @command('debuglabelcomplete', [], _('LABEL...'))
  1717 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
  1684 def debuglabelcomplete(ui, repo, *args):
  1718 def debuglabelcomplete(ui, repo, *args):
  1685     '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
  1719     '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
  1686     debugnamecomplete(ui, repo, *args)
  1720     debugnamecomplete(ui, repo, *args)
  1687 
  1721 
  1688 
  1722 
  1689 @command(
  1723 @command(
  1690     'debuglocks',
  1724     b'debuglocks',
  1691     [
  1725     [
  1692         ('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
  1726         (b'L', b'force-lock', None, _(b'free the store lock (DANGEROUS)')),
  1693         (
  1727         (
  1694             'W',
  1728             b'W',
  1695             'force-wlock',
  1729             b'force-wlock',
  1696             None,
  1730             None,
  1697             _('free the working state lock (DANGEROUS)'),
  1731             _(b'free the working state lock (DANGEROUS)'),
  1698         ),
  1732         ),
  1699         ('s', 'set-lock', None, _('set the store lock until stopped')),
  1733         (b's', b'set-lock', None, _(b'set the store lock until stopped')),
  1700         ('S', 'set-wlock', None, _('set the working state lock until stopped')),
  1734         (
       
  1735             b'S',
       
  1736             b'set-wlock',
       
  1737             None,
       
  1738             _(b'set the working state lock until stopped'),
       
  1739         ),
  1701     ],
  1740     ],
  1702     _('[OPTION]...'),
  1741     _(b'[OPTION]...'),
  1703 )
  1742 )
  1704 def debuglocks(ui, repo, **opts):
  1743 def debuglocks(ui, repo, **opts):
  1705     """show or modify state of locks
  1744     """show or modify state of locks
  1706 
  1745 
  1707     By default, this command will show which locks are held. This
  1746     By default, this command will show which locks are held. This
  1725     Returns 0 if no locks are held.
  1764     Returns 0 if no locks are held.
  1726 
  1765 
  1727     """
  1766     """
  1728 
  1767 
  1729     if opts.get(r'force_lock'):
  1768     if opts.get(r'force_lock'):
  1730         repo.svfs.unlink('lock')
  1769         repo.svfs.unlink(b'lock')
  1731     if opts.get(r'force_wlock'):
  1770     if opts.get(r'force_wlock'):
  1732         repo.vfs.unlink('wlock')
  1771         repo.vfs.unlink(b'wlock')
  1733     if opts.get(r'force_lock') or opts.get(r'force_wlock'):
  1772     if opts.get(r'force_lock') or opts.get(r'force_wlock'):
  1734         return 0
  1773         return 0
  1735 
  1774 
  1736     locks = []
  1775     locks = []
  1737     try:
  1776     try:
  1738         if opts.get(r'set_wlock'):
  1777         if opts.get(r'set_wlock'):
  1739             try:
  1778             try:
  1740                 locks.append(repo.wlock(False))
  1779                 locks.append(repo.wlock(False))
  1741             except error.LockHeld:
  1780             except error.LockHeld:
  1742                 raise error.Abort(_('wlock is already held'))
  1781                 raise error.Abort(_(b'wlock is already held'))
  1743         if opts.get(r'set_lock'):
  1782         if opts.get(r'set_lock'):
  1744             try:
  1783             try:
  1745                 locks.append(repo.lock(False))
  1784                 locks.append(repo.lock(False))
  1746             except error.LockHeld:
  1785             except error.LockHeld:
  1747                 raise error.Abort(_('lock is already held'))
  1786                 raise error.Abort(_(b'lock is already held'))
  1748         if len(locks):
  1787         if len(locks):
  1749             ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
  1788             ui.promptchoice(_(b"ready to release the lock (y)? $$ &Yes"))
  1750             return 0
  1789             return 0
  1751     finally:
  1790     finally:
  1752         release(*locks)
  1791         release(*locks)
  1753 
  1792 
  1754     now = time.time()
  1793     now = time.time()
  1767             try:
  1806             try:
  1768                 st = vfs.lstat(name)
  1807                 st = vfs.lstat(name)
  1769                 age = now - st[stat.ST_MTIME]
  1808                 age = now - st[stat.ST_MTIME]
  1770                 user = util.username(st.st_uid)
  1809                 user = util.username(st.st_uid)
  1771                 locker = vfs.readlock(name)
  1810                 locker = vfs.readlock(name)
  1772                 if ":" in locker:
  1811                 if b":" in locker:
  1773                     host, pid = locker.split(':')
  1812                     host, pid = locker.split(b':')
  1774                     if host == socket.gethostname():
  1813                     if host == socket.gethostname():
  1775                         locker = 'user %s, process %s' % (user or b'None', pid)
  1814                         locker = b'user %s, process %s' % (user or b'None', pid)
  1776                     else:
  1815                     else:
  1777                         locker = 'user %s, process %s, host %s' % (
  1816                         locker = b'user %s, process %s, host %s' % (
  1778                             user or b'None',
  1817                             user or b'None',
  1779                             pid,
  1818                             pid,
  1780                             host,
  1819                             host,
  1781                         )
  1820                         )
  1782                 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
  1821                 ui.write(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
  1783                 return 1
  1822                 return 1
  1784             except OSError as e:
  1823             except OSError as e:
  1785                 if e.errno != errno.ENOENT:
  1824                 if e.errno != errno.ENOENT:
  1786                     raise
  1825                     raise
  1787 
  1826 
  1788         ui.write("%-6s free\n" % (name + ":"))
  1827         ui.write(b"%-6s free\n" % (name + b":"))
  1789         return 0
  1828         return 0
  1790 
  1829 
  1791     held += report(repo.svfs, "lock", repo.lock)
  1830     held += report(repo.svfs, b"lock", repo.lock)
  1792     held += report(repo.vfs, "wlock", repo.wlock)
  1831     held += report(repo.vfs, b"wlock", repo.wlock)
  1793 
  1832 
  1794     return held
  1833     return held
  1795 
  1834 
  1796 
  1835 
  1797 @command(
  1836 @command(
  1798     'debugmanifestfulltextcache',
  1837     b'debugmanifestfulltextcache',
  1799     [
  1838     [
  1800         ('', 'clear', False, _('clear the cache')),
  1839         (b'', b'clear', False, _(b'clear the cache')),
  1801         (
  1840         (
  1802             'a',
  1841             b'a',
  1803             'add',
  1842             b'add',
  1804             [],
  1843             [],
  1805             _('add the given manifest nodes to the cache'),
  1844             _(b'add the given manifest nodes to the cache'),
  1806             _('NODE'),
  1845             _(b'NODE'),
  1807         ),
  1846         ),
  1808     ],
  1847     ],
  1809     '',
  1848     b'',
  1810 )
  1849 )
  1811 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
  1850 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
  1812     """show, clear or amend the contents of the manifest fulltext cache"""
  1851     """show, clear or amend the contents of the manifest fulltext cache"""
  1813 
  1852 
  1814     def getcache():
  1853     def getcache():
  1815         r = repo.manifestlog.getstorage(b'')
  1854         r = repo.manifestlog.getstorage(b'')
  1816         try:
  1855         try:
  1817             return r._fulltextcache
  1856             return r._fulltextcache
  1818         except AttributeError:
  1857         except AttributeError:
  1819             msg = _(
  1858             msg = _(
  1820                 "Current revlog implementation doesn't appear to have a "
  1859                 b"Current revlog implementation doesn't appear to have a "
  1821                 "manifest fulltext cache\n"
  1860                 b"manifest fulltext cache\n"
  1822             )
  1861             )
  1823             raise error.Abort(msg)
  1862             raise error.Abort(msg)
  1824 
  1863 
  1825     if opts.get(r'clear'):
  1864     if opts.get(r'clear'):
  1826         with repo.wlock():
  1865         with repo.wlock():
  1834             store = m.getstorage(b'')
  1873             store = m.getstorage(b'')
  1835             for n in add:
  1874             for n in add:
  1836                 try:
  1875                 try:
  1837                     manifest = m[store.lookup(n)]
  1876                     manifest = m[store.lookup(n)]
  1838                 except error.LookupError as e:
  1877                 except error.LookupError as e:
  1839                     raise error.Abort(e, hint="Check your manifest node id")
  1878                     raise error.Abort(e, hint=b"Check your manifest node id")
  1840                 manifest.read()  # stores revisision in cache too
  1879                 manifest.read()  # stores revisision in cache too
  1841             return
  1880             return
  1842 
  1881 
  1843     cache = getcache()
  1882     cache = getcache()
  1844     if not len(cache):
  1883     if not len(cache):
  1845         ui.write(_('cache empty\n'))
  1884         ui.write(_(b'cache empty\n'))
  1846     else:
  1885     else:
  1847         ui.write(
  1886         ui.write(
  1848             _(
  1887             _(
  1849                 'cache contains %d manifest entries, in order of most to '
  1888                 b'cache contains %d manifest entries, in order of most to '
  1850                 'least recent:\n'
  1889                 b'least recent:\n'
  1851             )
  1890             )
  1852             % (len(cache),)
  1891             % (len(cache),)
  1853         )
  1892         )
  1854         totalsize = 0
  1893         totalsize = 0
  1855         for nodeid in cache:
  1894         for nodeid in cache:
  1856             # Use cache.get to not update the LRU order
  1895             # Use cache.get to not update the LRU order
  1857             data = cache.peek(nodeid)
  1896             data = cache.peek(nodeid)
  1858             size = len(data)
  1897             size = len(data)
  1859             totalsize += size + 24  # 20 bytes nodeid, 4 bytes size
  1898             totalsize += size + 24  # 20 bytes nodeid, 4 bytes size
  1860             ui.write(
  1899             ui.write(
  1861                 _('id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
  1900                 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
  1862             )
  1901             )
  1863         ondisk = cache._opener.stat('manifestfulltextcache').st_size
  1902         ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
  1864         ui.write(
  1903         ui.write(
  1865             _('total cache data size %s, on-disk %s\n')
  1904             _(b'total cache data size %s, on-disk %s\n')
  1866             % (util.bytecount(totalsize), util.bytecount(ondisk))
  1905             % (util.bytecount(totalsize), util.bytecount(ondisk))
  1867         )
  1906         )
  1868 
  1907 
  1869 
  1908 
  1870 @command('debugmergestate', [], '')
  1909 @command(b'debugmergestate', [], b'')
  1871 def debugmergestate(ui, repo, *args):
  1910 def debugmergestate(ui, repo, *args):
  1872     """print merge state
  1911     """print merge state
  1873 
  1912 
  1874     Use --verbose to print out information about whether v1 or v2 merge state
  1913     Use --verbose to print out information about whether v1 or v2 merge state
  1875     was chosen."""
  1914     was chosen."""
  1876 
  1915 
  1877     def _hashornull(h):
  1916     def _hashornull(h):
  1878         if h == nullhex:
  1917         if h == nullhex:
  1879             return 'null'
  1918             return b'null'
  1880         else:
  1919         else:
  1881             return h
  1920             return h
  1882 
  1921 
  1883     def printrecords(version):
  1922     def printrecords(version):
  1884         ui.write('* version %d records\n' % version)
  1923         ui.write(b'* version %d records\n' % version)
  1885         if version == 1:
  1924         if version == 1:
  1886             records = v1records
  1925             records = v1records
  1887         else:
  1926         else:
  1888             records = v2records
  1927             records = v2records
  1889 
  1928 
  1890         for rtype, record in records:
  1929         for rtype, record in records:
  1891             # pretty print some record types
  1930             # pretty print some record types
  1892             if rtype == 'L':
  1931             if rtype == b'L':
  1893                 ui.write('local: %s\n' % record)
  1932                 ui.write(b'local: %s\n' % record)
  1894             elif rtype == 'O':
  1933             elif rtype == b'O':
  1895                 ui.write('other: %s\n' % record)
  1934                 ui.write(b'other: %s\n' % record)
  1896             elif rtype == 'm':
  1935             elif rtype == b'm':
  1897                 driver, mdstate = record.split('\0', 1)
  1936                 driver, mdstate = record.split(b'\0', 1)
  1898                 ui.write('merge driver: %s (state "%s")\n' % (driver, mdstate))
  1937                 ui.write(b'merge driver: %s (state "%s")\n' % (driver, mdstate))
  1899             elif rtype in 'FDC':
  1938             elif rtype in b'FDC':
  1900                 r = record.split('\0')
  1939                 r = record.split(b'\0')
  1901                 f, state, hash, lfile, afile, anode, ofile = r[0:7]
  1940                 f, state, hash, lfile, afile, anode, ofile = r[0:7]
  1902                 if version == 1:
  1941                 if version == 1:
  1903                     onode = 'not stored in v1 format'
  1942                     onode = b'not stored in v1 format'
  1904                     flags = r[7]
  1943                     flags = r[7]
  1905                 else:
  1944                 else:
  1906                     onode, flags = r[7:9]
  1945                     onode, flags = r[7:9]
  1907                 ui.write(
  1946                 ui.write(
  1908                     'file: %s (record type "%s", state "%s", hash %s)\n'
  1947                     b'file: %s (record type "%s", state "%s", hash %s)\n'
  1909                     % (f, rtype, state, _hashornull(hash))
  1948                     % (f, rtype, state, _hashornull(hash))
  1910                 )
  1949                 )
  1911                 ui.write('  local path: %s (flags "%s")\n' % (lfile, flags))
  1950                 ui.write(b'  local path: %s (flags "%s")\n' % (lfile, flags))
  1912                 ui.write(
  1951                 ui.write(
  1913                     '  ancestor path: %s (node %s)\n'
  1952                     b'  ancestor path: %s (node %s)\n'
  1914                     % (afile, _hashornull(anode))
  1953                     % (afile, _hashornull(anode))
  1915                 )
  1954                 )
  1916                 ui.write(
  1955                 ui.write(
  1917                     '  other path: %s (node %s)\n' % (ofile, _hashornull(onode))
  1956                     b'  other path: %s (node %s)\n'
       
  1957                     % (ofile, _hashornull(onode))
  1918                 )
  1958                 )
  1919             elif rtype == 'f':
  1959             elif rtype == b'f':
  1920                 filename, rawextras = record.split('\0', 1)
  1960                 filename, rawextras = record.split(b'\0', 1)
  1921                 extras = rawextras.split('\0')
  1961                 extras = rawextras.split(b'\0')
  1922                 i = 0
  1962                 i = 0
  1923                 extrastrings = []
  1963                 extrastrings = []
  1924                 while i < len(extras):
  1964                 while i < len(extras):
  1925                     extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
  1965                     extrastrings.append(b'%s = %s' % (extras[i], extras[i + 1]))
  1926                     i += 2
  1966                     i += 2
  1927 
  1967 
  1928                 ui.write(
  1968                 ui.write(
  1929                     'file extras: %s (%s)\n'
  1969                     b'file extras: %s (%s)\n'
  1930                     % (filename, ', '.join(extrastrings))
  1970                     % (filename, b', '.join(extrastrings))
  1931                 )
  1971                 )
  1932             elif rtype == 'l':
  1972             elif rtype == b'l':
  1933                 labels = record.split('\0', 2)
  1973                 labels = record.split(b'\0', 2)
  1934                 labels = [l for l in labels if len(l) > 0]
  1974                 labels = [l for l in labels if len(l) > 0]
  1935                 ui.write('labels:\n')
  1975                 ui.write(b'labels:\n')
  1936                 ui.write(('  local: %s\n' % labels[0]))
  1976                 ui.write((b'  local: %s\n' % labels[0]))
  1937                 ui.write(('  other: %s\n' % labels[1]))
  1977                 ui.write((b'  other: %s\n' % labels[1]))
  1938                 if len(labels) > 2:
  1978                 if len(labels) > 2:
  1939                     ui.write(('  base:  %s\n' % labels[2]))
  1979                     ui.write((b'  base:  %s\n' % labels[2]))
  1940             else:
  1980             else:
  1941                 ui.write(
  1981                 ui.write(
  1942                     'unrecognized entry: %s\t%s\n'
  1982                     b'unrecognized entry: %s\t%s\n'
  1943                     % (rtype, record.replace('\0', '\t'))
  1983                     % (rtype, record.replace(b'\0', b'\t'))
  1944                 )
  1984                 )
  1945 
  1985 
  1946     # Avoid mergestate.read() since it may raise an exception for unsupported
  1986     # Avoid mergestate.read() since it may raise an exception for unsupported
  1947     # merge state records. We shouldn't be doing this, but this is OK since this
  1987     # merge state records. We shouldn't be doing this, but this is OK since this
  1948     # command is pretty low-level.
  1988     # command is pretty low-level.
  1949     ms = mergemod.mergestate(repo)
  1989     ms = mergemod.mergestate(repo)
  1950 
  1990 
  1951     # sort so that reasonable information is on top
  1991     # sort so that reasonable information is on top
  1952     v1records = ms._readrecordsv1()
  1992     v1records = ms._readrecordsv1()
  1953     v2records = ms._readrecordsv2()
  1993     v2records = ms._readrecordsv2()
  1954     order = 'LOml'
  1994     order = b'LOml'
  1955 
  1995 
  1956     def key(r):
  1996     def key(r):
  1957         idx = order.find(r[0])
  1997         idx = order.find(r[0])
  1958         if idx == -1:
  1998         if idx == -1:
  1959             return (1, r[1])
  1999             return (1, r[1])
  1962 
  2002 
  1963     v1records.sort(key=key)
  2003     v1records.sort(key=key)
  1964     v2records.sort(key=key)
  2004     v2records.sort(key=key)
  1965 
  2005 
  1966     if not v1records and not v2records:
  2006     if not v1records and not v2records:
  1967         ui.write('no merge state found\n')
  2007         ui.write(b'no merge state found\n')
  1968     elif not v2records:
  2008     elif not v2records:
  1969         ui.note('no version 2 merge state\n')
  2009         ui.note(b'no version 2 merge state\n')
  1970         printrecords(1)
  2010         printrecords(1)
  1971     elif ms._v1v2match(v1records, v2records):
  2011     elif ms._v1v2match(v1records, v2records):
  1972         ui.note('v1 and v2 states match: using v2\n')
  2012         ui.note(b'v1 and v2 states match: using v2\n')
  1973         printrecords(2)
  2013         printrecords(2)
  1974     else:
  2014     else:
  1975         ui.note('v1 and v2 states mismatch: using v1\n')
  2015         ui.note(b'v1 and v2 states mismatch: using v1\n')
  1976         printrecords(1)
  2016         printrecords(1)
  1977         if ui.verbose:
  2017         if ui.verbose:
  1978             printrecords(2)
  2018             printrecords(2)
  1979 
  2019 
  1980 
  2020 
  1981 @command('debugnamecomplete', [], _('NAME...'))
  2021 @command(b'debugnamecomplete', [], _(b'NAME...'))
  1982 def debugnamecomplete(ui, repo, *args):
  2022 def debugnamecomplete(ui, repo, *args):
  1983     '''complete "names" - tags, open branch names, bookmark names'''
  2023     '''complete "names" - tags, open branch names, bookmark names'''
  1984 
  2024 
  1985     names = set()
  2025     names = set()
  1986     # since we previously only listed open branches, we will handle that
  2026     # since we previously only listed open branches, we will handle that
  1987     # specially (after this for loop)
  2027     # specially (after this for loop)
  1988     for name, ns in repo.names.iteritems():
  2028     for name, ns in repo.names.iteritems():
  1989         if name != 'branches':
  2029         if name != b'branches':
  1990             names.update(ns.listnames(repo))
  2030             names.update(ns.listnames(repo))
  1991     names.update(
  2031     names.update(
  1992         tag
  2032         tag
  1993         for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
  2033         for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
  1994         if not closed
  2034         if not closed
  1995     )
  2035     )
  1996     completions = set()
  2036     completions = set()
  1997     if not args:
  2037     if not args:
  1998         args = ['']
  2038         args = [b'']
  1999     for a in args:
  2039     for a in args:
  2000         completions.update(n for n in names if n.startswith(a))
  2040         completions.update(n for n in names if n.startswith(a))
  2001     ui.write('\n'.join(sorted(completions)))
  2041     ui.write(b'\n'.join(sorted(completions)))
  2002     ui.write('\n')
  2042     ui.write(b'\n')
  2003 
  2043 
  2004 
  2044 
  2005 @command(
  2045 @command(
  2006     'debugobsolete',
  2046     b'debugobsolete',
  2007     [
  2047     [
  2008         ('', 'flags', 0, _('markers flag')),
  2048         (b'', b'flags', 0, _(b'markers flag')),
  2009         (
  2049         (
  2010             '',
  2050             b'',
  2011             'record-parents',
  2051             b'record-parents',
  2012             False,
  2052             False,
  2013             _('record parent information for the precursor'),
  2053             _(b'record parent information for the precursor'),
  2014         ),
  2054         ),
  2015         ('r', 'rev', [], _('display markers relevant to REV')),
  2055         (b'r', b'rev', [], _(b'display markers relevant to REV')),
  2016         (
  2056         (
  2017             '',
  2057             b'',
  2018             'exclusive',
  2058             b'exclusive',
  2019             False,
  2059             False,
  2020             _('restrict display to markers only ' 'relevant to REV'),
  2060             _(b'restrict display to markers only ' b'relevant to REV'),
  2021         ),
  2061         ),
  2022         ('', 'index', False, _('display index of the marker')),
  2062         (b'', b'index', False, _(b'display index of the marker')),
  2023         ('', 'delete', [], _('delete markers specified by indices')),
  2063         (b'', b'delete', [], _(b'delete markers specified by indices')),
  2024     ]
  2064     ]
  2025     + cmdutil.commitopts2
  2065     + cmdutil.commitopts2
  2026     + cmdutil.formatteropts,
  2066     + cmdutil.formatteropts,
  2027     _('[OBSOLETED [REPLACEMENT ...]]'),
  2067     _(b'[OBSOLETED [REPLACEMENT ...]]'),
  2028 )
  2068 )
  2029 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
  2069 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
  2030     """create arbitrary obsolete marker
  2070     """create arbitrary obsolete marker
  2031 
  2071 
  2032     With no arguments, displays the list of obsolescence markers."""
  2072     With no arguments, displays the list of obsolescence markers."""
  2042             if len(n) != len(nullid):
  2082             if len(n) != len(nullid):
  2043                 raise TypeError()
  2083                 raise TypeError()
  2044             return n
  2084             return n
  2045         except TypeError:
  2085         except TypeError:
  2046             raise error.Abort(
  2086             raise error.Abort(
  2047                 'changeset references must be full hexadecimal '
  2087                 b'changeset references must be full hexadecimal '
  2048                 'node identifiers'
  2088                 b'node identifiers'
  2049             )
  2089             )
  2050 
  2090 
  2051     if opts.get('delete'):
  2091     if opts.get(b'delete'):
  2052         indices = []
  2092         indices = []
  2053         for v in opts.get('delete'):
  2093         for v in opts.get(b'delete'):
  2054             try:
  2094             try:
  2055                 indices.append(int(v))
  2095                 indices.append(int(v))
  2056             except ValueError:
  2096             except ValueError:
  2057                 raise error.Abort(
  2097                 raise error.Abort(
  2058                     _('invalid index value: %r') % v,
  2098                     _(b'invalid index value: %r') % v,
  2059                     hint=_('use integers for indices'),
  2099                     hint=_(b'use integers for indices'),
  2060                 )
  2100                 )
  2061 
  2101 
  2062         if repo.currenttransaction():
  2102         if repo.currenttransaction():
  2063             raise error.Abort(
  2103             raise error.Abort(
  2064                 _('cannot delete obsmarkers in the middle ' 'of transaction.')
  2104                 _(b'cannot delete obsmarkers in the middle ' b'of transaction.')
  2065             )
  2105             )
  2066 
  2106 
  2067         with repo.lock():
  2107         with repo.lock():
  2068             n = repair.deleteobsmarkers(repo.obsstore, indices)
  2108             n = repair.deleteobsmarkers(repo.obsstore, indices)
  2069             ui.write(_('deleted %i obsolescence markers\n') % n)
  2109             ui.write(_(b'deleted %i obsolescence markers\n') % n)
  2070 
  2110 
  2071         return
  2111         return
  2072 
  2112 
  2073     if precursor is not None:
  2113     if precursor is not None:
  2074         if opts['rev']:
  2114         if opts[b'rev']:
  2075             raise error.Abort('cannot select revision when creating marker')
  2115             raise error.Abort(b'cannot select revision when creating marker')
  2076         metadata = {}
  2116         metadata = {}
  2077         metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
  2117         metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
  2078         succs = tuple(parsenodeid(succ) for succ in successors)
  2118         succs = tuple(parsenodeid(succ) for succ in successors)
  2079         l = repo.lock()
  2119         l = repo.lock()
  2080         try:
  2120         try:
  2081             tr = repo.transaction('debugobsolete')
  2121             tr = repo.transaction(b'debugobsolete')
  2082             try:
  2122             try:
  2083                 date = opts.get('date')
  2123                 date = opts.get(b'date')
  2084                 if date:
  2124                 if date:
  2085                     date = dateutil.parsedate(date)
  2125                     date = dateutil.parsedate(date)
  2086                 else:
  2126                 else:
  2087                     date = None
  2127                     date = None
  2088                 prec = parsenodeid(precursor)
  2128                 prec = parsenodeid(precursor)
  2089                 parents = None
  2129                 parents = None
  2090                 if opts['record_parents']:
  2130                 if opts[b'record_parents']:
  2091                     if prec not in repo.unfiltered():
  2131                     if prec not in repo.unfiltered():
  2092                         raise error.Abort(
  2132                         raise error.Abort(
  2093                             'cannot used --record-parents on '
  2133                             b'cannot used --record-parents on '
  2094                             'unknown changesets'
  2134                             b'unknown changesets'
  2095                         )
  2135                         )
  2096                     parents = repo.unfiltered()[prec].parents()
  2136                     parents = repo.unfiltered()[prec].parents()
  2097                     parents = tuple(p.node() for p in parents)
  2137                     parents = tuple(p.node() for p in parents)
  2098                 repo.obsstore.create(
  2138                 repo.obsstore.create(
  2099                     tr,
  2139                     tr,
  2100                     prec,
  2140                     prec,
  2101                     succs,
  2141                     succs,
  2102                     opts['flags'],
  2142                     opts[b'flags'],
  2103                     parents=parents,
  2143                     parents=parents,
  2104                     date=date,
  2144                     date=date,
  2105                     metadata=metadata,
  2145                     metadata=metadata,
  2106                     ui=ui,
  2146                     ui=ui,
  2107                 )
  2147                 )
  2108                 tr.close()
  2148                 tr.close()
  2109             except ValueError as exc:
  2149             except ValueError as exc:
  2110                 raise error.Abort(
  2150                 raise error.Abort(
  2111                     _('bad obsmarker input: %s') % pycompat.bytestr(exc)
  2151                     _(b'bad obsmarker input: %s') % pycompat.bytestr(exc)
  2112                 )
  2152                 )
  2113             finally:
  2153             finally:
  2114                 tr.release()
  2154                 tr.release()
  2115         finally:
  2155         finally:
  2116             l.release()
  2156             l.release()
  2117     else:
  2157     else:
  2118         if opts['rev']:
  2158         if opts[b'rev']:
  2119             revs = scmutil.revrange(repo, opts['rev'])
  2159             revs = scmutil.revrange(repo, opts[b'rev'])
  2120             nodes = [repo[r].node() for r in revs]
  2160             nodes = [repo[r].node() for r in revs]
  2121             markers = list(
  2161             markers = list(
  2122                 obsutil.getmarkers(
  2162                 obsutil.getmarkers(
  2123                     repo, nodes=nodes, exclusive=opts['exclusive']
  2163                     repo, nodes=nodes, exclusive=opts[b'exclusive']
  2124                 )
  2164                 )
  2125             )
  2165             )
  2126             markers.sort(key=lambda x: x._data)
  2166             markers.sort(key=lambda x: x._data)
  2127         else:
  2167         else:
  2128             markers = obsutil.getmarkers(repo)
  2168             markers = obsutil.getmarkers(repo)
  2129 
  2169 
  2130         markerstoiter = markers
  2170         markerstoiter = markers
  2131         isrelevant = lambda m: True
  2171         isrelevant = lambda m: True
  2132         if opts.get('rev') and opts.get('index'):
  2172         if opts.get(b'rev') and opts.get(b'index'):
  2133             markerstoiter = obsutil.getmarkers(repo)
  2173             markerstoiter = obsutil.getmarkers(repo)
  2134             markerset = set(markers)
  2174             markerset = set(markers)
  2135             isrelevant = lambda m: m in markerset
  2175             isrelevant = lambda m: m in markerset
  2136 
  2176 
  2137         fm = ui.formatter('debugobsolete', opts)
  2177         fm = ui.formatter(b'debugobsolete', opts)
  2138         for i, m in enumerate(markerstoiter):
  2178         for i, m in enumerate(markerstoiter):
  2139             if not isrelevant(m):
  2179             if not isrelevant(m):
  2140                 # marker can be irrelevant when we're iterating over a set
  2180                 # marker can be irrelevant when we're iterating over a set
  2141                 # of markers (markerstoiter) which is bigger than the set
  2181                 # of markers (markerstoiter) which is bigger than the set
  2142                 # of markers we want to display (markers)
  2182                 # of markers we want to display (markers)
  2144                 # provided and thus we need to iterate over all of the markers
  2184                 # provided and thus we need to iterate over all of the markers
  2145                 # to get the correct indices, but only display the ones that
  2185                 # to get the correct indices, but only display the ones that
  2146                 # are relevant to --rev value
  2186                 # are relevant to --rev value
  2147                 continue
  2187                 continue
  2148             fm.startitem()
  2188             fm.startitem()
  2149             ind = i if opts.get('index') else None
  2189             ind = i if opts.get(b'index') else None
  2150             cmdutil.showmarker(fm, m, index=ind)
  2190             cmdutil.showmarker(fm, m, index=ind)
  2151         fm.end()
  2191         fm.end()
  2152 
  2192 
  2153 
  2193 
  2154 @command(
  2194 @command(
  2155     'debugp1copies',
  2195     b'debugp1copies',
  2156     [('r', 'rev', '', _('revision to debug'), _('REV'))],
  2196     [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
  2157     _('[-r REV]'),
  2197     _(b'[-r REV]'),
  2158 )
  2198 )
  2159 def debugp1copies(ui, repo, **opts):
  2199 def debugp1copies(ui, repo, **opts):
  2160     """dump copy information compared to p1"""
  2200     """dump copy information compared to p1"""
  2161 
  2201 
  2162     opts = pycompat.byteskwargs(opts)
  2202     opts = pycompat.byteskwargs(opts)
  2163     ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
  2203     ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
  2164     for dst, src in ctx.p1copies().items():
  2204     for dst, src in ctx.p1copies().items():
  2165         ui.write('%s -> %s\n' % (src, dst))
  2205         ui.write(b'%s -> %s\n' % (src, dst))
  2166 
  2206 
  2167 
  2207 
  2168 @command(
  2208 @command(
  2169     'debugp2copies',
  2209     b'debugp2copies',
  2170     [('r', 'rev', '', _('revision to debug'), _('REV'))],
  2210     [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
  2171     _('[-r REV]'),
  2211     _(b'[-r REV]'),
  2172 )
  2212 )
  2173 def debugp1copies(ui, repo, **opts):
  2213 def debugp1copies(ui, repo, **opts):
  2174     """dump copy information compared to p2"""
  2214     """dump copy information compared to p2"""
  2175 
  2215 
  2176     opts = pycompat.byteskwargs(opts)
  2216     opts = pycompat.byteskwargs(opts)
  2177     ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
  2217     ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
  2178     for dst, src in ctx.p2copies().items():
  2218     for dst, src in ctx.p2copies().items():
  2179         ui.write('%s -> %s\n' % (src, dst))
  2219         ui.write(b'%s -> %s\n' % (src, dst))
  2180 
  2220 
  2181 
  2221 
  2182 @command(
  2222 @command(
  2183     'debugpathcomplete',
  2223     b'debugpathcomplete',
  2184     [
  2224     [
  2185         ('f', 'full', None, _('complete an entire path')),
  2225         (b'f', b'full', None, _(b'complete an entire path')),
  2186         ('n', 'normal', None, _('show only normal files')),
  2226         (b'n', b'normal', None, _(b'show only normal files')),
  2187         ('a', 'added', None, _('show only added files')),
  2227         (b'a', b'added', None, _(b'show only added files')),
  2188         ('r', 'removed', None, _('show only removed files')),
  2228         (b'r', b'removed', None, _(b'show only removed files')),
  2189     ],
  2229     ],
  2190     _('FILESPEC...'),
  2230     _(b'FILESPEC...'),
  2191 )
  2231 )
  2192 def debugpathcomplete(ui, repo, *specs, **opts):
  2232 def debugpathcomplete(ui, repo, *specs, **opts):
  2193     '''complete part or all of a tracked path
  2233     '''complete part or all of a tracked path
  2194 
  2234 
  2195     This command supports shells that offer path name completion. It
  2235     This command supports shells that offer path name completion. It
  2203         spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
  2243         spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
  2204         rootdir = repo.root + pycompat.ossep
  2244         rootdir = repo.root + pycompat.ossep
  2205         if spec != repo.root and not spec.startswith(rootdir):
  2245         if spec != repo.root and not spec.startswith(rootdir):
  2206             return [], []
  2246             return [], []
  2207         if os.path.isdir(spec):
  2247         if os.path.isdir(spec):
  2208             spec += '/'
  2248             spec += b'/'
  2209         spec = spec[len(rootdir) :]
  2249         spec = spec[len(rootdir) :]
  2210         fixpaths = pycompat.ossep != '/'
  2250         fixpaths = pycompat.ossep != b'/'
  2211         if fixpaths:
  2251         if fixpaths:
  2212             spec = spec.replace(pycompat.ossep, '/')
  2252             spec = spec.replace(pycompat.ossep, b'/')
  2213         speclen = len(spec)
  2253         speclen = len(spec)
  2214         fullpaths = opts[r'full']
  2254         fullpaths = opts[r'full']
  2215         files, dirs = set(), set()
  2255         files, dirs = set(), set()
  2216         adddir, addfile = dirs.add, files.add
  2256         adddir, addfile = dirs.add, files.add
  2217         for f, st in dirstate.iteritems():
  2257         for f, st in dirstate.iteritems():
  2218             if f.startswith(spec) and st[0] in acceptable:
  2258             if f.startswith(spec) and st[0] in acceptable:
  2219                 if fixpaths:
  2259                 if fixpaths:
  2220                     f = f.replace('/', pycompat.ossep)
  2260                     f = f.replace(b'/', pycompat.ossep)
  2221                 if fullpaths:
  2261                 if fullpaths:
  2222                     addfile(f)
  2262                     addfile(f)
  2223                     continue
  2263                     continue
  2224                 s = f.find(pycompat.ossep, speclen)
  2264                 s = f.find(pycompat.ossep, speclen)
  2225                 if s >= 0:
  2265                 if s >= 0:
  2226                     adddir(f[:s])
  2266                     adddir(f[:s])
  2227                 else:
  2267                 else:
  2228                     addfile(f)
  2268                     addfile(f)
  2229         return files, dirs
  2269         return files, dirs
  2230 
  2270 
  2231     acceptable = ''
  2271     acceptable = b''
  2232     if opts[r'normal']:
  2272     if opts[r'normal']:
  2233         acceptable += 'nm'
  2273         acceptable += b'nm'
  2234     if opts[r'added']:
  2274     if opts[r'added']:
  2235         acceptable += 'a'
  2275         acceptable += b'a'
  2236     if opts[r'removed']:
  2276     if opts[r'removed']:
  2237         acceptable += 'r'
  2277         acceptable += b'r'
  2238     cwd = repo.getcwd()
  2278     cwd = repo.getcwd()
  2239     if not specs:
  2279     if not specs:
  2240         specs = ['.']
  2280         specs = [b'.']
  2241 
  2281 
  2242     files, dirs = set(), set()
  2282     files, dirs = set(), set()
  2243     for spec in specs:
  2283     for spec in specs:
  2244         f, d = complete(spec, acceptable or 'nmar')
  2284         f, d = complete(spec, acceptable or b'nmar')
  2245         files.update(f)
  2285         files.update(f)
  2246         dirs.update(d)
  2286         dirs.update(d)
  2247     files.update(dirs)
  2287     files.update(dirs)
  2248     ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
  2288     ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
  2249     ui.write('\n')
  2289     ui.write(b'\n')
  2250 
  2290 
  2251 
  2291 
  2252 @command(
  2292 @command(
  2253     'debugpathcopies',
  2293     b'debugpathcopies',
  2254     cmdutil.walkopts,
  2294     cmdutil.walkopts,
  2255     'hg debugpathcopies REV1 REV2 [FILE]',
  2295     b'hg debugpathcopies REV1 REV2 [FILE]',
  2256     inferrepo=True,
  2296     inferrepo=True,
  2257 )
  2297 )
  2258 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
  2298 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
  2259     """show copies between two revisions"""
  2299     """show copies between two revisions"""
  2260     ctx1 = scmutil.revsingle(repo, rev1)
  2300     ctx1 = scmutil.revsingle(repo, rev1)
  2261     ctx2 = scmutil.revsingle(repo, rev2)
  2301     ctx2 = scmutil.revsingle(repo, rev2)
  2262     m = scmutil.match(ctx1, pats, opts)
  2302     m = scmutil.match(ctx1, pats, opts)
  2263     for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
  2303     for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
  2264         ui.write('%s -> %s\n' % (src, dst))
  2304         ui.write(b'%s -> %s\n' % (src, dst))
  2265 
  2305 
  2266 
  2306 
  2267 @command('debugpeer', [], _('PATH'), norepo=True)
  2307 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
  2268 def debugpeer(ui, path):
  2308 def debugpeer(ui, path):
  2269     """establish a connection to a peer repository"""
  2309     """establish a connection to a peer repository"""
  2270     # Always enable peer request logging. Requires --debug to display
  2310     # Always enable peer request logging. Requires --debug to display
  2271     # though.
  2311     # though.
  2272     overrides = {
  2312     overrides = {
  2273         ('devel', 'debug.peer-request'): True,
  2313         (b'devel', b'debug.peer-request'): True,
  2274     }
  2314     }
  2275 
  2315 
  2276     with ui.configoverride(overrides):
  2316     with ui.configoverride(overrides):
  2277         peer = hg.peer(ui, {}, path)
  2317         peer = hg.peer(ui, {}, path)
  2278 
  2318 
  2279         local = peer.local() is not None
  2319         local = peer.local() is not None
  2280         canpush = peer.canpush()
  2320         canpush = peer.canpush()
  2281 
  2321 
  2282         ui.write(_('url: %s\n') % peer.url())
  2322         ui.write(_(b'url: %s\n') % peer.url())
  2283         ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
  2323         ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
  2284         ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
  2324         ui.write(_(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no')))
  2285 
  2325 
  2286 
  2326 
  2287 @command(
  2327 @command(
  2288     'debugpickmergetool',
  2328     b'debugpickmergetool',
  2289     [
  2329     [
  2290         ('r', 'rev', '', _('check for files in this revision'), _('REV')),
  2330         (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
  2291         ('', 'changedelete', None, _('emulate merging change and delete')),
  2331         (b'', b'changedelete', None, _(b'emulate merging change and delete')),
  2292     ]
  2332     ]
  2293     + cmdutil.walkopts
  2333     + cmdutil.walkopts
  2294     + cmdutil.mergetoolopts,
  2334     + cmdutil.mergetoolopts,
  2295     _('[PATTERN]...'),
  2335     _(b'[PATTERN]...'),
  2296     inferrepo=True,
  2336     inferrepo=True,
  2297 )
  2337 )
  2298 def debugpickmergetool(ui, repo, *pats, **opts):
  2338 def debugpickmergetool(ui, repo, *pats, **opts):
  2299     """examine which merge tool is chosen for specified file
  2339     """examine which merge tool is chosen for specified file
  2300 
  2340 
  2337     information, even with --debug. In such case, information above is
  2377     information, even with --debug. In such case, information above is
  2338     useful to know why a merge tool is chosen.
  2378     useful to know why a merge tool is chosen.
  2339     """
  2379     """
  2340     opts = pycompat.byteskwargs(opts)
  2380     opts = pycompat.byteskwargs(opts)
  2341     overrides = {}
  2381     overrides = {}
  2342     if opts['tool']:
  2382     if opts[b'tool']:
  2343         overrides[('ui', 'forcemerge')] = opts['tool']
  2383         overrides[(b'ui', b'forcemerge')] = opts[b'tool']
  2344         ui.note('with --tool %r\n' % (pycompat.bytestr(opts['tool'])))
  2384         ui.note(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
  2345 
  2385 
  2346     with ui.configoverride(overrides, 'debugmergepatterns'):
  2386     with ui.configoverride(overrides, b'debugmergepatterns'):
  2347         hgmerge = encoding.environ.get("HGMERGE")
  2387         hgmerge = encoding.environ.get(b"HGMERGE")
  2348         if hgmerge is not None:
  2388         if hgmerge is not None:
  2349             ui.note('with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
  2389             ui.note(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
  2350         uimerge = ui.config("ui", "merge")
  2390         uimerge = ui.config(b"ui", b"merge")
  2351         if uimerge:
  2391         if uimerge:
  2352             ui.note('with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
  2392             ui.note(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
  2353 
  2393 
  2354         ctx = scmutil.revsingle(repo, opts.get('rev'))
  2394         ctx = scmutil.revsingle(repo, opts.get(b'rev'))
  2355         m = scmutil.match(ctx, pats, opts)
  2395         m = scmutil.match(ctx, pats, opts)
  2356         changedelete = opts['changedelete']
  2396         changedelete = opts[b'changedelete']
  2357         for path in ctx.walk(m):
  2397         for path in ctx.walk(m):
  2358             fctx = ctx[path]
  2398             fctx = ctx[path]
  2359             try:
  2399             try:
  2360                 if not ui.debugflag:
  2400                 if not ui.debugflag:
  2361                     ui.pushbuffer(error=True)
  2401                     ui.pushbuffer(error=True)
  2362                 tool, toolpath = filemerge._picktool(
  2402                 tool, toolpath = filemerge._picktool(
  2363                     repo,
  2403                     repo,
  2364                     ui,
  2404                     ui,
  2365                     path,
  2405                     path,
  2366                     fctx.isbinary(),
  2406                     fctx.isbinary(),
  2367                     'l' in fctx.flags(),
  2407                     b'l' in fctx.flags(),
  2368                     changedelete,
  2408                     changedelete,
  2369                 )
  2409                 )
  2370             finally:
  2410             finally:
  2371                 if not ui.debugflag:
  2411                 if not ui.debugflag:
  2372                     ui.popbuffer()
  2412                     ui.popbuffer()
  2373             ui.write('%s = %s\n' % (path, tool))
  2413             ui.write(b'%s = %s\n' % (path, tool))
  2374 
  2414 
  2375 
  2415 
  2376 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
  2416 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
  2377 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
  2417 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
  2378     '''access the pushkey key/value protocol
  2418     '''access the pushkey key/value protocol
  2379 
  2419 
  2380     With two args, list the keys in the given namespace.
  2420     With two args, list the keys in the given namespace.
  2381 
  2421 
  2386     target = hg.peer(ui, {}, repopath)
  2426     target = hg.peer(ui, {}, repopath)
  2387     if keyinfo:
  2427     if keyinfo:
  2388         key, old, new = keyinfo
  2428         key, old, new = keyinfo
  2389         with target.commandexecutor() as e:
  2429         with target.commandexecutor() as e:
  2390             r = e.callcommand(
  2430             r = e.callcommand(
  2391                 'pushkey',
  2431                 b'pushkey',
  2392                 {'namespace': namespace, 'key': key, 'old': old, 'new': new,},
  2432                 {
       
  2433                     b'namespace': namespace,
       
  2434                     b'key': key,
       
  2435                     b'old': old,
       
  2436                     b'new': new,
       
  2437                 },
  2393             ).result()
  2438             ).result()
  2394 
  2439 
  2395         ui.status(pycompat.bytestr(r) + '\n')
  2440         ui.status(pycompat.bytestr(r) + b'\n')
  2396         return not r
  2441         return not r
  2397     else:
  2442     else:
  2398         for k, v in sorted(target.listkeys(namespace).iteritems()):
  2443         for k, v in sorted(target.listkeys(namespace).iteritems()):
  2399             ui.write(
  2444             ui.write(
  2400                 "%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v))
  2445                 b"%s\t%s\n" % (stringutil.escapestr(k), stringutil.escapestr(v))
  2401             )
  2446             )
  2402 
  2447 
  2403 
  2448 
  2404 @command('debugpvec', [], _('A B'))
  2449 @command(b'debugpvec', [], _(b'A B'))
  2405 def debugpvec(ui, repo, a, b=None):
  2450 def debugpvec(ui, repo, a, b=None):
  2406     ca = scmutil.revsingle(repo, a)
  2451     ca = scmutil.revsingle(repo, a)
  2407     cb = scmutil.revsingle(repo, b)
  2452     cb = scmutil.revsingle(repo, b)
  2408     pa = pvec.ctxpvec(ca)
  2453     pa = pvec.ctxpvec(ca)
  2409     pb = pvec.ctxpvec(cb)
  2454     pb = pvec.ctxpvec(cb)
  2410     if pa == pb:
  2455     if pa == pb:
  2411         rel = "="
  2456         rel = b"="
  2412     elif pa > pb:
  2457     elif pa > pb:
  2413         rel = ">"
  2458         rel = b">"
  2414     elif pa < pb:
  2459     elif pa < pb:
  2415         rel = "<"
  2460         rel = b"<"
  2416     elif pa | pb:
  2461     elif pa | pb:
  2417         rel = "|"
  2462         rel = b"|"
  2418     ui.write(_("a: %s\n") % pa)
  2463     ui.write(_(b"a: %s\n") % pa)
  2419     ui.write(_("b: %s\n") % pb)
  2464     ui.write(_(b"b: %s\n") % pb)
  2420     ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
  2465     ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
  2421     ui.write(
  2466     ui.write(
  2422         _("delta: %d hdist: %d distance: %d relation: %s\n")
  2467         _(b"delta: %d hdist: %d distance: %d relation: %s\n")
  2423         % (
  2468         % (
  2424             abs(pa._depth - pb._depth),
  2469             abs(pa._depth - pb._depth),
  2425             pvec._hamming(pa._vec, pb._vec),
  2470             pvec._hamming(pa._vec, pb._vec),
  2426             pa.distance(pb),
  2471             pa.distance(pb),
  2427             rel,
  2472             rel,
  2428         )
  2473         )
  2429     )
  2474     )
  2430 
  2475 
  2431 
  2476 
  2432 @command(
  2477 @command(
  2433     'debugrebuilddirstate|debugrebuildstate',
  2478     b'debugrebuilddirstate|debugrebuildstate',
  2434     [
  2479     [
  2435         ('r', 'rev', '', _('revision to rebuild to'), _('REV')),
  2480         (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
  2436         (
  2481         (
  2437             '',
  2482             b'',
  2438             'minimal',
  2483             b'minimal',
  2439             None,
  2484             None,
  2440             _(
  2485             _(
  2441                 'only rebuild files that are inconsistent with '
  2486                 b'only rebuild files that are inconsistent with '
  2442                 'the working copy parent'
  2487                 b'the working copy parent'
  2443             ),
  2488             ),
  2444         ),
  2489         ),
  2445     ],
  2490     ],
  2446     _('[-r REV]'),
  2491     _(b'[-r REV]'),
  2447 )
  2492 )
  2448 def debugrebuilddirstate(ui, repo, rev, **opts):
  2493 def debugrebuilddirstate(ui, repo, rev, **opts):
  2449     """rebuild the dirstate as it would look like for the given revision
  2494     """rebuild the dirstate as it would look like for the given revision
  2450 
  2495 
  2451     If no revision is specified the first current parent will be used.
  2496     If no revision is specified the first current parent will be used.
  2470         if opts.get(r'minimal'):
  2515         if opts.get(r'minimal'):
  2471             manifestfiles = set(ctx.manifest().keys())
  2516             manifestfiles = set(ctx.manifest().keys())
  2472             dirstatefiles = set(dirstate)
  2517             dirstatefiles = set(dirstate)
  2473             manifestonly = manifestfiles - dirstatefiles
  2518             manifestonly = manifestfiles - dirstatefiles
  2474             dsonly = dirstatefiles - manifestfiles
  2519             dsonly = dirstatefiles - manifestfiles
  2475             dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
  2520             dsnotadded = set(f for f in dsonly if dirstate[f] != b'a')
  2476             changedfiles = manifestonly | dsnotadded
  2521             changedfiles = manifestonly | dsnotadded
  2477 
  2522 
  2478         dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
  2523         dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
  2479 
  2524 
  2480 
  2525 
  2481 @command('debugrebuildfncache', [], '')
  2526 @command(b'debugrebuildfncache', [], b'')
  2482 def debugrebuildfncache(ui, repo):
  2527 def debugrebuildfncache(ui, repo):
  2483     """rebuild the fncache file"""
  2528     """rebuild the fncache file"""
  2484     repair.rebuildfncache(ui, repo)
  2529     repair.rebuildfncache(ui, repo)
  2485 
  2530 
  2486 
  2531 
  2487 @command(
  2532 @command(
  2488     'debugrename',
  2533     b'debugrename',
  2489     [('r', 'rev', '', _('revision to debug'), _('REV'))],
  2534     [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
  2490     _('[-r REV] [FILE]...'),
  2535     _(b'[-r REV] [FILE]...'),
  2491 )
  2536 )
  2492 def debugrename(ui, repo, *pats, **opts):
  2537 def debugrename(ui, repo, *pats, **opts):
  2493     """dump rename information"""
  2538     """dump rename information"""
  2494 
  2539 
  2495     opts = pycompat.byteskwargs(opts)
  2540     opts = pycompat.byteskwargs(opts)
  2496     ctx = scmutil.revsingle(repo, opts.get('rev'))
  2541     ctx = scmutil.revsingle(repo, opts.get(b'rev'))
  2497     m = scmutil.match(ctx, pats, opts)
  2542     m = scmutil.match(ctx, pats, opts)
  2498     for abs in ctx.walk(m):
  2543     for abs in ctx.walk(m):
  2499         fctx = ctx[abs]
  2544         fctx = ctx[abs]
  2500         o = fctx.filelog().renamed(fctx.filenode())
  2545         o = fctx.filelog().renamed(fctx.filenode())
  2501         rel = repo.pathto(abs)
  2546         rel = repo.pathto(abs)
  2502         if o:
  2547         if o:
  2503             ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
  2548             ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
  2504         else:
  2549         else:
  2505             ui.write(_("%s not renamed\n") % rel)
  2550             ui.write(_(b"%s not renamed\n") % rel)
  2506 
  2551 
  2507 
  2552 
  2508 @command(
  2553 @command(
  2509     'debugrevlog',
  2554     b'debugrevlog',
  2510     cmdutil.debugrevlogopts + [('d', 'dump', False, _('dump index data'))],
  2555     cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
  2511     _('-c|-m|FILE'),
  2556     _(b'-c|-m|FILE'),
  2512     optionalrepo=True,
  2557     optionalrepo=True,
  2513 )
  2558 )
  2514 def debugrevlog(ui, repo, file_=None, **opts):
  2559 def debugrevlog(ui, repo, file_=None, **opts):
  2515     """show data and statistics about a revlog"""
  2560     """show data and statistics about a revlog"""
  2516     opts = pycompat.byteskwargs(opts)
  2561     opts = pycompat.byteskwargs(opts)
  2517     r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
  2562     r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
  2518 
  2563 
  2519     if opts.get("dump"):
  2564     if opts.get(b"dump"):
  2520         numrevs = len(r)
  2565         numrevs = len(r)
  2521         ui.write(
  2566         ui.write(
  2522             (
  2567             (
  2523                 "# rev p1rev p2rev start   end deltastart base   p1   p2"
  2568                 b"# rev p1rev p2rev start   end deltastart base   p1   p2"
  2524                 " rawsize totalsize compression heads chainlen\n"
  2569                 b" rawsize totalsize compression heads chainlen\n"
  2525             )
  2570             )
  2526         )
  2571         )
  2527         ts = 0
  2572         ts = 0
  2528         heads = set()
  2573         heads = set()
  2529 
  2574 
  2541             try:
  2586             try:
  2542                 compression = ts / r.end(rev)
  2587                 compression = ts / r.end(rev)
  2543             except ZeroDivisionError:
  2588             except ZeroDivisionError:
  2544                 compression = 0
  2589                 compression = 0
  2545             ui.write(
  2590             ui.write(
  2546                 "%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
  2591                 b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
  2547                 "%11d %5d %8d\n"
  2592                 b"%11d %5d %8d\n"
  2548                 % (
  2593                 % (
  2549                     rev,
  2594                     rev,
  2550                     p1,
  2595                     p1,
  2551                     p2,
  2596                     p2,
  2552                     r.start(rev),
  2597                     r.start(rev),
  2567     v = r.version
  2612     v = r.version
  2568     format = v & 0xFFFF
  2613     format = v & 0xFFFF
  2569     flags = []
  2614     flags = []
  2570     gdelta = False
  2615     gdelta = False
  2571     if v & revlog.FLAG_INLINE_DATA:
  2616     if v & revlog.FLAG_INLINE_DATA:
  2572         flags.append('inline')
  2617         flags.append(b'inline')
  2573     if v & revlog.FLAG_GENERALDELTA:
  2618     if v & revlog.FLAG_GENERALDELTA:
  2574         gdelta = True
  2619         gdelta = True
  2575         flags.append('generaldelta')
  2620         flags.append(b'generaldelta')
  2576     if not flags:
  2621     if not flags:
  2577         flags = ['(none)']
  2622         flags = [b'(none)']
  2578 
  2623 
  2579     ### tracks merge vs single parent
  2624     ### tracks merge vs single parent
  2580     nummerges = 0
  2625     nummerges = 0
  2581 
  2626 
  2582     ### tracks ways the "delta" are build
  2627     ### tracks ways the "delta" are build
  2674                     nump2 += 1
  2719                     nump2 += 1
  2675                 elif delta != nullrev:
  2720                 elif delta != nullrev:
  2676                     numother += 1
  2721                     numother += 1
  2677 
  2722 
  2678         # Obtain data on the raw chunks in the revlog.
  2723         # Obtain data on the raw chunks in the revlog.
  2679         if util.safehasattr(r, '_getsegmentforrevs'):
  2724         if util.safehasattr(r, b'_getsegmentforrevs'):
  2680             segment = r._getsegmentforrevs(rev, rev)[1]
  2725             segment = r._getsegmentforrevs(rev, rev)[1]
  2681         else:
  2726         else:
  2682             segment = r._revlog._getsegmentforrevs(rev, rev)[1]
  2727             segment = r._revlog._getsegmentforrevs(rev, rev)[1]
  2683         if segment:
  2728         if segment:
  2684             chunktype = bytes(segment[0:1])
  2729             chunktype = bytes(segment[0:1])
  2685         else:
  2730         else:
  2686             chunktype = 'empty'
  2731             chunktype = b'empty'
  2687 
  2732 
  2688         if chunktype not in chunktypecounts:
  2733         if chunktype not in chunktypecounts:
  2689             chunktypecounts[chunktype] = 0
  2734             chunktypecounts[chunktype] = 0
  2690             chunktypesizes[chunktype] = 0
  2735             chunktypesizes[chunktype] = 0
  2691 
  2736 
  2723     maxchainspan = max(chainspans)
  2768     maxchainspan = max(chainspans)
  2724     compratio = 1
  2769     compratio = 1
  2725     if totalsize:
  2770     if totalsize:
  2726         compratio = totalrawsize / totalsize
  2771         compratio = totalrawsize / totalsize
  2727 
  2772 
  2728     basedfmtstr = '%%%dd\n'
  2773     basedfmtstr = b'%%%dd\n'
  2729     basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
  2774     basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
  2730 
  2775 
  2731     def dfmtstr(max):
  2776     def dfmtstr(max):
  2732         return basedfmtstr % len(str(max))
  2777         return basedfmtstr % len(str(max))
  2733 
  2778 
  2734     def pcfmtstr(max, padding=0):
  2779     def pcfmtstr(max, padding=0):
  2735         return basepcfmtstr % (len(str(max)), ' ' * padding)
  2780         return basepcfmtstr % (len(str(max)), b' ' * padding)
  2736 
  2781 
  2737     def pcfmt(value, total):
  2782     def pcfmt(value, total):
  2738         if total:
  2783         if total:
  2739             return (value, 100 * float(value) / total)
  2784             return (value, 100 * float(value) / total)
  2740         else:
  2785         else:
  2741             return value, 100.0
  2786             return value, 100.0
  2742 
  2787 
  2743     ui.write('format : %d\n' % format)
  2788     ui.write(b'format : %d\n' % format)
  2744     ui.write('flags  : %s\n' % ', '.join(flags))
  2789     ui.write(b'flags  : %s\n' % b', '.join(flags))
  2745 
  2790 
  2746     ui.write('\n')
  2791     ui.write(b'\n')
  2747     fmt = pcfmtstr(totalsize)
  2792     fmt = pcfmtstr(totalsize)
  2748     fmt2 = dfmtstr(totalsize)
  2793     fmt2 = dfmtstr(totalsize)
  2749     ui.write('revisions     : ' + fmt2 % numrevs)
  2794     ui.write(b'revisions     : ' + fmt2 % numrevs)
  2750     ui.write('    merges    : ' + fmt % pcfmt(nummerges, numrevs))
  2795     ui.write(b'    merges    : ' + fmt % pcfmt(nummerges, numrevs))
  2751     ui.write('    normal    : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
  2796     ui.write(b'    normal    : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
  2752     ui.write('revisions     : ' + fmt2 % numrevs)
  2797     ui.write(b'revisions     : ' + fmt2 % numrevs)
  2753     ui.write('    empty     : ' + fmt % pcfmt(numempty, numrevs))
  2798     ui.write(b'    empty     : ' + fmt % pcfmt(numempty, numrevs))
  2754     ui.write(
  2799     ui.write(
  2755         '                   text  : '
  2800         b'                   text  : '
  2756         + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
  2801         + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
  2757     )
  2802     )
  2758     ui.write(
  2803     ui.write(
  2759         '                   delta : '
  2804         b'                   delta : '
  2760         + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
  2805         + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
  2761     )
  2806     )
  2762     ui.write('    snapshot  : ' + fmt % pcfmt(numfull + numsemi, numrevs))
  2807     ui.write(b'    snapshot  : ' + fmt % pcfmt(numfull + numsemi, numrevs))
  2763     for depth in sorted(numsnapdepth):
  2808     for depth in sorted(numsnapdepth):
  2764         ui.write(
  2809         ui.write(
  2765             ('      lvl-%-3d :       ' % depth)
  2810             (b'      lvl-%-3d :       ' % depth)
  2766             + fmt % pcfmt(numsnapdepth[depth], numrevs)
  2811             + fmt % pcfmt(numsnapdepth[depth], numrevs)
  2767         )
  2812         )
  2768     ui.write('    deltas    : ' + fmt % pcfmt(numdeltas, numrevs))
  2813     ui.write(b'    deltas    : ' + fmt % pcfmt(numdeltas, numrevs))
  2769     ui.write('revision size : ' + fmt2 % totalsize)
  2814     ui.write(b'revision size : ' + fmt2 % totalsize)
  2770     ui.write('    snapshot  : ' + fmt % pcfmt(fulltotal + semitotal, totalsize))
  2815     ui.write(
       
  2816         b'    snapshot  : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
       
  2817     )
  2771     for depth in sorted(numsnapdepth):
  2818     for depth in sorted(numsnapdepth):
  2772         ui.write(
  2819         ui.write(
  2773             ('      lvl-%-3d :       ' % depth)
  2820             (b'      lvl-%-3d :       ' % depth)
  2774             + fmt % pcfmt(snaptotal[depth], totalsize)
  2821             + fmt % pcfmt(snaptotal[depth], totalsize)
  2775         )
  2822         )
  2776     ui.write('    deltas    : ' + fmt % pcfmt(deltatotal, totalsize))
  2823     ui.write(b'    deltas    : ' + fmt % pcfmt(deltatotal, totalsize))
  2777 
  2824 
  2778     def fmtchunktype(chunktype):
  2825     def fmtchunktype(chunktype):
  2779         if chunktype == 'empty':
  2826         if chunktype == b'empty':
  2780             return '    %s     : ' % chunktype
  2827             return b'    %s     : ' % chunktype
  2781         elif chunktype in pycompat.bytestr(string.ascii_letters):
  2828         elif chunktype in pycompat.bytestr(string.ascii_letters):
  2782             return '    0x%s (%s)  : ' % (hex(chunktype), chunktype)
  2829             return b'    0x%s (%s)  : ' % (hex(chunktype), chunktype)
  2783         else:
  2830         else:
  2784             return '    0x%s      : ' % hex(chunktype)
  2831             return b'    0x%s      : ' % hex(chunktype)
  2785 
  2832 
  2786     ui.write('\n')
  2833     ui.write(b'\n')
  2787     ui.write('chunks        : ' + fmt2 % numrevs)
  2834     ui.write(b'chunks        : ' + fmt2 % numrevs)
  2788     for chunktype in sorted(chunktypecounts):
  2835     for chunktype in sorted(chunktypecounts):
  2789         ui.write(fmtchunktype(chunktype))
  2836         ui.write(fmtchunktype(chunktype))
  2790         ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
  2837         ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
  2791     ui.write('chunks size   : ' + fmt2 % totalsize)
  2838     ui.write(b'chunks size   : ' + fmt2 % totalsize)
  2792     for chunktype in sorted(chunktypecounts):
  2839     for chunktype in sorted(chunktypecounts):
  2793         ui.write(fmtchunktype(chunktype))
  2840         ui.write(fmtchunktype(chunktype))
  2794         ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
  2841         ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
  2795 
  2842 
  2796     ui.write('\n')
  2843     ui.write(b'\n')
  2797     fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
  2844     fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
  2798     ui.write('avg chain length  : ' + fmt % avgchainlen)
  2845     ui.write(b'avg chain length  : ' + fmt % avgchainlen)
  2799     ui.write('max chain length  : ' + fmt % maxchainlen)
  2846     ui.write(b'max chain length  : ' + fmt % maxchainlen)
  2800     ui.write('max chain reach   : ' + fmt % maxchainspan)
  2847     ui.write(b'max chain reach   : ' + fmt % maxchainspan)
  2801     ui.write('compression ratio : ' + fmt % compratio)
  2848     ui.write(b'compression ratio : ' + fmt % compratio)
  2802 
  2849 
  2803     if format > 0:
  2850     if format > 0:
  2804         ui.write('\n')
  2851         ui.write(b'\n')
  2805         ui.write(
  2852         ui.write(
  2806             'uncompressed data size (min/max/avg) : %d / %d / %d\n'
  2853             b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
  2807             % tuple(datasize)
  2854             % tuple(datasize)
  2808         )
  2855         )
  2809     ui.write(
  2856     ui.write(
  2810         'full revision size (min/max/avg)     : %d / %d / %d\n'
  2857         b'full revision size (min/max/avg)     : %d / %d / %d\n'
  2811         % tuple(fullsize)
  2858         % tuple(fullsize)
  2812     )
  2859     )
  2813     ui.write(
  2860     ui.write(
  2814         'inter-snapshot size (min/max/avg)    : %d / %d / %d\n'
  2861         b'inter-snapshot size (min/max/avg)    : %d / %d / %d\n'
  2815         % tuple(semisize)
  2862         % tuple(semisize)
  2816     )
  2863     )
  2817     for depth in sorted(snapsizedepth):
  2864     for depth in sorted(snapsizedepth):
  2818         if depth == 0:
  2865         if depth == 0:
  2819             continue
  2866             continue
  2820         ui.write(
  2867         ui.write(
  2821             '    level-%-3d (min/max/avg)          : %d / %d / %d\n'
  2868             b'    level-%-3d (min/max/avg)          : %d / %d / %d\n'
  2822             % ((depth,) + tuple(snapsizedepth[depth]))
  2869             % ((depth,) + tuple(snapsizedepth[depth]))
  2823         )
  2870         )
  2824     ui.write(
  2871     ui.write(
  2825         'delta size (min/max/avg)             : %d / %d / %d\n'
  2872         b'delta size (min/max/avg)             : %d / %d / %d\n'
  2826         % tuple(deltasize)
  2873         % tuple(deltasize)
  2827     )
  2874     )
  2828 
  2875 
  2829     if numdeltas > 0:
  2876     if numdeltas > 0:
  2830         ui.write('\n')
  2877         ui.write(b'\n')
  2831         fmt = pcfmtstr(numdeltas)
  2878         fmt = pcfmtstr(numdeltas)
  2832         fmt2 = pcfmtstr(numdeltas, 4)
  2879         fmt2 = pcfmtstr(numdeltas, 4)
  2833         ui.write('deltas against prev  : ' + fmt % pcfmt(numprev, numdeltas))
  2880         ui.write(b'deltas against prev  : ' + fmt % pcfmt(numprev, numdeltas))
  2834         if numprev > 0:
  2881         if numprev > 0:
  2835             ui.write(
  2882             ui.write(
  2836                 '    where prev = p1  : ' + fmt2 % pcfmt(nump1prev, numprev)
  2883                 b'    where prev = p1  : ' + fmt2 % pcfmt(nump1prev, numprev)
  2837             )
  2884             )
  2838             ui.write(
  2885             ui.write(
  2839                 '    where prev = p2  : ' + fmt2 % pcfmt(nump2prev, numprev)
  2886                 b'    where prev = p2  : ' + fmt2 % pcfmt(nump2prev, numprev)
  2840             )
  2887             )
  2841             ui.write(
  2888             ui.write(
  2842                 '    other            : ' + fmt2 % pcfmt(numoprev, numprev)
  2889                 b'    other            : ' + fmt2 % pcfmt(numoprev, numprev)
  2843             )
  2890             )
  2844         if gdelta:
  2891         if gdelta:
  2845             ui.write('deltas against p1    : ' + fmt % pcfmt(nump1, numdeltas))
  2892             ui.write(b'deltas against p1    : ' + fmt % pcfmt(nump1, numdeltas))
  2846             ui.write('deltas against p2    : ' + fmt % pcfmt(nump2, numdeltas))
  2893             ui.write(b'deltas against p2    : ' + fmt % pcfmt(nump2, numdeltas))
  2847             ui.write(
  2894             ui.write(
  2848                 'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
  2895                 b'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
  2849             )
  2896             )
  2850 
  2897 
  2851 
  2898 
  2852 @command(
  2899 @command(
  2853     'debugrevlogindex',
  2900     b'debugrevlogindex',
  2854     cmdutil.debugrevlogopts
  2901     cmdutil.debugrevlogopts
  2855     + [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
  2902     + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
  2856     _('[-f FORMAT] -c|-m|FILE'),
  2903     _(b'[-f FORMAT] -c|-m|FILE'),
  2857     optionalrepo=True,
  2904     optionalrepo=True,
  2858 )
  2905 )
  2859 def debugrevlogindex(ui, repo, file_=None, **opts):
  2906 def debugrevlogindex(ui, repo, file_=None, **opts):
  2860     """dump the contents of a revlog index"""
  2907     """dump the contents of a revlog index"""
  2861     opts = pycompat.byteskwargs(opts)
  2908     opts = pycompat.byteskwargs(opts)
  2862     r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts)
  2909     r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
  2863     format = opts.get('format', 0)
  2910     format = opts.get(b'format', 0)
  2864     if format not in (0, 1):
  2911     if format not in (0, 1):
  2865         raise error.Abort(_("unknown format %d") % format)
  2912         raise error.Abort(_(b"unknown format %d") % format)
  2866 
  2913 
  2867     if ui.debugflag:
  2914     if ui.debugflag:
  2868         shortfn = hex
  2915         shortfn = hex
  2869     else:
  2916     else:
  2870         shortfn = short
  2917         shortfn = short
  2876         break
  2923         break
  2877 
  2924 
  2878     if format == 0:
  2925     if format == 0:
  2879         if ui.verbose:
  2926         if ui.verbose:
  2880             ui.write(
  2927             ui.write(
  2881                 ("   rev    offset  length linkrev" " %s %s p2\n")
  2928                 (b"   rev    offset  length linkrev" b" %s %s p2\n")
  2882                 % ("nodeid".ljust(idlen), "p1".ljust(idlen))
  2929                 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
  2883             )
  2930             )
  2884         else:
  2931         else:
  2885             ui.write(
  2932             ui.write(
  2886                 "   rev linkrev %s %s p2\n"
  2933                 b"   rev linkrev %s %s p2\n"
  2887                 % ("nodeid".ljust(idlen), "p1".ljust(idlen))
  2934                 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
  2888             )
  2935             )
  2889     elif format == 1:
  2936     elif format == 1:
  2890         if ui.verbose:
  2937         if ui.verbose:
  2891             ui.write(
  2938             ui.write(
  2892                 (
  2939                 (
  2893                     "   rev flag   offset   length     size   link     p1"
  2940                     b"   rev flag   offset   length     size   link     p1"
  2894                     "     p2 %s\n"
  2941                     b"     p2 %s\n"
  2895                 )
  2942                 )
  2896                 % "nodeid".rjust(idlen)
  2943                 % b"nodeid".rjust(idlen)
  2897             )
  2944             )
  2898         else:
  2945         else:
  2899             ui.write(
  2946             ui.write(
  2900                 "   rev flag     size   link     p1     p2 %s\n"
  2947                 b"   rev flag     size   link     p1     p2 %s\n"
  2901                 % "nodeid".rjust(idlen)
  2948                 % b"nodeid".rjust(idlen)
  2902             )
  2949             )
  2903 
  2950 
  2904     for i in r:
  2951     for i in r:
  2905         node = r.node(i)
  2952         node = r.node(i)
  2906         if format == 0:
  2953         if format == 0:
  2908                 pp = r.parents(node)
  2955                 pp = r.parents(node)
  2909             except Exception:
  2956             except Exception:
  2910                 pp = [nullid, nullid]
  2957                 pp = [nullid, nullid]
  2911             if ui.verbose:
  2958             if ui.verbose:
  2912                 ui.write(
  2959                 ui.write(
  2913                     "% 6d % 9d % 7d % 7d %s %s %s\n"
  2960                     b"% 6d % 9d % 7d % 7d %s %s %s\n"
  2914                     % (
  2961                     % (
  2915                         i,
  2962                         i,
  2916                         r.start(i),
  2963                         r.start(i),
  2917                         r.length(i),
  2964                         r.length(i),
  2918                         r.linkrev(i),
  2965                         r.linkrev(i),
  2921                         shortfn(pp[1]),
  2968                         shortfn(pp[1]),
  2922                     )
  2969                     )
  2923                 )
  2970                 )
  2924             else:
  2971             else:
  2925                 ui.write(
  2972                 ui.write(
  2926                     "% 6d % 7d %s %s %s\n"
  2973                     b"% 6d % 7d %s %s %s\n"
  2927                     % (
  2974                     % (
  2928                         i,
  2975                         i,
  2929                         r.linkrev(i),
  2976                         r.linkrev(i),
  2930                         shortfn(node),
  2977                         shortfn(node),
  2931                         shortfn(pp[0]),
  2978                         shortfn(pp[0]),
  2934                 )
  2981                 )
  2935         elif format == 1:
  2982         elif format == 1:
  2936             pr = r.parentrevs(i)
  2983             pr = r.parentrevs(i)
  2937             if ui.verbose:
  2984             if ui.verbose:
  2938                 ui.write(
  2985                 ui.write(
  2939                     "% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
  2986                     b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
  2940                     % (
  2987                     % (
  2941                         i,
  2988                         i,
  2942                         r.flags(i),
  2989                         r.flags(i),
  2943                         r.start(i),
  2990                         r.start(i),
  2944                         r.length(i),
  2991                         r.length(i),
  2949                         shortfn(node),
  2996                         shortfn(node),
  2950                     )
  2997                     )
  2951                 )
  2998                 )
  2952             else:
  2999             else:
  2953                 ui.write(
  3000                 ui.write(
  2954                     "% 6d %04x % 8d % 6d % 6d % 6d %s\n"
  3001                     b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
  2955                     % (
  3002                     % (
  2956                         i,
  3003                         i,
  2957                         r.flags(i),
  3004                         r.flags(i),
  2958                         r.rawsize(i),
  3005                         r.rawsize(i),
  2959                         r.linkrev(i),
  3006                         r.linkrev(i),
  2963                     )
  3010                     )
  2964                 )
  3011                 )
  2965 
  3012 
  2966 
  3013 
  2967 @command(
  3014 @command(
  2968     'debugrevspec',
  3015     b'debugrevspec',
  2969     [
  3016     [
  2970         (
  3017         (
  2971             '',
  3018             b'',
  2972             'optimize',
  3019             b'optimize',
  2973             None,
  3020             None,
  2974             _('print parsed tree after optimizing (DEPRECATED)'),
  3021             _(b'print parsed tree after optimizing (DEPRECATED)'),
  2975         ),
       
  2976         ('', 'show-revs', True, _('print list of result revisions (default)')),
       
  2977         (
       
  2978             's',
       
  2979             'show-set',
       
  2980             None,
       
  2981             _('print internal representation of result set'),
       
  2982         ),
  3022         ),
  2983         (
  3023         (
  2984             'p',
  3024             b'',
  2985             'show-stage',
  3025             b'show-revs',
       
  3026             True,
       
  3027             _(b'print list of result revisions (default)'),
       
  3028         ),
       
  3029         (
       
  3030             b's',
       
  3031             b'show-set',
       
  3032             None,
       
  3033             _(b'print internal representation of result set'),
       
  3034         ),
       
  3035         (
       
  3036             b'p',
       
  3037             b'show-stage',
  2986             [],
  3038             [],
  2987             _('print parsed tree at the given stage'),
  3039             _(b'print parsed tree at the given stage'),
  2988             _('NAME'),
  3040             _(b'NAME'),
  2989         ),
  3041         ),
  2990         ('', 'no-optimized', False, _('evaluate tree without optimization')),
  3042         (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
  2991         ('', 'verify-optimized', False, _('verify optimized result')),
  3043         (b'', b'verify-optimized', False, _(b'verify optimized result')),
  2992     ],
  3044     ],
  2993     'REVSPEC',
  3045     b'REVSPEC',
  2994 )
  3046 )
  2995 def debugrevspec(ui, repo, expr, **opts):
  3047 def debugrevspec(ui, repo, expr, **opts):
  2996     """parse and apply a revision specification
  3048     """parse and apply a revision specification
  2997 
  3049 
  2998     Use -p/--show-stage option to print the parsed tree at the given stages.
  3050     Use -p/--show-stage option to print the parsed tree at the given stages.
  3003 
  3055 
  3004     Use --verify-optimized to compare the optimized result with the unoptimized
  3056     Use --verify-optimized to compare the optimized result with the unoptimized
  3005     one. Returns 1 if the optimized result differs.
  3057     one. Returns 1 if the optimized result differs.
  3006     """
  3058     """
  3007     opts = pycompat.byteskwargs(opts)
  3059     opts = pycompat.byteskwargs(opts)
  3008     aliases = ui.configitems('revsetalias')
  3060     aliases = ui.configitems(b'revsetalias')
  3009     stages = [
  3061     stages = [
  3010         ('parsed', lambda tree: tree),
  3062         (b'parsed', lambda tree: tree),
  3011         (
  3063         (
  3012             'expanded',
  3064             b'expanded',
  3013             lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
  3065             lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
  3014         ),
  3066         ),
  3015         ('concatenated', revsetlang.foldconcat),
  3067         (b'concatenated', revsetlang.foldconcat),
  3016         ('analyzed', revsetlang.analyze),
  3068         (b'analyzed', revsetlang.analyze),
  3017         ('optimized', revsetlang.optimize),
  3069         (b'optimized', revsetlang.optimize),
  3018     ]
  3070     ]
  3019     if opts['no_optimized']:
  3071     if opts[b'no_optimized']:
  3020         stages = stages[:-1]
  3072         stages = stages[:-1]
  3021     if opts['verify_optimized'] and opts['no_optimized']:
  3073     if opts[b'verify_optimized'] and opts[b'no_optimized']:
  3022         raise error.Abort(
  3074         raise error.Abort(
  3023             _('cannot use --verify-optimized with ' '--no-optimized')
  3075             _(b'cannot use --verify-optimized with ' b'--no-optimized')
  3024         )
  3076         )
  3025     stagenames = set(n for n, f in stages)
  3077     stagenames = set(n for n, f in stages)
  3026 
  3078 
  3027     showalways = set()
  3079     showalways = set()
  3028     showchanged = set()
  3080     showchanged = set()
  3029     if ui.verbose and not opts['show_stage']:
  3081     if ui.verbose and not opts[b'show_stage']:
  3030         # show parsed tree by --verbose (deprecated)
  3082         # show parsed tree by --verbose (deprecated)
  3031         showalways.add('parsed')
  3083         showalways.add(b'parsed')
  3032         showchanged.update(['expanded', 'concatenated'])
  3084         showchanged.update([b'expanded', b'concatenated'])
  3033         if opts['optimize']:
  3085         if opts[b'optimize']:
  3034             showalways.add('optimized')
  3086             showalways.add(b'optimized')
  3035     if opts['show_stage'] and opts['optimize']:
  3087     if opts[b'show_stage'] and opts[b'optimize']:
  3036         raise error.Abort(_('cannot use --optimize with --show-stage'))
  3088         raise error.Abort(_(b'cannot use --optimize with --show-stage'))
  3037     if opts['show_stage'] == ['all']:
  3089     if opts[b'show_stage'] == [b'all']:
  3038         showalways.update(stagenames)
  3090         showalways.update(stagenames)
  3039     else:
  3091     else:
  3040         for n in opts['show_stage']:
  3092         for n in opts[b'show_stage']:
  3041             if n not in stagenames:
  3093             if n not in stagenames:
  3042                 raise error.Abort(_('invalid stage name: %s') % n)
  3094                 raise error.Abort(_(b'invalid stage name: %s') % n)
  3043         showalways.update(opts['show_stage'])
  3095         showalways.update(opts[b'show_stage'])
  3044 
  3096 
  3045     treebystage = {}
  3097     treebystage = {}
  3046     printedtree = None
  3098     printedtree = None
  3047     tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
  3099     tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
  3048     for n, f in stages:
  3100     for n, f in stages:
  3049         treebystage[n] = tree = f(tree)
  3101         treebystage[n] = tree = f(tree)
  3050         if n in showalways or (n in showchanged and tree != printedtree):
  3102         if n in showalways or (n in showchanged and tree != printedtree):
  3051             if opts['show_stage'] or n != 'parsed':
  3103             if opts[b'show_stage'] or n != b'parsed':
  3052                 ui.write("* %s:\n" % n)
  3104                 ui.write(b"* %s:\n" % n)
  3053             ui.write(revsetlang.prettyformat(tree), "\n")
  3105             ui.write(revsetlang.prettyformat(tree), b"\n")
  3054             printedtree = tree
  3106             printedtree = tree
  3055 
  3107 
  3056     if opts['verify_optimized']:
  3108     if opts[b'verify_optimized']:
  3057         arevs = revset.makematcher(treebystage['analyzed'])(repo)
  3109         arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
  3058         brevs = revset.makematcher(treebystage['optimized'])(repo)
  3110         brevs = revset.makematcher(treebystage[b'optimized'])(repo)
  3059         if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
  3111         if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
  3060             ui.write("* analyzed set:\n", stringutil.prettyrepr(arevs), "\n")
  3112             ui.write(b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n")
  3061             ui.write("* optimized set:\n", stringutil.prettyrepr(brevs), "\n")
  3113             ui.write(b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n")
  3062         arevs = list(arevs)
  3114         arevs = list(arevs)
  3063         brevs = list(brevs)
  3115         brevs = list(brevs)
  3064         if arevs == brevs:
  3116         if arevs == brevs:
  3065             return 0
  3117             return 0
  3066         ui.write('--- analyzed\n', label='diff.file_a')
  3118         ui.write(b'--- analyzed\n', label=b'diff.file_a')
  3067         ui.write('+++ optimized\n', label='diff.file_b')
  3119         ui.write(b'+++ optimized\n', label=b'diff.file_b')
  3068         sm = difflib.SequenceMatcher(None, arevs, brevs)
  3120         sm = difflib.SequenceMatcher(None, arevs, brevs)
  3069         for tag, alo, ahi, blo, bhi in sm.get_opcodes():
  3121         for tag, alo, ahi, blo, bhi in sm.get_opcodes():
  3070             if tag in (r'delete', r'replace'):
  3122             if tag in (r'delete', r'replace'):
  3071                 for c in arevs[alo:ahi]:
  3123                 for c in arevs[alo:ahi]:
  3072                     ui.write('-%d\n' % c, label='diff.deleted')
  3124                     ui.write(b'-%d\n' % c, label=b'diff.deleted')
  3073             if tag in (r'insert', r'replace'):
  3125             if tag in (r'insert', r'replace'):
  3074                 for c in brevs[blo:bhi]:
  3126                 for c in brevs[blo:bhi]:
  3075                     ui.write('+%d\n' % c, label='diff.inserted')
  3127                     ui.write(b'+%d\n' % c, label=b'diff.inserted')
  3076             if tag == r'equal':
  3128             if tag == r'equal':
  3077                 for c in arevs[alo:ahi]:
  3129                 for c in arevs[alo:ahi]:
  3078                     ui.write(' %d\n' % c)
  3130                     ui.write(b' %d\n' % c)
  3079         return 1
  3131         return 1
  3080 
  3132 
  3081     func = revset.makematcher(tree)
  3133     func = revset.makematcher(tree)
  3082     revs = func(repo)
  3134     revs = func(repo)
  3083     if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
  3135     if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
  3084         ui.write("* set:\n", stringutil.prettyrepr(revs), "\n")
  3136         ui.write(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
  3085     if not opts['show_revs']:
  3137     if not opts[b'show_revs']:
  3086         return
  3138         return
  3087     for c in revs:
  3139     for c in revs:
  3088         ui.write("%d\n" % c)
  3140         ui.write(b"%d\n" % c)
  3089 
  3141 
  3090 
  3142 
  3091 @command(
  3143 @command(
  3092     'debugserve',
  3144     b'debugserve',
  3093     [
  3145     [
  3094         (
  3146         (
  3095             '',
  3147             b'',
  3096             'sshstdio',
  3148             b'sshstdio',
  3097             False,
  3149             False,
  3098             _('run an SSH server bound to process handles'),
  3150             _(b'run an SSH server bound to process handles'),
  3099         ),
  3151         ),
  3100         ('', 'logiofd', '', _('file descriptor to log server I/O to')),
  3152         (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
  3101         ('', 'logiofile', '', _('file to log server I/O to')),
  3153         (b'', b'logiofile', b'', _(b'file to log server I/O to')),
  3102     ],
  3154     ],
  3103     '',
  3155     b'',
  3104 )
  3156 )
  3105 def debugserve(ui, repo, **opts):
  3157 def debugserve(ui, repo, **opts):
  3106     """run a server with advanced settings
  3158     """run a server with advanced settings
  3107 
  3159 
  3108     This command is similar to :hg:`serve`. It exists partially as a
  3160     This command is similar to :hg:`serve`. It exists partially as a
  3109     workaround to the fact that ``hg serve --stdio`` must have specific
  3161     workaround to the fact that ``hg serve --stdio`` must have specific
  3110     arguments for security reasons.
  3162     arguments for security reasons.
  3111     """
  3163     """
  3112     opts = pycompat.byteskwargs(opts)
  3164     opts = pycompat.byteskwargs(opts)
  3113 
  3165 
  3114     if not opts['sshstdio']:
  3166     if not opts[b'sshstdio']:
  3115         raise error.Abort(_('only --sshstdio is currently supported'))
  3167         raise error.Abort(_(b'only --sshstdio is currently supported'))
  3116 
  3168 
  3117     logfh = None
  3169     logfh = None
  3118 
  3170 
  3119     if opts['logiofd'] and opts['logiofile']:
  3171     if opts[b'logiofd'] and opts[b'logiofile']:
  3120         raise error.Abort(_('cannot use both --logiofd and --logiofile'))
  3172         raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
  3121 
  3173 
  3122     if opts['logiofd']:
  3174     if opts[b'logiofd']:
  3123         # Line buffered because output is line based.
  3175         # Line buffered because output is line based.
  3124         try:
  3176         try:
  3125             logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
  3177             logfh = os.fdopen(int(opts[b'logiofd']), r'ab', 1)
  3126         except OSError as e:
  3178         except OSError as e:
  3127             if e.errno != errno.ESPIPE:
  3179             if e.errno != errno.ESPIPE:
  3128                 raise
  3180                 raise
  3129             # can't seek a pipe, so `ab` mode fails on py3
  3181             # can't seek a pipe, so `ab` mode fails on py3
  3130             logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
  3182             logfh = os.fdopen(int(opts[b'logiofd']), r'wb', 1)
  3131     elif opts['logiofile']:
  3183     elif opts[b'logiofile']:
  3132         logfh = open(opts['logiofile'], 'ab', 1)
  3184         logfh = open(opts[b'logiofile'], b'ab', 1)
  3133 
  3185 
  3134     s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
  3186     s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
  3135     s.serve_forever()
  3187     s.serve_forever()
  3136 
  3188 
  3137 
  3189 
  3138 @command('debugsetparents', [], _('REV1 [REV2]'))
  3190 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
  3139 def debugsetparents(ui, repo, rev1, rev2=None):
  3191 def debugsetparents(ui, repo, rev1, rev2=None):
  3140     """manually set the parents of the current working directory
  3192     """manually set the parents of the current working directory
  3141 
  3193 
  3142     This is useful for writing repository conversion tools, but should
  3194     This is useful for writing repository conversion tools, but should
  3143     be used with care. For example, neither the working directory nor the
  3195     be used with care. For example, neither the working directory nor the
  3146 
  3198 
  3147     Returns 0 on success.
  3199     Returns 0 on success.
  3148     """
  3200     """
  3149 
  3201 
  3150     node1 = scmutil.revsingle(repo, rev1).node()
  3202     node1 = scmutil.revsingle(repo, rev1).node()
  3151     node2 = scmutil.revsingle(repo, rev2, 'null').node()
  3203     node2 = scmutil.revsingle(repo, rev2, b'null').node()
  3152 
  3204 
  3153     with repo.wlock():
  3205     with repo.wlock():
  3154         repo.setparents(node1, node2)
  3206         repo.setparents(node1, node2)
  3155 
  3207 
  3156 
  3208 
  3157 @command('debugsidedata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
  3209 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
  3158 def debugsidedata(ui, repo, file_, rev=None, **opts):
  3210 def debugsidedata(ui, repo, file_, rev=None, **opts):
  3159     """dump the side data for a cl/manifest/file revision"""
  3211     """dump the side data for a cl/manifest/file revision"""
  3160     opts = pycompat.byteskwargs(opts)
  3212     opts = pycompat.byteskwargs(opts)
  3161     if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
  3213     if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
  3162         if rev is not None:
  3214         if rev is not None:
  3163             raise error.CommandError('debugdata', _('invalid arguments'))
  3215             raise error.CommandError(b'debugdata', _(b'invalid arguments'))
  3164         file_, rev = None, file_
  3216         file_, rev = None, file_
  3165     elif rev is None:
  3217     elif rev is None:
  3166         raise error.CommandError('debugdata', _('invalid arguments'))
  3218         raise error.CommandError(b'debugdata', _(b'invalid arguments'))
  3167     r = cmdutil.openstorage(repo, 'debugdata', file_, opts)
  3219     r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
  3168     r = getattr(r, '_revlog', r)
  3220     r = getattr(r, '_revlog', r)
  3169     try:
  3221     try:
  3170         sidedata = r.sidedata(r.lookup(rev))
  3222         sidedata = r.sidedata(r.lookup(rev))
  3171     except KeyError:
  3223     except KeyError:
  3172         raise error.Abort(_('invalid revision identifier %s') % rev)
  3224         raise error.Abort(_(b'invalid revision identifier %s') % rev)
  3173     if sidedata:
  3225     if sidedata:
  3174         sidedata = list(sidedata.items())
  3226         sidedata = list(sidedata.items())
  3175         sidedata.sort()
  3227         sidedata.sort()
  3176         ui.write(('%d sidedata entries\n' % len(sidedata)))
  3228         ui.write((b'%d sidedata entries\n' % len(sidedata)))
  3177         for key, value in sidedata:
  3229         for key, value in sidedata:
  3178             ui.write((' entry-%04o size %d\n' % (key, len(value))))
  3230             ui.write((b' entry-%04o size %d\n' % (key, len(value))))
  3179             if ui.verbose:
  3231             if ui.verbose:
  3180                 ui.write(('  %s\n' % stringutil.pprint(value)))
  3232                 ui.write((b'  %s\n' % stringutil.pprint(value)))
  3181 
  3233 
  3182 
  3234 
  3183 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
  3235 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
  3184 def debugssl(ui, repo, source=None, **opts):
  3236 def debugssl(ui, repo, source=None, **opts):
  3185     '''test a secure connection to a server
  3237     '''test a secure connection to a server
  3186 
  3238 
  3187     This builds the certificate chain for the server on Windows, installing the
  3239     This builds the certificate chain for the server on Windows, installing the
  3188     missing intermediates and trusted root via Windows Update if necessary.  It
  3240     missing intermediates and trusted root via Windows Update if necessary.  It
  3194     If the update succeeds, retry the original operation.  Otherwise, the cause
  3246     If the update succeeds, retry the original operation.  Otherwise, the cause
  3195     of the SSL error is likely another issue.
  3247     of the SSL error is likely another issue.
  3196     '''
  3248     '''
  3197     if not pycompat.iswindows:
  3249     if not pycompat.iswindows:
  3198         raise error.Abort(
  3250         raise error.Abort(
  3199             _('certificate chain building is only possible on ' 'Windows')
  3251             _(b'certificate chain building is only possible on ' b'Windows')
  3200         )
  3252         )
  3201 
  3253 
  3202     if not source:
  3254     if not source:
  3203         if not repo:
  3255         if not repo:
  3204             raise error.Abort(
  3256             raise error.Abort(
  3205                 _(
  3257                 _(
  3206                     "there is no Mercurial repository here, and no "
  3258                     b"there is no Mercurial repository here, and no "
  3207                     "server specified"
  3259                     b"server specified"
  3208                 )
  3260                 )
  3209             )
  3261             )
  3210         source = "default"
  3262         source = b"default"
  3211 
  3263 
  3212     source, branches = hg.parseurl(ui.expandpath(source))
  3264     source, branches = hg.parseurl(ui.expandpath(source))
  3213     url = util.url(source)
  3265     url = util.url(source)
  3214 
  3266 
  3215     defaultport = {'https': 443, 'ssh': 22}
  3267     defaultport = {b'https': 443, b'ssh': 22}
  3216     if url.scheme in defaultport:
  3268     if url.scheme in defaultport:
  3217         try:
  3269         try:
  3218             addr = (url.host, int(url.port or defaultport[url.scheme]))
  3270             addr = (url.host, int(url.port or defaultport[url.scheme]))
  3219         except ValueError:
  3271         except ValueError:
  3220             raise error.Abort(_("malformed port number in URL"))
  3272             raise error.Abort(_(b"malformed port number in URL"))
  3221     else:
  3273     else:
  3222         raise error.Abort(_("only https and ssh connections are supported"))
  3274         raise error.Abort(_(b"only https and ssh connections are supported"))
  3223 
  3275 
  3224     from . import win32
  3276     from . import win32
  3225 
  3277 
  3226     s = ssl.wrap_socket(
  3278     s = ssl.wrap_socket(
  3227         socket.socket(),
  3279         socket.socket(),
  3232 
  3284 
  3233     try:
  3285     try:
  3234         s.connect(addr)
  3286         s.connect(addr)
  3235         cert = s.getpeercert(True)
  3287         cert = s.getpeercert(True)
  3236 
  3288 
  3237         ui.status(_('checking the certificate chain for %s\n') % url.host)
  3289         ui.status(_(b'checking the certificate chain for %s\n') % url.host)
  3238 
  3290 
  3239         complete = win32.checkcertificatechain(cert, build=False)
  3291         complete = win32.checkcertificatechain(cert, build=False)
  3240 
  3292 
  3241         if not complete:
  3293         if not complete:
  3242             ui.status(_('certificate chain is incomplete, updating... '))
  3294             ui.status(_(b'certificate chain is incomplete, updating... '))
  3243 
  3295 
  3244             if not win32.checkcertificatechain(cert):
  3296             if not win32.checkcertificatechain(cert):
  3245                 ui.status(_('failed.\n'))
  3297                 ui.status(_(b'failed.\n'))
  3246             else:
  3298             else:
  3247                 ui.status(_('done.\n'))
  3299                 ui.status(_(b'done.\n'))
  3248         else:
  3300         else:
  3249             ui.status(_('full certificate chain is available\n'))
  3301             ui.status(_(b'full certificate chain is available\n'))
  3250     finally:
  3302     finally:
  3251         s.close()
  3303         s.close()
  3252 
  3304 
  3253 
  3305 
  3254 @command(
  3306 @command(
  3255     'debugsub',
  3307     b'debugsub',
  3256     [('r', 'rev', '', _('revision to check'), _('REV'))],
  3308     [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
  3257     _('[-r REV] [REV]'),
  3309     _(b'[-r REV] [REV]'),
  3258 )
  3310 )
  3259 def debugsub(ui, repo, rev=None):
  3311 def debugsub(ui, repo, rev=None):
  3260     ctx = scmutil.revsingle(repo, rev, None)
  3312     ctx = scmutil.revsingle(repo, rev, None)
  3261     for k, v in sorted(ctx.substate.items()):
  3313     for k, v in sorted(ctx.substate.items()):
  3262         ui.write('path %s\n' % k)
  3314         ui.write(b'path %s\n' % k)
  3263         ui.write(' source   %s\n' % v[0])
  3315         ui.write(b' source   %s\n' % v[0])
  3264         ui.write(' revision %s\n' % v[1])
  3316         ui.write(b' revision %s\n' % v[1])
  3265 
  3317 
  3266 
  3318 
  3267 @command(
  3319 @command(
  3268     'debugsuccessorssets',
  3320     b'debugsuccessorssets',
  3269     [('', 'closest', False, _('return closest successors sets only'))],
  3321     [(b'', b'closest', False, _(b'return closest successors sets only'))],
  3270     _('[REV]'),
  3322     _(b'[REV]'),
  3271 )
  3323 )
  3272 def debugsuccessorssets(ui, repo, *revs, **opts):
  3324 def debugsuccessorssets(ui, repo, *revs, **opts):
  3273     """show set of successors for revision
  3325     """show set of successors for revision
  3274 
  3326 
  3275     A successors set of changeset A is a consistent group of revisions that
  3327     A successors set of changeset A is a consistent group of revisions that
  3305     cache = {}
  3357     cache = {}
  3306     ctx2str = bytes
  3358     ctx2str = bytes
  3307     node2str = short
  3359     node2str = short
  3308     for rev in scmutil.revrange(repo, revs):
  3360     for rev in scmutil.revrange(repo, revs):
  3309         ctx = repo[rev]
  3361         ctx = repo[rev]
  3310         ui.write('%s\n' % ctx2str(ctx))
  3362         ui.write(b'%s\n' % ctx2str(ctx))
  3311         for succsset in obsutil.successorssets(
  3363         for succsset in obsutil.successorssets(
  3312             repo, ctx.node(), closest=opts[r'closest'], cache=cache
  3364             repo, ctx.node(), closest=opts[r'closest'], cache=cache
  3313         ):
  3365         ):
  3314             if succsset:
  3366             if succsset:
  3315                 ui.write('    ')
  3367                 ui.write(b'    ')
  3316                 ui.write(node2str(succsset[0]))
  3368                 ui.write(node2str(succsset[0]))
  3317                 for node in succsset[1:]:
  3369                 for node in succsset[1:]:
  3318                     ui.write(' ')
  3370                     ui.write(b' ')
  3319                     ui.write(node2str(node))
  3371                     ui.write(node2str(node))
  3320             ui.write('\n')
  3372             ui.write(b'\n')
  3321 
  3373 
  3322 
  3374 
  3323 @command(
  3375 @command(
  3324     'debugtemplate',
  3376     b'debugtemplate',
  3325     [
  3377     [
  3326         ('r', 'rev', [], _('apply template on changesets'), _('REV')),
  3378         (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
  3327         ('D', 'define', [], _('define template keyword'), _('KEY=VALUE')),
  3379         (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
  3328     ],
  3380     ],
  3329     _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
  3381     _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
  3330     optionalrepo=True,
  3382     optionalrepo=True,
  3331 )
  3383 )
  3332 def debugtemplate(ui, repo, tmpl, **opts):
  3384 def debugtemplate(ui, repo, tmpl, **opts):
  3333     """parse and apply a template
  3385     """parse and apply a template
  3334 
  3386 
  3340     """
  3392     """
  3341     revs = None
  3393     revs = None
  3342     if opts[r'rev']:
  3394     if opts[r'rev']:
  3343         if repo is None:
  3395         if repo is None:
  3344             raise error.RepoError(
  3396             raise error.RepoError(
  3345                 _('there is no Mercurial repository here ' '(.hg not found)')
  3397                 _(b'there is no Mercurial repository here ' b'(.hg not found)')
  3346             )
  3398             )
  3347         revs = scmutil.revrange(repo, opts[r'rev'])
  3399         revs = scmutil.revrange(repo, opts[r'rev'])
  3348 
  3400 
  3349     props = {}
  3401     props = {}
  3350     for d in opts[r'define']:
  3402     for d in opts[r'define']:
  3351         try:
  3403         try:
  3352             k, v = (e.strip() for e in d.split('=', 1))
  3404             k, v = (e.strip() for e in d.split(b'=', 1))
  3353             if not k or k == 'ui':
  3405             if not k or k == b'ui':
  3354                 raise ValueError
  3406                 raise ValueError
  3355             props[k] = v
  3407             props[k] = v
  3356         except ValueError:
  3408         except ValueError:
  3357             raise error.Abort(_('malformed keyword definition: %s') % d)
  3409             raise error.Abort(_(b'malformed keyword definition: %s') % d)
  3358 
  3410 
  3359     if ui.verbose:
  3411     if ui.verbose:
  3360         aliases = ui.configitems('templatealias')
  3412         aliases = ui.configitems(b'templatealias')
  3361         tree = templater.parse(tmpl)
  3413         tree = templater.parse(tmpl)
  3362         ui.note(templater.prettyformat(tree), '\n')
  3414         ui.note(templater.prettyformat(tree), b'\n')
  3363         newtree = templater.expandaliases(tree, aliases)
  3415         newtree = templater.expandaliases(tree, aliases)
  3364         if newtree != tree:
  3416         if newtree != tree:
  3365             ui.note("* expanded:\n", templater.prettyformat(newtree), '\n')
  3417             ui.note(b"* expanded:\n", templater.prettyformat(newtree), b'\n')
  3366 
  3418 
  3367     if revs is None:
  3419     if revs is None:
  3368         tres = formatter.templateresources(ui, repo)
  3420         tres = formatter.templateresources(ui, repo)
  3369         t = formatter.maketemplater(ui, tmpl, resources=tres)
  3421         t = formatter.maketemplater(ui, tmpl, resources=tres)
  3370         if ui.verbose:
  3422         if ui.verbose:
  3371             kwds, funcs = t.symbolsuseddefault()
  3423             kwds, funcs = t.symbolsuseddefault()
  3372             ui.write("* keywords: %s\n" % ', '.join(sorted(kwds)))
  3424             ui.write(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
  3373             ui.write("* functions: %s\n" % ', '.join(sorted(funcs)))
  3425             ui.write(b"* functions: %s\n" % b', '.join(sorted(funcs)))
  3374         ui.write(t.renderdefault(props))
  3426         ui.write(t.renderdefault(props))
  3375     else:
  3427     else:
  3376         displayer = logcmdutil.maketemplater(ui, repo, tmpl)
  3428         displayer = logcmdutil.maketemplater(ui, repo, tmpl)
  3377         if ui.verbose:
  3429         if ui.verbose:
  3378             kwds, funcs = displayer.t.symbolsuseddefault()
  3430             kwds, funcs = displayer.t.symbolsuseddefault()
  3379             ui.write("* keywords: %s\n" % ', '.join(sorted(kwds)))
  3431             ui.write(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
  3380             ui.write("* functions: %s\n" % ', '.join(sorted(funcs)))
  3432             ui.write(b"* functions: %s\n" % b', '.join(sorted(funcs)))
  3381         for r in revs:
  3433         for r in revs:
  3382             displayer.show(repo[r], **pycompat.strkwargs(props))
  3434             displayer.show(repo[r], **pycompat.strkwargs(props))
  3383         displayer.close()
  3435         displayer.close()
  3384 
  3436 
  3385 
  3437 
  3386 @command(
  3438 @command(
  3387     'debuguigetpass',
  3439     b'debuguigetpass',
  3388     [('p', 'prompt', '', _('prompt text'), _('TEXT')),],
  3440     [(b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),],
  3389     _('[-p TEXT]'),
  3441     _(b'[-p TEXT]'),
  3390     norepo=True,
  3442     norepo=True,
  3391 )
  3443 )
  3392 def debuguigetpass(ui, prompt=''):
  3444 def debuguigetpass(ui, prompt=b''):
  3393     """show prompt to type password"""
  3445     """show prompt to type password"""
  3394     r = ui.getpass(prompt)
  3446     r = ui.getpass(prompt)
  3395     ui.write('respose: %s\n' % r)
  3447     ui.write(b'respose: %s\n' % r)
  3396 
  3448 
  3397 
  3449 
  3398 @command(
  3450 @command(
  3399     'debuguiprompt',
  3451     b'debuguiprompt',
  3400     [('p', 'prompt', '', _('prompt text'), _('TEXT')),],
  3452     [(b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),],
  3401     _('[-p TEXT]'),
  3453     _(b'[-p TEXT]'),
  3402     norepo=True,
  3454     norepo=True,
  3403 )
  3455 )
  3404 def debuguiprompt(ui, prompt=''):
  3456 def debuguiprompt(ui, prompt=b''):
  3405     """show plain prompt"""
  3457     """show plain prompt"""
  3406     r = ui.prompt(prompt)
  3458     r = ui.prompt(prompt)
  3407     ui.write('response: %s\n' % r)
  3459     ui.write(b'response: %s\n' % r)
  3408 
  3460 
  3409 
  3461 
  3410 @command('debugupdatecaches', [])
  3462 @command(b'debugupdatecaches', [])
  3411 def debugupdatecaches(ui, repo, *pats, **opts):
  3463 def debugupdatecaches(ui, repo, *pats, **opts):
  3412     """warm all known caches in the repository"""
  3464     """warm all known caches in the repository"""
  3413     with repo.wlock(), repo.lock():
  3465     with repo.wlock(), repo.lock():
  3414         repo.updatecaches(full=True)
  3466         repo.updatecaches(full=True)
  3415 
  3467 
  3416 
  3468 
  3417 @command(
  3469 @command(
  3418     'debugupgraderepo',
  3470     b'debugupgraderepo',
  3419     [
  3471     [
  3420         ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
  3472         (
  3421         ('', 'run', False, _('performs an upgrade')),
  3473             b'o',
  3422         ('', 'backup', True, _('keep the old repository content around')),
  3474             b'optimize',
  3423         ('', 'changelog', None, _('select the changelog for upgrade')),
  3475             [],
  3424         ('', 'manifest', None, _('select the manifest for upgrade')),
  3476             _(b'extra optimization to perform'),
       
  3477             _(b'NAME'),
       
  3478         ),
       
  3479         (b'', b'run', False, _(b'performs an upgrade')),
       
  3480         (b'', b'backup', True, _(b'keep the old repository content around')),
       
  3481         (b'', b'changelog', None, _(b'select the changelog for upgrade')),
       
  3482         (b'', b'manifest', None, _(b'select the manifest for upgrade')),
  3425     ],
  3483     ],
  3426 )
  3484 )
  3427 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
  3485 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
  3428     """upgrade a repository to use different features
  3486     """upgrade a repository to use different features
  3429 
  3487 
  3455         ui, repo, run=run, optimize=optimize, backup=backup, **opts
  3513         ui, repo, run=run, optimize=optimize, backup=backup, **opts
  3456     )
  3514     )
  3457 
  3515 
  3458 
  3516 
  3459 @command(
  3517 @command(
  3460     'debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'), inferrepo=True
  3518     b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
  3461 )
  3519 )
  3462 def debugwalk(ui, repo, *pats, **opts):
  3520 def debugwalk(ui, repo, *pats, **opts):
  3463     """show how files match on given patterns"""
  3521     """show how files match on given patterns"""
  3464     opts = pycompat.byteskwargs(opts)
  3522     opts = pycompat.byteskwargs(opts)
  3465     m = scmutil.match(repo[None], pats, opts)
  3523     m = scmutil.match(repo[None], pats, opts)
  3466     if ui.verbose:
  3524     if ui.verbose:
  3467         ui.write('* matcher:\n', stringutil.prettyrepr(m), '\n')
  3525         ui.write(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
  3468     items = list(repo[None].walk(m))
  3526     items = list(repo[None].walk(m))
  3469     if not items:
  3527     if not items:
  3470         return
  3528         return
  3471     f = lambda fn: fn
  3529     f = lambda fn: fn
  3472     if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
  3530     if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
  3473         f = lambda fn: util.normpath(fn)
  3531         f = lambda fn: util.normpath(fn)
  3474     fmt = 'f  %%-%ds  %%-%ds  %%s' % (
  3532     fmt = b'f  %%-%ds  %%-%ds  %%s' % (
  3475         max([len(abs) for abs in items]),
  3533         max([len(abs) for abs in items]),
  3476         max([len(repo.pathto(abs)) for abs in items]),
  3534         max([len(repo.pathto(abs)) for abs in items]),
  3477     )
  3535     )
  3478     for abs in items:
  3536     for abs in items:
  3479         line = fmt % (abs, f(repo.pathto(abs)), m.exact(abs) and 'exact' or '')
  3537         line = fmt % (
  3480         ui.write("%s\n" % line.rstrip())
  3538             abs,
  3481 
  3539             f(repo.pathto(abs)),
  3482 
  3540             m.exact(abs) and b'exact' or b'',
  3483 @command('debugwhyunstable', [], _('REV'))
  3541         )
       
  3542         ui.write(b"%s\n" % line.rstrip())
       
  3543 
       
  3544 
       
  3545 @command(b'debugwhyunstable', [], _(b'REV'))
  3484 def debugwhyunstable(ui, repo, rev):
  3546 def debugwhyunstable(ui, repo, rev):
  3485     """explain instabilities of a changeset"""
  3547     """explain instabilities of a changeset"""
  3486     for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
  3548     for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
  3487         dnodes = ''
  3549         dnodes = b''
  3488         if entry.get('divergentnodes'):
  3550         if entry.get(b'divergentnodes'):
  3489             dnodes = (
  3551             dnodes = (
  3490                 ' '.join(
  3552                 b' '.join(
  3491                     '%s (%s)' % (ctx.hex(), ctx.phasestr())
  3553                     b'%s (%s)' % (ctx.hex(), ctx.phasestr())
  3492                     for ctx in entry['divergentnodes']
  3554                     for ctx in entry[b'divergentnodes']
  3493                 )
  3555                 )
  3494                 + ' '
  3556                 + b' '
  3495             )
  3557             )
  3496         ui.write(
  3558         ui.write(
  3497             '%s: %s%s %s\n'
  3559             b'%s: %s%s %s\n'
  3498             % (entry['instability'], dnodes, entry['reason'], entry['node'])
  3560             % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
  3499         )
  3561         )
  3500 
  3562 
  3501 
  3563 
  3502 @command(
  3564 @command(
  3503     'debugwireargs',
  3565     b'debugwireargs',
  3504     [
  3566     [
  3505         ('', 'three', '', 'three'),
  3567         (b'', b'three', b'', b'three'),
  3506         ('', 'four', '', 'four'),
  3568         (b'', b'four', b'', b'four'),
  3507         ('', 'five', '', 'five'),
  3569         (b'', b'five', b'', b'five'),
  3508     ]
  3570     ]
  3509     + cmdutil.remoteopts,
  3571     + cmdutil.remoteopts,
  3510     _('REPO [OPTIONS]... [ONE [TWO]]'),
  3572     _(b'REPO [OPTIONS]... [ONE [TWO]]'),
  3511     norepo=True,
  3573     norepo=True,
  3512 )
  3574 )
  3513 def debugwireargs(ui, repopath, *vals, **opts):
  3575 def debugwireargs(ui, repopath, *vals, **opts):
  3514     opts = pycompat.byteskwargs(opts)
  3576     opts = pycompat.byteskwargs(opts)
  3515     repo = hg.peer(ui, opts, repopath)
  3577     repo = hg.peer(ui, opts, repopath)
  3521             args[k] = v
  3583             args[k] = v
  3522     args = pycompat.strkwargs(args)
  3584     args = pycompat.strkwargs(args)
  3523     # run twice to check that we don't mess up the stream for the next command
  3585     # run twice to check that we don't mess up the stream for the next command
  3524     res1 = repo.debugwireargs(*vals, **args)
  3586     res1 = repo.debugwireargs(*vals, **args)
  3525     res2 = repo.debugwireargs(*vals, **args)
  3587     res2 = repo.debugwireargs(*vals, **args)
  3526     ui.write("%s\n" % res1)
  3588     ui.write(b"%s\n" % res1)
  3527     if res1 != res2:
  3589     if res1 != res2:
  3528         ui.warn("%s\n" % res2)
  3590         ui.warn(b"%s\n" % res2)
  3529 
  3591 
  3530 
  3592 
  3531 def _parsewirelangblocks(fh):
  3593 def _parsewirelangblocks(fh):
  3532     activeaction = None
  3594     activeaction = None
  3533     blocklines = []
  3595     blocklines = []
  3552             continue
  3614             continue
  3553 
  3615 
  3554         # Else we start with an indent.
  3616         # Else we start with an indent.
  3555 
  3617 
  3556         if not activeaction:
  3618         if not activeaction:
  3557             raise error.Abort(_('indented line outside of block'))
  3619             raise error.Abort(_(b'indented line outside of block'))
  3558 
  3620 
  3559         indent = len(line) - len(line.lstrip())
  3621         indent = len(line) - len(line.lstrip())
  3560 
  3622 
  3561         # If this line is indented more than the last line, concatenate it.
  3623         # If this line is indented more than the last line, concatenate it.
  3562         if indent > lastindent and blocklines:
  3624         if indent > lastindent and blocklines:
  3569     if activeaction:
  3631     if activeaction:
  3570         yield activeaction, blocklines
  3632         yield activeaction, blocklines
  3571 
  3633 
  3572 
  3634 
  3573 @command(
  3635 @command(
  3574     'debugwireproto',
  3636     b'debugwireproto',
  3575     [
  3637     [
  3576         ('', 'localssh', False, _('start an SSH server for this repo')),
  3638         (b'', b'localssh', False, _(b'start an SSH server for this repo')),
  3577         ('', 'peer', '', _('construct a specific version of the peer')),
  3639         (b'', b'peer', b'', _(b'construct a specific version of the peer')),
  3578         ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
       
  3579         (
  3640         (
  3580             '',
  3641             b'',
  3581             'nologhandshake',
  3642             b'noreadstderr',
  3582             False,
  3643             False,
  3583             _('do not log I/O related to the peer handshake'),
  3644             _(b'do not read from stderr of the remote'),
       
  3645         ),
       
  3646         (
       
  3647             b'',
       
  3648             b'nologhandshake',
       
  3649             False,
       
  3650             _(b'do not log I/O related to the peer handshake'),
  3584         ),
  3651         ),
  3585     ]
  3652     ]
  3586     + cmdutil.remoteopts,
  3653     + cmdutil.remoteopts,
  3587     _('[PATH]'),
  3654     _(b'[PATH]'),
  3588     optionalrepo=True,
  3655     optionalrepo=True,
  3589 )
  3656 )
  3590 def debugwireproto(ui, repo, path=None, **opts):
  3657 def debugwireproto(ui, repo, path=None, **opts):
  3591     """send wire protocol commands to a server
  3658     """send wire protocol commands to a server
  3592 
  3659 
  3768     resulting object is fed into a CBOR encoder. Otherwise it is interpreted
  3835     resulting object is fed into a CBOR encoder. Otherwise it is interpreted
  3769     as a Python byte string literal.
  3836     as a Python byte string literal.
  3770     """
  3837     """
  3771     opts = pycompat.byteskwargs(opts)
  3838     opts = pycompat.byteskwargs(opts)
  3772 
  3839 
  3773     if opts['localssh'] and not repo:
  3840     if opts[b'localssh'] and not repo:
  3774         raise error.Abort(_('--localssh requires a repository'))
  3841         raise error.Abort(_(b'--localssh requires a repository'))
  3775 
  3842 
  3776     if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
  3843     if opts[b'peer'] and opts[b'peer'] not in (
       
  3844         b'raw',
       
  3845         b'http2',
       
  3846         b'ssh1',
       
  3847         b'ssh2',
       
  3848     ):
  3777         raise error.Abort(
  3849         raise error.Abort(
  3778             _('invalid value for --peer'),
  3850             _(b'invalid value for --peer'),
  3779             hint=_('valid values are "raw", "ssh1", and "ssh2"'),
  3851             hint=_(b'valid values are "raw", "ssh1", and "ssh2"'),
  3780         )
  3852         )
  3781 
  3853 
  3782     if path and opts['localssh']:
  3854     if path and opts[b'localssh']:
  3783         raise error.Abort(
  3855         raise error.Abort(
  3784             _('cannot specify --localssh with an explicit ' 'path')
  3856             _(b'cannot specify --localssh with an explicit ' b'path')
  3785         )
  3857         )
  3786 
  3858 
  3787     if ui.interactive():
  3859     if ui.interactive():
  3788         ui.write(_('(waiting for commands on stdin)\n'))
  3860         ui.write(_(b'(waiting for commands on stdin)\n'))
  3789 
  3861 
  3790     blocks = list(_parsewirelangblocks(ui.fin))
  3862     blocks = list(_parsewirelangblocks(ui.fin))
  3791 
  3863 
  3792     proc = None
  3864     proc = None
  3793     stdin = None
  3865     stdin = None
  3794     stdout = None
  3866     stdout = None
  3795     stderr = None
  3867     stderr = None
  3796     opener = None
  3868     opener = None
  3797 
  3869 
  3798     if opts['localssh']:
  3870     if opts[b'localssh']:
  3799         # We start the SSH server in its own process so there is process
  3871         # We start the SSH server in its own process so there is process
  3800         # separation. This prevents a whole class of potential bugs around
  3872         # separation. This prevents a whole class of potential bugs around
  3801         # shared state from interfering with server operation.
  3873         # shared state from interfering with server operation.
  3802         args = procutil.hgcmd() + [
  3874         args = procutil.hgcmd() + [
  3803             '-R',
  3875             b'-R',
  3804             repo.root,
  3876             repo.root,
  3805             'debugserve',
  3877             b'debugserve',
  3806             '--sshstdio',
  3878             b'--sshstdio',
  3807         ]
  3879         ]
  3808         proc = subprocess.Popen(
  3880         proc = subprocess.Popen(
  3809             pycompat.rapply(procutil.tonativestr, args),
  3881             pycompat.rapply(procutil.tonativestr, args),
  3810             stdin=subprocess.PIPE,
  3882             stdin=subprocess.PIPE,
  3811             stdout=subprocess.PIPE,
  3883             stdout=subprocess.PIPE,
  3816         stdin = proc.stdin
  3888         stdin = proc.stdin
  3817         stdout = proc.stdout
  3889         stdout = proc.stdout
  3818         stderr = proc.stderr
  3890         stderr = proc.stderr
  3819 
  3891 
  3820         # We turn the pipes into observers so we can log I/O.
  3892         # We turn the pipes into observers so we can log I/O.
  3821         if ui.verbose or opts['peer'] == 'raw':
  3893         if ui.verbose or opts[b'peer'] == b'raw':
  3822             stdin = util.makeloggingfileobject(
  3894             stdin = util.makeloggingfileobject(
  3823                 ui, proc.stdin, b'i', logdata=True
  3895                 ui, proc.stdin, b'i', logdata=True
  3824             )
  3896             )
  3825             stdout = util.makeloggingfileobject(
  3897             stdout = util.makeloggingfileobject(
  3826                 ui, proc.stdout, b'o', logdata=True
  3898                 ui, proc.stdout, b'o', logdata=True
  3829                 ui, proc.stderr, b'e', logdata=True
  3901                 ui, proc.stderr, b'e', logdata=True
  3830             )
  3902             )
  3831 
  3903 
  3832         # --localssh also implies the peer connection settings.
  3904         # --localssh also implies the peer connection settings.
  3833 
  3905 
  3834         url = 'ssh://localserver'
  3906         url = b'ssh://localserver'
  3835         autoreadstderr = not opts['noreadstderr']
  3907         autoreadstderr = not opts[b'noreadstderr']
  3836 
  3908 
  3837         if opts['peer'] == 'ssh1':
  3909         if opts[b'peer'] == b'ssh1':
  3838             ui.write(_('creating ssh peer for wire protocol version 1\n'))
  3910             ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
  3839             peer = sshpeer.sshv1peer(
  3911             peer = sshpeer.sshv1peer(
  3840                 ui,
  3912                 ui,
  3841                 url,
  3913                 url,
  3842                 proc,
  3914                 proc,
  3843                 stdin,
  3915                 stdin,
  3844                 stdout,
  3916                 stdout,
  3845                 stderr,
  3917                 stderr,
  3846                 None,
  3918                 None,
  3847                 autoreadstderr=autoreadstderr,
  3919                 autoreadstderr=autoreadstderr,
  3848             )
  3920             )
  3849         elif opts['peer'] == 'ssh2':
  3921         elif opts[b'peer'] == b'ssh2':
  3850             ui.write(_('creating ssh peer for wire protocol version 2\n'))
  3922             ui.write(_(b'creating ssh peer for wire protocol version 2\n'))
  3851             peer = sshpeer.sshv2peer(
  3923             peer = sshpeer.sshv2peer(
  3852                 ui,
  3924                 ui,
  3853                 url,
  3925                 url,
  3854                 proc,
  3926                 proc,
  3855                 stdin,
  3927                 stdin,
  3856                 stdout,
  3928                 stdout,
  3857                 stderr,
  3929                 stderr,
  3858                 None,
  3930                 None,
  3859                 autoreadstderr=autoreadstderr,
  3931                 autoreadstderr=autoreadstderr,
  3860             )
  3932             )
  3861         elif opts['peer'] == 'raw':
  3933         elif opts[b'peer'] == b'raw':
  3862             ui.write(_('using raw connection to peer\n'))
  3934             ui.write(_(b'using raw connection to peer\n'))
  3863             peer = None
  3935             peer = None
  3864         else:
  3936         else:
  3865             ui.write(_('creating ssh peer from handshake results\n'))
  3937             ui.write(_(b'creating ssh peer from handshake results\n'))
  3866             peer = sshpeer.makepeer(
  3938             peer = sshpeer.makepeer(
  3867                 ui,
  3939                 ui,
  3868                 url,
  3940                 url,
  3869                 proc,
  3941                 proc,
  3870                 stdin,
  3942                 stdin,
  3876     elif path:
  3948     elif path:
  3877         # We bypass hg.peer() so we can proxy the sockets.
  3949         # We bypass hg.peer() so we can proxy the sockets.
  3878         # TODO consider not doing this because we skip
  3950         # TODO consider not doing this because we skip
  3879         # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
  3951         # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
  3880         u = util.url(path)
  3952         u = util.url(path)
  3881         if u.scheme != 'http':
  3953         if u.scheme != b'http':
  3882             raise error.Abort(_('only http:// paths are currently supported'))
  3954             raise error.Abort(_(b'only http:// paths are currently supported'))
  3883 
  3955 
  3884         url, authinfo = u.authinfo()
  3956         url, authinfo = u.authinfo()
  3885         openerargs = {
  3957         openerargs = {
  3886             r'useragent': b'Mercurial debugwireproto',
  3958             r'useragent': b'Mercurial debugwireproto',
  3887         }
  3959         }
  3900             openerargs[r'loggingopts'][r'logdataapis'] = True
  3972             openerargs[r'loggingopts'][r'logdataapis'] = True
  3901 
  3973 
  3902         # Don't send default headers when in raw mode. This allows us to
  3974         # Don't send default headers when in raw mode. This allows us to
  3903         # bypass most of the behavior of our URL handling code so we can
  3975         # bypass most of the behavior of our URL handling code so we can
  3904         # have near complete control over what's sent on the wire.
  3976         # have near complete control over what's sent on the wire.
  3905         if opts['peer'] == 'raw':
  3977         if opts[b'peer'] == b'raw':
  3906             openerargs[r'sendaccept'] = False
  3978             openerargs[r'sendaccept'] = False
  3907 
  3979 
  3908         opener = urlmod.opener(ui, authinfo, **openerargs)
  3980         opener = urlmod.opener(ui, authinfo, **openerargs)
  3909 
  3981 
  3910         if opts['peer'] == 'http2':
  3982         if opts[b'peer'] == b'http2':
  3911             ui.write(_('creating http peer for wire protocol version 2\n'))
  3983             ui.write(_(b'creating http peer for wire protocol version 2\n'))
  3912             # We go through makepeer() because we need an API descriptor for
  3984             # We go through makepeer() because we need an API descriptor for
  3913             # the peer instance to be useful.
  3985             # the peer instance to be useful.
  3914             with ui.configoverride(
  3986             with ui.configoverride(
  3915                 {('experimental', 'httppeer.advertise-v2'): True}
  3987                 {(b'experimental', b'httppeer.advertise-v2'): True}
  3916             ):
  3988             ):
  3917                 if opts['nologhandshake']:
  3989                 if opts[b'nologhandshake']:
  3918                     ui.pushbuffer()
  3990                     ui.pushbuffer()
  3919 
  3991 
  3920                 peer = httppeer.makepeer(ui, path, opener=opener)
  3992                 peer = httppeer.makepeer(ui, path, opener=opener)
  3921 
  3993 
  3922                 if opts['nologhandshake']:
  3994                 if opts[b'nologhandshake']:
  3923                     ui.popbuffer()
  3995                     ui.popbuffer()
  3924 
  3996 
  3925             if not isinstance(peer, httppeer.httpv2peer):
  3997             if not isinstance(peer, httppeer.httpv2peer):
  3926                 raise error.Abort(
  3998                 raise error.Abort(
  3927                     _(
  3999                     _(
  3928                         'could not instantiate HTTP peer for '
  4000                         b'could not instantiate HTTP peer for '
  3929                         'wire protocol version 2'
  4001                         b'wire protocol version 2'
  3930                     ),
  4002                     ),
  3931                     hint=_(
  4003                     hint=_(
  3932                         'the server may not have the feature '
  4004                         b'the server may not have the feature '
  3933                         'enabled or is not allowing this '
  4005                         b'enabled or is not allowing this '
  3934                         'client version'
  4006                         b'client version'
  3935                     ),
  4007                     ),
  3936                 )
  4008                 )
  3937 
  4009 
  3938         elif opts['peer'] == 'raw':
  4010         elif opts[b'peer'] == b'raw':
  3939             ui.write(_('using raw connection to peer\n'))
  4011             ui.write(_(b'using raw connection to peer\n'))
  3940             peer = None
  4012             peer = None
  3941         elif opts['peer']:
  4013         elif opts[b'peer']:
  3942             raise error.Abort(
  4014             raise error.Abort(
  3943                 _('--peer %s not supported with HTTP peers') % opts['peer']
  4015                 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
  3944             )
  4016             )
  3945         else:
  4017         else:
  3946             peer = httppeer.makepeer(ui, path, opener=opener)
  4018             peer = httppeer.makepeer(ui, path, opener=opener)
  3947 
  4019 
  3948         # We /could/ populate stdin/stdout with sock.makefile()...
  4020         # We /could/ populate stdin/stdout with sock.makefile()...
  3949     else:
  4021     else:
  3950         raise error.Abort(_('unsupported connection configuration'))
  4022         raise error.Abort(_(b'unsupported connection configuration'))
  3951 
  4023 
  3952     batchedcommands = None
  4024     batchedcommands = None
  3953 
  4025 
  3954     # Now perform actions based on the parsed wire language instructions.
  4026     # Now perform actions based on the parsed wire language instructions.
  3955     for action, lines in blocks:
  4027     for action, lines in blocks:
  3956         if action in ('raw', 'raw+'):
  4028         if action in (b'raw', b'raw+'):
  3957             if not stdin:
  4029             if not stdin:
  3958                 raise error.Abort(_('cannot call raw/raw+ on this peer'))
  4030                 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
  3959 
  4031 
  3960             # Concatenate the data together.
  4032             # Concatenate the data together.
  3961             data = ''.join(l.lstrip() for l in lines)
  4033             data = b''.join(l.lstrip() for l in lines)
  3962             data = stringutil.unescapestr(data)
  4034             data = stringutil.unescapestr(data)
  3963             stdin.write(data)
  4035             stdin.write(data)
  3964 
  4036 
  3965             if action == 'raw+':
  4037             if action == b'raw+':
  3966                 stdin.flush()
  4038                 stdin.flush()
  3967         elif action == 'flush':
  4039         elif action == b'flush':
  3968             if not stdin:
  4040             if not stdin:
  3969                 raise error.Abort(_('cannot call flush on this peer'))
  4041                 raise error.Abort(_(b'cannot call flush on this peer'))
  3970             stdin.flush()
  4042             stdin.flush()
  3971         elif action.startswith('command'):
  4043         elif action.startswith(b'command'):
  3972             if not peer:
  4044             if not peer:
  3973                 raise error.Abort(
  4045                 raise error.Abort(
  3974                     _(
  4046                     _(
  3975                         'cannot send commands unless peer instance '
  4047                         b'cannot send commands unless peer instance '
  3976                         'is available'
  4048                         b'is available'
  3977                     )
  4049                     )
  3978                 )
  4050                 )
  3979 
  4051 
  3980             command = action.split(' ', 1)[1]
  4052             command = action.split(b' ', 1)[1]
  3981 
  4053 
  3982             args = {}
  4054             args = {}
  3983             for line in lines:
  4055             for line in lines:
  3984                 # We need to allow empty values.
  4056                 # We need to allow empty values.
  3985                 fields = line.lstrip().split(' ', 1)
  4057                 fields = line.lstrip().split(b' ', 1)
  3986                 if len(fields) == 1:
  4058                 if len(fields) == 1:
  3987                     key = fields[0]
  4059                     key = fields[0]
  3988                     value = ''
  4060                     value = b''
  3989                 else:
  4061                 else:
  3990                     key, value = fields
  4062                     key, value = fields
  3991 
  4063 
  3992                 if value.startswith('eval:'):
  4064                 if value.startswith(b'eval:'):
  3993                     value = stringutil.evalpythonliteral(value[5:])
  4065                     value = stringutil.evalpythonliteral(value[5:])
  3994                 else:
  4066                 else:
  3995                     value = stringutil.unescapestr(value)
  4067                     value = stringutil.unescapestr(value)
  3996 
  4068 
  3997                 args[key] = value
  4069                 args[key] = value
  3998 
  4070 
  3999             if batchedcommands is not None:
  4071             if batchedcommands is not None:
  4000                 batchedcommands.append((command, args))
  4072                 batchedcommands.append((command, args))
  4001                 continue
  4073                 continue
  4002 
  4074 
  4003             ui.status(_('sending %s command\n') % command)
  4075             ui.status(_(b'sending %s command\n') % command)
  4004 
  4076 
  4005             if 'PUSHFILE' in args:
  4077             if b'PUSHFILE' in args:
  4006                 with open(args['PUSHFILE'], r'rb') as fh:
  4078                 with open(args[b'PUSHFILE'], r'rb') as fh:
  4007                     del args['PUSHFILE']
  4079                     del args[b'PUSHFILE']
  4008                     res, output = peer._callpush(
  4080                     res, output = peer._callpush(
  4009                         command, fh, **pycompat.strkwargs(args)
  4081                         command, fh, **pycompat.strkwargs(args)
  4010                     )
  4082                     )
  4011                     ui.status(_('result: %s\n') % stringutil.escapestr(res))
  4083                     ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
  4012                     ui.status(
  4084                     ui.status(
  4013                         _('remote output: %s\n') % stringutil.escapestr(output)
  4085                         _(b'remote output: %s\n') % stringutil.escapestr(output)
  4014                     )
  4086                     )
  4015             else:
  4087             else:
  4016                 with peer.commandexecutor() as e:
  4088                 with peer.commandexecutor() as e:
  4017                     res = e.callcommand(command, args).result()
  4089                     res = e.callcommand(command, args).result()
  4018 
  4090 
  4019                 if isinstance(res, wireprotov2peer.commandresponse):
  4091                 if isinstance(res, wireprotov2peer.commandresponse):
  4020                     val = res.objects()
  4092                     val = res.objects()
  4021                     ui.status(
  4093                     ui.status(
  4022                         _('response: %s\n')
  4094                         _(b'response: %s\n')
  4023                         % stringutil.pprint(val, bprefix=True, indent=2)
  4095                         % stringutil.pprint(val, bprefix=True, indent=2)
  4024                     )
  4096                     )
  4025                 else:
  4097                 else:
  4026                     ui.status(
  4098                     ui.status(
  4027                         _('response: %s\n')
  4099                         _(b'response: %s\n')
  4028                         % stringutil.pprint(res, bprefix=True, indent=2)
  4100                         % stringutil.pprint(res, bprefix=True, indent=2)
  4029                     )
  4101                     )
  4030 
  4102 
  4031         elif action == 'batchbegin':
  4103         elif action == b'batchbegin':
  4032             if batchedcommands is not None:
  4104             if batchedcommands is not None:
  4033                 raise error.Abort(_('nested batchbegin not allowed'))
  4105                 raise error.Abort(_(b'nested batchbegin not allowed'))
  4034 
  4106 
  4035             batchedcommands = []
  4107             batchedcommands = []
  4036         elif action == 'batchsubmit':
  4108         elif action == b'batchsubmit':
  4037             # There is a batching API we could go through. But it would be
  4109             # There is a batching API we could go through. But it would be
  4038             # difficult to normalize requests into function calls. It is easier
  4110             # difficult to normalize requests into function calls. It is easier
  4039             # to bypass this layer and normalize to commands + args.
  4111             # to bypass this layer and normalize to commands + args.
  4040             ui.status(
  4112             ui.status(
  4041                 _('sending batch with %d sub-commands\n') % len(batchedcommands)
  4113                 _(b'sending batch with %d sub-commands\n')
       
  4114                 % len(batchedcommands)
  4042             )
  4115             )
  4043             for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
  4116             for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
  4044                 ui.status(
  4117                 ui.status(
  4045                     _('response #%d: %s\n') % (i, stringutil.escapestr(chunk))
  4118                     _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
  4046                 )
  4119                 )
  4047 
  4120 
  4048             batchedcommands = None
  4121             batchedcommands = None
  4049 
  4122 
  4050         elif action.startswith('httprequest '):
  4123         elif action.startswith(b'httprequest '):
  4051             if not opener:
  4124             if not opener:
  4052                 raise error.Abort(
  4125                 raise error.Abort(
  4053                     _('cannot use httprequest without an HTTP ' 'peer')
  4126                     _(b'cannot use httprequest without an HTTP ' b'peer')
  4054                 )
  4127                 )
  4055 
  4128 
  4056             request = action.split(' ', 2)
  4129             request = action.split(b' ', 2)
  4057             if len(request) != 3:
  4130             if len(request) != 3:
  4058                 raise error.Abort(
  4131                 raise error.Abort(
  4059                     _(
  4132                     _(
  4060                         'invalid httprequest: expected format is '
  4133                         b'invalid httprequest: expected format is '
  4061                         '"httprequest <method> <path>'
  4134                         b'"httprequest <method> <path>'
  4062                     )
  4135                     )
  4063                 )
  4136                 )
  4064 
  4137 
  4065             method, httppath = request[1:]
  4138             method, httppath = request[1:]
  4066             headers = {}
  4139             headers = {}
  4075                     value = pycompat.strurl(m.group(2))
  4148                     value = pycompat.strurl(m.group(2))
  4076                     headers[key] = value
  4149                     headers[key] = value
  4077                     continue
  4150                     continue
  4078 
  4151 
  4079                 if line.startswith(b'BODYFILE '):
  4152                 if line.startswith(b'BODYFILE '):
  4080                     with open(line.split(b' ', 1), 'rb') as fh:
  4153                     with open(line.split(b' ', 1), b'rb') as fh:
  4081                         body = fh.read()
  4154                         body = fh.read()
  4082                 elif line.startswith(b'frame '):
  4155                 elif line.startswith(b'frame '):
  4083                     frame = wireprotoframing.makeframefromhumanstring(
  4156                     frame = wireprotoframing.makeframefromhumanstring(
  4084                         line[len(b'frame ') :]
  4157                         line[len(b'frame ') :]
  4085                     )
  4158                     )
  4086 
  4159 
  4087                     frames.append(frame)
  4160                     frames.append(frame)
  4088                 else:
  4161                 else:
  4089                     raise error.Abort(
  4162                     raise error.Abort(
  4090                         _('unknown argument to httprequest: %s') % line
  4163                         _(b'unknown argument to httprequest: %s') % line
  4091                     )
  4164                     )
  4092 
  4165 
  4093             url = path + httppath
  4166             url = path + httppath
  4094 
  4167 
  4095             if frames:
  4168             if frames:
  4111                 continue
  4184                 continue
  4112 
  4185 
  4113             ct = res.headers.get(r'Content-Type')
  4186             ct = res.headers.get(r'Content-Type')
  4114             if ct == r'application/mercurial-cbor':
  4187             if ct == r'application/mercurial-cbor':
  4115                 ui.write(
  4188                 ui.write(
  4116                     _('cbor> %s\n')
  4189                     _(b'cbor> %s\n')
  4117                     % stringutil.pprint(
  4190                     % stringutil.pprint(
  4118                         cborutil.decodeall(body), bprefix=True, indent=2
  4191                         cborutil.decodeall(body), bprefix=True, indent=2
  4119                     )
  4192                     )
  4120                 )
  4193                 )
  4121 
  4194 
  4122         elif action == 'close':
  4195         elif action == b'close':
  4123             peer.close()
  4196             peer.close()
  4124         elif action == 'readavailable':
  4197         elif action == b'readavailable':
  4125             if not stdout or not stderr:
  4198             if not stdout or not stderr:
  4126                 raise error.Abort(_('readavailable not available on this peer'))
  4199                 raise error.Abort(
       
  4200                     _(b'readavailable not available on this peer')
       
  4201                 )
  4127 
  4202 
  4128             stdin.close()
  4203             stdin.close()
  4129             stdout.read()
  4204             stdout.read()
  4130             stderr.read()
  4205             stderr.read()
  4131 
  4206 
  4132         elif action == 'readline':
  4207         elif action == b'readline':
  4133             if not stdout:
  4208             if not stdout:
  4134                 raise error.Abort(_('readline not available on this peer'))
  4209                 raise error.Abort(_(b'readline not available on this peer'))
  4135             stdout.readline()
  4210             stdout.readline()
  4136         elif action == 'ereadline':
  4211         elif action == b'ereadline':
  4137             if not stderr:
  4212             if not stderr:
  4138                 raise error.Abort(_('ereadline not available on this peer'))
  4213                 raise error.Abort(_(b'ereadline not available on this peer'))
  4139             stderr.readline()
  4214             stderr.readline()
  4140         elif action.startswith('read '):
  4215         elif action.startswith(b'read '):
  4141             count = int(action.split(' ', 1)[1])
  4216             count = int(action.split(b' ', 1)[1])
  4142             if not stdout:
  4217             if not stdout:
  4143                 raise error.Abort(_('read not available on this peer'))
  4218                 raise error.Abort(_(b'read not available on this peer'))
  4144             stdout.read(count)
  4219             stdout.read(count)
  4145         elif action.startswith('eread '):
  4220         elif action.startswith(b'eread '):
  4146             count = int(action.split(' ', 1)[1])
  4221             count = int(action.split(b' ', 1)[1])
  4147             if not stderr:
  4222             if not stderr:
  4148                 raise error.Abort(_('eread not available on this peer'))
  4223                 raise error.Abort(_(b'eread not available on this peer'))
  4149             stderr.read(count)
  4224             stderr.read(count)
  4150         else:
  4225         else:
  4151             raise error.Abort(_('unknown action: %s') % action)
  4226             raise error.Abort(_(b'unknown action: %s') % action)
  4152 
  4227 
  4153     if batchedcommands is not None:
  4228     if batchedcommands is not None:
  4154         raise error.Abort(_('unclosed "batchbegin" request'))
  4229         raise error.Abort(_(b'unclosed "batchbegin" request'))
  4155 
  4230 
  4156     if peer:
  4231     if peer:
  4157         peer.close()
  4232         peer.close()
  4158 
  4233 
  4159     if proc:
  4234     if proc: