##// END OF EJS Templates
util: extract all date-related utils in utils/dateutil module...
util: extract all date-related utils in utils/dateutil module With this commit, util.py lose 262 lines Note for extensions author, if this commit breaks your extension, you can pull the step-by-step split here to help you more easily pinpoint the renaming that broke your extension: hg pull https://bitbucket.org/octobus/mercurial-devel/ -r ac1f6453010d Differential Revision: https://phab.mercurial-scm.org/D2282

File last commit:

r36625:c6061cad default
r36625:c6061cad default
Show More
debugcommands.py
2839 lines | 101.9 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
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
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
import tempfile
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,
Gregory Szorc
debugcommands: move 'debugdiscovery' in the module...
r30517 dagutil,
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,
Gregory Szorc
debugcommands: move 'debugfileset' in the new module
r30524 fileset,
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: 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,
Pierre-Yves David
debugcommands: move 'debugrevspec' in the new module
r30952 smartset,
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
debugcommands: add debugserve command...
r36544 wireprotoserver,
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401 )
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 from .utils import dateutil
Gregory Szorc
debugcommands: introduce standalone module for debug commands...
r30401
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
Augie Fackler
debugbuilddag: use '%d' instead of str() to get numbered lines...
r36336 initialmergedlines = ['%d' % i for i in xrange(0, total * linesperrev)]
Gregory Szorc
debugcommands: move debugbuilddag...
r30402 initialmergedlines.append("")
tags = []
wlock = lock = tr = None
try:
wlock = repo.wlock()
lock = repo.lock()
tr = repo.transaction("builddag")
at = -1
atbranch = 'default'
nodeids = []
id = 0
ui.progress(_('building'), id, unit=_('revisions'), total=total)
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
ui.progress(_('building'), id, unit=_('revisions'), total=total)
tr.close()
if tags:
repo.vfs.write("localtags", "".join(tags))
finally:
ui.progress(_('building'), None)
release(tr, lock, wlock)
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
Augie Fackler
debugcommands: stabilize output of debugbundle by having a custom repr...
r34027 ui.write('%s -- %s\n' % (part.type, _quasirepr(part.params)))
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')
_debugchangegroup(ui, cg, all=all, indent=4, **opts)
debugbundle: display the content of obsmarkers parts...
r32517 if part.type == 'obsmarkers':
Martin von Zweigbergk
debugcommands: pass part, not read data, into _debugobsmarker()...
r33029 _debugobsmarkers(ui, part, indent=4, **opts)
Martin von Zweigbergk
bundle: add config option to include phases...
r33031 if part.type == 'phase-heads':
_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"""
ui.write(('color mode: %s\n') % 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'))
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'))
r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
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
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 start = r.start
length = r.length
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
chainratio = float(chainsize) / float(uncomp)
extraratio = float(extradist) / float(chainsize)
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
Paul Morelle
debugdeltachain: output information about sparse read if enabled
r35050 for revschunk in revlog._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
readdensity = float(chainsize) / float(readsize)
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)))
dag = dagutil.revlogdag(repo.changelog)
all = dag.ancestorset(dag.internalizeall(common))
common = dag.externalizeall(dag.headsetofconnecteds(all))
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()
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debugextensions', cmdutil.formatteropts, [], norepo=True)
Gregory Szorc
debugcommands: move 'debugextensions' to the new module
r30518 def debugextensions(ui, **opts):
'''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',
[('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
_('[-r REV] FILESPEC'))
def debugfileset(ui, repo, expr, **opts):
'''parse and apply a fileset specification'''
Pulkit Goyal
py3: use r'' to prevent the addition of b'' by transformer...
r33101 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
Gregory Szorc
debugcommands: move 'debugfileset' in the new module
r30524 if ui.verbose:
tree = fileset.parse(expr)
ui.note(fileset.prettyformat(tree), "\n")
for f in ctx.getfileset(expr):
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',
[] + cmdutil.formatteropts,
_(''))
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:
with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
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
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 @command('debugindex', cmdutil.debugrevlogopts +
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
_('[-f FORMAT] -c|-m|FILE'),
optionalrepo=True)
def debugindex(ui, repo, file_=None, **opts):
"""dump the contents of an index file"""
Pulkit Goyal
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes...
r33100 opts = pycompat.byteskwargs(opts)
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
format = opts.get('format', 0)
if format not in (0, 1):
raise error.Abort(_("unknown format %d") % format)
Gregory Szorc
revlog: rename constants (API)...
r32316 generaldelta = r.version & revlog.FLAG_GENERALDELTA
Gregory Szorc
debugcommands: move 'debugindex' and 'debugindexdot' in the new module
r30528 if generaldelta:
basehdr = ' delta'
else:
basehdr = ' base'
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:
ui.write((" rev offset length " + basehdr + " linkrev"
" %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
elif format == 1:
ui.write((" rev flag offset length"
" size " + basehdr + " link p1 p2"
" %s\n") % "nodeid".rjust(idlen))
for i in r:
node = r.node(i)
if generaldelta:
base = r.deltaparent(i)
else:
base = r.chainbase(i)
if format == 0:
try:
pp = r.parents(node)
except Exception:
pp = [nullid, nullid]
ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
i, r.start(i), r.length(i), base, r.linkrev(i),
shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
elif format == 1:
pr = r.parentrevs(i)
ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
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: move 'debugindex' and 'debugindexdot' in the new module
r30528 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
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):
(fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
Pulkit Goyal
py3: convert the mode argument of os.fdopen to unicodes...
r30988 f = os.fdopen(fd, pycompat.sysstr("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
debuginstall: do not pass exception object to formatter (issue5676)
r34132 err = util.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
debuginstall: do not pass exception object to formatter (issue5676)
r34132 err = util.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
debuginstall: do not pass exception object to formatter (issue5676)
r34132 err = util.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
util: factor out shellsplit() function...
r36433 editorbin = util.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)
cmdpath = util.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
debuginstall: do not pass exception object to formatter (issue5676)
r34132 err = util.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:
stat = vfs.lstat(name)
age = now - stat.st_mtime
user = util.username(stat.st_uid)
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
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 = {}
metadata['user'] = opts['user'] or ui.username()
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']
ui.note(('with --tool %r\n') % (opts['tool']))
with ui.configoverride(overrides, 'debugmergepatterns'):
hgmerge = encoding.environ.get("HGMERGE")
if hgmerge is not None:
ui.note(('with HGMERGE=%r\n') % (hgmerge))
uimerge = ui.config("ui", "merge")
if uimerge:
ui.note(('with ui.merge=%r\n') % (uimerge))
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
r = target.pushkey(namespace, key, old, new)
ui.status(str(r) + '\n')
return not r
else:
for k, v in sorted(target.listkeys(namespace).iteritems()):
Yuya Nishihara
util: wrap s.encode('string_escape') call for future py3 compatibility
r31451 ui.write("%s\t%s\n" % (util.escapestr(k),
util.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()
for rev in xrange(numrevs):
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)']
nummerges = 0
numfull = 0
numprev = 0
nump1 = 0
nump2 = 0
numother = 0
nump1prev = 0
nump2prev = 0
chainlengths = []
debugrevlog: also display the largest delta chain span...
r33057 chainbases = []
chainspans = []
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951
datasize = [None, 0, 0]
fullsize = [None, 0, 0]
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)
for rev in xrange(numrevs):
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)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 numfull += 1
addsize(size, fullsize)
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)
Pierre-Yves David
debugcommands: move 'debugrevlog' in the new module
r30951 addsize(size, deltasize)
if delta == rev - 1:
numprev += 1
if delta == p1:
nump1prev += 1
elif delta == p2:
nump2prev += 1
elif delta == p1:
nump1 += 1
elif delta == p2:
nump2 += 1
elif delta != nullrev:
numother += 1
# Obtain data on the raw chunks in the revlog.
Gregory Szorc
revlog: rename _chunkraw to _getsegmentforrevs()...
r32224 segment = r._getsegmentforrevs(rev, rev)[1]
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
for size in (datasize, fullsize, deltasize):
if size[0] is None:
size[0] = 0
numdeltas = numrevs - numfull
numoprev = numprev - nump1prev - nump2prev
totalrawsize = datasize[2]
datasize[2] /= numrevs
fulltotal = fullsize[2]
fullsize[2] /= numfull
deltatotal = deltasize[2]
if numrevs - numfull > 0:
deltasize[2] /= numrevs - numfull
totalsize = fulltotal + deltatotal
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)
ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
ui.write(('revision size : ') + fmt2 % totalsize)
ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
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))
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))
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
Yuya Nishihara
revset: split language services to revsetlang module (API)...
r31024 tree = revsetlang.parse(expr, lookup=repo.__contains__)
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):
ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
ui.write(("* optimized set:\n"), smartset.prettyformat(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):
ui.write(("* set:\n"), smartset.prettyformat(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: add an r prefix to make file mode for fdopen a sysstr...
r36604 logfh = os.fdopen(int(opts['logiofd']), r'ab', 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.
"""
r1 = scmutil.revsingle(repo, rev1).node()
r2 = scmutil.revsingle(repo, rev2, 'null').node()
with repo.wlock():
repo.setparents(r1, r2)
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 simple interface for unnamed template (API)...
r32873 ui.write(t.render(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)
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()
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():
repo.updatecaches()
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)
Martin von Zweigbergk
debugwalk: also print matcher representation...
r32453 ui.write(('matcher: %r\n' % m))
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
@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
if not line.startswith(' '):
# 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: add debugwireproto command...
r36545 ] + cmdutil.remoteopts,
_('[REPO]'),
optionalrepo=True)
def debugwireproto(ui, repo, **opts):
"""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``,
``ssh1``, and ``ssh2``. ``raw`` instances only allow sending raw data
payloads and don't support higher-level command actions.
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
Values are interpreted as Python b'' literals. This allows encoding
special byte sequences via backslash escaping.
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: add debugwireproto command...
r36545 close
-----
Close the connection to the server.
flush
-----
Flush data written to the server.
readavailable
-------------
Read all available data from the server.
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.
"""
opts = pycompat.byteskwargs(opts)
if opts['localssh'] and not repo:
raise error.Abort(_('--localssh requires a repository'))
if opts['peer'] and opts['peer'] not in ('raw', 'ssh1', 'ssh2'):
raise error.Abort(_('invalid value for --peer'),
hint=_('valid values are "raw", "ssh1", and "ssh2"'))
if ui.interactive():
ui.write(_('(waiting for commands on stdin)\n'))
blocks = list(_parsewirelangblocks(ui.fin))
proc = None
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.
args = util.hgcmd() + [
'-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
else:
raise error.Abort(_('only --localssh is currently supported'))
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+'):
# Concatenate the data together.
data = ''.join(l.lstrip() for l in lines)
data = util.unescapestr(data)
stdin.write(data)
if action == 'raw+':
stdin.flush()
elif action == 'flush':
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
args[key] = util.unescapestr(value)
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))
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 ui.status(_('result: %s\n') % util.escapedata(res))
ui.status(_('remote output: %s\n') %
util.escapedata(output))
else:
Augie Fackler
debugcommands: add some strkwargs love to some **args calls...
r36605 res = peer._call(command, **pycompat.strkwargs(args))
Gregory Szorc
debugcommands: support for triggering push protocol...
r36551 ui.status(_('response: %s\n') % util.escapedata(res))
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)):
ui.status(_('response #%d: %s\n') % (i, util.escapedata(chunk)))
batchedcommands = None
Gregory Szorc
debugcommands: add debugwireproto command...
r36545 elif action == 'close':
peer.close()
elif action == 'readavailable':
fds = util.poll([stdout.fileno(), stderr.fileno()])
if stdout.fileno() in fds:
util.readpipe(stdout)
if stderr.fileno() in fds:
util.readpipe(stderr)
elif action == 'readline':
stdout.readline()
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()