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