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