##// END OF EJS Templates
debugfs: display the tested path and mount point of the filesystem, if known...
Matt Harbison -
r35532:58803186 default
parent child Browse files
Show More
@@ -1,2446 +1,2448 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 _('[--rev REV] [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(('path: %s\n') % path)
915 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
914 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
916 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
915 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
917 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
916 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
918 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'))
919 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
918 casesensitive = '(unknown)'
920 casesensitive = '(unknown)'
919 try:
921 try:
920 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
922 with tempfile.NamedTemporaryFile(prefix='.debugfsinfo', dir=path) as f:
921 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
923 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
922 except OSError:
924 except OSError:
923 pass
925 pass
924 ui.write(('case-sensitive: %s\n') % casesensitive)
926 ui.write(('case-sensitive: %s\n') % casesensitive)
925
927
926 @command('debuggetbundle',
928 @command('debuggetbundle',
927 [('H', 'head', [], _('id of head node'), _('ID')),
929 [('H', 'head', [], _('id of head node'), _('ID')),
928 ('C', 'common', [], _('id of common node'), _('ID')),
930 ('C', 'common', [], _('id of common node'), _('ID')),
929 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
931 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
930 _('REPO FILE [-H|-C ID]...'),
932 _('REPO FILE [-H|-C ID]...'),
931 norepo=True)
933 norepo=True)
932 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
934 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
933 """retrieves a bundle from a repo
935 """retrieves a bundle from a repo
934
936
935 Every ID must be a full-length hex node id string. Saves the bundle to the
937 Every ID must be a full-length hex node id string. Saves the bundle to the
936 given file.
938 given file.
937 """
939 """
938 opts = pycompat.byteskwargs(opts)
940 opts = pycompat.byteskwargs(opts)
939 repo = hg.peer(ui, opts, repopath)
941 repo = hg.peer(ui, opts, repopath)
940 if not repo.capable('getbundle'):
942 if not repo.capable('getbundle'):
941 raise error.Abort("getbundle() not supported by target repository")
943 raise error.Abort("getbundle() not supported by target repository")
942 args = {}
944 args = {}
943 if common:
945 if common:
944 args[r'common'] = [bin(s) for s in common]
946 args[r'common'] = [bin(s) for s in common]
945 if head:
947 if head:
946 args[r'heads'] = [bin(s) for s in head]
948 args[r'heads'] = [bin(s) for s in head]
947 # TODO: get desired bundlecaps from command line.
949 # TODO: get desired bundlecaps from command line.
948 args[r'bundlecaps'] = None
950 args[r'bundlecaps'] = None
949 bundle = repo.getbundle('debug', **args)
951 bundle = repo.getbundle('debug', **args)
950
952
951 bundletype = opts.get('type', 'bzip2').lower()
953 bundletype = opts.get('type', 'bzip2').lower()
952 btypes = {'none': 'HG10UN',
954 btypes = {'none': 'HG10UN',
953 'bzip2': 'HG10BZ',
955 'bzip2': 'HG10BZ',
954 'gzip': 'HG10GZ',
956 'gzip': 'HG10GZ',
955 'bundle2': 'HG20'}
957 'bundle2': 'HG20'}
956 bundletype = btypes.get(bundletype)
958 bundletype = btypes.get(bundletype)
957 if bundletype not in bundle2.bundletypes:
959 if bundletype not in bundle2.bundletypes:
958 raise error.Abort(_('unknown bundle type specified with --type'))
960 raise error.Abort(_('unknown bundle type specified with --type'))
959 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
961 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
960
962
961 @command('debugignore', [], '[FILE]')
963 @command('debugignore', [], '[FILE]')
962 def debugignore(ui, repo, *files, **opts):
964 def debugignore(ui, repo, *files, **opts):
963 """display the combined ignore pattern and information about ignored files
965 """display the combined ignore pattern and information about ignored files
964
966
965 With no argument display the combined ignore pattern.
967 With no argument display the combined ignore pattern.
966
968
967 Given space separated file names, shows if the given file is ignored and
969 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.
970 if so, show the ignore rule (file and line number) that matched it.
969 """
971 """
970 ignore = repo.dirstate._ignore
972 ignore = repo.dirstate._ignore
971 if not files:
973 if not files:
972 # Show all the patterns
974 # Show all the patterns
973 ui.write("%s\n" % repr(ignore))
975 ui.write("%s\n" % repr(ignore))
974 else:
976 else:
975 m = scmutil.match(repo[None], pats=files)
977 m = scmutil.match(repo[None], pats=files)
976 for f in m.files():
978 for f in m.files():
977 nf = util.normpath(f)
979 nf = util.normpath(f)
978 ignored = None
980 ignored = None
979 ignoredata = None
981 ignoredata = None
980 if nf != '.':
982 if nf != '.':
981 if ignore(nf):
983 if ignore(nf):
982 ignored = nf
984 ignored = nf
983 ignoredata = repo.dirstate._ignorefileandline(nf)
985 ignoredata = repo.dirstate._ignorefileandline(nf)
984 else:
986 else:
985 for p in util.finddirs(nf):
987 for p in util.finddirs(nf):
986 if ignore(p):
988 if ignore(p):
987 ignored = p
989 ignored = p
988 ignoredata = repo.dirstate._ignorefileandline(p)
990 ignoredata = repo.dirstate._ignorefileandline(p)
989 break
991 break
990 if ignored:
992 if ignored:
991 if ignored == nf:
993 if ignored == nf:
992 ui.write(_("%s is ignored\n") % m.uipath(f))
994 ui.write(_("%s is ignored\n") % m.uipath(f))
993 else:
995 else:
994 ui.write(_("%s is ignored because of "
996 ui.write(_("%s is ignored because of "
995 "containing folder %s\n")
997 "containing folder %s\n")
996 % (m.uipath(f), ignored))
998 % (m.uipath(f), ignored))
997 ignorefile, lineno, line = ignoredata
999 ignorefile, lineno, line = ignoredata
998 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1000 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
999 % (ignorefile, lineno, line))
1001 % (ignorefile, lineno, line))
1000 else:
1002 else:
1001 ui.write(_("%s is not ignored\n") % m.uipath(f))
1003 ui.write(_("%s is not ignored\n") % m.uipath(f))
1002
1004
1003 @command('debugindex', cmdutil.debugrevlogopts +
1005 @command('debugindex', cmdutil.debugrevlogopts +
1004 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1006 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1005 _('[-f FORMAT] -c|-m|FILE'),
1007 _('[-f FORMAT] -c|-m|FILE'),
1006 optionalrepo=True)
1008 optionalrepo=True)
1007 def debugindex(ui, repo, file_=None, **opts):
1009 def debugindex(ui, repo, file_=None, **opts):
1008 """dump the contents of an index file"""
1010 """dump the contents of an index file"""
1009 opts = pycompat.byteskwargs(opts)
1011 opts = pycompat.byteskwargs(opts)
1010 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1012 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1011 format = opts.get('format', 0)
1013 format = opts.get('format', 0)
1012 if format not in (0, 1):
1014 if format not in (0, 1):
1013 raise error.Abort(_("unknown format %d") % format)
1015 raise error.Abort(_("unknown format %d") % format)
1014
1016
1015 generaldelta = r.version & revlog.FLAG_GENERALDELTA
1017 generaldelta = r.version & revlog.FLAG_GENERALDELTA
1016 if generaldelta:
1018 if generaldelta:
1017 basehdr = ' delta'
1019 basehdr = ' delta'
1018 else:
1020 else:
1019 basehdr = ' base'
1021 basehdr = ' base'
1020
1022
1021 if ui.debugflag:
1023 if ui.debugflag:
1022 shortfn = hex
1024 shortfn = hex
1023 else:
1025 else:
1024 shortfn = short
1026 shortfn = short
1025
1027
1026 # There might not be anything in r, so have a sane default
1028 # There might not be anything in r, so have a sane default
1027 idlen = 12
1029 idlen = 12
1028 for i in r:
1030 for i in r:
1029 idlen = len(shortfn(r.node(i)))
1031 idlen = len(shortfn(r.node(i)))
1030 break
1032 break
1031
1033
1032 if format == 0:
1034 if format == 0:
1033 ui.write((" rev offset length " + basehdr + " linkrev"
1035 ui.write((" rev offset length " + basehdr + " linkrev"
1034 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
1036 " %s %s p2\n") % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
1035 elif format == 1:
1037 elif format == 1:
1036 ui.write((" rev flag offset length"
1038 ui.write((" rev flag offset length"
1037 " size " + basehdr + " link p1 p2"
1039 " size " + basehdr + " link p1 p2"
1038 " %s\n") % "nodeid".rjust(idlen))
1040 " %s\n") % "nodeid".rjust(idlen))
1039
1041
1040 for i in r:
1042 for i in r:
1041 node = r.node(i)
1043 node = r.node(i)
1042 if generaldelta:
1044 if generaldelta:
1043 base = r.deltaparent(i)
1045 base = r.deltaparent(i)
1044 else:
1046 else:
1045 base = r.chainbase(i)
1047 base = r.chainbase(i)
1046 if format == 0:
1048 if format == 0:
1047 try:
1049 try:
1048 pp = r.parents(node)
1050 pp = r.parents(node)
1049 except Exception:
1051 except Exception:
1050 pp = [nullid, nullid]
1052 pp = [nullid, nullid]
1051 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1053 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1052 i, r.start(i), r.length(i), base, r.linkrev(i),
1054 i, r.start(i), r.length(i), base, r.linkrev(i),
1053 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1055 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
1054 elif format == 1:
1056 elif format == 1:
1055 pr = r.parentrevs(i)
1057 pr = r.parentrevs(i)
1056 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1058 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),
1059 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1058 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
1060 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
1059
1061
1060 @command('debugindexdot', cmdutil.debugrevlogopts,
1062 @command('debugindexdot', cmdutil.debugrevlogopts,
1061 _('-c|-m|FILE'), optionalrepo=True)
1063 _('-c|-m|FILE'), optionalrepo=True)
1062 def debugindexdot(ui, repo, file_=None, **opts):
1064 def debugindexdot(ui, repo, file_=None, **opts):
1063 """dump an index DAG as a graphviz dot file"""
1065 """dump an index DAG as a graphviz dot file"""
1064 opts = pycompat.byteskwargs(opts)
1066 opts = pycompat.byteskwargs(opts)
1065 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1067 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
1066 ui.write(("digraph G {\n"))
1068 ui.write(("digraph G {\n"))
1067 for i in r:
1069 for i in r:
1068 node = r.node(i)
1070 node = r.node(i)
1069 pp = r.parents(node)
1071 pp = r.parents(node)
1070 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1072 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1071 if pp[1] != nullid:
1073 if pp[1] != nullid:
1072 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1074 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1073 ui.write("}\n")
1075 ui.write("}\n")
1074
1076
1075 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1077 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1076 def debuginstall(ui, **opts):
1078 def debuginstall(ui, **opts):
1077 '''test Mercurial installation
1079 '''test Mercurial installation
1078
1080
1079 Returns 0 on success.
1081 Returns 0 on success.
1080 '''
1082 '''
1081 opts = pycompat.byteskwargs(opts)
1083 opts = pycompat.byteskwargs(opts)
1082
1084
1083 def writetemp(contents):
1085 def writetemp(contents):
1084 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1086 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1085 f = os.fdopen(fd, pycompat.sysstr("wb"))
1087 f = os.fdopen(fd, pycompat.sysstr("wb"))
1086 f.write(contents)
1088 f.write(contents)
1087 f.close()
1089 f.close()
1088 return name
1090 return name
1089
1091
1090 problems = 0
1092 problems = 0
1091
1093
1092 fm = ui.formatter('debuginstall', opts)
1094 fm = ui.formatter('debuginstall', opts)
1093 fm.startitem()
1095 fm.startitem()
1094
1096
1095 # encoding
1097 # encoding
1096 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1098 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1097 err = None
1099 err = None
1098 try:
1100 try:
1099 codecs.lookup(pycompat.sysstr(encoding.encoding))
1101 codecs.lookup(pycompat.sysstr(encoding.encoding))
1100 except LookupError as inst:
1102 except LookupError as inst:
1101 err = util.forcebytestr(inst)
1103 err = util.forcebytestr(inst)
1102 problems += 1
1104 problems += 1
1103 fm.condwrite(err, 'encodingerror', _(" %s\n"
1105 fm.condwrite(err, 'encodingerror', _(" %s\n"
1104 " (check that your locale is properly set)\n"), err)
1106 " (check that your locale is properly set)\n"), err)
1105
1107
1106 # Python
1108 # Python
1107 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1109 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1108 pycompat.sysexecutable)
1110 pycompat.sysexecutable)
1109 fm.write('pythonver', _("checking Python version (%s)\n"),
1111 fm.write('pythonver', _("checking Python version (%s)\n"),
1110 ("%d.%d.%d" % sys.version_info[:3]))
1112 ("%d.%d.%d" % sys.version_info[:3]))
1111 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1113 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1112 os.path.dirname(pycompat.fsencode(os.__file__)))
1114 os.path.dirname(pycompat.fsencode(os.__file__)))
1113
1115
1114 security = set(sslutil.supportedprotocols)
1116 security = set(sslutil.supportedprotocols)
1115 if sslutil.hassni:
1117 if sslutil.hassni:
1116 security.add('sni')
1118 security.add('sni')
1117
1119
1118 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1120 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1119 fm.formatlist(sorted(security), name='protocol',
1121 fm.formatlist(sorted(security), name='protocol',
1120 fmt='%s', sep=','))
1122 fmt='%s', sep=','))
1121
1123
1122 # These are warnings, not errors. So don't increment problem count. This
1124 # These are warnings, not errors. So don't increment problem count. This
1123 # may change in the future.
1125 # may change in the future.
1124 if 'tls1.2' not in security:
1126 if 'tls1.2' not in security:
1125 fm.plain(_(' TLS 1.2 not supported by Python install; '
1127 fm.plain(_(' TLS 1.2 not supported by Python install; '
1126 'network connections lack modern security\n'))
1128 'network connections lack modern security\n'))
1127 if 'sni' not in security:
1129 if 'sni' not in security:
1128 fm.plain(_(' SNI not supported by Python install; may have '
1130 fm.plain(_(' SNI not supported by Python install; may have '
1129 'connectivity issues with some servers\n'))
1131 'connectivity issues with some servers\n'))
1130
1132
1131 # TODO print CA cert info
1133 # TODO print CA cert info
1132
1134
1133 # hg version
1135 # hg version
1134 hgver = util.version()
1136 hgver = util.version()
1135 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1137 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1136 hgver.split('+')[0])
1138 hgver.split('+')[0])
1137 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1139 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1138 '+'.join(hgver.split('+')[1:]))
1140 '+'.join(hgver.split('+')[1:]))
1139
1141
1140 # compiled modules
1142 # compiled modules
1141 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1143 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1142 policy.policy)
1144 policy.policy)
1143 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1145 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1144 os.path.dirname(pycompat.fsencode(__file__)))
1146 os.path.dirname(pycompat.fsencode(__file__)))
1145
1147
1146 if policy.policy in ('c', 'allow'):
1148 if policy.policy in ('c', 'allow'):
1147 err = None
1149 err = None
1148 try:
1150 try:
1149 from .cext import (
1151 from .cext import (
1150 base85,
1152 base85,
1151 bdiff,
1153 bdiff,
1152 mpatch,
1154 mpatch,
1153 osutil,
1155 osutil,
1154 )
1156 )
1155 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1157 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1156 except Exception as inst:
1158 except Exception as inst:
1157 err = util.forcebytestr(inst)
1159 err = util.forcebytestr(inst)
1158 problems += 1
1160 problems += 1
1159 fm.condwrite(err, 'extensionserror', " %s\n", err)
1161 fm.condwrite(err, 'extensionserror', " %s\n", err)
1160
1162
1161 compengines = util.compengines._engines.values()
1163 compengines = util.compengines._engines.values()
1162 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1164 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1163 fm.formatlist(sorted(e.name() for e in compengines),
1165 fm.formatlist(sorted(e.name() for e in compengines),
1164 name='compengine', fmt='%s', sep=', '))
1166 name='compengine', fmt='%s', sep=', '))
1165 fm.write('compenginesavail', _('checking available compression engines '
1167 fm.write('compenginesavail', _('checking available compression engines '
1166 '(%s)\n'),
1168 '(%s)\n'),
1167 fm.formatlist(sorted(e.name() for e in compengines
1169 fm.formatlist(sorted(e.name() for e in compengines
1168 if e.available()),
1170 if e.available()),
1169 name='compengine', fmt='%s', sep=', '))
1171 name='compengine', fmt='%s', sep=', '))
1170 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1172 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1171 fm.write('compenginesserver', _('checking available compression engines '
1173 fm.write('compenginesserver', _('checking available compression engines '
1172 'for wire protocol (%s)\n'),
1174 'for wire protocol (%s)\n'),
1173 fm.formatlist([e.name() for e in wirecompengines
1175 fm.formatlist([e.name() for e in wirecompengines
1174 if e.wireprotosupport()],
1176 if e.wireprotosupport()],
1175 name='compengine', fmt='%s', sep=', '))
1177 name='compengine', fmt='%s', sep=', '))
1176 re2 = 'missing'
1178 re2 = 'missing'
1177 if util._re2:
1179 if util._re2:
1178 re2 = 'available'
1180 re2 = 'available'
1179 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1181 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1180 fm.data(re2=bool(util._re2))
1182 fm.data(re2=bool(util._re2))
1181
1183
1182 # templates
1184 # templates
1183 p = templater.templatepaths()
1185 p = templater.templatepaths()
1184 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1186 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1185 fm.condwrite(not p, '', _(" no template directories found\n"))
1187 fm.condwrite(not p, '', _(" no template directories found\n"))
1186 if p:
1188 if p:
1187 m = templater.templatepath("map-cmdline.default")
1189 m = templater.templatepath("map-cmdline.default")
1188 if m:
1190 if m:
1189 # template found, check if it is working
1191 # template found, check if it is working
1190 err = None
1192 err = None
1191 try:
1193 try:
1192 templater.templater.frommapfile(m)
1194 templater.templater.frommapfile(m)
1193 except Exception as inst:
1195 except Exception as inst:
1194 err = util.forcebytestr(inst)
1196 err = util.forcebytestr(inst)
1195 p = None
1197 p = None
1196 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1198 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1197 else:
1199 else:
1198 p = None
1200 p = None
1199 fm.condwrite(p, 'defaulttemplate',
1201 fm.condwrite(p, 'defaulttemplate',
1200 _("checking default template (%s)\n"), m)
1202 _("checking default template (%s)\n"), m)
1201 fm.condwrite(not m, 'defaulttemplatenotfound',
1203 fm.condwrite(not m, 'defaulttemplatenotfound',
1202 _(" template '%s' not found\n"), "default")
1204 _(" template '%s' not found\n"), "default")
1203 if not p:
1205 if not p:
1204 problems += 1
1206 problems += 1
1205 fm.condwrite(not p, '',
1207 fm.condwrite(not p, '',
1206 _(" (templates seem to have been installed incorrectly)\n"))
1208 _(" (templates seem to have been installed incorrectly)\n"))
1207
1209
1208 # editor
1210 # editor
1209 editor = ui.geteditor()
1211 editor = ui.geteditor()
1210 editor = util.expandpath(editor)
1212 editor = util.expandpath(editor)
1211 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
1213 fm.write('editor', _("checking commit editor... (%s)\n"), editor)
1212 cmdpath = util.findexe(pycompat.shlexsplit(editor)[0])
1214 cmdpath = util.findexe(pycompat.shlexsplit(editor)[0])
1213 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1215 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1214 _(" No commit editor set and can't find %s in PATH\n"
1216 _(" No commit editor set and can't find %s in PATH\n"
1215 " (specify a commit editor in your configuration"
1217 " (specify a commit editor in your configuration"
1216 " file)\n"), not cmdpath and editor == 'vi' and editor)
1218 " file)\n"), not cmdpath and editor == 'vi' and editor)
1217 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1219 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1218 _(" Can't find editor '%s' in PATH\n"
1220 _(" Can't find editor '%s' in PATH\n"
1219 " (specify a commit editor in your configuration"
1221 " (specify a commit editor in your configuration"
1220 " file)\n"), not cmdpath and editor)
1222 " file)\n"), not cmdpath and editor)
1221 if not cmdpath and editor != 'vi':
1223 if not cmdpath and editor != 'vi':
1222 problems += 1
1224 problems += 1
1223
1225
1224 # check username
1226 # check username
1225 username = None
1227 username = None
1226 err = None
1228 err = None
1227 try:
1229 try:
1228 username = ui.username()
1230 username = ui.username()
1229 except error.Abort as e:
1231 except error.Abort as e:
1230 err = util.forcebytestr(e)
1232 err = util.forcebytestr(e)
1231 problems += 1
1233 problems += 1
1232
1234
1233 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1235 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1234 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1236 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1235 " (specify a username in your configuration file)\n"), err)
1237 " (specify a username in your configuration file)\n"), err)
1236
1238
1237 fm.condwrite(not problems, '',
1239 fm.condwrite(not problems, '',
1238 _("no problems detected\n"))
1240 _("no problems detected\n"))
1239 if not problems:
1241 if not problems:
1240 fm.data(problems=problems)
1242 fm.data(problems=problems)
1241 fm.condwrite(problems, 'problems',
1243 fm.condwrite(problems, 'problems',
1242 _("%d problems detected,"
1244 _("%d problems detected,"
1243 " please check your install!\n"), problems)
1245 " please check your install!\n"), problems)
1244 fm.end()
1246 fm.end()
1245
1247
1246 return problems
1248 return problems
1247
1249
1248 @command('debugknown', [], _('REPO ID...'), norepo=True)
1250 @command('debugknown', [], _('REPO ID...'), norepo=True)
1249 def debugknown(ui, repopath, *ids, **opts):
1251 def debugknown(ui, repopath, *ids, **opts):
1250 """test whether node ids are known to a repo
1252 """test whether node ids are known to a repo
1251
1253
1252 Every ID must be a full-length hex node id string. Returns a list of 0s
1254 Every ID must be a full-length hex node id string. Returns a list of 0s
1253 and 1s indicating unknown/known.
1255 and 1s indicating unknown/known.
1254 """
1256 """
1255 opts = pycompat.byteskwargs(opts)
1257 opts = pycompat.byteskwargs(opts)
1256 repo = hg.peer(ui, opts, repopath)
1258 repo = hg.peer(ui, opts, repopath)
1257 if not repo.capable('known'):
1259 if not repo.capable('known'):
1258 raise error.Abort("known() not supported by target repository")
1260 raise error.Abort("known() not supported by target repository")
1259 flags = repo.known([bin(s) for s in ids])
1261 flags = repo.known([bin(s) for s in ids])
1260 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1262 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1261
1263
1262 @command('debuglabelcomplete', [], _('LABEL...'))
1264 @command('debuglabelcomplete', [], _('LABEL...'))
1263 def debuglabelcomplete(ui, repo, *args):
1265 def debuglabelcomplete(ui, repo, *args):
1264 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1266 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1265 debugnamecomplete(ui, repo, *args)
1267 debugnamecomplete(ui, repo, *args)
1266
1268
1267 @command('debuglocks',
1269 @command('debuglocks',
1268 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1270 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1269 ('W', 'force-wlock', None,
1271 ('W', 'force-wlock', None,
1270 _('free the working state lock (DANGEROUS)')),
1272 _('free the working state lock (DANGEROUS)')),
1271 ('s', 'set-lock', None, _('set the store lock until stopped')),
1273 ('s', 'set-lock', None, _('set the store lock until stopped')),
1272 ('S', 'set-wlock', None,
1274 ('S', 'set-wlock', None,
1273 _('set the working state lock until stopped'))],
1275 _('set the working state lock until stopped'))],
1274 _('[OPTION]...'))
1276 _('[OPTION]...'))
1275 def debuglocks(ui, repo, **opts):
1277 def debuglocks(ui, repo, **opts):
1276 """show or modify state of locks
1278 """show or modify state of locks
1277
1279
1278 By default, this command will show which locks are held. This
1280 By default, this command will show which locks are held. This
1279 includes the user and process holding the lock, the amount of time
1281 includes the user and process holding the lock, the amount of time
1280 the lock has been held, and the machine name where the process is
1282 the lock has been held, and the machine name where the process is
1281 running if it's not local.
1283 running if it's not local.
1282
1284
1283 Locks protect the integrity of Mercurial's data, so should be
1285 Locks protect the integrity of Mercurial's data, so should be
1284 treated with care. System crashes or other interruptions may cause
1286 treated with care. System crashes or other interruptions may cause
1285 locks to not be properly released, though Mercurial will usually
1287 locks to not be properly released, though Mercurial will usually
1286 detect and remove such stale locks automatically.
1288 detect and remove such stale locks automatically.
1287
1289
1288 However, detecting stale locks may not always be possible (for
1290 However, detecting stale locks may not always be possible (for
1289 instance, on a shared filesystem). Removing locks may also be
1291 instance, on a shared filesystem). Removing locks may also be
1290 blocked by filesystem permissions.
1292 blocked by filesystem permissions.
1291
1293
1292 Setting a lock will prevent other commands from changing the data.
1294 Setting a lock will prevent other commands from changing the data.
1293 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1295 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1294 The set locks are removed when the command exits.
1296 The set locks are removed when the command exits.
1295
1297
1296 Returns 0 if no locks are held.
1298 Returns 0 if no locks are held.
1297
1299
1298 """
1300 """
1299
1301
1300 if opts.get(r'force_lock'):
1302 if opts.get(r'force_lock'):
1301 repo.svfs.unlink('lock')
1303 repo.svfs.unlink('lock')
1302 if opts.get(r'force_wlock'):
1304 if opts.get(r'force_wlock'):
1303 repo.vfs.unlink('wlock')
1305 repo.vfs.unlink('wlock')
1304 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1306 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1305 return 0
1307 return 0
1306
1308
1307 locks = []
1309 locks = []
1308 try:
1310 try:
1309 if opts.get(r'set_wlock'):
1311 if opts.get(r'set_wlock'):
1310 try:
1312 try:
1311 locks.append(repo.wlock(False))
1313 locks.append(repo.wlock(False))
1312 except error.LockHeld:
1314 except error.LockHeld:
1313 raise error.Abort(_('wlock is already held'))
1315 raise error.Abort(_('wlock is already held'))
1314 if opts.get(r'set_lock'):
1316 if opts.get(r'set_lock'):
1315 try:
1317 try:
1316 locks.append(repo.lock(False))
1318 locks.append(repo.lock(False))
1317 except error.LockHeld:
1319 except error.LockHeld:
1318 raise error.Abort(_('lock is already held'))
1320 raise error.Abort(_('lock is already held'))
1319 if len(locks):
1321 if len(locks):
1320 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1322 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1321 return 0
1323 return 0
1322 finally:
1324 finally:
1323 release(*locks)
1325 release(*locks)
1324
1326
1325 now = time.time()
1327 now = time.time()
1326 held = 0
1328 held = 0
1327
1329
1328 def report(vfs, name, method):
1330 def report(vfs, name, method):
1329 # this causes stale locks to get reaped for more accurate reporting
1331 # this causes stale locks to get reaped for more accurate reporting
1330 try:
1332 try:
1331 l = method(False)
1333 l = method(False)
1332 except error.LockHeld:
1334 except error.LockHeld:
1333 l = None
1335 l = None
1334
1336
1335 if l:
1337 if l:
1336 l.release()
1338 l.release()
1337 else:
1339 else:
1338 try:
1340 try:
1339 stat = vfs.lstat(name)
1341 stat = vfs.lstat(name)
1340 age = now - stat.st_mtime
1342 age = now - stat.st_mtime
1341 user = util.username(stat.st_uid)
1343 user = util.username(stat.st_uid)
1342 locker = vfs.readlock(name)
1344 locker = vfs.readlock(name)
1343 if ":" in locker:
1345 if ":" in locker:
1344 host, pid = locker.split(':')
1346 host, pid = locker.split(':')
1345 if host == socket.gethostname():
1347 if host == socket.gethostname():
1346 locker = 'user %s, process %s' % (user, pid)
1348 locker = 'user %s, process %s' % (user, pid)
1347 else:
1349 else:
1348 locker = 'user %s, process %s, host %s' \
1350 locker = 'user %s, process %s, host %s' \
1349 % (user, pid, host)
1351 % (user, pid, host)
1350 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1352 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1351 return 1
1353 return 1
1352 except OSError as e:
1354 except OSError as e:
1353 if e.errno != errno.ENOENT:
1355 if e.errno != errno.ENOENT:
1354 raise
1356 raise
1355
1357
1356 ui.write(("%-6s free\n") % (name + ":"))
1358 ui.write(("%-6s free\n") % (name + ":"))
1357 return 0
1359 return 0
1358
1360
1359 held += report(repo.svfs, "lock", repo.lock)
1361 held += report(repo.svfs, "lock", repo.lock)
1360 held += report(repo.vfs, "wlock", repo.wlock)
1362 held += report(repo.vfs, "wlock", repo.wlock)
1361
1363
1362 return held
1364 return held
1363
1365
1364 @command('debugmergestate', [], '')
1366 @command('debugmergestate', [], '')
1365 def debugmergestate(ui, repo, *args):
1367 def debugmergestate(ui, repo, *args):
1366 """print merge state
1368 """print merge state
1367
1369
1368 Use --verbose to print out information about whether v1 or v2 merge state
1370 Use --verbose to print out information about whether v1 or v2 merge state
1369 was chosen."""
1371 was chosen."""
1370 def _hashornull(h):
1372 def _hashornull(h):
1371 if h == nullhex:
1373 if h == nullhex:
1372 return 'null'
1374 return 'null'
1373 else:
1375 else:
1374 return h
1376 return h
1375
1377
1376 def printrecords(version):
1378 def printrecords(version):
1377 ui.write(('* version %s records\n') % version)
1379 ui.write(('* version %s records\n') % version)
1378 if version == 1:
1380 if version == 1:
1379 records = v1records
1381 records = v1records
1380 else:
1382 else:
1381 records = v2records
1383 records = v2records
1382
1384
1383 for rtype, record in records:
1385 for rtype, record in records:
1384 # pretty print some record types
1386 # pretty print some record types
1385 if rtype == 'L':
1387 if rtype == 'L':
1386 ui.write(('local: %s\n') % record)
1388 ui.write(('local: %s\n') % record)
1387 elif rtype == 'O':
1389 elif rtype == 'O':
1388 ui.write(('other: %s\n') % record)
1390 ui.write(('other: %s\n') % record)
1389 elif rtype == 'm':
1391 elif rtype == 'm':
1390 driver, mdstate = record.split('\0', 1)
1392 driver, mdstate = record.split('\0', 1)
1391 ui.write(('merge driver: %s (state "%s")\n')
1393 ui.write(('merge driver: %s (state "%s")\n')
1392 % (driver, mdstate))
1394 % (driver, mdstate))
1393 elif rtype in 'FDC':
1395 elif rtype in 'FDC':
1394 r = record.split('\0')
1396 r = record.split('\0')
1395 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1397 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1396 if version == 1:
1398 if version == 1:
1397 onode = 'not stored in v1 format'
1399 onode = 'not stored in v1 format'
1398 flags = r[7]
1400 flags = r[7]
1399 else:
1401 else:
1400 onode, flags = r[7:9]
1402 onode, flags = r[7:9]
1401 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1403 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1402 % (f, rtype, state, _hashornull(hash)))
1404 % (f, rtype, state, _hashornull(hash)))
1403 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1405 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1404 ui.write((' ancestor path: %s (node %s)\n')
1406 ui.write((' ancestor path: %s (node %s)\n')
1405 % (afile, _hashornull(anode)))
1407 % (afile, _hashornull(anode)))
1406 ui.write((' other path: %s (node %s)\n')
1408 ui.write((' other path: %s (node %s)\n')
1407 % (ofile, _hashornull(onode)))
1409 % (ofile, _hashornull(onode)))
1408 elif rtype == 'f':
1410 elif rtype == 'f':
1409 filename, rawextras = record.split('\0', 1)
1411 filename, rawextras = record.split('\0', 1)
1410 extras = rawextras.split('\0')
1412 extras = rawextras.split('\0')
1411 i = 0
1413 i = 0
1412 extrastrings = []
1414 extrastrings = []
1413 while i < len(extras):
1415 while i < len(extras):
1414 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1416 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1415 i += 2
1417 i += 2
1416
1418
1417 ui.write(('file extras: %s (%s)\n')
1419 ui.write(('file extras: %s (%s)\n')
1418 % (filename, ', '.join(extrastrings)))
1420 % (filename, ', '.join(extrastrings)))
1419 elif rtype == 'l':
1421 elif rtype == 'l':
1420 labels = record.split('\0', 2)
1422 labels = record.split('\0', 2)
1421 labels = [l for l in labels if len(l) > 0]
1423 labels = [l for l in labels if len(l) > 0]
1422 ui.write(('labels:\n'))
1424 ui.write(('labels:\n'))
1423 ui.write((' local: %s\n' % labels[0]))
1425 ui.write((' local: %s\n' % labels[0]))
1424 ui.write((' other: %s\n' % labels[1]))
1426 ui.write((' other: %s\n' % labels[1]))
1425 if len(labels) > 2:
1427 if len(labels) > 2:
1426 ui.write((' base: %s\n' % labels[2]))
1428 ui.write((' base: %s\n' % labels[2]))
1427 else:
1429 else:
1428 ui.write(('unrecognized entry: %s\t%s\n')
1430 ui.write(('unrecognized entry: %s\t%s\n')
1429 % (rtype, record.replace('\0', '\t')))
1431 % (rtype, record.replace('\0', '\t')))
1430
1432
1431 # Avoid mergestate.read() since it may raise an exception for unsupported
1433 # Avoid mergestate.read() since it may raise an exception for unsupported
1432 # merge state records. We shouldn't be doing this, but this is OK since this
1434 # merge state records. We shouldn't be doing this, but this is OK since this
1433 # command is pretty low-level.
1435 # command is pretty low-level.
1434 ms = mergemod.mergestate(repo)
1436 ms = mergemod.mergestate(repo)
1435
1437
1436 # sort so that reasonable information is on top
1438 # sort so that reasonable information is on top
1437 v1records = ms._readrecordsv1()
1439 v1records = ms._readrecordsv1()
1438 v2records = ms._readrecordsv2()
1440 v2records = ms._readrecordsv2()
1439 order = 'LOml'
1441 order = 'LOml'
1440 def key(r):
1442 def key(r):
1441 idx = order.find(r[0])
1443 idx = order.find(r[0])
1442 if idx == -1:
1444 if idx == -1:
1443 return (1, r[1])
1445 return (1, r[1])
1444 else:
1446 else:
1445 return (0, idx)
1447 return (0, idx)
1446 v1records.sort(key=key)
1448 v1records.sort(key=key)
1447 v2records.sort(key=key)
1449 v2records.sort(key=key)
1448
1450
1449 if not v1records and not v2records:
1451 if not v1records and not v2records:
1450 ui.write(('no merge state found\n'))
1452 ui.write(('no merge state found\n'))
1451 elif not v2records:
1453 elif not v2records:
1452 ui.note(('no version 2 merge state\n'))
1454 ui.note(('no version 2 merge state\n'))
1453 printrecords(1)
1455 printrecords(1)
1454 elif ms._v1v2match(v1records, v2records):
1456 elif ms._v1v2match(v1records, v2records):
1455 ui.note(('v1 and v2 states match: using v2\n'))
1457 ui.note(('v1 and v2 states match: using v2\n'))
1456 printrecords(2)
1458 printrecords(2)
1457 else:
1459 else:
1458 ui.note(('v1 and v2 states mismatch: using v1\n'))
1460 ui.note(('v1 and v2 states mismatch: using v1\n'))
1459 printrecords(1)
1461 printrecords(1)
1460 if ui.verbose:
1462 if ui.verbose:
1461 printrecords(2)
1463 printrecords(2)
1462
1464
1463 @command('debugnamecomplete', [], _('NAME...'))
1465 @command('debugnamecomplete', [], _('NAME...'))
1464 def debugnamecomplete(ui, repo, *args):
1466 def debugnamecomplete(ui, repo, *args):
1465 '''complete "names" - tags, open branch names, bookmark names'''
1467 '''complete "names" - tags, open branch names, bookmark names'''
1466
1468
1467 names = set()
1469 names = set()
1468 # since we previously only listed open branches, we will handle that
1470 # since we previously only listed open branches, we will handle that
1469 # specially (after this for loop)
1471 # specially (after this for loop)
1470 for name, ns in repo.names.iteritems():
1472 for name, ns in repo.names.iteritems():
1471 if name != 'branches':
1473 if name != 'branches':
1472 names.update(ns.listnames(repo))
1474 names.update(ns.listnames(repo))
1473 names.update(tag for (tag, heads, tip, closed)
1475 names.update(tag for (tag, heads, tip, closed)
1474 in repo.branchmap().iterbranches() if not closed)
1476 in repo.branchmap().iterbranches() if not closed)
1475 completions = set()
1477 completions = set()
1476 if not args:
1478 if not args:
1477 args = ['']
1479 args = ['']
1478 for a in args:
1480 for a in args:
1479 completions.update(n for n in names if n.startswith(a))
1481 completions.update(n for n in names if n.startswith(a))
1480 ui.write('\n'.join(sorted(completions)))
1482 ui.write('\n'.join(sorted(completions)))
1481 ui.write('\n')
1483 ui.write('\n')
1482
1484
1483 @command('debugobsolete',
1485 @command('debugobsolete',
1484 [('', 'flags', 0, _('markers flag')),
1486 [('', 'flags', 0, _('markers flag')),
1485 ('', 'record-parents', False,
1487 ('', 'record-parents', False,
1486 _('record parent information for the precursor')),
1488 _('record parent information for the precursor')),
1487 ('r', 'rev', [], _('display markers relevant to REV')),
1489 ('r', 'rev', [], _('display markers relevant to REV')),
1488 ('', 'exclusive', False, _('restrict display to markers only '
1490 ('', 'exclusive', False, _('restrict display to markers only '
1489 'relevant to REV')),
1491 'relevant to REV')),
1490 ('', 'index', False, _('display index of the marker')),
1492 ('', 'index', False, _('display index of the marker')),
1491 ('', 'delete', [], _('delete markers specified by indices')),
1493 ('', 'delete', [], _('delete markers specified by indices')),
1492 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1494 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1493 _('[OBSOLETED [REPLACEMENT ...]]'))
1495 _('[OBSOLETED [REPLACEMENT ...]]'))
1494 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1496 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1495 """create arbitrary obsolete marker
1497 """create arbitrary obsolete marker
1496
1498
1497 With no arguments, displays the list of obsolescence markers."""
1499 With no arguments, displays the list of obsolescence markers."""
1498
1500
1499 opts = pycompat.byteskwargs(opts)
1501 opts = pycompat.byteskwargs(opts)
1500
1502
1501 def parsenodeid(s):
1503 def parsenodeid(s):
1502 try:
1504 try:
1503 # We do not use revsingle/revrange functions here to accept
1505 # We do not use revsingle/revrange functions here to accept
1504 # arbitrary node identifiers, possibly not present in the
1506 # arbitrary node identifiers, possibly not present in the
1505 # local repository.
1507 # local repository.
1506 n = bin(s)
1508 n = bin(s)
1507 if len(n) != len(nullid):
1509 if len(n) != len(nullid):
1508 raise TypeError()
1510 raise TypeError()
1509 return n
1511 return n
1510 except TypeError:
1512 except TypeError:
1511 raise error.Abort('changeset references must be full hexadecimal '
1513 raise error.Abort('changeset references must be full hexadecimal '
1512 'node identifiers')
1514 'node identifiers')
1513
1515
1514 if opts.get('delete'):
1516 if opts.get('delete'):
1515 indices = []
1517 indices = []
1516 for v in opts.get('delete'):
1518 for v in opts.get('delete'):
1517 try:
1519 try:
1518 indices.append(int(v))
1520 indices.append(int(v))
1519 except ValueError:
1521 except ValueError:
1520 raise error.Abort(_('invalid index value: %r') % v,
1522 raise error.Abort(_('invalid index value: %r') % v,
1521 hint=_('use integers for indices'))
1523 hint=_('use integers for indices'))
1522
1524
1523 if repo.currenttransaction():
1525 if repo.currenttransaction():
1524 raise error.Abort(_('cannot delete obsmarkers in the middle '
1526 raise error.Abort(_('cannot delete obsmarkers in the middle '
1525 'of transaction.'))
1527 'of transaction.'))
1526
1528
1527 with repo.lock():
1529 with repo.lock():
1528 n = repair.deleteobsmarkers(repo.obsstore, indices)
1530 n = repair.deleteobsmarkers(repo.obsstore, indices)
1529 ui.write(_('deleted %i obsolescence markers\n') % n)
1531 ui.write(_('deleted %i obsolescence markers\n') % n)
1530
1532
1531 return
1533 return
1532
1534
1533 if precursor is not None:
1535 if precursor is not None:
1534 if opts['rev']:
1536 if opts['rev']:
1535 raise error.Abort('cannot select revision when creating marker')
1537 raise error.Abort('cannot select revision when creating marker')
1536 metadata = {}
1538 metadata = {}
1537 metadata['user'] = opts['user'] or ui.username()
1539 metadata['user'] = opts['user'] or ui.username()
1538 succs = tuple(parsenodeid(succ) for succ in successors)
1540 succs = tuple(parsenodeid(succ) for succ in successors)
1539 l = repo.lock()
1541 l = repo.lock()
1540 try:
1542 try:
1541 tr = repo.transaction('debugobsolete')
1543 tr = repo.transaction('debugobsolete')
1542 try:
1544 try:
1543 date = opts.get('date')
1545 date = opts.get('date')
1544 if date:
1546 if date:
1545 date = util.parsedate(date)
1547 date = util.parsedate(date)
1546 else:
1548 else:
1547 date = None
1549 date = None
1548 prec = parsenodeid(precursor)
1550 prec = parsenodeid(precursor)
1549 parents = None
1551 parents = None
1550 if opts['record_parents']:
1552 if opts['record_parents']:
1551 if prec not in repo.unfiltered():
1553 if prec not in repo.unfiltered():
1552 raise error.Abort('cannot used --record-parents on '
1554 raise error.Abort('cannot used --record-parents on '
1553 'unknown changesets')
1555 'unknown changesets')
1554 parents = repo.unfiltered()[prec].parents()
1556 parents = repo.unfiltered()[prec].parents()
1555 parents = tuple(p.node() for p in parents)
1557 parents = tuple(p.node() for p in parents)
1556 repo.obsstore.create(tr, prec, succs, opts['flags'],
1558 repo.obsstore.create(tr, prec, succs, opts['flags'],
1557 parents=parents, date=date,
1559 parents=parents, date=date,
1558 metadata=metadata, ui=ui)
1560 metadata=metadata, ui=ui)
1559 tr.close()
1561 tr.close()
1560 except ValueError as exc:
1562 except ValueError as exc:
1561 raise error.Abort(_('bad obsmarker input: %s') % exc)
1563 raise error.Abort(_('bad obsmarker input: %s') % exc)
1562 finally:
1564 finally:
1563 tr.release()
1565 tr.release()
1564 finally:
1566 finally:
1565 l.release()
1567 l.release()
1566 else:
1568 else:
1567 if opts['rev']:
1569 if opts['rev']:
1568 revs = scmutil.revrange(repo, opts['rev'])
1570 revs = scmutil.revrange(repo, opts['rev'])
1569 nodes = [repo[r].node() for r in revs]
1571 nodes = [repo[r].node() for r in revs]
1570 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1572 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1571 exclusive=opts['exclusive']))
1573 exclusive=opts['exclusive']))
1572 markers.sort(key=lambda x: x._data)
1574 markers.sort(key=lambda x: x._data)
1573 else:
1575 else:
1574 markers = obsutil.getmarkers(repo)
1576 markers = obsutil.getmarkers(repo)
1575
1577
1576 markerstoiter = markers
1578 markerstoiter = markers
1577 isrelevant = lambda m: True
1579 isrelevant = lambda m: True
1578 if opts.get('rev') and opts.get('index'):
1580 if opts.get('rev') and opts.get('index'):
1579 markerstoiter = obsutil.getmarkers(repo)
1581 markerstoiter = obsutil.getmarkers(repo)
1580 markerset = set(markers)
1582 markerset = set(markers)
1581 isrelevant = lambda m: m in markerset
1583 isrelevant = lambda m: m in markerset
1582
1584
1583 fm = ui.formatter('debugobsolete', opts)
1585 fm = ui.formatter('debugobsolete', opts)
1584 for i, m in enumerate(markerstoiter):
1586 for i, m in enumerate(markerstoiter):
1585 if not isrelevant(m):
1587 if not isrelevant(m):
1586 # marker can be irrelevant when we're iterating over a set
1588 # marker can be irrelevant when we're iterating over a set
1587 # of markers (markerstoiter) which is bigger than the set
1589 # of markers (markerstoiter) which is bigger than the set
1588 # of markers we want to display (markers)
1590 # of markers we want to display (markers)
1589 # this can happen if both --index and --rev options are
1591 # this can happen if both --index and --rev options are
1590 # provided and thus we need to iterate over all of the markers
1592 # provided and thus we need to iterate over all of the markers
1591 # to get the correct indices, but only display the ones that
1593 # to get the correct indices, but only display the ones that
1592 # are relevant to --rev value
1594 # are relevant to --rev value
1593 continue
1595 continue
1594 fm.startitem()
1596 fm.startitem()
1595 ind = i if opts.get('index') else None
1597 ind = i if opts.get('index') else None
1596 cmdutil.showmarker(fm, m, index=ind)
1598 cmdutil.showmarker(fm, m, index=ind)
1597 fm.end()
1599 fm.end()
1598
1600
1599 @command('debugpathcomplete',
1601 @command('debugpathcomplete',
1600 [('f', 'full', None, _('complete an entire path')),
1602 [('f', 'full', None, _('complete an entire path')),
1601 ('n', 'normal', None, _('show only normal files')),
1603 ('n', 'normal', None, _('show only normal files')),
1602 ('a', 'added', None, _('show only added files')),
1604 ('a', 'added', None, _('show only added files')),
1603 ('r', 'removed', None, _('show only removed files'))],
1605 ('r', 'removed', None, _('show only removed files'))],
1604 _('FILESPEC...'))
1606 _('FILESPEC...'))
1605 def debugpathcomplete(ui, repo, *specs, **opts):
1607 def debugpathcomplete(ui, repo, *specs, **opts):
1606 '''complete part or all of a tracked path
1608 '''complete part or all of a tracked path
1607
1609
1608 This command supports shells that offer path name completion. It
1610 This command supports shells that offer path name completion. It
1609 currently completes only files already known to the dirstate.
1611 currently completes only files already known to the dirstate.
1610
1612
1611 Completion extends only to the next path segment unless
1613 Completion extends only to the next path segment unless
1612 --full is specified, in which case entire paths are used.'''
1614 --full is specified, in which case entire paths are used.'''
1613
1615
1614 def complete(path, acceptable):
1616 def complete(path, acceptable):
1615 dirstate = repo.dirstate
1617 dirstate = repo.dirstate
1616 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1618 spec = os.path.normpath(os.path.join(pycompat.getcwd(), path))
1617 rootdir = repo.root + pycompat.ossep
1619 rootdir = repo.root + pycompat.ossep
1618 if spec != repo.root and not spec.startswith(rootdir):
1620 if spec != repo.root and not spec.startswith(rootdir):
1619 return [], []
1621 return [], []
1620 if os.path.isdir(spec):
1622 if os.path.isdir(spec):
1621 spec += '/'
1623 spec += '/'
1622 spec = spec[len(rootdir):]
1624 spec = spec[len(rootdir):]
1623 fixpaths = pycompat.ossep != '/'
1625 fixpaths = pycompat.ossep != '/'
1624 if fixpaths:
1626 if fixpaths:
1625 spec = spec.replace(pycompat.ossep, '/')
1627 spec = spec.replace(pycompat.ossep, '/')
1626 speclen = len(spec)
1628 speclen = len(spec)
1627 fullpaths = opts[r'full']
1629 fullpaths = opts[r'full']
1628 files, dirs = set(), set()
1630 files, dirs = set(), set()
1629 adddir, addfile = dirs.add, files.add
1631 adddir, addfile = dirs.add, files.add
1630 for f, st in dirstate.iteritems():
1632 for f, st in dirstate.iteritems():
1631 if f.startswith(spec) and st[0] in acceptable:
1633 if f.startswith(spec) and st[0] in acceptable:
1632 if fixpaths:
1634 if fixpaths:
1633 f = f.replace('/', pycompat.ossep)
1635 f = f.replace('/', pycompat.ossep)
1634 if fullpaths:
1636 if fullpaths:
1635 addfile(f)
1637 addfile(f)
1636 continue
1638 continue
1637 s = f.find(pycompat.ossep, speclen)
1639 s = f.find(pycompat.ossep, speclen)
1638 if s >= 0:
1640 if s >= 0:
1639 adddir(f[:s])
1641 adddir(f[:s])
1640 else:
1642 else:
1641 addfile(f)
1643 addfile(f)
1642 return files, dirs
1644 return files, dirs
1643
1645
1644 acceptable = ''
1646 acceptable = ''
1645 if opts[r'normal']:
1647 if opts[r'normal']:
1646 acceptable += 'nm'
1648 acceptable += 'nm'
1647 if opts[r'added']:
1649 if opts[r'added']:
1648 acceptable += 'a'
1650 acceptable += 'a'
1649 if opts[r'removed']:
1651 if opts[r'removed']:
1650 acceptable += 'r'
1652 acceptable += 'r'
1651 cwd = repo.getcwd()
1653 cwd = repo.getcwd()
1652 if not specs:
1654 if not specs:
1653 specs = ['.']
1655 specs = ['.']
1654
1656
1655 files, dirs = set(), set()
1657 files, dirs = set(), set()
1656 for spec in specs:
1658 for spec in specs:
1657 f, d = complete(spec, acceptable or 'nmar')
1659 f, d = complete(spec, acceptable or 'nmar')
1658 files.update(f)
1660 files.update(f)
1659 dirs.update(d)
1661 dirs.update(d)
1660 files.update(dirs)
1662 files.update(dirs)
1661 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1663 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1662 ui.write('\n')
1664 ui.write('\n')
1663
1665
1664 @command('debugpickmergetool',
1666 @command('debugpickmergetool',
1665 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1667 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1666 ('', 'changedelete', None, _('emulate merging change and delete')),
1668 ('', 'changedelete', None, _('emulate merging change and delete')),
1667 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1669 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1668 _('[PATTERN]...'),
1670 _('[PATTERN]...'),
1669 inferrepo=True)
1671 inferrepo=True)
1670 def debugpickmergetool(ui, repo, *pats, **opts):
1672 def debugpickmergetool(ui, repo, *pats, **opts):
1671 """examine which merge tool is chosen for specified file
1673 """examine which merge tool is chosen for specified file
1672
1674
1673 As described in :hg:`help merge-tools`, Mercurial examines
1675 As described in :hg:`help merge-tools`, Mercurial examines
1674 configurations below in this order to decide which merge tool is
1676 configurations below in this order to decide which merge tool is
1675 chosen for specified file.
1677 chosen for specified file.
1676
1678
1677 1. ``--tool`` option
1679 1. ``--tool`` option
1678 2. ``HGMERGE`` environment variable
1680 2. ``HGMERGE`` environment variable
1679 3. configurations in ``merge-patterns`` section
1681 3. configurations in ``merge-patterns`` section
1680 4. configuration of ``ui.merge``
1682 4. configuration of ``ui.merge``
1681 5. configurations in ``merge-tools`` section
1683 5. configurations in ``merge-tools`` section
1682 6. ``hgmerge`` tool (for historical reason only)
1684 6. ``hgmerge`` tool (for historical reason only)
1683 7. default tool for fallback (``:merge`` or ``:prompt``)
1685 7. default tool for fallback (``:merge`` or ``:prompt``)
1684
1686
1685 This command writes out examination result in the style below::
1687 This command writes out examination result in the style below::
1686
1688
1687 FILE = MERGETOOL
1689 FILE = MERGETOOL
1688
1690
1689 By default, all files known in the first parent context of the
1691 By default, all files known in the first parent context of the
1690 working directory are examined. Use file patterns and/or -I/-X
1692 working directory are examined. Use file patterns and/or -I/-X
1691 options to limit target files. -r/--rev is also useful to examine
1693 options to limit target files. -r/--rev is also useful to examine
1692 files in another context without actual updating to it.
1694 files in another context without actual updating to it.
1693
1695
1694 With --debug, this command shows warning messages while matching
1696 With --debug, this command shows warning messages while matching
1695 against ``merge-patterns`` and so on, too. It is recommended to
1697 against ``merge-patterns`` and so on, too. It is recommended to
1696 use this option with explicit file patterns and/or -I/-X options,
1698 use this option with explicit file patterns and/or -I/-X options,
1697 because this option increases amount of output per file according
1699 because this option increases amount of output per file according
1698 to configurations in hgrc.
1700 to configurations in hgrc.
1699
1701
1700 With -v/--verbose, this command shows configurations below at
1702 With -v/--verbose, this command shows configurations below at
1701 first (only if specified).
1703 first (only if specified).
1702
1704
1703 - ``--tool`` option
1705 - ``--tool`` option
1704 - ``HGMERGE`` environment variable
1706 - ``HGMERGE`` environment variable
1705 - configuration of ``ui.merge``
1707 - configuration of ``ui.merge``
1706
1708
1707 If merge tool is chosen before matching against
1709 If merge tool is chosen before matching against
1708 ``merge-patterns``, this command can't show any helpful
1710 ``merge-patterns``, this command can't show any helpful
1709 information, even with --debug. In such case, information above is
1711 information, even with --debug. In such case, information above is
1710 useful to know why a merge tool is chosen.
1712 useful to know why a merge tool is chosen.
1711 """
1713 """
1712 opts = pycompat.byteskwargs(opts)
1714 opts = pycompat.byteskwargs(opts)
1713 overrides = {}
1715 overrides = {}
1714 if opts['tool']:
1716 if opts['tool']:
1715 overrides[('ui', 'forcemerge')] = opts['tool']
1717 overrides[('ui', 'forcemerge')] = opts['tool']
1716 ui.note(('with --tool %r\n') % (opts['tool']))
1718 ui.note(('with --tool %r\n') % (opts['tool']))
1717
1719
1718 with ui.configoverride(overrides, 'debugmergepatterns'):
1720 with ui.configoverride(overrides, 'debugmergepatterns'):
1719 hgmerge = encoding.environ.get("HGMERGE")
1721 hgmerge = encoding.environ.get("HGMERGE")
1720 if hgmerge is not None:
1722 if hgmerge is not None:
1721 ui.note(('with HGMERGE=%r\n') % (hgmerge))
1723 ui.note(('with HGMERGE=%r\n') % (hgmerge))
1722 uimerge = ui.config("ui", "merge")
1724 uimerge = ui.config("ui", "merge")
1723 if uimerge:
1725 if uimerge:
1724 ui.note(('with ui.merge=%r\n') % (uimerge))
1726 ui.note(('with ui.merge=%r\n') % (uimerge))
1725
1727
1726 ctx = scmutil.revsingle(repo, opts.get('rev'))
1728 ctx = scmutil.revsingle(repo, opts.get('rev'))
1727 m = scmutil.match(ctx, pats, opts)
1729 m = scmutil.match(ctx, pats, opts)
1728 changedelete = opts['changedelete']
1730 changedelete = opts['changedelete']
1729 for path in ctx.walk(m):
1731 for path in ctx.walk(m):
1730 fctx = ctx[path]
1732 fctx = ctx[path]
1731 try:
1733 try:
1732 if not ui.debugflag:
1734 if not ui.debugflag:
1733 ui.pushbuffer(error=True)
1735 ui.pushbuffer(error=True)
1734 tool, toolpath = filemerge._picktool(repo, ui, path,
1736 tool, toolpath = filemerge._picktool(repo, ui, path,
1735 fctx.isbinary(),
1737 fctx.isbinary(),
1736 'l' in fctx.flags(),
1738 'l' in fctx.flags(),
1737 changedelete)
1739 changedelete)
1738 finally:
1740 finally:
1739 if not ui.debugflag:
1741 if not ui.debugflag:
1740 ui.popbuffer()
1742 ui.popbuffer()
1741 ui.write(('%s = %s\n') % (path, tool))
1743 ui.write(('%s = %s\n') % (path, tool))
1742
1744
1743 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1745 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1744 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1746 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1745 '''access the pushkey key/value protocol
1747 '''access the pushkey key/value protocol
1746
1748
1747 With two args, list the keys in the given namespace.
1749 With two args, list the keys in the given namespace.
1748
1750
1749 With five args, set a key to new if it currently is set to old.
1751 With five args, set a key to new if it currently is set to old.
1750 Reports success or failure.
1752 Reports success or failure.
1751 '''
1753 '''
1752
1754
1753 target = hg.peer(ui, {}, repopath)
1755 target = hg.peer(ui, {}, repopath)
1754 if keyinfo:
1756 if keyinfo:
1755 key, old, new = keyinfo
1757 key, old, new = keyinfo
1756 r = target.pushkey(namespace, key, old, new)
1758 r = target.pushkey(namespace, key, old, new)
1757 ui.status(str(r) + '\n')
1759 ui.status(str(r) + '\n')
1758 return not r
1760 return not r
1759 else:
1761 else:
1760 for k, v in sorted(target.listkeys(namespace).iteritems()):
1762 for k, v in sorted(target.listkeys(namespace).iteritems()):
1761 ui.write("%s\t%s\n" % (util.escapestr(k),
1763 ui.write("%s\t%s\n" % (util.escapestr(k),
1762 util.escapestr(v)))
1764 util.escapestr(v)))
1763
1765
1764 @command('debugpvec', [], _('A B'))
1766 @command('debugpvec', [], _('A B'))
1765 def debugpvec(ui, repo, a, b=None):
1767 def debugpvec(ui, repo, a, b=None):
1766 ca = scmutil.revsingle(repo, a)
1768 ca = scmutil.revsingle(repo, a)
1767 cb = scmutil.revsingle(repo, b)
1769 cb = scmutil.revsingle(repo, b)
1768 pa = pvec.ctxpvec(ca)
1770 pa = pvec.ctxpvec(ca)
1769 pb = pvec.ctxpvec(cb)
1771 pb = pvec.ctxpvec(cb)
1770 if pa == pb:
1772 if pa == pb:
1771 rel = "="
1773 rel = "="
1772 elif pa > pb:
1774 elif pa > pb:
1773 rel = ">"
1775 rel = ">"
1774 elif pa < pb:
1776 elif pa < pb:
1775 rel = "<"
1777 rel = "<"
1776 elif pa | pb:
1778 elif pa | pb:
1777 rel = "|"
1779 rel = "|"
1778 ui.write(_("a: %s\n") % pa)
1780 ui.write(_("a: %s\n") % pa)
1779 ui.write(_("b: %s\n") % pb)
1781 ui.write(_("b: %s\n") % pb)
1780 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1782 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1781 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1783 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1782 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1784 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1783 pa.distance(pb), rel))
1785 pa.distance(pb), rel))
1784
1786
1785 @command('debugrebuilddirstate|debugrebuildstate',
1787 @command('debugrebuilddirstate|debugrebuildstate',
1786 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1788 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1787 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1789 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1788 'the working copy parent')),
1790 'the working copy parent')),
1789 ],
1791 ],
1790 _('[-r REV]'))
1792 _('[-r REV]'))
1791 def debugrebuilddirstate(ui, repo, rev, **opts):
1793 def debugrebuilddirstate(ui, repo, rev, **opts):
1792 """rebuild the dirstate as it would look like for the given revision
1794 """rebuild the dirstate as it would look like for the given revision
1793
1795
1794 If no revision is specified the first current parent will be used.
1796 If no revision is specified the first current parent will be used.
1795
1797
1796 The dirstate will be set to the files of the given revision.
1798 The dirstate will be set to the files of the given revision.
1797 The actual working directory content or existing dirstate
1799 The actual working directory content or existing dirstate
1798 information such as adds or removes is not considered.
1800 information such as adds or removes is not considered.
1799
1801
1800 ``minimal`` will only rebuild the dirstate status for files that claim to be
1802 ``minimal`` will only rebuild the dirstate status for files that claim to be
1801 tracked but are not in the parent manifest, or that exist in the parent
1803 tracked but are not in the parent manifest, or that exist in the parent
1802 manifest but are not in the dirstate. It will not change adds, removes, or
1804 manifest but are not in the dirstate. It will not change adds, removes, or
1803 modified files that are in the working copy parent.
1805 modified files that are in the working copy parent.
1804
1806
1805 One use of this command is to make the next :hg:`status` invocation
1807 One use of this command is to make the next :hg:`status` invocation
1806 check the actual file content.
1808 check the actual file content.
1807 """
1809 """
1808 ctx = scmutil.revsingle(repo, rev)
1810 ctx = scmutil.revsingle(repo, rev)
1809 with repo.wlock():
1811 with repo.wlock():
1810 dirstate = repo.dirstate
1812 dirstate = repo.dirstate
1811 changedfiles = None
1813 changedfiles = None
1812 # See command doc for what minimal does.
1814 # See command doc for what minimal does.
1813 if opts.get(r'minimal'):
1815 if opts.get(r'minimal'):
1814 manifestfiles = set(ctx.manifest().keys())
1816 manifestfiles = set(ctx.manifest().keys())
1815 dirstatefiles = set(dirstate)
1817 dirstatefiles = set(dirstate)
1816 manifestonly = manifestfiles - dirstatefiles
1818 manifestonly = manifestfiles - dirstatefiles
1817 dsonly = dirstatefiles - manifestfiles
1819 dsonly = dirstatefiles - manifestfiles
1818 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1820 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
1819 changedfiles = manifestonly | dsnotadded
1821 changedfiles = manifestonly | dsnotadded
1820
1822
1821 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1823 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
1822
1824
1823 @command('debugrebuildfncache', [], '')
1825 @command('debugrebuildfncache', [], '')
1824 def debugrebuildfncache(ui, repo):
1826 def debugrebuildfncache(ui, repo):
1825 """rebuild the fncache file"""
1827 """rebuild the fncache file"""
1826 repair.rebuildfncache(ui, repo)
1828 repair.rebuildfncache(ui, repo)
1827
1829
1828 @command('debugrename',
1830 @command('debugrename',
1829 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1831 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1830 _('[-r REV] FILE'))
1832 _('[-r REV] FILE'))
1831 def debugrename(ui, repo, file1, *pats, **opts):
1833 def debugrename(ui, repo, file1, *pats, **opts):
1832 """dump rename information"""
1834 """dump rename information"""
1833
1835
1834 opts = pycompat.byteskwargs(opts)
1836 opts = pycompat.byteskwargs(opts)
1835 ctx = scmutil.revsingle(repo, opts.get('rev'))
1837 ctx = scmutil.revsingle(repo, opts.get('rev'))
1836 m = scmutil.match(ctx, (file1,) + pats, opts)
1838 m = scmutil.match(ctx, (file1,) + pats, opts)
1837 for abs in ctx.walk(m):
1839 for abs in ctx.walk(m):
1838 fctx = ctx[abs]
1840 fctx = ctx[abs]
1839 o = fctx.filelog().renamed(fctx.filenode())
1841 o = fctx.filelog().renamed(fctx.filenode())
1840 rel = m.rel(abs)
1842 rel = m.rel(abs)
1841 if o:
1843 if o:
1842 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1844 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1843 else:
1845 else:
1844 ui.write(_("%s not renamed\n") % rel)
1846 ui.write(_("%s not renamed\n") % rel)
1845
1847
1846 @command('debugrevlog', cmdutil.debugrevlogopts +
1848 @command('debugrevlog', cmdutil.debugrevlogopts +
1847 [('d', 'dump', False, _('dump index data'))],
1849 [('d', 'dump', False, _('dump index data'))],
1848 _('-c|-m|FILE'),
1850 _('-c|-m|FILE'),
1849 optionalrepo=True)
1851 optionalrepo=True)
1850 def debugrevlog(ui, repo, file_=None, **opts):
1852 def debugrevlog(ui, repo, file_=None, **opts):
1851 """show data and statistics about a revlog"""
1853 """show data and statistics about a revlog"""
1852 opts = pycompat.byteskwargs(opts)
1854 opts = pycompat.byteskwargs(opts)
1853 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1855 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1854
1856
1855 if opts.get("dump"):
1857 if opts.get("dump"):
1856 numrevs = len(r)
1858 numrevs = len(r)
1857 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1859 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
1858 " rawsize totalsize compression heads chainlen\n"))
1860 " rawsize totalsize compression heads chainlen\n"))
1859 ts = 0
1861 ts = 0
1860 heads = set()
1862 heads = set()
1861
1863
1862 for rev in xrange(numrevs):
1864 for rev in xrange(numrevs):
1863 dbase = r.deltaparent(rev)
1865 dbase = r.deltaparent(rev)
1864 if dbase == -1:
1866 if dbase == -1:
1865 dbase = rev
1867 dbase = rev
1866 cbase = r.chainbase(rev)
1868 cbase = r.chainbase(rev)
1867 clen = r.chainlen(rev)
1869 clen = r.chainlen(rev)
1868 p1, p2 = r.parentrevs(rev)
1870 p1, p2 = r.parentrevs(rev)
1869 rs = r.rawsize(rev)
1871 rs = r.rawsize(rev)
1870 ts = ts + rs
1872 ts = ts + rs
1871 heads -= set(r.parentrevs(rev))
1873 heads -= set(r.parentrevs(rev))
1872 heads.add(rev)
1874 heads.add(rev)
1873 try:
1875 try:
1874 compression = ts / r.end(rev)
1876 compression = ts / r.end(rev)
1875 except ZeroDivisionError:
1877 except ZeroDivisionError:
1876 compression = 0
1878 compression = 0
1877 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1879 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
1878 "%11d %5d %8d\n" %
1880 "%11d %5d %8d\n" %
1879 (rev, p1, p2, r.start(rev), r.end(rev),
1881 (rev, p1, p2, r.start(rev), r.end(rev),
1880 r.start(dbase), r.start(cbase),
1882 r.start(dbase), r.start(cbase),
1881 r.start(p1), r.start(p2),
1883 r.start(p1), r.start(p2),
1882 rs, ts, compression, len(heads), clen))
1884 rs, ts, compression, len(heads), clen))
1883 return 0
1885 return 0
1884
1886
1885 v = r.version
1887 v = r.version
1886 format = v & 0xFFFF
1888 format = v & 0xFFFF
1887 flags = []
1889 flags = []
1888 gdelta = False
1890 gdelta = False
1889 if v & revlog.FLAG_INLINE_DATA:
1891 if v & revlog.FLAG_INLINE_DATA:
1890 flags.append('inline')
1892 flags.append('inline')
1891 if v & revlog.FLAG_GENERALDELTA:
1893 if v & revlog.FLAG_GENERALDELTA:
1892 gdelta = True
1894 gdelta = True
1893 flags.append('generaldelta')
1895 flags.append('generaldelta')
1894 if not flags:
1896 if not flags:
1895 flags = ['(none)']
1897 flags = ['(none)']
1896
1898
1897 nummerges = 0
1899 nummerges = 0
1898 numfull = 0
1900 numfull = 0
1899 numprev = 0
1901 numprev = 0
1900 nump1 = 0
1902 nump1 = 0
1901 nump2 = 0
1903 nump2 = 0
1902 numother = 0
1904 numother = 0
1903 nump1prev = 0
1905 nump1prev = 0
1904 nump2prev = 0
1906 nump2prev = 0
1905 chainlengths = []
1907 chainlengths = []
1906 chainbases = []
1908 chainbases = []
1907 chainspans = []
1909 chainspans = []
1908
1910
1909 datasize = [None, 0, 0]
1911 datasize = [None, 0, 0]
1910 fullsize = [None, 0, 0]
1912 fullsize = [None, 0, 0]
1911 deltasize = [None, 0, 0]
1913 deltasize = [None, 0, 0]
1912 chunktypecounts = {}
1914 chunktypecounts = {}
1913 chunktypesizes = {}
1915 chunktypesizes = {}
1914
1916
1915 def addsize(size, l):
1917 def addsize(size, l):
1916 if l[0] is None or size < l[0]:
1918 if l[0] is None or size < l[0]:
1917 l[0] = size
1919 l[0] = size
1918 if size > l[1]:
1920 if size > l[1]:
1919 l[1] = size
1921 l[1] = size
1920 l[2] += size
1922 l[2] += size
1921
1923
1922 numrevs = len(r)
1924 numrevs = len(r)
1923 for rev in xrange(numrevs):
1925 for rev in xrange(numrevs):
1924 p1, p2 = r.parentrevs(rev)
1926 p1, p2 = r.parentrevs(rev)
1925 delta = r.deltaparent(rev)
1927 delta = r.deltaparent(rev)
1926 if format > 0:
1928 if format > 0:
1927 addsize(r.rawsize(rev), datasize)
1929 addsize(r.rawsize(rev), datasize)
1928 if p2 != nullrev:
1930 if p2 != nullrev:
1929 nummerges += 1
1931 nummerges += 1
1930 size = r.length(rev)
1932 size = r.length(rev)
1931 if delta == nullrev:
1933 if delta == nullrev:
1932 chainlengths.append(0)
1934 chainlengths.append(0)
1933 chainbases.append(r.start(rev))
1935 chainbases.append(r.start(rev))
1934 chainspans.append(size)
1936 chainspans.append(size)
1935 numfull += 1
1937 numfull += 1
1936 addsize(size, fullsize)
1938 addsize(size, fullsize)
1937 else:
1939 else:
1938 chainlengths.append(chainlengths[delta] + 1)
1940 chainlengths.append(chainlengths[delta] + 1)
1939 baseaddr = chainbases[delta]
1941 baseaddr = chainbases[delta]
1940 revaddr = r.start(rev)
1942 revaddr = r.start(rev)
1941 chainbases.append(baseaddr)
1943 chainbases.append(baseaddr)
1942 chainspans.append((revaddr - baseaddr) + size)
1944 chainspans.append((revaddr - baseaddr) + size)
1943 addsize(size, deltasize)
1945 addsize(size, deltasize)
1944 if delta == rev - 1:
1946 if delta == rev - 1:
1945 numprev += 1
1947 numprev += 1
1946 if delta == p1:
1948 if delta == p1:
1947 nump1prev += 1
1949 nump1prev += 1
1948 elif delta == p2:
1950 elif delta == p2:
1949 nump2prev += 1
1951 nump2prev += 1
1950 elif delta == p1:
1952 elif delta == p1:
1951 nump1 += 1
1953 nump1 += 1
1952 elif delta == p2:
1954 elif delta == p2:
1953 nump2 += 1
1955 nump2 += 1
1954 elif delta != nullrev:
1956 elif delta != nullrev:
1955 numother += 1
1957 numother += 1
1956
1958
1957 # Obtain data on the raw chunks in the revlog.
1959 # Obtain data on the raw chunks in the revlog.
1958 segment = r._getsegmentforrevs(rev, rev)[1]
1960 segment = r._getsegmentforrevs(rev, rev)[1]
1959 if segment:
1961 if segment:
1960 chunktype = bytes(segment[0:1])
1962 chunktype = bytes(segment[0:1])
1961 else:
1963 else:
1962 chunktype = 'empty'
1964 chunktype = 'empty'
1963
1965
1964 if chunktype not in chunktypecounts:
1966 if chunktype not in chunktypecounts:
1965 chunktypecounts[chunktype] = 0
1967 chunktypecounts[chunktype] = 0
1966 chunktypesizes[chunktype] = 0
1968 chunktypesizes[chunktype] = 0
1967
1969
1968 chunktypecounts[chunktype] += 1
1970 chunktypecounts[chunktype] += 1
1969 chunktypesizes[chunktype] += size
1971 chunktypesizes[chunktype] += size
1970
1972
1971 # Adjust size min value for empty cases
1973 # Adjust size min value for empty cases
1972 for size in (datasize, fullsize, deltasize):
1974 for size in (datasize, fullsize, deltasize):
1973 if size[0] is None:
1975 if size[0] is None:
1974 size[0] = 0
1976 size[0] = 0
1975
1977
1976 numdeltas = numrevs - numfull
1978 numdeltas = numrevs - numfull
1977 numoprev = numprev - nump1prev - nump2prev
1979 numoprev = numprev - nump1prev - nump2prev
1978 totalrawsize = datasize[2]
1980 totalrawsize = datasize[2]
1979 datasize[2] /= numrevs
1981 datasize[2] /= numrevs
1980 fulltotal = fullsize[2]
1982 fulltotal = fullsize[2]
1981 fullsize[2] /= numfull
1983 fullsize[2] /= numfull
1982 deltatotal = deltasize[2]
1984 deltatotal = deltasize[2]
1983 if numrevs - numfull > 0:
1985 if numrevs - numfull > 0:
1984 deltasize[2] /= numrevs - numfull
1986 deltasize[2] /= numrevs - numfull
1985 totalsize = fulltotal + deltatotal
1987 totalsize = fulltotal + deltatotal
1986 avgchainlen = sum(chainlengths) / numrevs
1988 avgchainlen = sum(chainlengths) / numrevs
1987 maxchainlen = max(chainlengths)
1989 maxchainlen = max(chainlengths)
1988 maxchainspan = max(chainspans)
1990 maxchainspan = max(chainspans)
1989 compratio = 1
1991 compratio = 1
1990 if totalsize:
1992 if totalsize:
1991 compratio = totalrawsize / totalsize
1993 compratio = totalrawsize / totalsize
1992
1994
1993 basedfmtstr = '%%%dd\n'
1995 basedfmtstr = '%%%dd\n'
1994 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1996 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
1995
1997
1996 def dfmtstr(max):
1998 def dfmtstr(max):
1997 return basedfmtstr % len(str(max))
1999 return basedfmtstr % len(str(max))
1998 def pcfmtstr(max, padding=0):
2000 def pcfmtstr(max, padding=0):
1999 return basepcfmtstr % (len(str(max)), ' ' * padding)
2001 return basepcfmtstr % (len(str(max)), ' ' * padding)
2000
2002
2001 def pcfmt(value, total):
2003 def pcfmt(value, total):
2002 if total:
2004 if total:
2003 return (value, 100 * float(value) / total)
2005 return (value, 100 * float(value) / total)
2004 else:
2006 else:
2005 return value, 100.0
2007 return value, 100.0
2006
2008
2007 ui.write(('format : %d\n') % format)
2009 ui.write(('format : %d\n') % format)
2008 ui.write(('flags : %s\n') % ', '.join(flags))
2010 ui.write(('flags : %s\n') % ', '.join(flags))
2009
2011
2010 ui.write('\n')
2012 ui.write('\n')
2011 fmt = pcfmtstr(totalsize)
2013 fmt = pcfmtstr(totalsize)
2012 fmt2 = dfmtstr(totalsize)
2014 fmt2 = dfmtstr(totalsize)
2013 ui.write(('revisions : ') + fmt2 % numrevs)
2015 ui.write(('revisions : ') + fmt2 % numrevs)
2014 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2016 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2015 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2017 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2016 ui.write(('revisions : ') + fmt2 % numrevs)
2018 ui.write(('revisions : ') + fmt2 % numrevs)
2017 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2019 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2018 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2020 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2019 ui.write(('revision size : ') + fmt2 % totalsize)
2021 ui.write(('revision size : ') + fmt2 % totalsize)
2020 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2022 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2021 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2023 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2022
2024
2023 def fmtchunktype(chunktype):
2025 def fmtchunktype(chunktype):
2024 if chunktype == 'empty':
2026 if chunktype == 'empty':
2025 return ' %s : ' % chunktype
2027 return ' %s : ' % chunktype
2026 elif chunktype in pycompat.bytestr(string.ascii_letters):
2028 elif chunktype in pycompat.bytestr(string.ascii_letters):
2027 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2029 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2028 else:
2030 else:
2029 return ' 0x%s : ' % hex(chunktype)
2031 return ' 0x%s : ' % hex(chunktype)
2030
2032
2031 ui.write('\n')
2033 ui.write('\n')
2032 ui.write(('chunks : ') + fmt2 % numrevs)
2034 ui.write(('chunks : ') + fmt2 % numrevs)
2033 for chunktype in sorted(chunktypecounts):
2035 for chunktype in sorted(chunktypecounts):
2034 ui.write(fmtchunktype(chunktype))
2036 ui.write(fmtchunktype(chunktype))
2035 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2037 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2036 ui.write(('chunks size : ') + fmt2 % totalsize)
2038 ui.write(('chunks size : ') + fmt2 % totalsize)
2037 for chunktype in sorted(chunktypecounts):
2039 for chunktype in sorted(chunktypecounts):
2038 ui.write(fmtchunktype(chunktype))
2040 ui.write(fmtchunktype(chunktype))
2039 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2041 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2040
2042
2041 ui.write('\n')
2043 ui.write('\n')
2042 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2044 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2043 ui.write(('avg chain length : ') + fmt % avgchainlen)
2045 ui.write(('avg chain length : ') + fmt % avgchainlen)
2044 ui.write(('max chain length : ') + fmt % maxchainlen)
2046 ui.write(('max chain length : ') + fmt % maxchainlen)
2045 ui.write(('max chain reach : ') + fmt % maxchainspan)
2047 ui.write(('max chain reach : ') + fmt % maxchainspan)
2046 ui.write(('compression ratio : ') + fmt % compratio)
2048 ui.write(('compression ratio : ') + fmt % compratio)
2047
2049
2048 if format > 0:
2050 if format > 0:
2049 ui.write('\n')
2051 ui.write('\n')
2050 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2052 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2051 % tuple(datasize))
2053 % tuple(datasize))
2052 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2054 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2053 % tuple(fullsize))
2055 % tuple(fullsize))
2054 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2056 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2055 % tuple(deltasize))
2057 % tuple(deltasize))
2056
2058
2057 if numdeltas > 0:
2059 if numdeltas > 0:
2058 ui.write('\n')
2060 ui.write('\n')
2059 fmt = pcfmtstr(numdeltas)
2061 fmt = pcfmtstr(numdeltas)
2060 fmt2 = pcfmtstr(numdeltas, 4)
2062 fmt2 = pcfmtstr(numdeltas, 4)
2061 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2063 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2062 if numprev > 0:
2064 if numprev > 0:
2063 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2065 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2064 numprev))
2066 numprev))
2065 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2067 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2066 numprev))
2068 numprev))
2067 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2069 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2068 numprev))
2070 numprev))
2069 if gdelta:
2071 if gdelta:
2070 ui.write(('deltas against p1 : ')
2072 ui.write(('deltas against p1 : ')
2071 + fmt % pcfmt(nump1, numdeltas))
2073 + fmt % pcfmt(nump1, numdeltas))
2072 ui.write(('deltas against p2 : ')
2074 ui.write(('deltas against p2 : ')
2073 + fmt % pcfmt(nump2, numdeltas))
2075 + fmt % pcfmt(nump2, numdeltas))
2074 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2076 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2075 numdeltas))
2077 numdeltas))
2076
2078
2077 @command('debugrevspec',
2079 @command('debugrevspec',
2078 [('', 'optimize', None,
2080 [('', 'optimize', None,
2079 _('print parsed tree after optimizing (DEPRECATED)')),
2081 _('print parsed tree after optimizing (DEPRECATED)')),
2080 ('', 'show-revs', True, _('print list of result revisions (default)')),
2082 ('', 'show-revs', True, _('print list of result revisions (default)')),
2081 ('s', 'show-set', None, _('print internal representation of result set')),
2083 ('s', 'show-set', None, _('print internal representation of result set')),
2082 ('p', 'show-stage', [],
2084 ('p', 'show-stage', [],
2083 _('print parsed tree at the given stage'), _('NAME')),
2085 _('print parsed tree at the given stage'), _('NAME')),
2084 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2086 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2085 ('', 'verify-optimized', False, _('verify optimized result')),
2087 ('', 'verify-optimized', False, _('verify optimized result')),
2086 ],
2088 ],
2087 ('REVSPEC'))
2089 ('REVSPEC'))
2088 def debugrevspec(ui, repo, expr, **opts):
2090 def debugrevspec(ui, repo, expr, **opts):
2089 """parse and apply a revision specification
2091 """parse and apply a revision specification
2090
2092
2091 Use -p/--show-stage option to print the parsed tree at the given stages.
2093 Use -p/--show-stage option to print the parsed tree at the given stages.
2092 Use -p all to print tree at every stage.
2094 Use -p all to print tree at every stage.
2093
2095
2094 Use --no-show-revs option with -s or -p to print only the set
2096 Use --no-show-revs option with -s or -p to print only the set
2095 representation or the parsed tree respectively.
2097 representation or the parsed tree respectively.
2096
2098
2097 Use --verify-optimized to compare the optimized result with the unoptimized
2099 Use --verify-optimized to compare the optimized result with the unoptimized
2098 one. Returns 1 if the optimized result differs.
2100 one. Returns 1 if the optimized result differs.
2099 """
2101 """
2100 opts = pycompat.byteskwargs(opts)
2102 opts = pycompat.byteskwargs(opts)
2101 aliases = ui.configitems('revsetalias')
2103 aliases = ui.configitems('revsetalias')
2102 stages = [
2104 stages = [
2103 ('parsed', lambda tree: tree),
2105 ('parsed', lambda tree: tree),
2104 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2106 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2105 ui.warn)),
2107 ui.warn)),
2106 ('concatenated', revsetlang.foldconcat),
2108 ('concatenated', revsetlang.foldconcat),
2107 ('analyzed', revsetlang.analyze),
2109 ('analyzed', revsetlang.analyze),
2108 ('optimized', revsetlang.optimize),
2110 ('optimized', revsetlang.optimize),
2109 ]
2111 ]
2110 if opts['no_optimized']:
2112 if opts['no_optimized']:
2111 stages = stages[:-1]
2113 stages = stages[:-1]
2112 if opts['verify_optimized'] and opts['no_optimized']:
2114 if opts['verify_optimized'] and opts['no_optimized']:
2113 raise error.Abort(_('cannot use --verify-optimized with '
2115 raise error.Abort(_('cannot use --verify-optimized with '
2114 '--no-optimized'))
2116 '--no-optimized'))
2115 stagenames = set(n for n, f in stages)
2117 stagenames = set(n for n, f in stages)
2116
2118
2117 showalways = set()
2119 showalways = set()
2118 showchanged = set()
2120 showchanged = set()
2119 if ui.verbose and not opts['show_stage']:
2121 if ui.verbose and not opts['show_stage']:
2120 # show parsed tree by --verbose (deprecated)
2122 # show parsed tree by --verbose (deprecated)
2121 showalways.add('parsed')
2123 showalways.add('parsed')
2122 showchanged.update(['expanded', 'concatenated'])
2124 showchanged.update(['expanded', 'concatenated'])
2123 if opts['optimize']:
2125 if opts['optimize']:
2124 showalways.add('optimized')
2126 showalways.add('optimized')
2125 if opts['show_stage'] and opts['optimize']:
2127 if opts['show_stage'] and opts['optimize']:
2126 raise error.Abort(_('cannot use --optimize with --show-stage'))
2128 raise error.Abort(_('cannot use --optimize with --show-stage'))
2127 if opts['show_stage'] == ['all']:
2129 if opts['show_stage'] == ['all']:
2128 showalways.update(stagenames)
2130 showalways.update(stagenames)
2129 else:
2131 else:
2130 for n in opts['show_stage']:
2132 for n in opts['show_stage']:
2131 if n not in stagenames:
2133 if n not in stagenames:
2132 raise error.Abort(_('invalid stage name: %s') % n)
2134 raise error.Abort(_('invalid stage name: %s') % n)
2133 showalways.update(opts['show_stage'])
2135 showalways.update(opts['show_stage'])
2134
2136
2135 treebystage = {}
2137 treebystage = {}
2136 printedtree = None
2138 printedtree = None
2137 tree = revsetlang.parse(expr, lookup=repo.__contains__)
2139 tree = revsetlang.parse(expr, lookup=repo.__contains__)
2138 for n, f in stages:
2140 for n, f in stages:
2139 treebystage[n] = tree = f(tree)
2141 treebystage[n] = tree = f(tree)
2140 if n in showalways or (n in showchanged and tree != printedtree):
2142 if n in showalways or (n in showchanged and tree != printedtree):
2141 if opts['show_stage'] or n != 'parsed':
2143 if opts['show_stage'] or n != 'parsed':
2142 ui.write(("* %s:\n") % n)
2144 ui.write(("* %s:\n") % n)
2143 ui.write(revsetlang.prettyformat(tree), "\n")
2145 ui.write(revsetlang.prettyformat(tree), "\n")
2144 printedtree = tree
2146 printedtree = tree
2145
2147
2146 if opts['verify_optimized']:
2148 if opts['verify_optimized']:
2147 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2149 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2148 brevs = revset.makematcher(treebystage['optimized'])(repo)
2150 brevs = revset.makematcher(treebystage['optimized'])(repo)
2149 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2151 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2150 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2152 ui.write(("* analyzed set:\n"), smartset.prettyformat(arevs), "\n")
2151 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2153 ui.write(("* optimized set:\n"), smartset.prettyformat(brevs), "\n")
2152 arevs = list(arevs)
2154 arevs = list(arevs)
2153 brevs = list(brevs)
2155 brevs = list(brevs)
2154 if arevs == brevs:
2156 if arevs == brevs:
2155 return 0
2157 return 0
2156 ui.write(('--- analyzed\n'), label='diff.file_a')
2158 ui.write(('--- analyzed\n'), label='diff.file_a')
2157 ui.write(('+++ optimized\n'), label='diff.file_b')
2159 ui.write(('+++ optimized\n'), label='diff.file_b')
2158 sm = difflib.SequenceMatcher(None, arevs, brevs)
2160 sm = difflib.SequenceMatcher(None, arevs, brevs)
2159 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2161 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2160 if tag in ('delete', 'replace'):
2162 if tag in ('delete', 'replace'):
2161 for c in arevs[alo:ahi]:
2163 for c in arevs[alo:ahi]:
2162 ui.write('-%s\n' % c, label='diff.deleted')
2164 ui.write('-%s\n' % c, label='diff.deleted')
2163 if tag in ('insert', 'replace'):
2165 if tag in ('insert', 'replace'):
2164 for c in brevs[blo:bhi]:
2166 for c in brevs[blo:bhi]:
2165 ui.write('+%s\n' % c, label='diff.inserted')
2167 ui.write('+%s\n' % c, label='diff.inserted')
2166 if tag == 'equal':
2168 if tag == 'equal':
2167 for c in arevs[alo:ahi]:
2169 for c in arevs[alo:ahi]:
2168 ui.write(' %s\n' % c)
2170 ui.write(' %s\n' % c)
2169 return 1
2171 return 1
2170
2172
2171 func = revset.makematcher(tree)
2173 func = revset.makematcher(tree)
2172 revs = func(repo)
2174 revs = func(repo)
2173 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2175 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2174 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2176 ui.write(("* set:\n"), smartset.prettyformat(revs), "\n")
2175 if not opts['show_revs']:
2177 if not opts['show_revs']:
2176 return
2178 return
2177 for c in revs:
2179 for c in revs:
2178 ui.write("%s\n" % c)
2180 ui.write("%s\n" % c)
2179
2181
2180 @command('debugsetparents', [], _('REV1 [REV2]'))
2182 @command('debugsetparents', [], _('REV1 [REV2]'))
2181 def debugsetparents(ui, repo, rev1, rev2=None):
2183 def debugsetparents(ui, repo, rev1, rev2=None):
2182 """manually set the parents of the current working directory
2184 """manually set the parents of the current working directory
2183
2185
2184 This is useful for writing repository conversion tools, but should
2186 This is useful for writing repository conversion tools, but should
2185 be used with care. For example, neither the working directory nor the
2187 be used with care. For example, neither the working directory nor the
2186 dirstate is updated, so file status may be incorrect after running this
2188 dirstate is updated, so file status may be incorrect after running this
2187 command.
2189 command.
2188
2190
2189 Returns 0 on success.
2191 Returns 0 on success.
2190 """
2192 """
2191
2193
2192 r1 = scmutil.revsingle(repo, rev1).node()
2194 r1 = scmutil.revsingle(repo, rev1).node()
2193 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2195 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2194
2196
2195 with repo.wlock():
2197 with repo.wlock():
2196 repo.setparents(r1, r2)
2198 repo.setparents(r1, r2)
2197
2199
2198 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2200 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2199 def debugssl(ui, repo, source=None, **opts):
2201 def debugssl(ui, repo, source=None, **opts):
2200 '''test a secure connection to a server
2202 '''test a secure connection to a server
2201
2203
2202 This builds the certificate chain for the server on Windows, installing the
2204 This builds the certificate chain for the server on Windows, installing the
2203 missing intermediates and trusted root via Windows Update if necessary. It
2205 missing intermediates and trusted root via Windows Update if necessary. It
2204 does nothing on other platforms.
2206 does nothing on other platforms.
2205
2207
2206 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2208 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2207 that server is used. See :hg:`help urls` for more information.
2209 that server is used. See :hg:`help urls` for more information.
2208
2210
2209 If the update succeeds, retry the original operation. Otherwise, the cause
2211 If the update succeeds, retry the original operation. Otherwise, the cause
2210 of the SSL error is likely another issue.
2212 of the SSL error is likely another issue.
2211 '''
2213 '''
2212 if not pycompat.iswindows:
2214 if not pycompat.iswindows:
2213 raise error.Abort(_('certificate chain building is only possible on '
2215 raise error.Abort(_('certificate chain building is only possible on '
2214 'Windows'))
2216 'Windows'))
2215
2217
2216 if not source:
2218 if not source:
2217 if not repo:
2219 if not repo:
2218 raise error.Abort(_("there is no Mercurial repository here, and no "
2220 raise error.Abort(_("there is no Mercurial repository here, and no "
2219 "server specified"))
2221 "server specified"))
2220 source = "default"
2222 source = "default"
2221
2223
2222 source, branches = hg.parseurl(ui.expandpath(source))
2224 source, branches = hg.parseurl(ui.expandpath(source))
2223 url = util.url(source)
2225 url = util.url(source)
2224 addr = None
2226 addr = None
2225
2227
2226 defaultport = {'https': 443, 'ssh': 22}
2228 defaultport = {'https': 443, 'ssh': 22}
2227 if url.scheme in defaultport:
2229 if url.scheme in defaultport:
2228 try:
2230 try:
2229 addr = (url.host, int(url.port or defaultport[url.scheme]))
2231 addr = (url.host, int(url.port or defaultport[url.scheme]))
2230 except ValueError:
2232 except ValueError:
2231 raise error.Abort(_("malformed port number in URL"))
2233 raise error.Abort(_("malformed port number in URL"))
2232 else:
2234 else:
2233 raise error.Abort(_("only https and ssh connections are supported"))
2235 raise error.Abort(_("only https and ssh connections are supported"))
2234
2236
2235 from . import win32
2237 from . import win32
2236
2238
2237 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2239 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2238 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2240 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2239
2241
2240 try:
2242 try:
2241 s.connect(addr)
2243 s.connect(addr)
2242 cert = s.getpeercert(True)
2244 cert = s.getpeercert(True)
2243
2245
2244 ui.status(_('checking the certificate chain for %s\n') % url.host)
2246 ui.status(_('checking the certificate chain for %s\n') % url.host)
2245
2247
2246 complete = win32.checkcertificatechain(cert, build=False)
2248 complete = win32.checkcertificatechain(cert, build=False)
2247
2249
2248 if not complete:
2250 if not complete:
2249 ui.status(_('certificate chain is incomplete, updating... '))
2251 ui.status(_('certificate chain is incomplete, updating... '))
2250
2252
2251 if not win32.checkcertificatechain(cert):
2253 if not win32.checkcertificatechain(cert):
2252 ui.status(_('failed.\n'))
2254 ui.status(_('failed.\n'))
2253 else:
2255 else:
2254 ui.status(_('done.\n'))
2256 ui.status(_('done.\n'))
2255 else:
2257 else:
2256 ui.status(_('full certificate chain is available\n'))
2258 ui.status(_('full certificate chain is available\n'))
2257 finally:
2259 finally:
2258 s.close()
2260 s.close()
2259
2261
2260 @command('debugsub',
2262 @command('debugsub',
2261 [('r', 'rev', '',
2263 [('r', 'rev', '',
2262 _('revision to check'), _('REV'))],
2264 _('revision to check'), _('REV'))],
2263 _('[-r REV] [REV]'))
2265 _('[-r REV] [REV]'))
2264 def debugsub(ui, repo, rev=None):
2266 def debugsub(ui, repo, rev=None):
2265 ctx = scmutil.revsingle(repo, rev, None)
2267 ctx = scmutil.revsingle(repo, rev, None)
2266 for k, v in sorted(ctx.substate.items()):
2268 for k, v in sorted(ctx.substate.items()):
2267 ui.write(('path %s\n') % k)
2269 ui.write(('path %s\n') % k)
2268 ui.write((' source %s\n') % v[0])
2270 ui.write((' source %s\n') % v[0])
2269 ui.write((' revision %s\n') % v[1])
2271 ui.write((' revision %s\n') % v[1])
2270
2272
2271 @command('debugsuccessorssets',
2273 @command('debugsuccessorssets',
2272 [('', 'closest', False, _('return closest successors sets only'))],
2274 [('', 'closest', False, _('return closest successors sets only'))],
2273 _('[REV]'))
2275 _('[REV]'))
2274 def debugsuccessorssets(ui, repo, *revs, **opts):
2276 def debugsuccessorssets(ui, repo, *revs, **opts):
2275 """show set of successors for revision
2277 """show set of successors for revision
2276
2278
2277 A successors set of changeset A is a consistent group of revisions that
2279 A successors set of changeset A is a consistent group of revisions that
2278 succeed A. It contains non-obsolete changesets only unless closests
2280 succeed A. It contains non-obsolete changesets only unless closests
2279 successors set is set.
2281 successors set is set.
2280
2282
2281 In most cases a changeset A has a single successors set containing a single
2283 In most cases a changeset A has a single successors set containing a single
2282 successor (changeset A replaced by A').
2284 successor (changeset A replaced by A').
2283
2285
2284 A changeset that is made obsolete with no successors are called "pruned".
2286 A changeset that is made obsolete with no successors are called "pruned".
2285 Such changesets have no successors sets at all.
2287 Such changesets have no successors sets at all.
2286
2288
2287 A changeset that has been "split" will have a successors set containing
2289 A changeset that has been "split" will have a successors set containing
2288 more than one successor.
2290 more than one successor.
2289
2291
2290 A changeset that has been rewritten in multiple different ways is called
2292 A changeset that has been rewritten in multiple different ways is called
2291 "divergent". Such changesets have multiple successor sets (each of which
2293 "divergent". Such changesets have multiple successor sets (each of which
2292 may also be split, i.e. have multiple successors).
2294 may also be split, i.e. have multiple successors).
2293
2295
2294 Results are displayed as follows::
2296 Results are displayed as follows::
2295
2297
2296 <rev1>
2298 <rev1>
2297 <successors-1A>
2299 <successors-1A>
2298 <rev2>
2300 <rev2>
2299 <successors-2A>
2301 <successors-2A>
2300 <successors-2B1> <successors-2B2> <successors-2B3>
2302 <successors-2B1> <successors-2B2> <successors-2B3>
2301
2303
2302 Here rev2 has two possible (i.e. divergent) successors sets. The first
2304 Here rev2 has two possible (i.e. divergent) successors sets. The first
2303 holds one element, whereas the second holds three (i.e. the changeset has
2305 holds one element, whereas the second holds three (i.e. the changeset has
2304 been split).
2306 been split).
2305 """
2307 """
2306 # passed to successorssets caching computation from one call to another
2308 # passed to successorssets caching computation from one call to another
2307 cache = {}
2309 cache = {}
2308 ctx2str = str
2310 ctx2str = str
2309 node2str = short
2311 node2str = short
2310 for rev in scmutil.revrange(repo, revs):
2312 for rev in scmutil.revrange(repo, revs):
2311 ctx = repo[rev]
2313 ctx = repo[rev]
2312 ui.write('%s\n'% ctx2str(ctx))
2314 ui.write('%s\n'% ctx2str(ctx))
2313 for succsset in obsutil.successorssets(repo, ctx.node(),
2315 for succsset in obsutil.successorssets(repo, ctx.node(),
2314 closest=opts[r'closest'],
2316 closest=opts[r'closest'],
2315 cache=cache):
2317 cache=cache):
2316 if succsset:
2318 if succsset:
2317 ui.write(' ')
2319 ui.write(' ')
2318 ui.write(node2str(succsset[0]))
2320 ui.write(node2str(succsset[0]))
2319 for node in succsset[1:]:
2321 for node in succsset[1:]:
2320 ui.write(' ')
2322 ui.write(' ')
2321 ui.write(node2str(node))
2323 ui.write(node2str(node))
2322 ui.write('\n')
2324 ui.write('\n')
2323
2325
2324 @command('debugtemplate',
2326 @command('debugtemplate',
2325 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2327 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2326 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2328 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2327 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2329 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2328 optionalrepo=True)
2330 optionalrepo=True)
2329 def debugtemplate(ui, repo, tmpl, **opts):
2331 def debugtemplate(ui, repo, tmpl, **opts):
2330 """parse and apply a template
2332 """parse and apply a template
2331
2333
2332 If -r/--rev is given, the template is processed as a log template and
2334 If -r/--rev is given, the template is processed as a log template and
2333 applied to the given changesets. Otherwise, it is processed as a generic
2335 applied to the given changesets. Otherwise, it is processed as a generic
2334 template.
2336 template.
2335
2337
2336 Use --verbose to print the parsed tree.
2338 Use --verbose to print the parsed tree.
2337 """
2339 """
2338 revs = None
2340 revs = None
2339 if opts[r'rev']:
2341 if opts[r'rev']:
2340 if repo is None:
2342 if repo is None:
2341 raise error.RepoError(_('there is no Mercurial repository here '
2343 raise error.RepoError(_('there is no Mercurial repository here '
2342 '(.hg not found)'))
2344 '(.hg not found)'))
2343 revs = scmutil.revrange(repo, opts[r'rev'])
2345 revs = scmutil.revrange(repo, opts[r'rev'])
2344
2346
2345 props = {}
2347 props = {}
2346 for d in opts[r'define']:
2348 for d in opts[r'define']:
2347 try:
2349 try:
2348 k, v = (e.strip() for e in d.split('=', 1))
2350 k, v = (e.strip() for e in d.split('=', 1))
2349 if not k or k == 'ui':
2351 if not k or k == 'ui':
2350 raise ValueError
2352 raise ValueError
2351 props[k] = v
2353 props[k] = v
2352 except ValueError:
2354 except ValueError:
2353 raise error.Abort(_('malformed keyword definition: %s') % d)
2355 raise error.Abort(_('malformed keyword definition: %s') % d)
2354
2356
2355 if ui.verbose:
2357 if ui.verbose:
2356 aliases = ui.configitems('templatealias')
2358 aliases = ui.configitems('templatealias')
2357 tree = templater.parse(tmpl)
2359 tree = templater.parse(tmpl)
2358 ui.note(templater.prettyformat(tree), '\n')
2360 ui.note(templater.prettyformat(tree), '\n')
2359 newtree = templater.expandaliases(tree, aliases)
2361 newtree = templater.expandaliases(tree, aliases)
2360 if newtree != tree:
2362 if newtree != tree:
2361 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2363 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2362
2364
2363 if revs is None:
2365 if revs is None:
2364 tres = formatter.templateresources(ui, repo)
2366 tres = formatter.templateresources(ui, repo)
2365 t = formatter.maketemplater(ui, tmpl, resources=tres)
2367 t = formatter.maketemplater(ui, tmpl, resources=tres)
2366 ui.write(t.render(props))
2368 ui.write(t.render(props))
2367 else:
2369 else:
2368 displayer = cmdutil.makelogtemplater(ui, repo, tmpl)
2370 displayer = cmdutil.makelogtemplater(ui, repo, tmpl)
2369 for r in revs:
2371 for r in revs:
2370 displayer.show(repo[r], **pycompat.strkwargs(props))
2372 displayer.show(repo[r], **pycompat.strkwargs(props))
2371 displayer.close()
2373 displayer.close()
2372
2374
2373 @command('debugupdatecaches', [])
2375 @command('debugupdatecaches', [])
2374 def debugupdatecaches(ui, repo, *pats, **opts):
2376 def debugupdatecaches(ui, repo, *pats, **opts):
2375 """warm all known caches in the repository"""
2377 """warm all known caches in the repository"""
2376 with repo.wlock(), repo.lock():
2378 with repo.wlock(), repo.lock():
2377 repo.updatecaches()
2379 repo.updatecaches()
2378
2380
2379 @command('debugupgraderepo', [
2381 @command('debugupgraderepo', [
2380 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2382 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2381 ('', 'run', False, _('performs an upgrade')),
2383 ('', 'run', False, _('performs an upgrade')),
2382 ])
2384 ])
2383 def debugupgraderepo(ui, repo, run=False, optimize=None):
2385 def debugupgraderepo(ui, repo, run=False, optimize=None):
2384 """upgrade a repository to use different features
2386 """upgrade a repository to use different features
2385
2387
2386 If no arguments are specified, the repository is evaluated for upgrade
2388 If no arguments are specified, the repository is evaluated for upgrade
2387 and a list of problems and potential optimizations is printed.
2389 and a list of problems and potential optimizations is printed.
2388
2390
2389 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2391 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2390 can be influenced via additional arguments. More details will be provided
2392 can be influenced via additional arguments. More details will be provided
2391 by the command output when run without ``--run``.
2393 by the command output when run without ``--run``.
2392
2394
2393 During the upgrade, the repository will be locked and no writes will be
2395 During the upgrade, the repository will be locked and no writes will be
2394 allowed.
2396 allowed.
2395
2397
2396 At the end of the upgrade, the repository may not be readable while new
2398 At the end of the upgrade, the repository may not be readable while new
2397 repository data is swapped in. This window will be as long as it takes to
2399 repository data is swapped in. This window will be as long as it takes to
2398 rename some directories inside the ``.hg`` directory. On most machines, this
2400 rename some directories inside the ``.hg`` directory. On most machines, this
2399 should complete almost instantaneously and the chances of a consumer being
2401 should complete almost instantaneously and the chances of a consumer being
2400 unable to access the repository should be low.
2402 unable to access the repository should be low.
2401 """
2403 """
2402 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2404 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize)
2403
2405
2404 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2406 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2405 inferrepo=True)
2407 inferrepo=True)
2406 def debugwalk(ui, repo, *pats, **opts):
2408 def debugwalk(ui, repo, *pats, **opts):
2407 """show how files match on given patterns"""
2409 """show how files match on given patterns"""
2408 opts = pycompat.byteskwargs(opts)
2410 opts = pycompat.byteskwargs(opts)
2409 m = scmutil.match(repo[None], pats, opts)
2411 m = scmutil.match(repo[None], pats, opts)
2410 ui.write(('matcher: %r\n' % m))
2412 ui.write(('matcher: %r\n' % m))
2411 items = list(repo[None].walk(m))
2413 items = list(repo[None].walk(m))
2412 if not items:
2414 if not items:
2413 return
2415 return
2414 f = lambda fn: fn
2416 f = lambda fn: fn
2415 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2417 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2416 f = lambda fn: util.normpath(fn)
2418 f = lambda fn: util.normpath(fn)
2417 fmt = 'f %%-%ds %%-%ds %%s' % (
2419 fmt = 'f %%-%ds %%-%ds %%s' % (
2418 max([len(abs) for abs in items]),
2420 max([len(abs) for abs in items]),
2419 max([len(m.rel(abs)) for abs in items]))
2421 max([len(m.rel(abs)) for abs in items]))
2420 for abs in items:
2422 for abs in items:
2421 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2423 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2422 ui.write("%s\n" % line.rstrip())
2424 ui.write("%s\n" % line.rstrip())
2423
2425
2424 @command('debugwireargs',
2426 @command('debugwireargs',
2425 [('', 'three', '', 'three'),
2427 [('', 'three', '', 'three'),
2426 ('', 'four', '', 'four'),
2428 ('', 'four', '', 'four'),
2427 ('', 'five', '', 'five'),
2429 ('', 'five', '', 'five'),
2428 ] + cmdutil.remoteopts,
2430 ] + cmdutil.remoteopts,
2429 _('REPO [OPTIONS]... [ONE [TWO]]'),
2431 _('REPO [OPTIONS]... [ONE [TWO]]'),
2430 norepo=True)
2432 norepo=True)
2431 def debugwireargs(ui, repopath, *vals, **opts):
2433 def debugwireargs(ui, repopath, *vals, **opts):
2432 opts = pycompat.byteskwargs(opts)
2434 opts = pycompat.byteskwargs(opts)
2433 repo = hg.peer(ui, opts, repopath)
2435 repo = hg.peer(ui, opts, repopath)
2434 for opt in cmdutil.remoteopts:
2436 for opt in cmdutil.remoteopts:
2435 del opts[opt[1]]
2437 del opts[opt[1]]
2436 args = {}
2438 args = {}
2437 for k, v in opts.iteritems():
2439 for k, v in opts.iteritems():
2438 if v:
2440 if v:
2439 args[k] = v
2441 args[k] = v
2440 args = pycompat.strkwargs(args)
2442 args = pycompat.strkwargs(args)
2441 # run twice to check that we don't mess up the stream for the next command
2443 # run twice to check that we don't mess up the stream for the next command
2442 res1 = repo.debugwireargs(*vals, **args)
2444 res1 = repo.debugwireargs(*vals, **args)
2443 res2 = repo.debugwireargs(*vals, **args)
2445 res2 = repo.debugwireargs(*vals, **args)
2444 ui.write("%s\n" % res1)
2446 ui.write("%s\n" % res1)
2445 if res1 != res2:
2447 if res1 != res2:
2446 ui.warn("%s\n" % res2)
2448 ui.warn("%s\n" % res2)
General Comments 0
You need to be logged in to leave comments. Login now