##// END OF EJS Templates
exchangev2: fetch manifest revisions...
exchangev2: fetch manifest revisions Now that the server has support for retrieving manifest data, we can implement the client bits to call it. We teach the changeset fetching code to capture the manifest revisions that are encountered on incoming changesets. We then feed this into a new function which filters out known manifests and then batches up manifest data requests to the server. This is different from the previous wire protocol in a few notable ways. First, the client fetches manifest data separately and explicitly. Before, we'd ask the server for data pertaining to some changesets (via a "getbundle" command) and manifests (and files) would be sent automatically. Providing an API for looking up just manifest data separately gives clients much more flexibility for manifest management. For example, a client may choose to only fetch manifest data on demand instead of prefetching it (i.e. partial clone). Second, we send N commands to the server for manifest retrieval instead of 1. This property has a few nice side-effects. One is that the deterministic nature of the requests lends itself to server-side caching. For example, say the remote has 50,000 manifests. If the server is configured to cache responses, each time a new commit arrives, you will have a cache miss and need to regenerate all outgoing data. But if you makes N requests requesting 10,000 manifests each, a new commit will still yield cache hits on the initial, unchanged manifest batches/requests. A derived benefit from these properties is that resumable clone is conceptually simpler to implement. When making a monolithic request for all of the repository data, recovering from an interrupted clone is hard because the server was in the driver's seat and was maintaining state about all the data that needed transferred. With the client driving fetching, the client can persist the set of unfetched entities and retry/resume a fetch if something goes wrong. Or we can fetch all data N changesets at a time and slowly build up a repository. This approach is drastically easier to implement when we have server APIs exposing low-level repository primitives (such as manifests and files). We don't yet support tree manifests. But it should be possible to implement that with the existing wire protocol command. Differential Revision: https://phab.mercurial-scm.org/D4489

File last commit:

r39597:d06834e0 default
r39674:d292328e default
Show More
debugcommands.py
3364 lines | 121.2 KiB | text/x-python | PythonLexer
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 # debugcommands.py - command processing for debug* commands
#
# Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
Yuya Nishihara
debuginstall: use codecs.lookup() to detect invalid encoding...
r34131 import codecs
Augie Fackler
debugcommands: stabilize output of debugbundle by having a custom repr...
r34027 import collections
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 import difflib
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 import errno
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518 import operator
Gregory Szorc
debugcommands: move 'debugfsinfo' in the new module
r30525 import os
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 import random
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 import re
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 import socket
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 import ssl
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 import stat
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 import string
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 import subprocess
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 import sys
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 import time
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401
from .i18n import _
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 from .node import (
Gregory Szorc
debugcommands: move 'debuggetbundle' in the new module
r30526 bin,
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 hex,
Pierre-Yves David
debugcommands: move 'debugmergestate' in the new module
r30936 nullhex,
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 nullid,
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 nullrev,
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 short,
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 )
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 from . import (
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 bundle2,
changegroup,
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 cmdutil,
Pierre-Yves David
color: move 'debugcolor' into the 'debugcommands' modules...
r31120 color,
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 context,
dagparser,
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 encoding,
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 error,
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 exchange,
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518 extensions,
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256 filemerge,
Yuya Nishihara
fileset: extract language processing part to new module (API)...
r38841 filesetlang,
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 formatter,
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 hg,
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 httppeer,
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 localrepo,
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 lock as lockmod,
Yuya Nishihara
cmdutil: drop aliases for logcmdutil functions (API)...
r35906 logcmdutil,
Pierre-Yves David
debugcommands: move 'debugmergestate' in the new module
r30936 merge as mergemod,
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 obsolete,
obsutil: move 'successorssets' to the new modules...
r33143 obsutil,
Gregory Szorc
debugcommands: issue warning when repo has secret changesets (issue5589)...
r32745 phases,
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 policy,
Pierre-Yves David
debugcommands: move 'debugpvec' in the new module
r30947 pvec,
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 pycompat,
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 registrar,
Gregory Szorc
repair: implement requirements checking for upgrades...
r30775 repair,
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 revlog,
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 revset,
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 revsetlang,
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 scmutil,
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 setdiscovery,
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 simplemerge,
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 sshpeer,
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 sslutil,
Gregory Szorc
debugcommands: move debug{create,apply}streambundleclone to the new module
r30502 streamclone,
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 templater,
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 treediscovery,
Pierre-Yves David
upgrade: extract code in its own module...
r31864 upgrade,
Boris Feld
debug: add a 'debugdownload' command...
r35578 url as urlmod,
Gregory Szorc
debugcommands: move 'debugdate' in the new module
r30516 util,
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.debugcommand'...
r31239 vfs as vfsmod,
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069 wireprotoframing,
Gregory Szorc
debugcommands: add debugserve command...
r36544 wireprotoserver,
Gregory Szorc
wireprotov2: establish a type for representing command response...
r37738 wireprotov2peer,
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 )
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
Gregory Szorc
debugcommands: use our CBOR decoder...
r39480 cborutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 dateutil,
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 procutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
)
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401
Boris Feld
revlog: split functionality related to deltas computation in a new module...
r39366 from .revlogutils import (
deltas as deltautil
)
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 release = lockmod.release
Yuya Nishihara
debugcommands: use temporary dict for its command table...
r32377 command = registrar.command()
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401
@command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
def debugancestor(ui, repo, *args):
"""find the ancestor revision of two revisions in a given index"""
if len(args) == 3:
index, rev1, rev2 = args
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.debugcommand'...
r31239 r = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False), index)
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 lookup = r.lookup
elif len(args) == 2:
if not repo:
raise error.Abort(_('there is no Mercurial repository here '
'(.hg not found)'))
rev1, rev2 = args
r = repo.changelog
lookup = repo.lookup
else:
raise error.Abort(_('either two or three arguments required'))
a = r.ancestor(lookup(rev1), lookup(rev2))
ui.write('%d:%s\n' % (r.rev(a), hex(a)))
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
Gregory Szorc
debugcommands: sort command order...
r30541 @command('debugapplystreamclonebundle', [], 'FILE')
def debugapplystreamclonebundle(ui, repo, fname):
"""apply a stream clone bundle file"""
f = hg.openpath(ui, fname)
gen = exchange.readbundle(ui, f, fname)
gen.apply(repo)
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 @command('debugbuilddag',
[('m', 'mergeable-file', None, _('add single file mergeable changes')),
('o', 'overwritten-file', None, _('add single file all revs overwrite')),
('n', 'new-file', None, _('add new file at each rev'))],
_('[OPTION]... [TEXT]'))
def debugbuilddag(ui, repo, text=None,
mergeable_file=False,
overwritten_file=False,
new_file=False):
"""builds a repo with a given DAG from scratch in the current empty repo
The description of the DAG is read from stdin if not given on the
command line.
Elements:
- "+n" is a linear run of n nodes based on the current default parent
- "." is a single node based on the current default parent
- "$" resets the default parent to null (implied at the start);
otherwise the default parent is always the last node created
- "<p" sets the default parent to the backref p
- "*p" is a fork at parent p, which is a backref
- "*p1/p2" is a merge of parents p1 and p2, which are backrefs
- "/p2" is a merge of the preceding node and p2
- ":tag" defines a local tag for the preceding node
- "@branch" sets the named branch for subsequent nodes
- "#...\\n" is a comment up to the end of the line
Whitespace between the above elements is ignored.
A backref is either
- a number n, which references the node curr-n, where curr is the current
node, or
- the name of a local tag you placed earlier using ":tag", or
- empty to denote the default parent.
All string valued-elements are either strictly alphanumeric, or must
be enclosed in double quotes ("..."), with "\\" as escape character.
"""
if text is None:
ui.status(_("reading DAG from stdin\n"))
text = ui.fin.read()
cl = repo.changelog
if len(cl) > 0:
raise error.Abort(_('repository is not empty'))
# determine number of revs in DAG
total = 0
for type, data in dagparser.parsedag(text):
if type == 'n':
total += 1
if mergeable_file:
linesperrev = 2
# make a file with k lines per rev
Gregory Szorc
global: use pycompat.xrange()...
r38806 initialmergedlines = ['%d' % i
for i in pycompat.xrange(0, total * linesperrev)]
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 initialmergedlines.append("")
tags = []
Martin von Zweigbergk
debugbuilddag: use progress helper...
r38394 progress = ui.makeprogress(_('building'), unit=_('revisions'),
total=total)
Martin von Zweigbergk
debugbuilddag: use context manager for progress, locks, transaction...
r38395 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 at = -1
atbranch = 'default'
nodeids = []
id = 0
Martin von Zweigbergk
debugbuilddag: use progress helper...
r38394 progress.update(id)
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 for type, data in dagparser.parsedag(text):
if type == 'n':
Pulkit Goyal
py3: use pycompat.bytestr() instead of str()...
r35603 ui.note(('node %s\n' % pycompat.bytestr(data)))
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 id, ps = data
files = []
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 filecontent = {}
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
p2 = None
if mergeable_file:
fn = "mf"
p1 = repo[ps[0]]
if len(ps) > 1:
p2 = repo[ps[1]]
pa = p1.ancestor(p2)
base, local, other = [x[fn].data() for x in (pa, p1,
p2)]
m3 = simplemerge.Merge3Text(base, local, other)
ml = [l.strip() for l in m3.merge_lines()]
ml.append("")
elif at > 0:
ml = p1[fn].data().split("\n")
else:
ml = initialmergedlines
ml[id * linesperrev] += " r%i" % id
mergedtext = "\n".join(ml)
files.append(fn)
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 filecontent[fn] = mergedtext
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
if overwritten_file:
fn = "of"
files.append(fn)
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 filecontent[fn] = "r%i\n" % id
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
if new_file:
fn = "nf%i" % id
files.append(fn)
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 filecontent[fn] = "r%i\n" % id
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 if len(ps) > 1:
if not p2:
p2 = repo[ps[1]]
for fn in p2:
if fn.startswith("nf"):
files.append(fn)
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 filecontent[fn] = p2[fn].data()
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
def fctxfn(repo, cx, path):
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 if path in filecontent:
Martin von Zweigbergk
memfilectx: make changectx argument mandatory in constructor (API)...
r35401 return context.memfilectx(repo, cx, path,
filecontent[path])
Martin von Zweigbergk
debugbuilddag: create filectx instance in 'filectxfn' callback...
r35400 return None
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
if len(ps) == 0 or ps[0] < 0:
pars = [None, None]
elif len(ps) == 1:
pars = [nodeids[ps[0]], None]
else:
pars = [nodeids[p] for p in ps]
cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
date=(id, 0),
user="debugbuilddag",
extra={'branch': atbranch})
nodeid = repo.commitctx(cx)
nodeids.append(nodeid)
at = id
elif type == 'l':
id, name = data
ui.note(('tag %s\n' % name))
tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
elif type == 'a':
ui.note(('branch %s\n' % data))
atbranch = data
Martin von Zweigbergk
debugbuilddag: use progress helper...
r38394 progress.update(id)
Gregory Szorc
debugcommands: move debugbuilddag...
r30402
if tags:
repo.vfs.write("localtags", "".join(tags))
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501
def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
indent_string = ' ' * indent
if all:
ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
% indent_string)
def showchunks(named):
ui.write("\n%s%s\n" % (indent_string, named))
Durham Goode
debug: update debugbundle to use new deltaiter api...
r34293 for deltadata in gen.deltaiter():
node, p1, p2, cs, deltabase, delta, flags = deltadata
Pulkit Goyal
py3: use '%d' to convert integers to bytes...
r36477 ui.write("%s%s %s %s %s %s %d\n" %
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 (indent_string, hex(node), hex(p1), hex(p2),
hex(cs), hex(deltabase), len(delta)))
chunkdata = gen.changelogheader()
showchunks("changelog")
chunkdata = gen.manifestheader()
showchunks("manifest")
for chunkdata in iter(gen.filelogheader, {}):
fname = chunkdata['filename']
showchunks(fname)
else:
if isinstance(gen, bundle2.unbundle20):
raise error.Abort(_('use debugbundle2 for this file'))
chunkdata = gen.changelogheader()
Durham Goode
debug: update debugbundle to use new deltaiter api...
r34293 for deltadata in gen.deltaiter():
node, p1, p2, cs, deltabase, delta, flags = deltadata
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 ui.write("%s%s\n" % (indent_string, hex(node)))
Martin von Zweigbergk
debugcommands: pass part, not read data, into _debugobsmarker()...
r33029 def _debugobsmarkers(ui, part, indent=0, **opts):
debugbundle: display the content of obsmarkers parts...
r32517 """display version and markers contained in 'data'"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Martin von Zweigbergk
debugcommands: pass part, not read data, into _debugobsmarker()...
r33029 data = part.read()
debugbundle: display the content of obsmarkers parts...
r32517 indent_string = ' ' * indent
try:
version, markers = obsolete._readmarkers(data)
except error.UnknownVersion as exc:
msg = "%sunsupported version: %s (%d bytes)\n"
msg %= indent_string, exc.version, len(data)
ui.write(msg)
else:
Pulkit Goyal
py3: use '%d' for integers rather than '%s'...
r35144 msg = "%sversion: %d (%d bytes)\n"
debugbundle: display the content of obsmarkers parts...
r32517 msg %= indent_string, version, len(data)
ui.write(msg)
fm = ui.formatter('debugobsolete', opts)
for rawmarker in sorted(markers):
obsutil: move the 'marker' class to the new modules...
r33149 m = obsutil.marker(None, rawmarker)
debugbundle: display the content of obsmarkers parts...
r32517 fm.startitem()
fm.plain(indent_string)
cmdutil.showmarker(fm, m)
fm.end()
Martin von Zweigbergk
bundle: add config option to include phases...
r33031 def _debugphaseheads(ui, data, indent=0):
"""display version and markers contained in 'data'"""
indent_string = ' ' * indent
Boris Feld
phases: move the binary decoding function in the phases module...
r34321 headsbyphase = phases.binarydecode(data)
Martin von Zweigbergk
bundle: add config option to include phases...
r33031 for phase in phases.allphases:
for head in headsbyphase[phase]:
ui.write(indent_string)
ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
Augie Fackler
debugcommands: stabilize output of debugbundle by having a custom repr...
r34027 def _quasirepr(thing):
if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
return '{%s}' % (
b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
return pycompat.bytestr(repr(thing))
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 def _debugbundle2(ui, gen, all=None, **opts):
"""lists the contents of a bundle2"""
if not isinstance(gen, bundle2.unbundle20):
raise error.Abort(_('not a bundle2 file'))
Augie Fackler
debugcommands: stabilize output of debugbundle by having a custom repr...
r34027 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 parttypes = opts.get(r'part_type', [])
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 for part in gen.iterparts():
Danek Duvall
debugbundle: add --part-type flag to emit only named part types...
r32694 if parttypes and part.type not in parttypes:
continue
Boris Feld
debugbundle: also display if a part is mandatory or advisory...
r37919 msg = '%s -- %s (mandatory: %r)\n'
ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
Gregory Szorc
debugcommands: move 'debugbundle' in the new module
r30501 if part.type == 'changegroup':
version = part.params.get('version', '01')
cg = changegroup.getunbundler(version, part, 'UN')
Boris Feld
debugbundle: do not display detailed part data in --quiet mode...
r36969 if not ui.quiet:
_debugchangegroup(ui, cg, all=all, indent=4, **opts)
debugbundle: display the content of obsmarkers parts...
r32517 if part.type == 'obsmarkers':
Boris Feld
debugbundle: do not display detailed part data in --quiet mode...
r36969 if not ui.quiet:
_debugobsmarkers(ui, part, indent=4, **opts)
Martin von Zweigbergk
bundle: add config option to include phases...
r33031 if part.type == 'phase-heads':
Boris Feld
debugbundle: do not display detailed part data in --quiet mode...
r36969 if not ui.quiet:
_debugphaseheads(ui, part, indent=4)
Gregory Szorc
debugcommands: move debug{create,apply}streambundleclone to the new module
r30502
Gregory Szorc
debugcommands: sort command order...
r30541 @command('debugbundle',
[('a', 'all', None, _('show all details')),
Danek Duvall
debugbundle: add --part-type flag to emit only named part types...
r32694 ('', 'part-type', [], _('show only the named part type')),
Gregory Szorc
debugcommands: sort command order...
r30541 ('', 'spec', None, _('print the bundlespec of the bundle'))],
_('FILE'),
norepo=True)
def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
"""lists the contents of a bundle"""
with hg.openpath(ui, bundlepath) as f:
if spec:
spec = exchange.getbundlespec(ui, f)
ui.write('%s\n' % spec)
return
Gregory Szorc
debugcommands: move debug{create,apply}streambundleclone to the new module
r30502
Gregory Szorc
debugcommands: sort command order...
r30541 gen = exchange.readbundle(ui, f, bundlepath)
if isinstance(gen, bundle2.unbundle20):
return _debugbundle2(ui, gen, all=all, **opts)
_debugchangegroup(ui, gen, all=all, **opts)
Gregory Szorc
debugcommands: move 'debugcheckstate' in the new module
r30503
Boris Feld
debug: add a debugcapabilities commands...
r34960 @command('debugcapabilities',
[], _('PATH'),
norepo=True)
def debugcapabilities(ui, path, **opts):
"""lists the capabilities of a remote peer"""
Pulkit Goyal
py3: handle keyword arguments correctly in debugcommands.py...
r35402 opts = pycompat.byteskwargs(opts)
Boris Feld
debug: add a debugcapabilities commands...
r34960 peer = hg.peer(ui, opts, path)
caps = peer.capabilities()
ui.write(('Main capabilities:\n'))
for c in sorted(caps):
ui.write((' %s\n') % c)
Boris Feld
debug: print parsed bundle2 capabilities with debugcapabilities...
r34961 b2caps = bundle2.bundle2caps(peer)
if b2caps:
ui.write(('Bundle2 capabilities:\n'))
for key, values in sorted(b2caps.iteritems()):
ui.write((' %s\n') % key)
for v in values:
ui.write((' %s\n') % v)
Gregory Szorc
debugcommands: move 'debugcheckstate' in the new module
r30503 @command('debugcheckstate', [], '')
def debugcheckstate(ui, repo):
"""validate the correctness of the current dirstate"""
parent1, parent2 = repo.dirstate.parents()
m1 = repo[parent1].manifest()
m2 = repo[parent2].manifest()
errors = 0
for f in repo.dirstate:
state = repo.dirstate[f]
if state in "nr" and f not in m1:
ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
errors += 1
if state in "a" and f in m1:
ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
errors += 1
if state in "m" and f not in m1 and f not in m2:
ui.warn(_("%s in state %s, but not in either manifest\n") %
(f, state))
errors += 1
for f in m1:
state = repo.dirstate[f]
if state not in "nrm":
ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
errors += 1
if errors:
error = _(".hg/dirstate inconsistent with current parent's manifest")
raise error.Abort(error)
Gregory Szorc
debugcommands: move 'debugcommands' in the new module...
r30504
Pierre-Yves David
color: move 'debugcolor' into the 'debugcommands' modules...
r31120 @command('debugcolor',
[('', 'style', None, _('show all configured styles'))],
'hg debugcolor')
def debugcolor(ui, repo, **opts):
"""show available color, effects or style"""
Pulkit Goyal
py3: use stringutil.pprint() to print NoneType...
r38463 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode))
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts.get(r'style'):
Pierre-Yves David
color: move 'debugcolor' into the 'debugcommands' modules...
r31120 return _debugdisplaystyle(ui)
else:
return _debugdisplaycolor(ui)
def _debugdisplaycolor(ui):
Pierre-Yves David
color: cleanup 'debugcolor' logic...
r31121 ui = ui.copy()
ui._styles.clear()
Matt Harbison
color: stop mutating the default effects map...
r31689 for effect in color._activeeffects(ui).keys():
Pierre-Yves David
color: cleanup 'debugcolor' logic...
r31121 ui._styles[effect] = effect
if ui._terminfoparams:
for k, v in ui.configitems('color'):
if k.startswith('color.'):
ui._styles[k] = k[6:]
elif k.startswith('terminfo.'):
ui._styles[k] = k[9:]
ui.write(_('available colors:\n'))
# sort label with a '_' after the other to group '_background' entry.
items = sorted(ui._styles.items(),
key=lambda i: ('_' in i[0], i[0], i[1]))
for colorname, label in items:
ui.write(('%s\n') % colorname, label=label)
Pierre-Yves David
color: move 'debugcolor' into the 'debugcommands' modules...
r31120
def _debugdisplaystyle(ui):
ui.write(_('available style:\n'))
Yuya Nishihara
debugcolor: fix crash by empty styles (issue5856)
r37841 if not ui._styles:
return
Pierre-Yves David
color: move 'debugcolor' into the 'debugcommands' modules...
r31120 width = max(len(s) for s in ui._styles)
for label, effects in sorted(ui._styles.items()):
ui.write('%s' % label, label=label)
if effects:
# 50
ui.write(': ')
ui.write(' ' * (max(0, width - len(label))))
ui.write(', '.join(ui.label(e, e) for e in effects.split()))
ui.write('\n')
Gregory Szorc
debugcommands: sort command order...
r30541 @command('debugcreatestreamclonebundle', [], 'FILE')
def debugcreatestreamclonebundle(ui, repo, fname):
"""create a stream clone bundle file
Stream bundles are special bundles that are essentially archives of
revlog files. They are commonly used for cloning very quickly.
"""
Gregory Szorc
debugcommands: issue warning when repo has secret changesets (issue5589)...
r32745 # TODO we may want to turn this into an abort when this functionality
# is moved into `hg bundle`.
if phases.hassecret(repo):
ui.warn(_('(warning: stream clone bundle will contain secret '
'revisions)\n'))
Gregory Szorc
debugcommands: sort command order...
r30541 requirements, gen = streamclone.generatebundlev1(repo)
changegroup.writechunks(ui, gen, fname)
ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
Gregory Szorc
debugcommands: move 'debugdag' into the new module
r30514 @command('debugdag',
[('t', 'tags', None, _('use tags as labels')),
('b', 'branches', None, _('annotate with branch names')),
('', 'dots', None, _('use dots for runs')),
('s', 'spaces', None, _('separate elements by spaces'))],
_('[OPTION]... [FILE [REV]...]'),
optionalrepo=True)
def debugdag(ui, repo, file_=None, *revs, **opts):
"""format the changelog or an index DAG as a concise textual description
If you pass a revlog index, the revlog's DAG is emitted. If you list
revision numbers, they get labeled in the output as rN.
Otherwise, the changelog DAG of the current repo is emitted.
"""
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 spaces = opts.get(r'spaces')
dots = opts.get(r'dots')
Gregory Szorc
debugcommands: move 'debugdag' into the new module
r30514 if file_:
Pierre-Yves David
vfs: use 'vfs' module directly in 'mercurial.debugcommand'...
r31239 rlog = revlog.revlog(vfsmod.vfs(pycompat.getcwd(), audit=False),
Pulkit Goyal
py3: use pycompat.getcwd() instead of os.getcwd()...
r30519 file_)
Gregory Szorc
debugcommands: move 'debugdag' into the new module
r30514 revs = set((int(r) for r in revs))
def events():
for r in rlog:
yield 'n', (r, list(p for p in rlog.parentrevs(r)
if p != -1))
if r in revs:
yield 'l', (r, "r%i" % r)
elif repo:
cl = repo.changelog
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 tags = opts.get(r'tags')
branches = opts.get(r'branches')
Gregory Szorc
debugcommands: move 'debugdag' into the new module
r30514 if tags:
labels = {}
for l, n in repo.tags().items():
labels.setdefault(cl.rev(n), []).append(l)
def events():
b = "default"
for r in cl:
if branches:
newb = cl.read(cl.node(r))[5]['branch']
if newb != b:
yield 'a', newb
b = newb
yield 'n', (r, list(p for p in cl.parentrevs(r)
if p != -1))
if tags:
ls = labels.get(r)
if ls:
for l in ls:
yield 'l', (r, l)
else:
raise error.Abort(_('need repo for changelog dag'))
for line in dagparser.dagtextlines(events(),
addspaces=spaces,
wraplabels=True,
wrapannotations=True,
wrapnonlinear=dots,
usedots=dots,
maxlinewidth=70):
ui.write(line)
ui.write("\n")
Gregory Szorc
debugcommands: move 'debugrevlogopts' into the new module...
r30515
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
Gregory Szorc
debugcommands: move 'debugrevlogopts' into the new module...
r30515 def debugdata(ui, repo, file_, rev=None, **opts):
"""dump the contents of a data file revision"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: move 'debugrevlogopts' into the new module...
r30515 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
if rev is not None:
raise error.CommandError('debugdata', _('invalid arguments'))
file_, rev = None, file_
elif rev is None:
raise error.CommandError('debugdata', _('invalid arguments'))
Gregory Szorc
debugcommands: use openstorage() in debugdata (BC)...
r39317 r = cmdutil.openstorage(repo, 'debugdata', file_, opts)
Gregory Szorc
debugcommands: move 'debugrevlogopts' into the new module...
r30515 try:
Remi Chaintron
revlog: add 'raw' argument to revision and _addrevision...
r30743 ui.write(r.revision(r.lookup(rev), raw=True))
Gregory Szorc
debugcommands: move 'debugrevlogopts' into the new module...
r30515 except KeyError:
raise error.Abort(_('invalid revision identifier %s') % rev)
Gregory Szorc
debugcommands: move 'debugdate' in the new module
r30516
@command('debugdate',
[('e', 'extended', None, _('try extended date formats'))],
_('[-e] DATE [RANGE]'),
norepo=True, optionalrepo=True)
def debugdate(ui, date, range=None, **opts):
"""parse and display a date"""
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts[r"extended"]:
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 d = dateutil.parsedate(date, util.extendeddateformats)
Gregory Szorc
debugcommands: move 'debugdate' in the new module
r30516 else:
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 d = dateutil.parsedate(date)
Pulkit Goyal
py3: use '%d' for integers instead of '%s'...
r36417 ui.write(("internal: %d %d\n") % d)
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 ui.write(("standard: %s\n") % dateutil.datestr(d))
Gregory Szorc
debugcommands: move 'debugdate' in the new module
r30516 if range:
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 m = dateutil.matchdate(range)
Gregory Szorc
debugcommands: move 'debugdate' in the new module
r30516 ui.write(("match: %s\n") % m(d[0]))
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517
Gregory Szorc
debugcommands: sort command order...
r30541 @command('debugdeltachain',
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 cmdutil.debugrevlogopts + cmdutil.formatteropts,
Gregory Szorc
debugcommands: sort command order...
r30541 _('-c|-m|FILE'),
optionalrepo=True)
def debugdeltachain(ui, repo, file_=None, **opts):
"""dump information about delta chains in a revlog
Output can be templatized. Available template keywords are:
:``rev``: revision number
:``chainid``: delta chain identifier (numbered by unique base)
:``chainlen``: delta chain length to this revision
:``prevrev``: previous revision in delta chain
:``deltatype``: role of delta / how it was computed
:``compsize``: compressed size of revision
:``uncompsize``: uncompressed size of revision
:``chainsize``: total size of compressed revisions in chain
:``chainratio``: total chain size divided by uncompressed revision size
(new delta chains typically start at ratio 2.00)
:``lindist``: linear distance from base revision in delta chain to end
of this revision
:``extradist``: total size of revisions not part of this delta chain from
base of delta chain to end of this revision; a measurement
of how much extra data we need to read/seek across to read
the delta chain for this revision
:``extraratio``: extradist divided by chainsize; another representation of
how much unrelated data is needed to load this delta chain
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050
If the repository is configured to use the sparse read, additional keywords
are available:
:``readsize``: total size of data read from the disk for a revision
(sum of the sizes of all the blocks)
:``largestblock``: size of the largest block of data read from the disk
:``readdensity``: density of useful bytes in the data read from the disk
Paul Morelle
debugdeltachain: display how many chunks would be read in sparse-read mode
r35696 :``srchunks``: in how many data hunks the whole revision would be read
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050
The sparse read can be enabled with experimental.sparse-read = True
Gregory Szorc
debugcommands: sort command order...
r30541 """
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: sort command order...
r30541 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
index = r.index
Paul Morelle
debugdeltachain: r.start and r.length can be retrieved outside the loop
r38127 start = r.start
length = r.length
Gregory Szorc
revlog: rename constants (API)...
r32316 generaldelta = r.version & revlog.FLAG_GENERALDELTA
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 withsparseread = getattr(r, '_withsparseread', False)
Gregory Szorc
debugcommands: sort command order...
r30541
def revinfo(rev):
e = index[rev]
compsize = e[1]
uncompsize = e[2]
chainsize = 0
if generaldelta:
if e[3] == e[5]:
deltatype = 'p1'
elif e[3] == e[6]:
deltatype = 'p2'
elif e[3] == rev - 1:
deltatype = 'prev'
elif e[3] == rev:
deltatype = 'base'
else:
deltatype = 'other'
else:
if e[3] == rev:
deltatype = 'base'
else:
deltatype = 'prev'
chain = r._deltachain(rev)[0]
for iterrev in chain:
e = index[iterrev]
chainsize += e[1]
return compsize, uncompsize, deltatype, chain, chainsize
fm = ui.formatter('debugdeltachain', opts)
fm.plain(' rev chain# chainlen prev delta '
'size rawsize chainsize ratio lindist extradist '
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 'extraratio')
if withsparseread:
Paul Morelle
debugdeltachain: display how many chunks would be read in sparse-read mode
r35696 fm.plain(' readsize largestblk rddensity srchunks')
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 fm.plain('\n')
Gregory Szorc
debugcommands: sort command order...
r30541
chainbases = {}
for rev in r:
comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
chainbase = chain[0]
chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 basestart = start(chainbase)
revstart = start(rev)
Gregory Szorc
debugcommands: sort command order...
r30541 lineardist = revstart + comp - basestart
extradist = lineardist - chainsize
try:
prevrev = chain[-2]
except IndexError:
prevrev = -1
Paul Morelle
debugdeltachain: avoid division by zero when a chain is empty...
r38668 if uncomp != 0:
chainratio = float(chainsize) / float(uncomp)
else:
chainratio = chainsize
if chainsize != 0:
extraratio = float(extradist) / float(chainsize)
else:
extraratio = extradist
Gregory Szorc
debugcommands: sort command order...
r30541
fm.startitem()
fm.write('rev chainid chainlen prevrev deltatype compsize '
'uncompsize chainsize chainratio lindist extradist '
'extraratio',
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
Gregory Szorc
debugcommands: sort command order...
r30541 rev, chainid, len(chain), prevrev, deltatype, comp,
uncomp, chainsize, chainratio, lineardist, extradist,
extraratio,
rev=rev, chainid=chainid, chainlen=len(chain),
prevrev=prevrev, deltatype=deltatype, compsize=comp,
uncompsize=uncomp, chainsize=chainsize,
chainratio=chainratio, lindist=lineardist,
extradist=extradist, extraratio=extraratio)
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 if withsparseread:
readsize = 0
largestblock = 0
Paul Morelle
debugdeltachain: cleanup the double call to _slicechunk...
r35746 srchunks = 0
Boris Feld
revlog: split functionality related to deltas computation in a new module...
r39366 for revschunk in deltautil.slicechunk(r, chain):
Paul Morelle
debugdeltachain: cleanup the double call to _slicechunk...
r35746 srchunks += 1
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 blkend = start(revschunk[-1]) + length(revschunk[-1])
blksize = blkend - start(revschunk[0])
readsize += blksize
if largestblock < blksize:
largestblock = blksize
Boris Feld
debugdeltachain: protect against 0 readsize...
r38669 if readsize:
readdensity = float(chainsize) / float(readsize)
else:
readdensity = 1
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050
Paul Morelle
debugdeltachain: display how many chunks would be read in sparse-read mode
r35696 fm.write('readsize largestblock readdensity srchunks',
' %10d %10d %9.5f %8d',
readsize, largestblock, readdensity, srchunks,
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 readsize=readsize, largestblock=largestblock,
Paul Morelle
debugdeltachain: display how many chunks would be read in sparse-read mode
r35696 readdensity=readdensity, srchunks=srchunks)
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050
fm.plain('\n')
Gregory Szorc
debugcommands: sort command order...
r30541
fm.end()
Pierre-Yves David
debugcommands: move 'debugstate' in the new module
r30954 @command('debugdirstate|debugstate',
[('', 'nodates', None, _('do not display the saved mtime')),
('', 'datesort', None, _('sort by saved mtime'))],
_('[OPTION]...'))
def debugstate(ui, repo, **opts):
"""show the contents of the current dirstate"""
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 nodates = opts.get(r'nodates')
datesort = opts.get(r'datesort')
Pierre-Yves David
debugcommands: move 'debugstate' in the new module
r30954
timestr = ""
if datesort:
keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
else:
keyfunc = None # sort by filename
for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
if ent[3] == -1:
timestr = 'unset '
elif nodates:
timestr = 'set '
else:
Pulkit Goyal
py3: make sure the first argument of time.strftime() is str...
r35152 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
Pierre-Yves David
debugcommands: move 'debugstate' in the new module
r30954 time.localtime(ent[3]))
Pulkit Goyal
py3: use encoding.strtolocal() to convert string to bytes...
r35205 timestr = encoding.strtolocal(timestr)
Pierre-Yves David
debugcommands: move 'debugstate' in the new module
r30954 if ent[1] & 0o20000:
mode = 'lnk'
else:
mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
for f in repo.dirstate.copies():
ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 @command('debugdiscovery',
[('', 'old', None, _('use old-style discovery')),
('', 'nonheads', None,
_('use old-style discovery with non-heads included')),
Boris Feld
setdiscover: allow to ignore part of the local graph...
r35305 ('', 'rev', [], 'restrict discovery to this set of revs'),
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 ] + cmdutil.remoteopts,
Martin von Zweigbergk
debugdiscovery: correct and clean up command synopsis...
r35425 _('[--rev REV] [OTHER]'))
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 def debugdiscovery(ui, repo, remoteurl="default", **opts):
"""runs the changeset discovery protocol in isolation"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Martin von Zweigbergk
debugdiscovery: drop reference to invalid --branch option...
r35418 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 remote = hg.peer(repo, opts, remoteurl)
ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
# make sure tests are repeatable
random.seed(12323)
Boris Feld
setdiscover: allow to ignore part of the local graph...
r35305 def doit(pushedrevs, remoteheads, remote=remote):
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 if opts.get('old'):
if not util.safehasattr(remote, 'branches'):
# enable in-client legacy support
remote = localrepo.locallegacypeer(remote.local())
common, _in, hds = treediscovery.findcommonincoming(repo, remote,
force=True)
common = set(common)
if not opts.get('nonheads'):
ui.write(("unpruned common: %s\n") %
" ".join(sorted(short(n) for n in common)))
Gregory Szorc
debugcommands: use a revset instead of dagutil...
r39199
clnode = repo.changelog.node
common = repo.revs('heads(::%ln)', common)
common = {clnode(r) for r in common}
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 else:
Boris Feld
setdiscover: allow to ignore part of the local graph...
r35305 nodes = None
if pushedrevs:
revs = scmutil.revrange(repo, pushedrevs)
nodes = [repo[r].node() for r in revs]
common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
ancestorsof=nodes)
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 common = set(common)
rheads = set(hds)
lheads = set(repo.heads())
ui.write(("common heads: %s\n") %
" ".join(sorted(short(n) for n in common)))
if lheads <= common:
ui.write(("local is subset\n"))
elif rheads <= common:
ui.write(("remote is subset\n"))
Martin von Zweigbergk
debugdiscovery: drop reference to non-existent --remote-head option...
r35420 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
Martin von Zweigbergk
debugdiscovery: drop reference to non-existent --serverlog option...
r35419 localrevs = opts['rev']
doit(localrevs, remoterevs)
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518
Boris Feld
debug: add a 'debugdownload' command...
r35578 _chunksize = 4 << 10
@command('debugdownload',
[
('o', 'output', '', _('path')),
],
Boris Feld
debugdownload: read repository hgrc if there is one...
r35748 optionalrepo=True)
def debugdownload(ui, repo, url, output=None, **opts):
Boris Feld
debug: add a 'debugdownload' command...
r35578 """download a resource using Mercurial logic and config
"""
fh = urlmod.open(ui, url, output)
dest = ui
if output:
dest = open(output, "wb", _chunksize)
try:
data = fh.read(_chunksize)
while data:
dest.write(data)
data = fh.read(_chunksize)
finally:
if output:
dest.close()
Matt Harbison
debugextensions: process extensions loaded from the local repository too
r37998 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
def debugextensions(ui, repo, **opts):
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518 '''show information about active extensions'''
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518 exts = extensions.extensions(ui)
hgver = util.version()
fm = ui.formatter('debugextensions', opts)
for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
isinternal = extensions.ismoduleinternal(extmod)
Pulkit Goyal
py3: use pycompat.fsencode() to convert __file__ to bytes...
r31074 extsource = pycompat.fsencode(extmod.__file__)
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518 if isinternal:
exttestedwith = [] # never expose magic string to users
else:
exttestedwith = getattr(extmod, 'testedwith', '').split()
extbuglink = getattr(extmod, 'buglink', None)
fm.startitem()
if ui.quiet or ui.verbose:
fm.write('name', '%s\n', extname)
else:
fm.write('name', '%s', extname)
if isinternal or hgver in exttestedwith:
fm.plain('\n')
elif not exttestedwith:
fm.plain(_(' (untested!)\n'))
else:
lasttestedversion = exttestedwith[-1]
fm.plain(' (%s!)\n' % lasttestedversion)
fm.condwrite(ui.verbose and extsource, 'source',
_(' location: %s\n'), extsource or "")
if ui.verbose:
fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
fm.data(bundled=isinternal)
fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
_(' tested with: %s\n'),
fm.formatlist(exttestedwith, name='ver'))
fm.condwrite(ui.verbose and extbuglink, 'buglink',
_(' bug reporting: %s\n'), extbuglink or "")
fm.end()
Gregory Szorc
debugcommands: move 'debugfileset' in the new module
r30524
@command('debugfileset',
Yuya Nishihara
fileset: make debugfileset filter repository files...
r38629 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
('', 'all-files', False,
Yuya Nishihara
debugfileset: backport --show-stage option from debugrevspec...
r38837 _('test files from all revisions and working directory')),
Yuya Nishihara
debugfileset: add option to show matcher representation
r38838 ('s', 'show-matcher', None,
_('print internal representation of matcher')),
Yuya Nishihara
debugfileset: backport --show-stage option from debugrevspec...
r38837 ('p', 'show-stage', [],
_('print parsed tree at the given stage'), _('NAME'))],
_('[-r REV] [--all-files] [OPTION]... FILESPEC'))
Gregory Szorc
debugcommands: move 'debugfileset' in the new module
r30524 def debugfileset(ui, repo, expr, **opts):
'''parse and apply a fileset specification'''
Augie Fackler
debugcommands: force import of fileset in debugfileset...
r39008 from . import fileset
fileset.symbols # force import of fileset so we have predicates to optimize
Yuya Nishihara
fileset: make debugfileset filter repository files...
r38629 opts = pycompat.byteskwargs(opts)
ctx = scmutil.revsingle(repo, opts.get('rev'), None)
Yuya Nishihara
debugfileset: backport --show-stage option from debugrevspec...
r38837
stages = [
('parsed', pycompat.identity),
Yuya Nishihara
fileset: add phase to transform parsed tree...
r38862 ('analyzed', filesetlang.analyze),
Yuya Nishihara
fileset: add stub for weight-based optimization...
r38865 ('optimized', filesetlang.optimize),
Yuya Nishihara
debugfileset: backport --show-stage option from debugrevspec...
r38837 ]
stagenames = set(n for n, f in stages)
showalways = set()
if ui.verbose and not opts['show_stage']:
# show parsed tree by --verbose (deprecated)
showalways.add('parsed')
if opts['show_stage'] == ['all']:
showalways.update(stagenames)
else:
for n in opts['show_stage']:
if n not in stagenames:
raise error.Abort(_('invalid stage name: %s') % n)
showalways.update(opts['show_stage'])
Yuya Nishihara
fileset: extract language processing part to new module (API)...
r38841 tree = filesetlang.parse(expr)
Yuya Nishihara
debugfileset: backport --show-stage option from debugrevspec...
r38837 for n, f in stages:
tree = f(tree)
if n in showalways:
if opts['show_stage'] or n != 'parsed':
ui.write(("* %s:\n") % n)
Yuya Nishihara
fileset: extract language processing part to new module (API)...
r38841 ui.write(filesetlang.prettyformat(tree), "\n")
Gregory Szorc
debugcommands: move 'debugfileset' in the new module
r30524
Yuya Nishihara
fileset: make debugfileset filter repository files...
r38629 files = set()
if opts['all_files']:
for r in repo:
c = repo[r]
files.update(c.files())
files.update(c.substate)
if opts['all_files'] or ctx.rev() is None:
wctx = repo[None]
files.update(repo.dirstate.walk(scmutil.matchall(repo),
subrepos=list(wctx.substate),
unknown=True, ignored=True))
files.update(wctx.substate)
else:
files.update(ctx.files())
files.update(ctx.substate)
Yuya Nishihara
fileset: restrict getfileset() to not return a computed set (API)...
r38631 m = ctx.matchfileset(expr)
Yuya Nishihara
debugfileset: add option to show matcher representation
r38838 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
Yuya Nishihara
fileset: make debugfileset filter repository files...
r38629 for f in sorted(files):
if not m(f):
continue
Gregory Szorc
debugcommands: move 'debugfileset' in the new module
r30524 ui.write("%s\n" % f)
Gregory Szorc
debugcommands: move 'debugfsinfo' in the new module
r30525
Boris Feld
debugformat: add a 'debugformat' command...
r35337 @command('debugformat',
FUJIWARA Katsunori
i18n: omit redundant translatable synopsis text to avoid xgettext warning...
r38850 [] + cmdutil.formatteropts)
Boris Feld
debugformat: add a 'debugformat' command...
r35337 def debugformat(ui, repo, **opts):
Boris Feld
debugformat: add data about the config when verbose...
r35338 """display format information about the current repository
Use --verbose to get extra information about current config value and
Mercurial default."""
Pulkit Goyal
py3: handle keyword arguments correctly in debugcommands.py...
r35402 opts = pycompat.byteskwargs(opts)
Boris Feld
debugformat: add a 'debugformat' command...
r35337 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
maxvariantlength = max(len('format-variant'), maxvariantlength)
def makeformatname(name):
return '%s:' + (' ' * (maxvariantlength - len(name)))
Yuya Nishihara
debugformat: embed raw values in JSON and template output
r35379 fm = ui.formatter('debugformat', opts)
if fm.isplain():
def formatvalue(value):
if util.safehasattr(value, 'startswith'):
return value
if value:
return 'yes'
else:
return 'no'
else:
formatvalue = pycompat.identity
Boris Feld
debugformat: add a 'debugformat' command...
r35337
fm.plain('format-variant')
fm.plain(' ' * (maxvariantlength - len('format-variant')))
fm.plain(' repo')
Boris Feld
debugformat: add data about the config when verbose...
r35338 if ui.verbose:
fm.plain(' config default')
Boris Feld
debugformat: add a 'debugformat' command...
r35337 fm.plain('\n')
for fv in upgrade.allformatvariant:
Yuya Nishihara
debugformat: flush formatter output per item
r35378 fm.startitem()
Boris Feld
debugformat: add a 'debugformat' command...
r35337 repovalue = fv.fromrepo(repo)
Boris Feld
debugformat: add data about the config when verbose...
r35338 configvalue = fv.fromconfig(repo)
Boris Feld
debugformat: add a 'debugformat' command...
r35337
Boris Feld
debugformat: update label depending on value difference...
r35339 if repovalue != configvalue:
namelabel = 'formatvariant.name.mismatchconfig'
repolabel = 'formatvariant.repo.mismatchconfig'
elif repovalue != fv.default:
namelabel = 'formatvariant.name.mismatchdefault'
repolabel = 'formatvariant.repo.mismatchdefault'
else:
namelabel = 'formatvariant.name.uptodate'
repolabel = 'formatvariant.repo.uptodate'
Boris Feld
debugformat: add a 'debugformat' command...
r35337 fm.write('name', makeformatname(fv.name), fv.name,
Boris Feld
debugformat: update label depending on value difference...
r35339 label=namelabel)
Boris Feld
debugformat: add a 'debugformat' command...
r35337 fm.write('repo', ' %3s', formatvalue(repovalue),
Boris Feld
debugformat: update label depending on value difference...
r35339 label=repolabel)
if fv.default != configvalue:
configlabel = 'formatvariant.config.special'
else:
configlabel = 'formatvariant.config.default'
Boris Feld
debugformat: add data about the config when verbose...
r35338 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
Boris Feld
debugformat: update label depending on value difference...
r35339 label=configlabel)
Boris Feld
debugformat: add data about the config when verbose...
r35338 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
label='formatvariant.default')
Boris Feld
debugformat: add a 'debugformat' command...
r35337 fm.plain('\n')
Yuya Nishihara
debugformat: flush formatter output per item
r35378 fm.end()
Boris Feld
debugformat: add a 'debugformat' command...
r35337
Gregory Szorc
debugcommands: move 'debugfsinfo' in the new module
r30525 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
def debugfsinfo(ui, path="."):
"""show information detected about current filesystem"""
Matt Harbison
debugfs: display the tested path and mount point of the filesystem, if known...
r35532 ui.write(('path: %s\n') % path)
ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
Gregory Szorc
debugcommands: move 'debugfsinfo' in the new module
r30525 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
Jun Wu
debugfsinfo: show fstype for given path
r31633 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
Gregory Szorc
debugcommands: move 'debugfsinfo' in the new module
r30525 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
Jun Wu
debugfsinfo: improve case-sensitive testing...
r31634 casesensitive = '(unknown)'
try:
Yuya Nishihara
py3: wrap tempfile.NamedTemporaryFile() to return bytes fp.name...
r38184 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
Jun Wu
debugfsinfo: improve case-sensitive testing...
r31634 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
except OSError:
pass
ui.write(('case-sensitive: %s\n') % casesensitive)
Gregory Szorc
debugcommands: move 'debuggetbundle' in the new module
r30526
@command('debuggetbundle',
[('H', 'head', [], _('id of head node'), _('ID')),
('C', 'common', [], _('id of common node'), _('ID')),
('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
_('REPO FILE [-H|-C ID]...'),
norepo=True)
def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
"""retrieves a bundle from a repo
Every ID must be a full-length hex node id string. Saves the bundle to the
given file.
"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: move 'debuggetbundle' in the new module
r30526 repo = hg.peer(ui, opts, repopath)
if not repo.capable('getbundle'):
raise error.Abort("getbundle() not supported by target repository")
args = {}
if common:
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 args[r'common'] = [bin(s) for s in common]
Gregory Szorc
debugcommands: move 'debuggetbundle' in the new module
r30526 if head:
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 args[r'heads'] = [bin(s) for s in head]
Gregory Szorc
debugcommands: move 'debuggetbundle' in the new module
r30526 # TODO: get desired bundlecaps from command line.
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 args[r'bundlecaps'] = None
Gregory Szorc
debugcommands: move 'debuggetbundle' in the new module
r30526 bundle = repo.getbundle('debug', **args)
bundletype = opts.get('type', 'bzip2').lower()
btypes = {'none': 'HG10UN',
'bzip2': 'HG10BZ',
'gzip': 'HG10GZ',
'bundle2': 'HG20'}
bundletype = btypes.get(bundletype)
if bundletype not in bundle2.bundletypes:
raise error.Abort(_('unknown bundle type specified with --type'))
bundle2.writebundle(ui, bundle, bundlepath, bundletype)
Gregory Szorc
debugcommands: move 'debugignore' in the new module
r30527
@command('debugignore', [], '[FILE]')
def debugignore(ui, repo, *files, **opts):
"""display the combined ignore pattern and information about ignored files
With no argument display the combined ignore pattern.
Given space separated file names, shows if the given file is ignored and
if so, show the ignore rule (file and line number) that matched it.
"""
ignore = repo.dirstate._ignore
if not files:
# Show all the patterns
Augie Fackler
debugcommands: fix repr in debugignore print with pycompat.bytestr...
r36596 ui.write("%s\n" % pycompat.byterepr(ignore))
Gregory Szorc
debugcommands: move 'debugignore' in the new module
r30527 else:
Matt Harbison
debugignore: eliminate inconsistencies with `hg status` (issue5222)...
r33507 m = scmutil.match(repo[None], pats=files)
for f in m.files():
Gregory Szorc
debugcommands: move 'debugignore' in the new module
r30527 nf = util.normpath(f)
ignored = None
ignoredata = None
if nf != '.':
if ignore(nf):
ignored = nf
ignoredata = repo.dirstate._ignorefileandline(nf)
else:
for p in util.finddirs(nf):
if ignore(p):
ignored = p
ignoredata = repo.dirstate._ignorefileandline(p)
break
if ignored:
if ignored == nf:
Matt Harbison
debugignore: eliminate inconsistencies with `hg status` (issue5222)...
r33507 ui.write(_("%s is ignored\n") % m.uipath(f))
Gregory Szorc
debugcommands: move 'debugignore' in the new module
r30527 else:
ui.write(_("%s is ignored because of "
"containing folder %s\n")
Matt Harbison
debugignore: eliminate inconsistencies with `hg status` (issue5222)...
r33507 % (m.uipath(f), ignored))
Gregory Szorc
debugcommands: move 'debugignore' in the new module
r30527 ignorefile, lineno, line = ignoredata
ui.write(_("(ignore rule in %s, line %d: '%s')\n")
% (ignorefile, lineno, line))
else:
Matt Harbison
debugignore: eliminate inconsistencies with `hg status` (issue5222)...
r33507 ui.write(_("%s is not ignored\n") % m.uipath(f))
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528
Gregory Szorc
debugcommands: introduce debugrevlogindex (BC)...
r39318 @command('debugindex', cmdutil.debugrevlogopts + cmdutil.formatteropts,
_('-c|-m|FILE'))
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 def debugindex(ui, repo, file_=None, **opts):
Gregory Szorc
debugcommands: introduce debugrevlogindex (BC)...
r39318 """dump index data for a storage primitive"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: introduce debugrevlogindex (BC)...
r39318 store = cmdutil.openstorage(repo, 'debugindex', file_, opts)
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528
if ui.debugflag:
shortfn = hex
else:
shortfn = short
idlen = 12
Gregory Szorc
debugcommands: introduce debugrevlogindex (BC)...
r39318 for i in store:
idlen = len(shortfn(store.node(i)))
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 break
Gregory Szorc
debugcommands: introduce debugrevlogindex (BC)...
r39318 fm = ui.formatter('debugindex', opts)
fm.plain(b' rev linkrev %s %s p2\n' % (
b'nodeid'.ljust(idlen),
b'p1'.ljust(idlen)))
for rev in store:
node = store.node(rev)
parents = store.parents(node)
fm.startitem()
fm.write(b'rev', b'%6d ', rev)
fm.write(b'linkrev', '%7d ', store.linkrev(rev))
fm.write(b'node', '%s ', shortfn(node))
fm.write(b'p1', '%s ', shortfn(parents[0]))
fm.write(b'p2', '%s', shortfn(parents[1]))
fm.plain(b'\n')
fm.end()
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debugindexdot', cmdutil.debugrevlogopts,
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 _('-c|-m|FILE'), optionalrepo=True)
def debugindexdot(ui, repo, file_=None, **opts):
"""dump an index DAG as a graphviz dot file"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: use openstorage() in debugindexdot...
r39315 r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts)
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 ui.write(("digraph G {\n"))
for i in r:
node = r.node(i)
pp = r.parents(node)
ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
if pp[1] != nullid:
ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
ui.write("}\n")
Gregory Szorc
debugcommands: stub for debugupgraderepo command...
r30774
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 def debuginstall(ui, **opts):
'''test Mercurial installation
Returns 0 on success.
'''
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918
def writetemp(contents):
Yuya Nishihara
py3: wrap tempfile.mkstemp() to use bytes path...
r38182 (fd, name) = pycompat.mkstemp(prefix="hg-debuginstall-")
Yuya Nishihara
py3: use r'' instead of sysstr('') to get around code transformer...
r36853 f = os.fdopen(fd, r"wb")
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 f.write(contents)
f.close()
return name
problems = 0
fm = ui.formatter('debuginstall', opts)
fm.startitem()
# encoding
fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
err = None
try:
Yuya Nishihara
debuginstall: use codecs.lookup() to detect invalid encoding...
r34131 codecs.lookup(pycompat.sysstr(encoding.encoding))
except LookupError as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 err = stringutil.forcebytestr(inst)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 problems += 1
fm.condwrite(err, 'encodingerror', _(" %s\n"
" (check that your locale is properly set)\n"), err)
# Python
fm.write('pythonexe', _("checking Python executable (%s)\n"),
pycompat.sysexecutable)
fm.write('pythonver', _("checking Python version (%s)\n"),
("%d.%d.%d" % sys.version_info[:3]))
fm.write('pythonlib', _("checking Python lib (%s)...\n"),
os.path.dirname(pycompat.fsencode(os.__file__)))
security = set(sslutil.supportedprotocols)
if sslutil.hassni:
security.add('sni')
fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
fm.formatlist(sorted(security), name='protocol',
fmt='%s', sep=','))
# These are warnings, not errors. So don't increment problem count. This
# may change in the future.
if 'tls1.2' not in security:
fm.plain(_(' TLS 1.2 not supported by Python install; '
'network connections lack modern security\n'))
if 'sni' not in security:
fm.plain(_(' SNI not supported by Python install; may have '
'connectivity issues with some servers\n'))
# TODO print CA cert info
# hg version
hgver = util.version()
fm.write('hgver', _("checking Mercurial version (%s)\n"),
hgver.split('+')[0])
fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
'+'.join(hgver.split('+')[1:]))
# compiled modules
fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
policy.policy)
fm.write('hgmodules', _("checking installed modules (%s)...\n"),
Pulkit Goyal
py3: use pycompat.fsencode() to convert __file__ to bytes...
r31074 os.path.dirname(pycompat.fsencode(__file__)))
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918
Yuya Nishihara
debuginstall: check C extensions only if they are loadable per policy...
r32204 if policy.policy in ('c', 'allow'):
err = None
try:
Yuya Nishihara
osutil: switch to policy importer...
r32367 from .cext import (
Yuya Nishihara
base85: switch to policy importer
r32368 base85,
Yuya Nishihara
bdiff: switch to policy importer...
r32369 bdiff,
Yuya Nishihara
mpatch: switch to policy importer
r32371 mpatch,
Yuya Nishihara
debuginstall: check C extensions only if they are loadable per policy...
r32204 osutil,
)
dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
except Exception as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 err = stringutil.forcebytestr(inst)
Yuya Nishihara
debuginstall: check C extensions only if they are loadable per policy...
r32204 problems += 1
fm.condwrite(err, 'extensionserror', " %s\n", err)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918
compengines = util.compengines._engines.values()
fm.write('compengines', _('checking registered compression engines (%s)\n'),
fm.formatlist(sorted(e.name() for e in compengines),
name='compengine', fmt='%s', sep=', '))
fm.write('compenginesavail', _('checking available compression engines '
'(%s)\n'),
fm.formatlist(sorted(e.name() for e in compengines
if e.available()),
name='compengine', fmt='%s', sep=', '))
wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
fm.write('compenginesserver', _('checking available compression engines '
'for wire protocol (%s)\n'),
fm.formatlist([e.name() for e in wirecompengines
if e.wireprotosupport()],
name='compengine', fmt='%s', sep=', '))
Boris Feld
debuginstall: add a line about re2 availability...
r35464 re2 = 'missing'
if util._re2:
re2 = 'available'
fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
fm.data(re2=bool(util._re2))
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918
# templates
p = templater.templatepaths()
fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
fm.condwrite(not p, '', _(" no template directories found\n"))
if p:
m = templater.templatepath("map-cmdline.default")
if m:
# template found, check if it is working
err = None
try:
templater.templater.frommapfile(m)
except Exception as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 err = stringutil.forcebytestr(inst)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 p = None
fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
else:
p = None
fm.condwrite(p, 'defaulttemplate',
_("checking default template (%s)\n"), m)
fm.condwrite(not m, 'defaulttemplatenotfound',
_(" template '%s' not found\n"), "default")
if not p:
problems += 1
fm.condwrite(not p, '',
_(" (templates seem to have been installed incorrectly)\n"))
# editor
editor = ui.geteditor()
editor = util.expandpath(editor)
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 editorbin = procutil.shellsplit(editor)[0]
Kyle Lippincott
debugcommands: print out the editor that was searched for (post shlexsplit)...
r36254 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 cmdpath = procutil.findexe(editorbin)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
_(" No commit editor set and can't find %s in PATH\n"
" (specify a commit editor in your configuration"
Kyle Lippincott
debugcommands: print out the editor that was searched for (post shlexsplit)...
r36254 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
_(" Can't find editor '%s' in PATH\n"
" (specify a commit editor in your configuration"
Kyle Lippincott
debugcommands: print out the editor that was searched for (post shlexsplit)...
r36254 " file)\n"), not cmdpath and editorbin)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 if not cmdpath and editor != 'vi':
problems += 1
# check username
username = None
err = None
try:
username = ui.username()
except error.Abort as e:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 err = stringutil.forcebytestr(e)
Pierre-Yves David
debugcommands: extract debuginstall in the debugcommands module
r30918 problems += 1
fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
" (specify a username in your configuration file)\n"), err)
fm.condwrite(not problems, '',
_("no problems detected\n"))
if not problems:
fm.data(problems=problems)
fm.condwrite(problems, 'problems',
_("%d problems detected,"
" please check your install!\n"), problems)
fm.end()
return problems
Pierre-Yves David
debugcommands: move 'debugknown' in the new module
r30919 @command('debugknown', [], _('REPO ID...'), norepo=True)
def debugknown(ui, repopath, *ids, **opts):
"""test whether node ids are known to a repo
Every ID must be a full-length hex node id string. Returns a list of 0s
and 1s indicating unknown/known.
"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: move 'debugknown' in the new module
r30919 repo = hg.peer(ui, opts, repopath)
if not repo.capable('known'):
raise error.Abort("known() not supported by target repository")
flags = repo.known([bin(s) for s in ids])
ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
Pierre-Yves David
debugcommands: move 'debuglabelcomplete' in the new module
r30935 @command('debuglabelcomplete', [], _('LABEL...'))
def debuglabelcomplete(ui, repo, *args):
'''backwards compatibility with old bash completion scripts (DEPRECATED)'''
Kyle Lippincott
debuglabelcomplete: fix to call debugnamecomplete in new location...
r31402 debugnamecomplete(ui, repo, *args)
Pierre-Yves David
debugcommands: move 'debuglabelcomplete' in the new module
r30935
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 @command('debuglocks',
[('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
('W', 'force-wlock', None,
Paul Morelle
debuglocks: allow setting a lock
r35396 _('free the working state lock (DANGEROUS)')),
('s', 'set-lock', None, _('set the store lock until stopped')),
('S', 'set-wlock', None,
_('set the working state lock until stopped'))],
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 _('[OPTION]...'))
def debuglocks(ui, repo, **opts):
"""show or modify state of locks
By default, this command will show which locks are held. This
includes the user and process holding the lock, the amount of time
the lock has been held, and the machine name where the process is
running if it's not local.
Locks protect the integrity of Mercurial's data, so should be
treated with care. System crashes or other interruptions may cause
locks to not be properly released, though Mercurial will usually
detect and remove such stale locks automatically.
However, detecting stale locks may not always be possible (for
instance, on a shared filesystem). Removing locks may also be
blocked by filesystem permissions.
Paul Morelle
debuglocks: allow setting a lock
r35396 Setting a lock will prevent other commands from changing the data.
The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
The set locks are removed when the command exits.
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 Returns 0 if no locks are held.
"""
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts.get(r'force_lock'):
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 repo.svfs.unlink('lock')
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts.get(r'force_wlock'):
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 repo.vfs.unlink('wlock')
Paul Morelle
debuglocks: add tests (and fix typo in early return)
r35395 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 return 0
Paul Morelle
debuglocks: allow setting a lock
r35396 locks = []
try:
if opts.get(r'set_wlock'):
try:
locks.append(repo.wlock(False))
except error.LockHeld:
raise error.Abort(_('wlock is already held'))
if opts.get(r'set_lock'):
try:
locks.append(repo.lock(False))
except error.LockHeld:
raise error.Abort(_('lock is already held'))
if len(locks):
ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
return 0
finally:
release(*locks)
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 now = time.time()
held = 0
def report(vfs, name, method):
# this causes stale locks to get reaped for more accurate reporting
try:
l = method(False)
except error.LockHeld:
l = None
if l:
l.release()
else:
try:
Augie Fackler
cleanup: use stat_result[stat.ST_MTIME] instead of stat_result.st_mtime...
r36799 st = vfs.lstat(name)
age = now - st[stat.ST_MTIME]
user = util.username(st.st_uid)
Pierre-Yves David
debugcommands: move 'debuglocks' in the new module
r30938 locker = vfs.readlock(name)
if ":" in locker:
host, pid = locker.split(':')
if host == socket.gethostname():
locker = 'user %s, process %s' % (user, pid)
else:
locker = 'user %s, process %s, host %s' \
% (user, pid, host)
ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
return 1
except OSError as e:
if e.errno != errno.ENOENT:
raise
ui.write(("%-6s free\n") % (name + ":"))
return 0
held += report(repo.svfs, "lock", repo.lock)
held += report(repo.vfs, "wlock", repo.wlock)
return held
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 @command('debugmanifestfulltextcache', [
('', 'clear', False, _('clear the cache')),
('a', 'add', '', _('add the given manifest node to the cache'),
_('NODE'))
], '')
def debugmanifestfulltextcache(ui, repo, add=None, **opts):
"""show, clear or amend the contents of the manifest fulltext cache"""
with repo.lock():
Gregory Szorc
manifest: add getstorage() to manifestlog and use it globally...
r39280 r = repo.manifestlog.getstorage(b'')
Martijn Pieters
manifest: persist the manifestfulltext cache...
r38803 try:
cache = r._fulltextcache
except AttributeError:
ui.warn(_(
"Current revlog implementation doesn't appear to have a "
'manifest fulltext cache\n'))
return
if opts.get(r'clear'):
cache.clear()
if add:
try:
manifest = repo.manifestlog[r.lookup(add)]
except error.LookupError as e:
raise error.Abort(e, hint="Check your manifest node id")
manifest.read() # stores revisision in cache too
if not len(cache):
ui.write(_('Cache empty'))
else:
ui.write(
_('Cache contains %d manifest entries, in order of most to '
'least recent:\n') % (len(cache),))
totalsize = 0
for nodeid in cache:
# Use cache.get to not update the LRU order
data = cache.get(nodeid)
size = len(data)
totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
ui.write(_('id: %s, size %s\n') % (
hex(nodeid), util.bytecount(size)))
ondisk = cache._opener.stat('manifestfulltextcache').st_size
ui.write(
_('Total cache data size %s, on-disk %s\n') % (
util.bytecount(totalsize), util.bytecount(ondisk))
)
Pierre-Yves David
debugcommands: move 'debugmergestate' in the new module
r30936 @command('debugmergestate', [], '')
def debugmergestate(ui, repo, *args):
"""print merge state
Use --verbose to print out information about whether v1 or v2 merge state
was chosen."""
def _hashornull(h):
if h == nullhex:
return 'null'
else:
return h
def printrecords(version):
Augie Fackler
debugcommands: mergestate version is an int, use %d on it...
r36171 ui.write(('* version %d records\n') % version)
Pierre-Yves David
debugcommands: move 'debugmergestate' in the new module
r30936 if version == 1:
records = v1records
else:
records = v2records
for rtype, record in records:
# pretty print some record types
if rtype == 'L':
ui.write(('local: %s\n') % record)
elif rtype == 'O':
ui.write(('other: %s\n') % record)
elif rtype == 'm':
driver, mdstate = record.split('\0', 1)
ui.write(('merge driver: %s (state "%s")\n')
% (driver, mdstate))
elif rtype in 'FDC':
r = record.split('\0')
f, state, hash, lfile, afile, anode, ofile = r[0:7]
if version == 1:
onode = 'not stored in v1 format'
flags = r[7]
else:
onode, flags = r[7:9]
ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
% (f, rtype, state, _hashornull(hash)))
ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
ui.write((' ancestor path: %s (node %s)\n')
% (afile, _hashornull(anode)))
ui.write((' other path: %s (node %s)\n')
% (ofile, _hashornull(onode)))
elif rtype == 'f':
filename, rawextras = record.split('\0', 1)
extras = rawextras.split('\0')
i = 0
extrastrings = []
while i < len(extras):
extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
i += 2
ui.write(('file extras: %s (%s)\n')
% (filename, ', '.join(extrastrings)))
elif rtype == 'l':
labels = record.split('\0', 2)
labels = [l for l in labels if len(l) > 0]
ui.write(('labels:\n'))
ui.write((' local: %s\n' % labels[0]))
ui.write((' other: %s\n' % labels[1]))
if len(labels) > 2:
ui.write((' base: %s\n' % labels[2]))
else:
ui.write(('unrecognized entry: %s\t%s\n')
% (rtype, record.replace('\0', '\t')))
# Avoid mergestate.read() since it may raise an exception for unsupported
# merge state records. We shouldn't be doing this, but this is OK since this
# command is pretty low-level.
ms = mergemod.mergestate(repo)
# sort so that reasonable information is on top
v1records = ms._readrecordsv1()
v2records = ms._readrecordsv2()
order = 'LOml'
def key(r):
idx = order.find(r[0])
if idx == -1:
return (1, r[1])
else:
return (0, idx)
v1records.sort(key=key)
v2records.sort(key=key)
if not v1records and not v2records:
ui.write(('no merge state found\n'))
elif not v2records:
ui.note(('no version 2 merge state\n'))
printrecords(1)
elif ms._v1v2match(v1records, v2records):
ui.note(('v1 and v2 states match: using v2\n'))
printrecords(2)
else:
ui.note(('v1 and v2 states mismatch: using v1\n'))
printrecords(1)
if ui.verbose:
printrecords(2)
Pierre-Yves David
debugcommands: move 'debugnamecomplete' in the new module
r30937 @command('debugnamecomplete', [], _('NAME...'))
def debugnamecomplete(ui, repo, *args):
'''complete "names" - tags, open branch names, bookmark names'''
names = set()
# since we previously only listed open branches, we will handle that
# specially (after this for loop)
for name, ns in repo.names.iteritems():
if name != 'branches':
names.update(ns.listnames(repo))
names.update(tag for (tag, heads, tip, closed)
in repo.branchmap().iterbranches() if not closed)
completions = set()
if not args:
args = ['']
for a in args:
completions.update(n for n in names if n.startswith(a))
ui.write('\n'.join(sorted(completions)))
ui.write('\n')
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 @command('debugobsolete',
[('', 'flags', 0, _('markers flag')),
('', 'record-parents', False,
_('record parent information for the precursor')),
('r', 'rev', [], _('display markers relevant to REV')),
obsolete: add a function to compute "exclusive-markers" for a set of nodes...
r32626 ('', 'exclusive', False, _('restrict display to markers only '
'relevant to REV')),
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 ('', 'index', False, _('display index of the marker')),
('', 'delete', [], _('delete markers specified by indices')),
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 _('[OBSOLETED [REPLACEMENT ...]]'))
def debugobsolete(ui, repo, precursor=None, *successors, **opts):
"""create arbitrary obsolete marker
With no arguments, displays the list of obsolescence markers."""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 def parsenodeid(s):
try:
# We do not use revsingle/revrange functions here to accept
# arbitrary node identifiers, possibly not present in the
# local repository.
n = bin(s)
if len(n) != len(nullid):
raise TypeError()
return n
except TypeError:
raise error.Abort('changeset references must be full hexadecimal '
'node identifiers')
if opts.get('delete'):
indices = []
for v in opts.get('delete'):
try:
indices.append(int(v))
except ValueError:
raise error.Abort(_('invalid index value: %r') % v,
hint=_('use integers for indices'))
if repo.currenttransaction():
raise error.Abort(_('cannot delete obsmarkers in the middle '
'of transaction.'))
with repo.lock():
n = repair.deleteobsmarkers(repo.obsstore, indices)
ui.write(_('deleted %i obsolescence markers\n') % n)
return
if precursor is not None:
if opts['rev']:
raise error.Abort('cannot select revision when creating marker')
metadata = {}
Yuya Nishihara
obsolete: store user name and note in UTF-8 (issue5754) (BC)...
r38729 metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 succs = tuple(parsenodeid(succ) for succ in successors)
l = repo.lock()
try:
tr = repo.transaction('debugobsolete')
try:
date = opts.get('date')
if date:
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 date = dateutil.parsedate(date)
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 else:
date = None
prec = parsenodeid(precursor)
parents = None
if opts['record_parents']:
if prec not in repo.unfiltered():
raise error.Abort('cannot used --record-parents on '
'unknown changesets')
parents = repo.unfiltered()[prec].parents()
parents = tuple(p.node() for p in parents)
repo.obsstore.create(tr, prec, succs, opts['flags'],
parents=parents, date=date,
Boris Feld
devel: use default-date config field when creating obsmarkers...
r32411 metadata=metadata, ui=ui)
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 tr.close()
except ValueError as exc:
Pulkit Goyal
py3: use pycompat.bytestr() to convert error instances to bytes...
r36510 raise error.Abort(_('bad obsmarker input: %s') %
pycompat.bytestr(exc))
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 finally:
tr.release()
finally:
l.release()
else:
if opts['rev']:
revs = scmutil.revrange(repo, opts['rev'])
nodes = [repo[r].node() for r in revs]
obsutil: move 'getmarkers' to the new modules...
r33150 markers = list(obsutil.getmarkers(repo, nodes=nodes,
obsolete: add a function to compute "exclusive-markers" for a set of nodes...
r32626 exclusive=opts['exclusive']))
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 markers.sort(key=lambda x: x._data)
else:
obsutil: move 'getmarkers' to the new modules...
r33150 markers = obsutil.getmarkers(repo)
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939
markerstoiter = markers
isrelevant = lambda m: True
if opts.get('rev') and opts.get('index'):
obsutil: move 'getmarkers' to the new modules...
r33150 markerstoiter = obsutil.getmarkers(repo)
Pierre-Yves David
debugcommands: move 'debugobsolete' in the new module
r30939 markerset = set(markers)
isrelevant = lambda m: m in markerset
fm = ui.formatter('debugobsolete', opts)
for i, m in enumerate(markerstoiter):
if not isrelevant(m):
# marker can be irrelevant when we're iterating over a set
# of markers (markerstoiter) which is bigger than the set
# of markers we want to display (markers)
# this can happen if both --index and --rev options are
# provided and thus we need to iterate over all of the markers
# to get the correct indices, but only display the ones that
# are relevant to --rev value
continue
fm.startitem()
ind = i if opts.get('index') else None
cmdutil.showmarker(fm, m, index=ind)
fm.end()
Pierre-Yves David
debugcommands: move 'debugpathcomplete' in the new module
r30940 @command('debugpathcomplete',
[('f', 'full', None, _('complete an entire path')),
('n', 'normal', None, _('show only normal files')),
('a', 'added', None, _('show only added files')),
('r', 'removed', None, _('show only removed files'))],
_('FILESPEC...'))
def debugpathcomplete(ui, repo, *specs, **opts):
'''complete part or all of a tracked path
This command supports shells that offer path name completion. It
currently completes only files already known to the dirstate.
Completion extends only to the next path segment unless
--full is specified, in which case entire paths are used.'''
def complete(path, acceptable):
dirstate = repo.dirstate
spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
rootdir = repo.root + pycompat.ossep
if spec != repo.root and not spec.startswith(rootdir):
return [], []
if os.path.isdir(spec):
spec += '/'
spec = spec[len(rootdir):]
fixpaths = pycompat.ossep != '/'
if fixpaths:
spec = spec.replace(pycompat.ossep, '/')
speclen = len(spec)
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 fullpaths = opts[r'full']
Pierre-Yves David
debugcommands: move 'debugpathcomplete' in the new module
r30940 files, dirs = set(), set()
adddir, addfile = dirs.add, files.add
for f, st in dirstate.iteritems():
if f.startswith(spec) and st[0] in acceptable:
if fixpaths:
f = f.replace('/', pycompat.ossep)
if fullpaths:
addfile(f)
continue
s = f.find(pycompat.ossep, speclen)
if s >= 0:
adddir(f[:s])
else:
addfile(f)
return files, dirs
acceptable = ''
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts[r'normal']:
Pierre-Yves David
debugcommands: move 'debugpathcomplete' in the new module
r30940 acceptable += 'nm'
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts[r'added']:
Pierre-Yves David
debugcommands: move 'debugpathcomplete' in the new module
r30940 acceptable += 'a'
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts[r'removed']:
Pierre-Yves David
debugcommands: move 'debugpathcomplete' in the new module
r30940 acceptable += 'r'
cwd = repo.getcwd()
if not specs:
specs = ['.']
files, dirs = set(), set()
for spec in specs:
f, d = complete(spec, acceptable or 'nmar')
files.update(f)
dirs.update(d)
files.update(dirs)
ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
ui.write('\n')
Gregory Szorc
debugcommands: introduce debugpeer command...
r35947 @command('debugpeer', [], _('PATH'), norepo=True)
def debugpeer(ui, path):
"""establish a connection to a peer repository"""
# Always enable peer request logging. Requires --debug to display
# though.
overrides = {
('devel', 'debug.peer-request'): True,
}
with ui.configoverride(overrides):
peer = hg.peer(ui, {}, path)
local = peer.local() is not None
canpush = peer.canpush()
ui.write(_('url: %s\n') % peer.url())
ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256 @command('debugpickmergetool',
[('r', 'rev', '', _('check for files in this revision'), _('REV')),
('', 'changedelete', None, _('emulate merging change and delete')),
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256 _('[PATTERN]...'),
inferrepo=True)
def debugpickmergetool(ui, repo, *pats, **opts):
"""examine which merge tool is chosen for specified file
As described in :hg:`help merge-tools`, Mercurial examines
configurations below in this order to decide which merge tool is
chosen for specified file.
1. ``--tool`` option
2. ``HGMERGE`` environment variable
3. configurations in ``merge-patterns`` section
4. configuration of ``ui.merge``
5. configurations in ``merge-tools`` section
6. ``hgmerge`` tool (for historical reason only)
7. default tool for fallback (``:merge`` or ``:prompt``)
This command writes out examination result in the style below::
FILE = MERGETOOL
By default, all files known in the first parent context of the
working directory are examined. Use file patterns and/or -I/-X
options to limit target files. -r/--rev is also useful to examine
files in another context without actual updating to it.
With --debug, this command shows warning messages while matching
against ``merge-patterns`` and so on, too. It is recommended to
use this option with explicit file patterns and/or -I/-X options,
because this option increases amount of output per file according
to configurations in hgrc.
With -v/--verbose, this command shows configurations below at
first (only if specified).
- ``--tool`` option
- ``HGMERGE`` environment variable
- configuration of ``ui.merge``
If merge tool is chosen before matching against
``merge-patterns``, this command can't show any helpful
information, even with --debug. In such case, information above is
useful to know why a merge tool is chosen.
"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256 overrides = {}
if opts['tool']:
overrides[('ui', 'forcemerge')] = opts['tool']
Augie Fackler
debugcommands: fix some %r output with bytestr() wrappers...
r36796 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256
with ui.configoverride(overrides, 'debugmergepatterns'):
hgmerge = encoding.environ.get("HGMERGE")
if hgmerge is not None:
Augie Fackler
debugcommands: fix some %r output with bytestr() wrappers...
r36796 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256 uimerge = ui.config("ui", "merge")
if uimerge:
Augie Fackler
debugcommands: fix some %r output with bytestr() wrappers...
r36796 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
FUJIWARA Katsunori
debugcommands: add debugpickmergetool to examine which merge tool is chosen...
r32256
ctx = scmutil.revsingle(repo, opts.get('rev'))
m = scmutil.match(ctx, pats, opts)
changedelete = opts['changedelete']
for path in ctx.walk(m):
fctx = ctx[path]
try:
if not ui.debugflag:
ui.pushbuffer(error=True)
tool, toolpath = filemerge._picktool(repo, ui, path,
fctx.isbinary(),
'l' in fctx.flags(),
changedelete)
finally:
if not ui.debugflag:
ui.popbuffer()
ui.write(('%s = %s\n') % (path, tool))
Pierre-Yves David
debugcommands: move 'debugpushkey' in the new module
r30946 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
'''access the pushkey key/value protocol
With two args, list the keys in the given namespace.
With five args, set a key to new if it currently is set to old.
Reports success or failure.
'''
target = hg.peer(ui, {}, repopath)
if keyinfo:
key, old, new = keyinfo
Gregory Szorc
exchange: use command executor for pushkey...
r37665 with target.commandexecutor() as e:
r = e.callcommand('pushkey', {
'namespace': namespace,
'key': key,
'old': old,
'new': new,
}).result()
Pulkit Goyal
py3: use pycompat.bytestr instead of str...
r36736 ui.status(pycompat.bytestr(r) + '\n')
Pierre-Yves David
debugcommands: move 'debugpushkey' in the new module
r30946 return not r
else:
for k, v in sorted(target.listkeys(namespace).iteritems()):
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
stringutil.escapestr(v)))
Pierre-Yves David
debugcommands: move 'debugpushkey' in the new module
r30946
Pierre-Yves David
debugcommands: move 'debugpvec' in the new module
r30947 @command('debugpvec', [], _('A B'))
def debugpvec(ui, repo, a, b=None):
ca = scmutil.revsingle(repo, a)
cb = scmutil.revsingle(repo, b)
pa = pvec.ctxpvec(ca)
pb = pvec.ctxpvec(cb)
if pa == pb:
rel = "="
elif pa > pb:
rel = ">"
elif pa < pb:
rel = "<"
elif pa | pb:
rel = "|"
ui.write(_("a: %s\n") % pa)
ui.write(_("b: %s\n") % pb)
ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
(abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
pa.distance(pb), rel))
Pierre-Yves David
debugcommands: move 'debugrebuilddirstate' in the new module
r30948 @command('debugrebuilddirstate|debugrebuildstate',
[('r', 'rev', '', _('revision to rebuild to'), _('REV')),
('', 'minimal', None, _('only rebuild files that are inconsistent with '
'the working copy parent')),
],
_('[-r REV]'))
def debugrebuilddirstate(ui, repo, rev, **opts):
"""rebuild the dirstate as it would look like for the given revision
If no revision is specified the first current parent will be used.
The dirstate will be set to the files of the given revision.
The actual working directory content or existing dirstate
information such as adds or removes is not considered.
``minimal`` will only rebuild the dirstate status for files that claim to be
tracked but are not in the parent manifest, or that exist in the parent
manifest but are not in the dirstate. It will not change adds, removes, or
modified files that are in the working copy parent.
One use of this command is to make the next :hg:`status` invocation
check the actual file content.
"""
ctx = scmutil.revsingle(repo, rev)
with repo.wlock():
dirstate = repo.dirstate
changedfiles = None
# See command doc for what minimal does.
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts.get(r'minimal'):
Pierre-Yves David
debugcommands: move 'debugrebuilddirstate' in the new module
r30948 manifestfiles = set(ctx.manifest().keys())
dirstatefiles = set(dirstate)
manifestonly = manifestfiles - dirstatefiles
dsonly = dirstatefiles - manifestfiles
dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
changedfiles = manifestonly | dsnotadded
dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
Pierre-Yves David
debugcommands: move 'debugrebuildfncache' in the new module
r30949 @command('debugrebuildfncache', [], '')
def debugrebuildfncache(ui, repo):
"""rebuild the fncache file"""
repair.rebuildfncache(ui, repo)
Pierre-Yves David
debugcommands: move 'debugrename' in the new module
r30950 @command('debugrename',
[('r', 'rev', '', _('revision to debug'), _('REV'))],
_('[-r REV] FILE'))
def debugrename(ui, repo, file1, *pats, **opts):
"""dump rename information"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: move 'debugrename' in the new module
r30950 ctx = scmutil.revsingle(repo, opts.get('rev'))
m = scmutil.match(ctx, (file1,) + pats, opts)
for abs in ctx.walk(m):
fctx = ctx[abs]
o = fctx.filelog().renamed(fctx.filenode())
rel = m.rel(abs)
if o:
ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
else:
ui.write(_("%s not renamed\n") % rel)
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debugrevlog', cmdutil.debugrevlogopts +
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 [('d', 'dump', False, _('dump index data'))],
_('-c|-m|FILE'),
optionalrepo=True)
def debugrevlog(ui, repo, file_=None, **opts):
"""show data and statistics about a revlog"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
if opts.get("dump"):
numrevs = len(r)
ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
" rawsize totalsize compression heads chainlen\n"))
ts = 0
heads = set()
Gregory Szorc
global: use pycompat.xrange()...
r38806 for rev in pycompat.xrange(numrevs):
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 dbase = r.deltaparent(rev)
if dbase == -1:
dbase = rev
cbase = r.chainbase(rev)
clen = r.chainlen(rev)
p1, p2 = r.parentrevs(rev)
rs = r.rawsize(rev)
ts = ts + rs
heads -= set(r.parentrevs(rev))
heads.add(rev)
try:
compression = ts / r.end(rev)
except ZeroDivisionError:
compression = 0
ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
"%11d %5d %8d\n" %
(rev, p1, p2, r.start(rev), r.end(rev),
r.start(dbase), r.start(cbase),
r.start(p1), r.start(p2),
rs, ts, compression, len(heads), clen))
return 0
v = r.version
format = v & 0xFFFF
flags = []
gdelta = False
Gregory Szorc
revlog: rename constants (API)...
r32316 if v & revlog.FLAG_INLINE_DATA:
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 flags.append('inline')
Gregory Szorc
revlog: rename constants (API)...
r32316 if v & revlog.FLAG_GENERALDELTA:
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 gdelta = True
flags.append('generaldelta')
if not flags:
flags = ['(none)']
Boris Feld
debugrevlog: document some of the variable used...
r39115 ### tracks merge vs single parent
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 nummerges = 0
Boris Feld
debugrevlog: document some of the variable used...
r39115
### tracks ways the "delta" are build
Boris Feld
debugrevlog: track empty revlog entries...
r39116 # nodelta
numempty = 0
Boris Feld
debugrevlog: display details about empty revision...
r39117 numemptytext = 0
numemptydelta = 0
Boris Feld
debugrevlog: document some of the variable used...
r39115 # full file content
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 numfull = 0
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 # intermediate snapshot against a prior snapshot
numsemi = 0
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 # snapshot count per depth
numsnapdepth = collections.defaultdict(lambda: 0)
Boris Feld
debugrevlog: document some of the variable used...
r39115 # delta against previous revision
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 numprev = 0
Boris Feld
debugrevlog: document some of the variable used...
r39115 # delta against first or second parent (not prev)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 nump1 = 0
nump2 = 0
Boris Feld
debugrevlog: document some of the variable used...
r39115 # delta against neither prev nor parents
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 numother = 0
Boris Feld
debugrevlog: document some of the variable used...
r39115 # delta against prev that are also first or second parent
# (details of `numprev`)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 nump1prev = 0
nump2prev = 0
Boris Feld
debugrevlog: document some of the variable used...
r39115
# data about delta chain of each revs
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 chainlengths = []
debugrevlog: also display the largest delta chain span...
r33057 chainbases = []
chainspans = []
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951
Boris Feld
debugrevlog: document some of the variable used...
r39115 # data about each revision
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 datasize = [None, 0, 0]
fullsize = [None, 0, 0]
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 semisize = [None, 0, 0]
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 # snapshot count per depth
snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 deltasize = [None, 0, 0]
chunktypecounts = {}
chunktypesizes = {}
def addsize(size, l):
if l[0] is None or size < l[0]:
l[0] = size
if size > l[1]:
l[1] = size
l[2] += size
numrevs = len(r)
Gregory Szorc
global: use pycompat.xrange()...
r38806 for rev in pycompat.xrange(numrevs):
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 p1, p2 = r.parentrevs(rev)
delta = r.deltaparent(rev)
if format > 0:
addsize(r.rawsize(rev), datasize)
if p2 != nullrev:
nummerges += 1
size = r.length(rev)
if delta == nullrev:
chainlengths.append(0)
debugrevlog: also display the largest delta chain span...
r33057 chainbases.append(r.start(rev))
chainspans.append(size)
Boris Feld
debugrevlog: track empty revlog entries...
r39116 if size == 0:
numempty += 1
Boris Feld
debugrevlog: display details about empty revision...
r39117 numemptytext += 1
Boris Feld
debugrevlog: track empty revlog entries...
r39116 else:
numfull += 1
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 numsnapdepth[0] += 1
Boris Feld
debugrevlog: track empty revlog entries...
r39116 addsize(size, fullsize)
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 addsize(size, snapsizedepth[0])
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 else:
chainlengths.append(chainlengths[delta] + 1)
debugrevlog: also display the largest delta chain span...
r33057 baseaddr = chainbases[delta]
revaddr = r.start(rev)
chainbases.append(baseaddr)
chainspans.append((revaddr - baseaddr) + size)
Boris Feld
debugrevlog: track empty revlog entries...
r39116 if size == 0:
numempty += 1
Boris Feld
debugrevlog: display details about empty revision...
r39117 numemptydelta += 1
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 elif r.issnapshot(rev):
addsize(size, semisize)
numsemi += 1
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 depth = r.snapshotdepth(rev)
numsnapdepth[depth] += 1
addsize(size, snapsizedepth[depth])
Boris Feld
debugrevlog: track empty revlog entries...
r39116 else:
addsize(size, deltasize)
if delta == rev - 1:
numprev += 1
if delta == p1:
nump1prev += 1
elif delta == p2:
nump2prev += 1
elif delta == p1:
nump1 += 1
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 elif delta == p2:
Boris Feld
debugrevlog: track empty revlog entries...
r39116 nump2 += 1
elif delta != nullrev:
numother += 1
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951
# Obtain data on the raw chunks in the revlog.
Boris Feld
debugrevlog: fix for non-manifest object...
r39184 if util.safehasattr(r, '_getsegmentforrevs'):
segment = r._getsegmentforrevs(rev, rev)[1]
else:
segment = r._revlog._getsegmentforrevs(rev, rev)[1]
Gregory Szorc
revlog: rename _chunkraw to _getsegmentforrevs()...
r32224 if segment:
Pulkit Goyal
py3: pass the memoryview object into bytes() to get the value
r33106 chunktype = bytes(segment[0:1])
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 else:
chunktype = 'empty'
if chunktype not in chunktypecounts:
chunktypecounts[chunktype] = 0
chunktypesizes[chunktype] = 0
chunktypecounts[chunktype] += 1
chunktypesizes[chunktype] += size
# Adjust size min value for empty cases
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 for size in (datasize, fullsize, semisize, deltasize):
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 if size[0] is None:
size[0] = 0
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 numdeltas = numrevs - numfull - numempty - numsemi
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 numoprev = numprev - nump1prev - nump2prev
totalrawsize = datasize[2]
datasize[2] /= numrevs
fulltotal = fullsize[2]
fullsize[2] /= numfull
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 semitotal = semisize[2]
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 snaptotal = {}
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 if 0 < numsemi:
semisize[2] /= numsemi
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 for depth in snapsizedepth:
snaptotal[depth] = snapsizedepth[depth][2]
snapsizedepth[depth][2] /= numsnapdepth[depth]
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 deltatotal = deltasize[2]
Boris Feld
debugrevlog: track empty revlog entries...
r39116 if numdeltas > 0:
deltasize[2] /= numdeltas
Boris Feld
debugrevlog: include information about intermediate snapshots...
r39187 totalsize = fulltotal + semitotal + deltatotal
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 avgchainlen = sum(chainlengths) / numrevs
maxchainlen = max(chainlengths)
debugrevlog: also display the largest delta chain span...
r33057 maxchainspan = max(chainspans)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 compratio = 1
if totalsize:
compratio = totalrawsize / totalsize
basedfmtstr = '%%%dd\n'
basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
def dfmtstr(max):
return basedfmtstr % len(str(max))
def pcfmtstr(max, padding=0):
return basepcfmtstr % (len(str(max)), ' ' * padding)
def pcfmt(value, total):
if total:
return (value, 100 * float(value) / total)
else:
return value, 100.0
ui.write(('format : %d\n') % format)
ui.write(('flags : %s\n') % ', '.join(flags))
ui.write('\n')
fmt = pcfmtstr(totalsize)
fmt2 = dfmtstr(totalsize)
ui.write(('revisions : ') + fmt2 % numrevs)
ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
ui.write(('revisions : ') + fmt2 % numrevs)
Boris Feld
debugrevlog: track empty revlog entries...
r39116 ui.write((' empty : ') + fmt % pcfmt(numempty, numrevs))
Boris Feld
debugrevlog: display details about empty revision...
r39117 ui.write((' text : ')
+ fmt % pcfmt(numemptytext, numemptytext + numemptydelta))
ui.write((' delta : ')
+ fmt % pcfmt(numemptydelta, numemptytext + numemptydelta))
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 ui.write((' snapshot : ') + fmt % pcfmt(numfull + numsemi, numrevs))
for depth in sorted(numsnapdepth):
ui.write((' lvl-%-3d : ' % depth)
+ fmt % pcfmt(numsnapdepth[depth], numrevs))
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
ui.write(('revision size : ') + fmt2 % totalsize)
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 ui.write((' snapshot : ')
+ fmt % pcfmt(fulltotal + semitotal, totalsize))
for depth in sorted(numsnapdepth):
ui.write((' lvl-%-3d : ' % depth)
+ fmt % pcfmt(snaptotal[depth], totalsize))
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
def fmtchunktype(chunktype):
if chunktype == 'empty':
return ' %s : ' % chunktype
Pulkit Goyal
py3: use pycompat.bytestr() to convert str to bytes
r33107 elif chunktype in pycompat.bytestr(string.ascii_letters):
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
else:
return ' 0x%s : ' % hex(chunktype)
ui.write('\n')
ui.write(('chunks : ') + fmt2 % numrevs)
for chunktype in sorted(chunktypecounts):
ui.write(fmtchunktype(chunktype))
ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
ui.write(('chunks size : ') + fmt2 % totalsize)
for chunktype in sorted(chunktypecounts):
ui.write(fmtchunktype(chunktype))
ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
ui.write('\n')
Yuya Nishihara
debugrevlog: align chain length, reach, and compression ratio...
r33062 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 ui.write(('avg chain length : ') + fmt % avgchainlen)
ui.write(('max chain length : ') + fmt % maxchainlen)
Yuya Nishihara
debugrevlog: align chain length, reach, and compression ratio...
r33062 ui.write(('max chain reach : ') + fmt % maxchainspan)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 ui.write(('compression ratio : ') + fmt % compratio)
if format > 0:
ui.write('\n')
ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
% tuple(datasize))
ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
% tuple(fullsize))
Boris Feld
debugrevlog: display snapshot details per depth...
r39189 ui.write(('inter-snapshot size (min/max/avg) : %d / %d / %d\n')
% tuple(semisize))
for depth in sorted(snapsizedepth):
if depth == 0:
continue
ui.write((' level-%-3d (min/max/avg) : %d / %d / %d\n')
% ((depth,) + tuple(snapsizedepth[depth])))
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
% tuple(deltasize))
if numdeltas > 0:
ui.write('\n')
fmt = pcfmtstr(numdeltas)
fmt2 = pcfmtstr(numdeltas, 4)
ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
if numprev > 0:
ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
numprev))
ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
numprev))
ui.write((' other : ') + fmt2 % pcfmt(numoprev,
numprev))
if gdelta:
ui.write(('deltas against p1 : ')
+ fmt % pcfmt(nump1, numdeltas))
ui.write(('deltas against p2 : ')
+ fmt % pcfmt(nump2, numdeltas))
ui.write(('deltas against other : ') + fmt % pcfmt(numother,
numdeltas))
Gregory Szorc
debugcommands: introduce debugrevlogindex (BC)...
r39318 @command('debugrevlogindex', cmdutil.debugrevlogopts +
[('f', 'format', 0, _('revlog format'), _('FORMAT'))],
_('[-f FORMAT] -c|-m|FILE'),
optionalrepo=True)
def debugrevlogindex(ui, repo, file_=None, **opts):
"""dump the contents of a revlog index"""
opts = pycompat.byteskwargs(opts)
r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts)
format = opts.get('format', 0)
if format not in (0, 1):
raise error.Abort(_("unknown format %d") % format)
if ui.debugflag:
shortfn = hex
else:
shortfn = short
# There might not be anything in r, so have a sane default
idlen = 12
for i in r:
idlen = len(shortfn(r.node(i)))
break
if format == 0:
if ui.verbose:
ui.write((" rev offset length linkrev"
" %s %s p2\n") % ("nodeid".ljust(idlen),
"p1".ljust(idlen)))
else:
ui.write((" rev linkrev %s %s p2\n") % (
"nodeid".ljust(idlen), "p1".ljust(idlen)))
elif format == 1:
if ui.verbose:
ui.write((" rev flag offset length size link p1"
" p2 %s\n") % "nodeid".rjust(idlen))
else:
ui.write((" rev flag size link p1 p2 %s\n") %
"nodeid".rjust(idlen))
for i in r:
node = r.node(i)
if format == 0:
try:
pp = r.parents(node)
except Exception:
pp = [nullid, nullid]
if ui.verbose:
ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
i, r.start(i), r.length(i), r.linkrev(i),
shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
else:
ui.write("% 6d % 7d %s %s %s\n" % (
i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
shortfn(pp[1])))
elif format == 1:
pr = r.parentrevs(i)
if ui.verbose:
ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
r.linkrev(i), pr[0], pr[1], shortfn(node)))
else:
ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
shortfn(node)))
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 @command('debugrevspec',
[('', 'optimize', None,
_('print parsed tree after optimizing (DEPRECATED)')),
Yuya Nishihara
debugrevspec: add option to suppress list of computed revisions...
r32796 ('', 'show-revs', True, _('print list of result revisions (default)')),
Yuya Nishihara
debugrevspec: add option to print representation of smartset object...
r32795 ('s', 'show-set', None, _('print internal representation of result set')),
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 ('p', 'show-stage', [],
_('print parsed tree at the given stage'), _('NAME')),
('', 'no-optimized', False, _('evaluate tree without optimization')),
('', 'verify-optimized', False, _('verify optimized result')),
],
('REVSPEC'))
def debugrevspec(ui, repo, expr, **opts):
"""parse and apply a revision specification
Use -p/--show-stage option to print the parsed tree at the given stages.
Use -p all to print tree at every stage.
Yuya Nishihara
debugrevspec: add option to suppress list of computed revisions...
r32796 Use --no-show-revs option with -s or -p to print only the set
representation or the parsed tree respectively.
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 Use --verify-optimized to compare the optimized result with the unoptimized
one. Returns 1 if the optimized result differs.
"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Jun Wu
revset: make repo.anyrevs accept customized alias override (API)...
r33336 aliases = ui.configitems('revsetalias')
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 stages = [
('parsed', lambda tree: tree),
Jun Wu
revset: make repo.anyrevs accept customized alias override (API)...
r33336 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
ui.warn)),
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 ('concatenated', revsetlang.foldconcat),
('analyzed', revsetlang.analyze),
('optimized', revsetlang.optimize),
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 ]
if opts['no_optimized']:
stages = stages[:-1]
if opts['verify_optimized'] and opts['no_optimized']:
raise error.Abort(_('cannot use --verify-optimized with '
'--no-optimized'))
stagenames = set(n for n, f in stages)
showalways = set()
showchanged = set()
if ui.verbose and not opts['show_stage']:
# show parsed tree by --verbose (deprecated)
showalways.add('parsed')
showchanged.update(['expanded', 'concatenated'])
if opts['optimize']:
showalways.add('optimized')
if opts['show_stage'] and opts['optimize']:
raise error.Abort(_('cannot use --optimize with --show-stage'))
if opts['show_stage'] == ['all']:
showalways.update(stagenames)
else:
for n in opts['show_stage']:
if n not in stagenames:
raise error.Abort(_('invalid stage name: %s') % n)
showalways.update(opts['show_stage'])
treebystage = {}
printedtree = None
Martin von Zweigbergk
revset: use revsymbol() for checking if a symbol is valid...
r37368 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 for n, f in stages:
treebystage[n] = tree = f(tree)
if n in showalways or (n in showchanged and tree != printedtree):
if opts['show_stage'] or n != 'parsed':
ui.write(("* %s:\n") % n)
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 ui.write(revsetlang.prettyformat(tree), "\n")
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 printedtree = tree
if opts['verify_optimized']:
arevs = revset.makematcher(treebystage['analyzed'])(repo)
brevs = revset.makematcher(treebystage['optimized'])(repo)
Yuya Nishihara
debugrevspec: add option to print representation of smartset object...
r32795 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
Yuya Nishihara
stringutil: promote smartset.prettyformat() to utility function...
r38280 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 arevs = list(arevs)
brevs = list(brevs)
if arevs == brevs:
return 0
ui.write(('--- analyzed\n'), label='diff.file_a')
ui.write(('+++ optimized\n'), label='diff.file_b')
sm = difflib.SequenceMatcher(None, arevs, brevs)
for tag, alo, ahi, blo, bhi in sm.get_opcodes():
if tag in ('delete', 'replace'):
for c in arevs[alo:ahi]:
ui.write('-%s\n' % c, label='diff.deleted')
if tag in ('insert', 'replace'):
for c in brevs[blo:bhi]:
ui.write('+%s\n' % c, label='diff.inserted')
if tag == 'equal':
for c in arevs[alo:ahi]:
ui.write(' %s\n' % c)
return 1
func = revset.makematcher(tree)
revs = func(repo)
Yuya Nishihara
debugrevspec: add option to print representation of smartset object...
r32795 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
Yuya Nishihara
stringutil: promote smartset.prettyformat() to utility function...
r38280 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
Yuya Nishihara
debugrevspec: add option to suppress list of computed revisions...
r32796 if not opts['show_revs']:
return
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 for c in revs:
Yuya Nishihara
py3: format revision number as '%d' in debugrevspec...
r35920 ui.write("%d\n" % c)
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952
Gregory Szorc
debugcommands: add debugserve command...
r36544 @command('debugserve', [
('', 'sshstdio', False, _('run an SSH server bound to process handles')),
('', 'logiofd', '', _('file descriptor to log server I/O to')),
('', 'logiofile', '', _('file to log server I/O to')),
], '')
def debugserve(ui, repo, **opts):
"""run a server with advanced settings
This command is similar to :hg:`serve`. It exists partially as a
workaround to the fact that ``hg serve --stdio`` must have specific
arguments for security reasons.
"""
opts = pycompat.byteskwargs(opts)
if not opts['sshstdio']:
raise error.Abort(_('only --sshstdio is currently supported'))
logfh = None
if opts['logiofd'] and opts['logiofile']:
raise error.Abort(_('cannot use both --logiofd and --logiofile'))
if opts['logiofd']:
# Line buffered because output is line based.
Augie Fackler
debugcommands: work around logiofd being a pipe and unseekable...
r38333 try:
logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
except OSError as e:
if e.errno != errno.ESPIPE:
raise
# can't seek a pipe, so `ab` mode fails on py3
logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
Gregory Szorc
debugcommands: add debugserve command...
r36544 elif opts['logiofile']:
logfh = open(opts['logiofile'], 'ab', 1)
s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
s.serve_forever()
Pierre-Yves David
debugcommands: move 'debugsetparents' in the new module
r30953 @command('debugsetparents', [], _('REV1 [REV2]'))
def debugsetparents(ui, repo, rev1, rev2=None):
"""manually set the parents of the current working directory
This is useful for writing repository conversion tools, but should
be used with care. For example, neither the working directory nor the
dirstate is updated, so file status may be incorrect after running this
command.
Returns 0 on success.
"""
Martin von Zweigbergk
debugsetparents: avoid using "r1/r2" variable names for nodeids...
r37161 node1 = scmutil.revsingle(repo, rev1).node()
node2 = scmutil.revsingle(repo, rev2, 'null').node()
Pierre-Yves David
debugcommands: move 'debugsetparents' in the new module
r30953
with repo.wlock():
Martin von Zweigbergk
debugsetparents: avoid using "r1/r2" variable names for nodeids...
r37161 repo.setparents(node1, node2)
Pierre-Yves David
debugcommands: move 'debugsetparents' in the new module
r30953
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
def debugssl(ui, repo, source=None, **opts):
'''test a secure connection to a server
This builds the certificate chain for the server on Windows, installing the
missing intermediates and trusted root via Windows Update if necessary. It
does nothing on other platforms.
If SOURCE is omitted, the 'default' path will be used. If a URL is given,
that server is used. See :hg:`help urls` for more information.
If the update succeeds, retry the original operation. Otherwise, the cause
of the SSL error is likely another issue.
'''
Jun Wu
codemod: use pycompat.iswindows...
r34646 if not pycompat.iswindows:
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 raise error.Abort(_('certificate chain building is only possible on '
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 'Windows'))
if not source:
Matt Harbison
debugssl: allow a URL to be specified without a local repository...
r34031 if not repo:
raise error.Abort(_("there is no Mercurial repository here, and no "
"server specified"))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 source = "default"
source, branches = hg.parseurl(ui.expandpath(source))
url = util.url(source)
addr = None
Yuya Nishihara
debugssl: convert port number to int (issue5757)...
r35444 defaultport = {'https': 443, 'ssh': 22}
if url.scheme in defaultport:
try:
addr = (url.host, int(url.port or defaultport[url.scheme]))
except ValueError:
raise error.Abort(_("malformed port number in URL"))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 else:
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 raise error.Abort(_("only https and ssh connections are supported"))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493
from . import win32
s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
cert_reqs=ssl.CERT_NONE, ca_certs=None)
try:
s.connect(addr)
cert = s.getpeercert(True)
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 ui.status(_('checking the certificate chain for %s\n') % url.host)
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493
complete = win32.checkcertificatechain(cert, build=False)
if not complete:
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 ui.status(_('certificate chain is incomplete, updating... '))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493
if not win32.checkcertificatechain(cert):
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 ui.status(_('failed.\n'))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 else:
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 ui.status(_('done.\n'))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 else:
Kevin Bullock
win32: copy-edit debugssl messages to match prevailing style
r33553 ui.status(_('full certificate chain is available\n'))
Matt Harbison
debug: add a method to check the state of, and built an SSL cert chain...
r33493 finally:
s.close()
Pierre-Yves David
debugcommands: move 'debugsub' in the new module
r30955 @command('debugsub',
[('r', 'rev', '',
_('revision to check'), _('REV'))],
_('[-r REV] [REV]'))
def debugsub(ui, repo, rev=None):
ctx = scmutil.revsingle(repo, rev, None)
for k, v in sorted(ctx.substate.items()):
ui.write(('path %s\n') % k)
ui.write((' source %s\n') % v[0])
ui.write((' revision %s\n') % v[1])
Pierre-Yves David
debugcommands: move 'debugsuccessorssets' in the new module
r30956 @command('debugsuccessorssets',
Boris Feld
obsolete: closest divergent support...
r33274 [('', 'closest', False, _('return closest successors sets only'))],
Pierre-Yves David
debugcommands: move 'debugsuccessorssets' in the new module
r30956 _('[REV]'))
Boris Feld
obsolete: closest divergent support...
r33274 def debugsuccessorssets(ui, repo, *revs, **opts):
Pierre-Yves David
debugcommands: move 'debugsuccessorssets' in the new module
r30956 """show set of successors for revision
A successors set of changeset A is a consistent group of revisions that
Boris Feld
obsolete: closest divergent support...
r33274 succeed A. It contains non-obsolete changesets only unless closests
successors set is set.
Pierre-Yves David
debugcommands: move 'debugsuccessorssets' in the new module
r30956
In most cases a changeset A has a single successors set containing a single
successor (changeset A replaced by A').
A changeset that is made obsolete with no successors are called "pruned".
Such changesets have no successors sets at all.
A changeset that has been "split" will have a successors set containing
more than one successor.
A changeset that has been rewritten in multiple different ways is called
"divergent". Such changesets have multiple successor sets (each of which
may also be split, i.e. have multiple successors).
Results are displayed as follows::
<rev1>
<successors-1A>
<rev2>
<successors-2A>
<successors-2B1> <successors-2B2> <successors-2B3>
Here rev2 has two possible (i.e. divergent) successors sets. The first
holds one element, whereas the second holds three (i.e. the changeset has
been split).
"""
# passed to successorssets caching computation from one call to another
cache = {}
Gregory Szorc
py3: convert context to bytes instead of str...
r36140 ctx2str = bytes
Pierre-Yves David
debugcommands: move 'debugsuccessorssets' in the new module
r30956 node2str = short
for rev in scmutil.revrange(repo, revs):
ctx = repo[rev]
ui.write('%s\n'% ctx2str(ctx))
Boris Feld
obsolete: closest divergent support...
r33274 for succsset in obsutil.successorssets(repo, ctx.node(),
Pulkit Goyal
py3: handle keyword arguments correctly in debugcommands.py...
r35402 closest=opts[r'closest'],
Boris Feld
obsolete: closest divergent support...
r33274 cache=cache):
Pierre-Yves David
debugcommands: move 'debugsuccessorssets' in the new module
r30956 if succsset:
ui.write(' ')
ui.write(node2str(succsset[0]))
for node in succsset[1:]:
ui.write(' ')
ui.write(node2str(node))
ui.write('\n')
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 @command('debugtemplate',
[('r', 'rev', [], _('apply template on changesets'), _('REV')),
('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
_('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
optionalrepo=True)
def debugtemplate(ui, repo, tmpl, **opts):
"""parse and apply a template
If -r/--rev is given, the template is processed as a log template and
applied to the given changesets. Otherwise, it is processed as a generic
template.
Use --verbose to print the parsed tree.
"""
revs = None
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 if opts[r'rev']:
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 if repo is None:
raise error.RepoError(_('there is no Mercurial repository here '
'(.hg not found)'))
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 revs = scmutil.revrange(repo, opts[r'rev'])
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957
props = {}
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 for d in opts[r'define']:
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 try:
k, v = (e.strip() for e in d.split('=', 1))
Yuya Nishihara
debugtemplate: pass ui to templater so label() works...
r31517 if not k or k == 'ui':
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 raise ValueError
props[k] = v
except ValueError:
raise error.Abort(_('malformed keyword definition: %s') % d)
if ui.verbose:
aliases = ui.configitems('templatealias')
tree = templater.parse(tmpl)
ui.note(templater.prettyformat(tree), '\n')
newtree = templater.expandaliases(tree, aliases)
if newtree != tree:
ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
if revs is None:
Yuya Nishihara
templater: move repo, ui and cache to per-engine resources
r35485 tres = formatter.templateresources(ui, repo)
t = formatter.maketemplater(ui, tmpl, resources=tres)
Yuya Nishihara
templater: add function to look up symbols used in template...
r38374 if ui.verbose:
kwds, funcs = t.symbolsuseddefault()
ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
Yuya Nishihara
templater: rename .render(mapping) to .renderdefault(mapping) (API)...
r37003 ui.write(t.renderdefault(props))
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 else:
Yuya Nishihara
cmdutil: drop aliases for logcmdutil functions (API)...
r35906 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
Yuya Nishihara
templater: add function to look up symbols used in template...
r38374 if ui.verbose:
kwds, funcs = displayer.t.symbolsuseddefault()
ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 for r in revs:
Pulkit Goyal
py3: use pycompat.strkwargs() to convert kwargs keys to str
r33102 displayer.show(repo[r], **pycompat.strkwargs(props))
Pierre-Yves David
debugcommands: move 'debugtemplate' in the new module
r30957 displayer.close()
Yuya Nishihara
ui: add debug commands to test interactive prompt...
r36810 @command('debuguigetpass', [
('p', 'prompt', '', _('prompt text'), _('TEXT')),
], _('[-p TEXT]'), norepo=True)
def debuguigetpass(ui, prompt=''):
"""show prompt to type password"""
r = ui.getpass(prompt)
ui.write(('respose: %s\n') % r)
@command('debuguiprompt', [
('p', 'prompt', '', _('prompt text'), _('TEXT')),
], _('[-p TEXT]'), norepo=True)
def debuguiprompt(ui, prompt=''):
"""show plain prompt"""
r = ui.prompt(prompt)
ui.write(('response: %s\n') % r)
Pierre-Yves David
caches: introduce a 'debugupdatecaches' command...
r32265 @command('debugupdatecaches', [])
def debugupdatecaches(ui, repo, *pats, **opts):
"""warm all known caches in the repository"""
Jun Wu
codemod: simplify nested withs...
r33438 with repo.wlock(), repo.lock():
Boris Feld
debugupdatecache: also warm rev branch cache...
r36970 repo.updatecaches(full=True)
Pierre-Yves David
caches: introduce a 'debugupdatecaches' command...
r32265
Gregory Szorc
debugcommands: stub for debugupgraderepo command...
r30774 @command('debugupgraderepo', [
('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
('', 'run', False, _('performs an upgrade')),
])
def debugupgraderepo(ui, repo, run=False, optimize=None):
"""upgrade a repository to use different features
If no arguments are specified, the repository is evaluated for upgrade
and a list of problems and potential optimizations is printed.
With ``--run``, a repository upgrade is performed. Behavior of the upgrade
can be influenced via additional arguments. More details will be provided
by the command output when run without ``--run``.
During the upgrade, the repository will be locked and no writes will be
allowed.
At the end of the upgrade, the repository may not be readable while new
repository data is swapped in. This window will be as long as it takes to
rename some directories inside the ``.hg`` directory. On most machines, this
should complete almost instantaneously and the chances of a consumer being
unable to access the repository should be low.
"""
Pierre-Yves David
upgrade: extract code in its own module...
r31864 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
Pierre-Yves David
debugcommands: move 'debugwalk' in the new module
r30958
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
Pierre-Yves David
debugcommands: move 'debugwalk' in the new module
r30958 inferrepo=True)
def debugwalk(ui, repo, *pats, **opts):
"""show how files match on given patterns"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: move 'debugwalk' in the new module
r30958 m = scmutil.match(repo[None], pats, opts)
Yuya Nishihara
debugwalk: show matcher output only if -v/--verbose...
r38281 if ui.verbose:
Yuya Nishihara
debugwalk: pretty-print nested matcher...
r38282 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
Augie Fackler
debugcommands: use repo[None].walk instead of repo.walk
r32363 items = list(repo[None].walk(m))
Pierre-Yves David
debugcommands: move 'debugwalk' in the new module
r30958 if not items:
return
f = lambda fn: fn
if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
f = lambda fn: util.normpath(fn)
fmt = 'f %%-%ds %%-%ds %%s' % (
max([len(abs) for abs in items]),
max([len(m.rel(abs)) for abs in items]))
for abs in items:
line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
ui.write("%s\n" % line.rstrip())
Pierre-Yves David
debugcommands: move 'debugwireargs' in the new module
r30959
av6
debug: add debugwhyunstable that explains instabilities...
r36972 @command('debugwhyunstable', [], _('REV'))
def debugwhyunstable(ui, repo, rev):
"""explain instabilities of a changeset"""
Martin von Zweigbergk
debugwhyunstable: add support for revsets...
r37414 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
av6
debug: add debugwhyunstable that explains instabilities...
r36972 dnodes = ''
if entry.get('divergentnodes'):
dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
for ctx in entry['divergentnodes']) + ' '
ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
entry['reason'], entry['node']))
Pierre-Yves David
debugcommands: move 'debugwireargs' in the new module
r30959 @command('debugwireargs',
[('', 'three', '', 'three'),
('', 'four', '', 'four'),
('', 'five', '', 'five'),
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 ] + cmdutil.remoteopts,
Pierre-Yves David
debugcommands: move 'debugwireargs' in the new module
r30959 _('REPO [OPTIONS]... [ONE [TWO]]'),
norepo=True)
def debugwireargs(ui, repopath, *vals, **opts):
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Pierre-Yves David
debugcommands: move 'debugwireargs' in the new module
r30959 repo = hg.peer(ui, opts, repopath)
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 for opt in cmdutil.remoteopts:
Pierre-Yves David
debugcommands: move 'debugwireargs' in the new module
r30959 del opts[opt[1]]
args = {}
for k, v in opts.iteritems():
if v:
args[k] = v
Pulkit Goyal
py3: handle keyword arguments correctly in debugcommands.py...
r35402 args = pycompat.strkwargs(args)
Pierre-Yves David
debugcommands: move 'debugwireargs' in the new module
r30959 # run twice to check that we don't mess up the stream for the next command
res1 = repo.debugwireargs(*vals, **args)
res2 = repo.debugwireargs(*vals, **args)
ui.write("%s\n" % res1)
if res1 != res2:
ui.warn("%s\n" % res2)
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
def _parsewirelangblocks(fh):
activeaction = None
blocklines = []
for line in fh:
line = line.rstrip()
if not line:
continue
if line.startswith(b'#'):
continue
Augie Fackler
debugcommands: fix a missing b prefix...
r39097 if not line.startswith(b' '):
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 # New block. Flush previous one.
if activeaction:
yield activeaction, blocklines
activeaction = line
blocklines = []
continue
# Else we start with an indent.
if not activeaction:
raise error.Abort(_('indented line outside of block'))
blocklines.append(line)
# Flush last block.
if activeaction:
yield activeaction, blocklines
@command('debugwireproto',
[
('', 'localssh', False, _('start an SSH server for this repo')),
('', 'peer', '', _('construct a specific version of the peer')),
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
Gregory Szorc
debugcommands: ability to suppress logging of handshake...
r37736 ('', 'nologhandshake', False,
_('do not log I/O related to the peer handshake')),
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 ] + cmdutil.remoteopts,
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 _('[PATH]'),
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 optionalrepo=True)
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 def debugwireproto(ui, repo, path=None, **opts):
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 """send wire protocol commands to a server
This command can be used to issue wire protocol commands to remote
peers and to debug the raw data being exchanged.
``--localssh`` will start an SSH server against the current repository
and connect to that. By default, the connection will perform a handshake
and establish an appropriate peer instance.
``--peer`` can be used to bypass the handshake protocol and construct a
peer instance using the specified class type. Valid values are ``raw``,
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
raw data payloads and don't support higher-level command actions.
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 ``--noreadstderr`` can be used to disable automatic reading from stderr
of the peer (for SSH connections only). Disabling automatic reading of
stderr is useful for making output more deterministic.
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 Commands are issued via a mini language which is specified via stdin.
The language consists of individual actions to perform. An action is
defined by a block. A block is defined as a line with no leading
space followed by 0 or more lines with leading space. Blocks are
effectively a high-level command with additional metadata.
Lines beginning with ``#`` are ignored.
The following sections denote available actions.
raw
---
Send raw data to the server.
The block payload contains the raw data to send as one atomic send
operation. The data may not actually be delivered in a single system
call: it depends on the abilities of the transport being used.
Each line in the block is de-indented and concatenated. Then, that
value is evaluated as a Python b'' literal. This allows the use of
backslash escaping, etc.
raw+
----
Behaves like ``raw`` except flushes output afterwards.
Gregory Szorc
debugcommands: allow sending of simple commands with debugwireproto...
r36547 command <X>
-----------
Send a request to run a named command, whose name follows the ``command``
string.
Arguments to the command are defined as lines in this block. The format of
each line is ``<key> <value>``. e.g.::
command listkeys
namespace bookmarks
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 If the value begins with ``eval:``, it will be interpreted as a Python
literal expression. Otherwise values are interpreted as Python b'' literals.
This allows sending complex types and encoding special byte sequences via
backslash escaping.
Gregory Szorc
debugcommands: allow sending of simple commands with debugwireproto...
r36547
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 The following arguments have special meaning:
``PUSHFILE``
When defined, the *push* mechanism of the peer will be used instead
of the static request-response mechanism and the content of the
file specified in the value of this argument will be sent as the
command payload.
This can be used to submit a local bundle file to the remote.
Gregory Szorc
debugcommands: support for sending "batch" requests...
r36548 batchbegin
----------
Instruct the peer to begin a batched send.
All ``command`` blocks are queued for execution until the next
``batchsubmit`` block.
batchsubmit
-----------
Submit previously queued ``command`` blocks as a batch request.
This action MUST be paired with a ``batchbegin`` action.
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 httprequest <method> <path>
---------------------------
(HTTP peer only)
Send an HTTP request to the peer.
The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
headers to add to the request. e.g. ``Accept: foo``.
The following arguments are special:
``BODYFILE``
The content of the file defined as the value to this argument will be
transferred verbatim as the HTTP request body.
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069 ``frame <type> <flags> <payload>``
Send a unified protocol frame as part of the request body.
All frames will be collected and sent as the body to the HTTP
request.
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 close
-----
Close the connection to the server.
flush
-----
Flush data written to the server.
readavailable
-------------
Yuya Nishihara
debugwireproto: close the write end before consuming all available data...
r36861 Close the write end of the connection and read all available data from
the server.
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
If the connection to the server encompasses multiple pipes, we poll both
pipes and read available data.
readline
--------
Read a line of output from the server. If there are multiple output
pipes, reads only the main pipe.
Gregory Szorc
debugcommands: introduce actions to perform deterministic reads...
r37025
ereadline
---------
Like ``readline``, but read from the stderr pipe, if available.
read <X>
--------
``read()`` N bytes from the server's main output pipe.
eread <X>
---------
``read()`` N bytes from the server's stderr pipe, if available.
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069
Specifying Unified Frame-Based Protocol Frames
----------------------------------------------
It is possible to emit a *Unified Frame-Based Protocol* by using special
syntax.
A frame is composed as a type, flags, and payload. These can be parsed
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 from a string of the form:
<request-id> <stream-id> <stream-flags> <type> <flags> <payload>
``request-id`` and ``stream-id`` are integers defining the request and
stream identifiers.
Gregory Szorc
wireproto: add request IDs to frames...
r37075
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069 ``type`` can be an integer value for the frame type or the string name
of the type. The strings are defined in ``wireprotoframing.py``. e.g.
``command-name``.
Gregory Szorc
wireproto: add streams to frame-based protocol...
r37304 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
components. Each component (and there can be just one) can be an integer
or a flag name for stream flags or frame flags, respectively. Values are
resolved to integers and then bitwise OR'd together.
Gregory Szorc
wireproto: syntax for encoding CBOR into frames...
r37306 ``payload`` represents the raw frame payload. If it begins with
``cbor:``, the following string is evaluated as Python code and the
resulting object is fed into a CBOR encoder. Otherwise it is interpreted
as a Python byte string literal.
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 """
opts = pycompat.byteskwargs(opts)
if opts['localssh'] and not repo:
raise error.Abort(_('--localssh requires a repository'))
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 raise error.Abort(_('invalid value for --peer'),
hint=_('valid values are "raw", "ssh1", and "ssh2"'))
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if path and opts['localssh']:
raise error.Abort(_('cannot specify --localssh with an explicit '
'path'))
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 if ui.interactive():
ui.write(_('(waiting for commands on stdin)\n'))
blocks = list(_parsewirelangblocks(ui.fin))
proc = None
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 stdin = None
stdout = None
stderr = None
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 opener = None
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
if opts['localssh']:
# We start the SSH server in its own process so there is process
# separation. This prevents a whole class of potential bugs around
# shared state from interfering with server operation.
Yuya Nishihara
procutil: bulk-replace function calls to point to new module
r37138 args = procutil.hgcmd() + [
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 '-R', repo.root,
'debugserve', '--sshstdio',
]
proc = subprocess.Popen(args, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
bufsize=0)
stdin = proc.stdin
stdout = proc.stdout
stderr = proc.stderr
# We turn the pipes into observers so we can log I/O.
if ui.verbose or opts['peer'] == 'raw':
stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
logdata=True)
stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
logdata=True)
stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
logdata=True)
# --localssh also implies the peer connection settings.
url = 'ssh://localserver'
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 autoreadstderr = not opts['noreadstderr']
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
if opts['peer'] == 'ssh1':
ui.write(_('creating ssh peer for wire protocol version 1\n'))
peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 None, autoreadstderr=autoreadstderr)
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 elif opts['peer'] == 'ssh2':
ui.write(_('creating ssh peer for wire protocol version 2\n'))
peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 None, autoreadstderr=autoreadstderr)
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 elif opts['peer'] == 'raw':
ui.write(_('using raw connection to peer\n'))
peer = None
else:
ui.write(_('creating ssh peer from handshake results\n'))
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
autoreadstderr=autoreadstderr)
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 elif path:
# We bypass hg.peer() so we can proxy the sockets.
# TODO consider not doing this because we skip
# ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
u = util.url(path)
if u.scheme != 'http':
raise error.Abort(_('only http:// paths are currently supported'))
url, authinfo = u.authinfo()
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 openerargs = {
r'useragent': b'Mercurial debugwireproto',
}
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030
# Turn pipes/sockets into observers so we can log I/O.
if ui.verbose:
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 openerargs.update({
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 r'loggingfh': ui,
r'loggingname': b's',
r'loggingopts': {
r'logdata': True,
Gregory Szorc
util: don't log low-level I/O calls for HTTP peer...
r37062 r'logdataapis': False,
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 },
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 })
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030
Gregory Szorc
util: don't log low-level I/O calls for HTTP peer...
r37062 if ui.debugflag:
openerargs[r'loggingopts'][r'logdataapis'] = True
Gregory Szorc
url: support suppressing Accept header...
r37063 # Don't send default headers when in raw mode. This allows us to
# bypass most of the behavior of our URL handling code so we can
# have near complete control over what's sent on the wire.
if opts['peer'] == 'raw':
openerargs[r'sendaccept'] = False
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 opener = urlmod.opener(ui, authinfo, **openerargs)
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 if opts['peer'] == 'http2':
ui.write(_('creating http peer for wire protocol version 2\n'))
Gregory Szorc
debugcommands: perform handshake when obtaining httpv2 peer...
r37663 # We go through makepeer() because we need an API descriptor for
# the peer instance to be useful.
with ui.configoverride({
('experimental', 'httppeer.advertise-v2'): True}):
Gregory Szorc
debugcommands: ability to suppress logging of handshake...
r37736 if opts['nologhandshake']:
ui.pushbuffer()
Gregory Szorc
debugcommands: perform handshake when obtaining httpv2 peer...
r37663 peer = httppeer.makepeer(ui, path, opener=opener)
Gregory Szorc
debugcommands: ability to suppress logging of handshake...
r37736 if opts['nologhandshake']:
ui.popbuffer()
Gregory Szorc
debugcommands: perform handshake when obtaining httpv2 peer...
r37663 if not isinstance(peer, httppeer.httpv2peer):
raise error.Abort(_('could not instantiate HTTP peer for '
'wire protocol version 2'),
hint=_('the server may not have the feature '
'enabled or is not allowing this '
'client version'))
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 elif opts['peer'] == 'raw':
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 ui.write(_('using raw connection to peer\n'))
peer = None
elif opts['peer']:
raise error.Abort(_('--peer %s not supported with HTTP peers') %
opts['peer'])
else:
Gregory Szorc
httppeer: allow opener to be passed to makepeer()...
r37571 peer = httppeer.makepeer(ui, path, opener=opener)
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030
# We /could/ populate stdin/stdout with sock.makefile()...
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 else:
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 raise error.Abort(_('unsupported connection configuration'))
Gregory Szorc
debugcommands: add debugwireproto command...
r36545
Gregory Szorc
debugcommands: support for sending "batch" requests...
r36548 batchedcommands = None
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 # Now perform actions based on the parsed wire language instructions.
for action, lines in blocks:
if action in ('raw', 'raw+'):
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stdin:
raise error.Abort(_('cannot call raw/raw+ on this peer'))
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 # Concatenate the data together.
data = ''.join(l.lstrip() for l in lines)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 data = stringutil.unescapestr(data)
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 stdin.write(data)
if action == 'raw+':
stdin.flush()
elif action == 'flush':
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stdin:
raise error.Abort(_('cannot call flush on this peer'))
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 stdin.flush()
Gregory Szorc
debugcommands: allow sending of simple commands with debugwireproto...
r36547 elif action.startswith('command'):
if not peer:
raise error.Abort(_('cannot send commands unless peer instance '
'is available'))
command = action.split(' ', 1)[1]
args = {}
for line in lines:
# We need to allow empty values.
fields = line.lstrip().split(' ', 1)
if len(fields) == 1:
key = fields[0]
value = ''
else:
key, value = fields
Gregory Szorc
wireproto: crude support for version 2 HTTP peer...
r37501 if value.startswith('eval:'):
value = stringutil.evalpythonliteral(value[5:])
else:
value = stringutil.unescapestr(value)
args[key] = value
Gregory Szorc
debugcommands: allow sending of simple commands with debugwireproto...
r36547
Gregory Szorc
debugcommands: support for sending "batch" requests...
r36548 if batchedcommands is not None:
batchedcommands.append((command, args))
continue
Gregory Szorc
debugcommands: allow sending of simple commands with debugwireproto...
r36547 ui.status(_('sending %s command\n') % command)
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551
if 'PUSHFILE' in args:
with open(args['PUSHFILE'], r'rb') as fh:
del args['PUSHFILE']
Augie Fackler
debugcommands: add some strkwargs love to some **args calls...
r36605 res, output = peer._callpush(command, fh,
**pycompat.strkwargs(args))
Yuya Nishihara
stringutil: drop escapedata() in favor of escapestr()...
r37338 ui.status(_('result: %s\n') % stringutil.escapestr(res))
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 ui.status(_('remote output: %s\n') %
Yuya Nishihara
stringutil: drop escapedata() in favor of escapestr()...
r37338 stringutil.escapestr(output))
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 else:
Gregory Szorc
debugcommands: use command executor for invoking commands...
r37670 with peer.commandexecutor() as e:
res = e.callcommand(command, args).result()
Gregory Szorc
wireprotov2: establish a type for representing command response...
r37738 if isinstance(res, wireprotov2peer.commandresponse):
Gregory Szorc
wireprotov2peer: stream decoded responses...
r39597 val = res.objects()
Yuya Nishihara
stringutil: flip the default of pprint() to bprefix=False...
r37961 ui.status(_('response: %s\n') %
Gregory Szorc
stringutil: teach pprint() to indent...
r39414 stringutil.pprint(val, bprefix=True, indent=2))
Gregory Szorc
wireprotov2: establish a type for representing command response...
r37738 else:
Yuya Nishihara
stringutil: flip the default of pprint() to bprefix=False...
r37961 ui.status(_('response: %s\n') %
Gregory Szorc
stringutil: teach pprint() to indent...
r39414 stringutil.pprint(res, bprefix=True, indent=2))
Gregory Szorc
debugcommands: allow sending of simple commands with debugwireproto...
r36547
Gregory Szorc
debugcommands: support for sending "batch" requests...
r36548 elif action == 'batchbegin':
if batchedcommands is not None:
raise error.Abort(_('nested batchbegin not allowed'))
batchedcommands = []
elif action == 'batchsubmit':
# There is a batching API we could go through. But it would be
# difficult to normalize requests into function calls. It is easier
# to bypass this layer and normalize to commands + args.
ui.status(_('sending batch with %d sub-commands\n') %
len(batchedcommands))
for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 ui.status(_('response #%d: %s\n') %
Yuya Nishihara
stringutil: drop escapedata() in favor of escapestr()...
r37338 (i, stringutil.escapestr(chunk)))
Gregory Szorc
debugcommands: support for sending "batch" requests...
r36548
batchedcommands = None
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031
elif action.startswith('httprequest '):
if not opener:
raise error.Abort(_('cannot use httprequest without an HTTP '
'peer'))
request = action.split(' ', 2)
if len(request) != 3:
raise error.Abort(_('invalid httprequest: expected format is '
'"httprequest <method> <path>'))
method, httppath = request[1:]
headers = {}
body = None
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069 frames = []
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 for line in lines:
line = line.lstrip()
m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
if m:
headers[m.group(1)] = m.group(2)
continue
if line.startswith(b'BODYFILE '):
with open(line.split(b' ', 1), 'rb') as fh:
body = fh.read()
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069 elif line.startswith(b'frame '):
frame = wireprotoframing.makeframefromhumanstring(
line[len(b'frame '):])
frames.append(frame)
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 else:
raise error.Abort(_('unknown argument to httprequest: %s') %
line)
url = path + httppath
Gregory Szorc
wireproto: define and implement protocol for issuing requests...
r37069
if frames:
body = b''.join(bytes(f) for f in frames)
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
Gregory Szorc
wireproto: define permissions-based routing of HTTPv2 wire protocol...
r37065 # urllib.Request insists on using has_data() as a proxy for
# determining the request method. Override that to use our
# explicitly requested method.
Augie Fackler
debugcommands: get_method should always return a sysstr...
r39099 req.get_method = lambda: pycompat.sysstr(method)
Gregory Szorc
wireproto: define permissions-based routing of HTTPv2 wire protocol...
r37065
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 try:
Gregory Szorc
wireproto: define and implement HTTP handshake to upgrade protocol...
r37575 res = opener.open(req)
body = res.read()
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031 except util.urlerr.urlerror as e:
Augie Fackler
debugcommands: urlerror only has a read() method in Python 2...
r39100 # read() method must be called, but only exists in Python 2
getattr(e, 'read', lambda: None)()
Gregory Szorc
wireproto: define and implement HTTP handshake to upgrade protocol...
r37575 continue
if res.headers.get('Content-Type') == 'application/mercurial-cbor':
Yuya Nishihara
stringutil: flip the default of pprint() to bprefix=False...
r37961 ui.write(_('cbor> %s\n') %
Gregory Szorc
debugcommands: use our CBOR decoder...
r39480 stringutil.pprint(cborutil.decodeall(body)[0],
bprefix=True,
Gregory Szorc
stringutil: teach pprint() to indent...
r39414 indent=2))
Gregory Szorc
debugcommands: support sending HTTP requests with debugwireproto...
r37031
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 elif action == 'close':
peer.close()
elif action == 'readavailable':
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stdout or not stderr:
raise error.Abort(_('readavailable not available on this peer'))
Yuya Nishihara
debugwireproto: close the write end before consuming all available data...
r36861 stdin.close()
stdout.read()
stderr.read()
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 elif action == 'readline':
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stdout:
raise error.Abort(_('readline not available on this peer'))
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 stdout.readline()
Gregory Szorc
debugcommands: introduce actions to perform deterministic reads...
r37025 elif action == 'ereadline':
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stderr:
raise error.Abort(_('ereadline not available on this peer'))
Gregory Szorc
debugcommands: introduce actions to perform deterministic reads...
r37025 stderr.readline()
elif action.startswith('read '):
count = int(action.split(' ', 1)[1])
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stdout:
raise error.Abort(_('read not available on this peer'))
Gregory Szorc
debugcommands: introduce actions to perform deterministic reads...
r37025 stdout.read(count)
elif action.startswith('eread '):
count = int(action.split(' ', 1)[1])
Gregory Szorc
debugcommands: support connecting to HTTP peers...
r37030 if not stderr:
raise error.Abort(_('eread not available on this peer'))
Gregory Szorc
debugcommands: introduce actions to perform deterministic reads...
r37025 stderr.read(count)
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 else:
raise error.Abort(_('unknown action: %s') % action)
Gregory Szorc
debugcommands: support for sending "batch" requests...
r36548 if batchedcommands is not None:
raise error.Abort(_('unclosed "batchbegin" request'))
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 if peer:
peer.close()
if proc:
proc.kill()