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