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