##// END OF EJS Templates
debug: add debug-revlog-stats command...
Franck Bret -
r50714:b1e4c74b default
parent child Browse files
Show More
@@ -0,0 +1,77
1 Force revlog max inline value to be smaller than default
2
3 $ mkdir $TESTTMP/ext
4 $ cat << EOF > $TESTTMP/ext/small_inline.py
5 > from mercurial import revlog
6 > revlog._maxinline = 8
7 > EOF
8
9 $ cat << EOF >> $HGRCPATH
10 > [extensions]
11 > small_inline=$TESTTMP/ext/small_inline.py
12 > EOF
13
14 $ hg init repo
15 $ cd repo
16
17 Try on an empty repository
18
19 $ hg debug-revlog-stats
20 rev-count data-size inl type target
21 0 0 yes changelog
22 0 0 yes manifest
23
24 $ mkdir folder
25 $ touch a b folder/c folder/d
26 $ hg commit -Aqm 0
27 $ echo "text" > a
28 $ hg rm b
29 $ echo "longer string" > folder/d
30 $ hg commit -Aqm 1
31
32 Differences in data size observed with pure is due to different compression
33 algorithms
34
35 $ hg debug-revlog-stats
36 rev-count data-size inl type target
37 2 138 no changelog (no-pure !)
38 2 137 no changelog (pure !)
39 2 177 no manifest (no-pure !)
40 2 168 no manifest (pure !)
41 2 6 yes file a
42 1 0 yes file b
43 1 0 yes file folder/c
44 2 15 no file folder/d
45
46 Test 'changelog' command argument
47
48 $ hg debug-revlog-stats -c
49 rev-count data-size inl type target
50 2 138 no changelog (no-pure !)
51 2 137 no changelog (pure !)
52
53 Test 'manifest' command argument
54
55 $ hg debug-revlog-stats -m
56 rev-count data-size inl type target
57 2 177 no manifest (no-pure !)
58 2 168 no manifest (pure !)
59
60 Test 'file' command argument
61
62 $ hg debug-revlog-stats -f
63 rev-count data-size inl type target
64 2 6 yes file a
65 1 0 yes file b
66 1 0 yes file folder/c
67 2 15 no file folder/d
68
69 Test multiple command arguments
70
71 $ hg debug-revlog-stats -cm
72 rev-count data-size inl type target
73 2 138 no changelog (no-pure !)
74 2 137 no changelog (pure !)
75 2 177 no manifest (no-pure !)
76 2 168 no manifest (pure !)
77
@@ -1,4716 +1,4743
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2016 Olivia Mackall <olivia@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
8
9 import binascii
9 import binascii
10 import codecs
10 import codecs
11 import collections
11 import collections
12 import contextlib
12 import contextlib
13 import difflib
13 import difflib
14 import errno
14 import errno
15 import glob
15 import glob
16 import operator
16 import operator
17 import os
17 import os
18 import platform
18 import platform
19 import random
19 import random
20 import re
20 import re
21 import socket
21 import socket
22 import ssl
22 import ssl
23 import stat
23 import stat
24 import subprocess
24 import subprocess
25 import sys
25 import sys
26 import time
26 import time
27
27
28 from .i18n import _
28 from .i18n import _
29 from .node import (
29 from .node import (
30 bin,
30 bin,
31 hex,
31 hex,
32 nullrev,
32 nullrev,
33 short,
33 short,
34 )
34 )
35 from .pycompat import (
35 from .pycompat import (
36 getattr,
36 getattr,
37 open,
37 open,
38 )
38 )
39 from . import (
39 from . import (
40 bundle2,
40 bundle2,
41 bundlerepo,
41 bundlerepo,
42 changegroup,
42 changegroup,
43 cmdutil,
43 cmdutil,
44 color,
44 color,
45 context,
45 context,
46 copies,
46 copies,
47 dagparser,
47 dagparser,
48 dirstateutils,
48 dirstateutils,
49 encoding,
49 encoding,
50 error,
50 error,
51 exchange,
51 exchange,
52 extensions,
52 extensions,
53 filemerge,
53 filemerge,
54 filesetlang,
54 filesetlang,
55 formatter,
55 formatter,
56 hg,
56 hg,
57 httppeer,
57 httppeer,
58 localrepo,
58 localrepo,
59 lock as lockmod,
59 lock as lockmod,
60 logcmdutil,
60 logcmdutil,
61 mergestate as mergestatemod,
61 mergestate as mergestatemod,
62 metadata,
62 metadata,
63 obsolete,
63 obsolete,
64 obsutil,
64 obsutil,
65 pathutil,
65 pathutil,
66 phases,
66 phases,
67 policy,
67 policy,
68 pvec,
68 pvec,
69 pycompat,
69 pycompat,
70 registrar,
70 registrar,
71 repair,
71 repair,
72 repoview,
72 repoview,
73 requirements,
73 requirements,
74 revlog,
74 revlog,
75 revset,
75 revset,
76 revsetlang,
76 revsetlang,
77 scmutil,
77 scmutil,
78 setdiscovery,
78 setdiscovery,
79 simplemerge,
79 simplemerge,
80 sshpeer,
80 sshpeer,
81 sslutil,
81 sslutil,
82 streamclone,
82 streamclone,
83 strip,
83 strip,
84 tags as tagsmod,
84 tags as tagsmod,
85 templater,
85 templater,
86 treediscovery,
86 treediscovery,
87 upgrade,
87 upgrade,
88 url as urlmod,
88 url as urlmod,
89 util,
89 util,
90 vfs as vfsmod,
90 vfs as vfsmod,
91 wireprotoframing,
91 wireprotoframing,
92 wireprotoserver,
92 wireprotoserver,
93 )
93 )
94 from .interfaces import repository
94 from .interfaces import repository
95 from .utils import (
95 from .utils import (
96 cborutil,
96 cborutil,
97 compression,
97 compression,
98 dateutil,
98 dateutil,
99 procutil,
99 procutil,
100 stringutil,
100 stringutil,
101 urlutil,
101 urlutil,
102 )
102 )
103
103
104 from .revlogutils import (
104 from .revlogutils import (
105 constants as revlog_constants,
105 constants as revlog_constants,
106 debug as revlog_debug,
106 debug as revlog_debug,
107 deltas as deltautil,
107 deltas as deltautil,
108 nodemap,
108 nodemap,
109 rewrite,
109 rewrite,
110 sidedata,
110 sidedata,
111 )
111 )
112
112
113 release = lockmod.release
113 release = lockmod.release
114
114
115 table = {}
115 table = {}
116 table.update(strip.command._table)
116 table.update(strip.command._table)
117 command = registrar.command(table)
117 command = registrar.command(table)
118
118
119
119
120 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
120 @command(b'debugancestor', [], _(b'[INDEX] REV1 REV2'), optionalrepo=True)
121 def debugancestor(ui, repo, *args):
121 def debugancestor(ui, repo, *args):
122 """find the ancestor revision of two revisions in a given index"""
122 """find the ancestor revision of two revisions in a given index"""
123 if len(args) == 3:
123 if len(args) == 3:
124 index, rev1, rev2 = args
124 index, rev1, rev2 = args
125 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
125 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
126 lookup = r.lookup
126 lookup = r.lookup
127 elif len(args) == 2:
127 elif len(args) == 2:
128 if not repo:
128 if not repo:
129 raise error.Abort(
129 raise error.Abort(
130 _(b'there is no Mercurial repository here (.hg not found)')
130 _(b'there is no Mercurial repository here (.hg not found)')
131 )
131 )
132 rev1, rev2 = args
132 rev1, rev2 = args
133 r = repo.changelog
133 r = repo.changelog
134 lookup = repo.lookup
134 lookup = repo.lookup
135 else:
135 else:
136 raise error.Abort(_(b'either two or three arguments required'))
136 raise error.Abort(_(b'either two or three arguments required'))
137 a = r.ancestor(lookup(rev1), lookup(rev2))
137 a = r.ancestor(lookup(rev1), lookup(rev2))
138 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
138 ui.write(b'%d:%s\n' % (r.rev(a), hex(a)))
139
139
140
140
141 @command(b'debugantivirusrunning', [])
141 @command(b'debugantivirusrunning', [])
142 def debugantivirusrunning(ui, repo):
142 def debugantivirusrunning(ui, repo):
143 """attempt to trigger an antivirus scanner to see if one is active"""
143 """attempt to trigger an antivirus scanner to see if one is active"""
144 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
144 with repo.cachevfs.open('eicar-test-file.com', b'wb') as f:
145 f.write(
145 f.write(
146 util.b85decode(
146 util.b85decode(
147 # This is a base85-armored version of the EICAR test file. See
147 # This is a base85-armored version of the EICAR test file. See
148 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
148 # https://en.wikipedia.org/wiki/EICAR_test_file for details.
149 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
149 b'ST#=}P$fV?P+K%yP+C|uG$>GBDK|qyDK~v2MM*<JQY}+dK~6+LQba95P'
150 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
150 b'E<)&Nm5l)EmTEQR4qnHOhq9iNGnJx'
151 )
151 )
152 )
152 )
153 # Give an AV engine time to scan the file.
153 # Give an AV engine time to scan the file.
154 time.sleep(2)
154 time.sleep(2)
155 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
155 util.unlink(repo.cachevfs.join('eicar-test-file.com'))
156
156
157
157
158 @command(b'debugapplystreamclonebundle', [], b'FILE')
158 @command(b'debugapplystreamclonebundle', [], b'FILE')
159 def debugapplystreamclonebundle(ui, repo, fname):
159 def debugapplystreamclonebundle(ui, repo, fname):
160 """apply a stream clone bundle file"""
160 """apply a stream clone bundle file"""
161 f = hg.openpath(ui, fname)
161 f = hg.openpath(ui, fname)
162 gen = exchange.readbundle(ui, f, fname)
162 gen = exchange.readbundle(ui, f, fname)
163 gen.apply(repo)
163 gen.apply(repo)
164
164
165
165
166 @command(
166 @command(
167 b'debugbuilddag',
167 b'debugbuilddag',
168 [
168 [
169 (
169 (
170 b'm',
170 b'm',
171 b'mergeable-file',
171 b'mergeable-file',
172 None,
172 None,
173 _(b'add single file mergeable changes'),
173 _(b'add single file mergeable changes'),
174 ),
174 ),
175 (
175 (
176 b'o',
176 b'o',
177 b'overwritten-file',
177 b'overwritten-file',
178 None,
178 None,
179 _(b'add single file all revs overwrite'),
179 _(b'add single file all revs overwrite'),
180 ),
180 ),
181 (b'n', b'new-file', None, _(b'add new file at each rev')),
181 (b'n', b'new-file', None, _(b'add new file at each rev')),
182 (
182 (
183 b'',
183 b'',
184 b'from-existing',
184 b'from-existing',
185 None,
185 None,
186 _(b'continue from a non-empty repository'),
186 _(b'continue from a non-empty repository'),
187 ),
187 ),
188 ],
188 ],
189 _(b'[OPTION]... [TEXT]'),
189 _(b'[OPTION]... [TEXT]'),
190 )
190 )
191 def debugbuilddag(
191 def debugbuilddag(
192 ui,
192 ui,
193 repo,
193 repo,
194 text=None,
194 text=None,
195 mergeable_file=False,
195 mergeable_file=False,
196 overwritten_file=False,
196 overwritten_file=False,
197 new_file=False,
197 new_file=False,
198 from_existing=False,
198 from_existing=False,
199 ):
199 ):
200 """builds a repo with a given DAG from scratch in the current empty repo
200 """builds a repo with a given DAG from scratch in the current empty repo
201
201
202 The description of the DAG is read from stdin if not given on the
202 The description of the DAG is read from stdin if not given on the
203 command line.
203 command line.
204
204
205 Elements:
205 Elements:
206
206
207 - "+n" is a linear run of n nodes based on the current default parent
207 - "+n" is a linear run of n nodes based on the current default parent
208 - "." is a single node based on the current default parent
208 - "." is a single node based on the current default parent
209 - "$" resets the default parent to null (implied at the start);
209 - "$" resets the default parent to null (implied at the start);
210 otherwise the default parent is always the last node created
210 otherwise the default parent is always the last node created
211 - "<p" sets the default parent to the backref p
211 - "<p" sets the default parent to the backref p
212 - "*p" is a fork at parent p, which is a backref
212 - "*p" is a fork at parent p, which is a backref
213 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
213 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
214 - "/p2" is a merge of the preceding node and p2
214 - "/p2" is a merge of the preceding node and p2
215 - ":tag" defines a local tag for the preceding node
215 - ":tag" defines a local tag for the preceding node
216 - "@branch" sets the named branch for subsequent nodes
216 - "@branch" sets the named branch for subsequent nodes
217 - "#...\\n" is a comment up to the end of the line
217 - "#...\\n" is a comment up to the end of the line
218
218
219 Whitespace between the above elements is ignored.
219 Whitespace between the above elements is ignored.
220
220
221 A backref is either
221 A backref is either
222
222
223 - a number n, which references the node curr-n, where curr is the current
223 - a number n, which references the node curr-n, where curr is the current
224 node, or
224 node, or
225 - the name of a local tag you placed earlier using ":tag", or
225 - the name of a local tag you placed earlier using ":tag", or
226 - empty to denote the default parent.
226 - empty to denote the default parent.
227
227
228 All string valued-elements are either strictly alphanumeric, or must
228 All string valued-elements are either strictly alphanumeric, or must
229 be enclosed in double quotes ("..."), with "\\" as escape character.
229 be enclosed in double quotes ("..."), with "\\" as escape character.
230 """
230 """
231
231
232 if text is None:
232 if text is None:
233 ui.status(_(b"reading DAG from stdin\n"))
233 ui.status(_(b"reading DAG from stdin\n"))
234 text = ui.fin.read()
234 text = ui.fin.read()
235
235
236 cl = repo.changelog
236 cl = repo.changelog
237 if len(cl) > 0 and not from_existing:
237 if len(cl) > 0 and not from_existing:
238 raise error.Abort(_(b'repository is not empty'))
238 raise error.Abort(_(b'repository is not empty'))
239
239
240 # determine number of revs in DAG
240 # determine number of revs in DAG
241 total = 0
241 total = 0
242 for type, data in dagparser.parsedag(text):
242 for type, data in dagparser.parsedag(text):
243 if type == b'n':
243 if type == b'n':
244 total += 1
244 total += 1
245
245
246 if mergeable_file:
246 if mergeable_file:
247 linesperrev = 2
247 linesperrev = 2
248 # make a file with k lines per rev
248 # make a file with k lines per rev
249 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
249 initialmergedlines = [b'%d' % i for i in range(0, total * linesperrev)]
250 initialmergedlines.append(b"")
250 initialmergedlines.append(b"")
251
251
252 tags = []
252 tags = []
253 progress = ui.makeprogress(
253 progress = ui.makeprogress(
254 _(b'building'), unit=_(b'revisions'), total=total
254 _(b'building'), unit=_(b'revisions'), total=total
255 )
255 )
256 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
256 with progress, repo.wlock(), repo.lock(), repo.transaction(b"builddag"):
257 at = -1
257 at = -1
258 atbranch = b'default'
258 atbranch = b'default'
259 nodeids = []
259 nodeids = []
260 id = 0
260 id = 0
261 progress.update(id)
261 progress.update(id)
262 for type, data in dagparser.parsedag(text):
262 for type, data in dagparser.parsedag(text):
263 if type == b'n':
263 if type == b'n':
264 ui.note((b'node %s\n' % pycompat.bytestr(data)))
264 ui.note((b'node %s\n' % pycompat.bytestr(data)))
265 id, ps = data
265 id, ps = data
266
266
267 files = []
267 files = []
268 filecontent = {}
268 filecontent = {}
269
269
270 p2 = None
270 p2 = None
271 if mergeable_file:
271 if mergeable_file:
272 fn = b"mf"
272 fn = b"mf"
273 p1 = repo[ps[0]]
273 p1 = repo[ps[0]]
274 if len(ps) > 1:
274 if len(ps) > 1:
275 p2 = repo[ps[1]]
275 p2 = repo[ps[1]]
276 pa = p1.ancestor(p2)
276 pa = p1.ancestor(p2)
277 base, local, other = [
277 base, local, other = [
278 x[fn].data() for x in (pa, p1, p2)
278 x[fn].data() for x in (pa, p1, p2)
279 ]
279 ]
280 m3 = simplemerge.Merge3Text(base, local, other)
280 m3 = simplemerge.Merge3Text(base, local, other)
281 ml = [
281 ml = [
282 l.strip()
282 l.strip()
283 for l in simplemerge.render_minimized(m3)[0]
283 for l in simplemerge.render_minimized(m3)[0]
284 ]
284 ]
285 ml.append(b"")
285 ml.append(b"")
286 elif at > 0:
286 elif at > 0:
287 ml = p1[fn].data().split(b"\n")
287 ml = p1[fn].data().split(b"\n")
288 else:
288 else:
289 ml = initialmergedlines
289 ml = initialmergedlines
290 ml[id * linesperrev] += b" r%i" % id
290 ml[id * linesperrev] += b" r%i" % id
291 mergedtext = b"\n".join(ml)
291 mergedtext = b"\n".join(ml)
292 files.append(fn)
292 files.append(fn)
293 filecontent[fn] = mergedtext
293 filecontent[fn] = mergedtext
294
294
295 if overwritten_file:
295 if overwritten_file:
296 fn = b"of"
296 fn = b"of"
297 files.append(fn)
297 files.append(fn)
298 filecontent[fn] = b"r%i\n" % id
298 filecontent[fn] = b"r%i\n" % id
299
299
300 if new_file:
300 if new_file:
301 fn = b"nf%i" % id
301 fn = b"nf%i" % id
302 files.append(fn)
302 files.append(fn)
303 filecontent[fn] = b"r%i\n" % id
303 filecontent[fn] = b"r%i\n" % id
304 if len(ps) > 1:
304 if len(ps) > 1:
305 if not p2:
305 if not p2:
306 p2 = repo[ps[1]]
306 p2 = repo[ps[1]]
307 for fn in p2:
307 for fn in p2:
308 if fn.startswith(b"nf"):
308 if fn.startswith(b"nf"):
309 files.append(fn)
309 files.append(fn)
310 filecontent[fn] = p2[fn].data()
310 filecontent[fn] = p2[fn].data()
311
311
312 def fctxfn(repo, cx, path):
312 def fctxfn(repo, cx, path):
313 if path in filecontent:
313 if path in filecontent:
314 return context.memfilectx(
314 return context.memfilectx(
315 repo, cx, path, filecontent[path]
315 repo, cx, path, filecontent[path]
316 )
316 )
317 return None
317 return None
318
318
319 if len(ps) == 0 or ps[0] < 0:
319 if len(ps) == 0 or ps[0] < 0:
320 pars = [None, None]
320 pars = [None, None]
321 elif len(ps) == 1:
321 elif len(ps) == 1:
322 pars = [nodeids[ps[0]], None]
322 pars = [nodeids[ps[0]], None]
323 else:
323 else:
324 pars = [nodeids[p] for p in ps]
324 pars = [nodeids[p] for p in ps]
325 cx = context.memctx(
325 cx = context.memctx(
326 repo,
326 repo,
327 pars,
327 pars,
328 b"r%i" % id,
328 b"r%i" % id,
329 files,
329 files,
330 fctxfn,
330 fctxfn,
331 date=(id, 0),
331 date=(id, 0),
332 user=b"debugbuilddag",
332 user=b"debugbuilddag",
333 extra={b'branch': atbranch},
333 extra={b'branch': atbranch},
334 )
334 )
335 nodeid = repo.commitctx(cx)
335 nodeid = repo.commitctx(cx)
336 nodeids.append(nodeid)
336 nodeids.append(nodeid)
337 at = id
337 at = id
338 elif type == b'l':
338 elif type == b'l':
339 id, name = data
339 id, name = data
340 ui.note((b'tag %s\n' % name))
340 ui.note((b'tag %s\n' % name))
341 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
341 tags.append(b"%s %s\n" % (hex(repo.changelog.node(id)), name))
342 elif type == b'a':
342 elif type == b'a':
343 ui.note((b'branch %s\n' % data))
343 ui.note((b'branch %s\n' % data))
344 atbranch = data
344 atbranch = data
345 progress.update(id)
345 progress.update(id)
346
346
347 if tags:
347 if tags:
348 repo.vfs.write(b"localtags", b"".join(tags))
348 repo.vfs.write(b"localtags", b"".join(tags))
349
349
350
350
351 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
351 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
352 indent_string = b' ' * indent
352 indent_string = b' ' * indent
353 if all:
353 if all:
354 ui.writenoi18n(
354 ui.writenoi18n(
355 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
355 b"%sformat: id, p1, p2, cset, delta base, len(delta)\n"
356 % indent_string
356 % indent_string
357 )
357 )
358
358
359 def showchunks(named):
359 def showchunks(named):
360 ui.write(b"\n%s%s\n" % (indent_string, named))
360 ui.write(b"\n%s%s\n" % (indent_string, named))
361 for deltadata in gen.deltaiter():
361 for deltadata in gen.deltaiter():
362 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
362 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
363 ui.write(
363 ui.write(
364 b"%s%s %s %s %s %s %d\n"
364 b"%s%s %s %s %s %s %d\n"
365 % (
365 % (
366 indent_string,
366 indent_string,
367 hex(node),
367 hex(node),
368 hex(p1),
368 hex(p1),
369 hex(p2),
369 hex(p2),
370 hex(cs),
370 hex(cs),
371 hex(deltabase),
371 hex(deltabase),
372 len(delta),
372 len(delta),
373 )
373 )
374 )
374 )
375
375
376 gen.changelogheader()
376 gen.changelogheader()
377 showchunks(b"changelog")
377 showchunks(b"changelog")
378 gen.manifestheader()
378 gen.manifestheader()
379 showchunks(b"manifest")
379 showchunks(b"manifest")
380 for chunkdata in iter(gen.filelogheader, {}):
380 for chunkdata in iter(gen.filelogheader, {}):
381 fname = chunkdata[b'filename']
381 fname = chunkdata[b'filename']
382 showchunks(fname)
382 showchunks(fname)
383 else:
383 else:
384 if isinstance(gen, bundle2.unbundle20):
384 if isinstance(gen, bundle2.unbundle20):
385 raise error.Abort(_(b'use debugbundle2 for this file'))
385 raise error.Abort(_(b'use debugbundle2 for this file'))
386 gen.changelogheader()
386 gen.changelogheader()
387 for deltadata in gen.deltaiter():
387 for deltadata in gen.deltaiter():
388 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
388 node, p1, p2, cs, deltabase, delta, flags, sidedata = deltadata
389 ui.write(b"%s%s\n" % (indent_string, hex(node)))
389 ui.write(b"%s%s\n" % (indent_string, hex(node)))
390
390
391
391
392 def _debugobsmarkers(ui, part, indent=0, **opts):
392 def _debugobsmarkers(ui, part, indent=0, **opts):
393 """display version and markers contained in 'data'"""
393 """display version and markers contained in 'data'"""
394 opts = pycompat.byteskwargs(opts)
394 opts = pycompat.byteskwargs(opts)
395 data = part.read()
395 data = part.read()
396 indent_string = b' ' * indent
396 indent_string = b' ' * indent
397 try:
397 try:
398 version, markers = obsolete._readmarkers(data)
398 version, markers = obsolete._readmarkers(data)
399 except error.UnknownVersion as exc:
399 except error.UnknownVersion as exc:
400 msg = b"%sunsupported version: %s (%d bytes)\n"
400 msg = b"%sunsupported version: %s (%d bytes)\n"
401 msg %= indent_string, exc.version, len(data)
401 msg %= indent_string, exc.version, len(data)
402 ui.write(msg)
402 ui.write(msg)
403 else:
403 else:
404 msg = b"%sversion: %d (%d bytes)\n"
404 msg = b"%sversion: %d (%d bytes)\n"
405 msg %= indent_string, version, len(data)
405 msg %= indent_string, version, len(data)
406 ui.write(msg)
406 ui.write(msg)
407 fm = ui.formatter(b'debugobsolete', opts)
407 fm = ui.formatter(b'debugobsolete', opts)
408 for rawmarker in sorted(markers):
408 for rawmarker in sorted(markers):
409 m = obsutil.marker(None, rawmarker)
409 m = obsutil.marker(None, rawmarker)
410 fm.startitem()
410 fm.startitem()
411 fm.plain(indent_string)
411 fm.plain(indent_string)
412 cmdutil.showmarker(fm, m)
412 cmdutil.showmarker(fm, m)
413 fm.end()
413 fm.end()
414
414
415
415
416 def _debugphaseheads(ui, data, indent=0):
416 def _debugphaseheads(ui, data, indent=0):
417 """display version and markers contained in 'data'"""
417 """display version and markers contained in 'data'"""
418 indent_string = b' ' * indent
418 indent_string = b' ' * indent
419 headsbyphase = phases.binarydecode(data)
419 headsbyphase = phases.binarydecode(data)
420 for phase in phases.allphases:
420 for phase in phases.allphases:
421 for head in headsbyphase[phase]:
421 for head in headsbyphase[phase]:
422 ui.write(indent_string)
422 ui.write(indent_string)
423 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
423 ui.write(b'%s %s\n' % (hex(head), phases.phasenames[phase]))
424
424
425
425
426 def _quasirepr(thing):
426 def _quasirepr(thing):
427 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
427 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
428 return b'{%s}' % (
428 return b'{%s}' % (
429 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
429 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing))
430 )
430 )
431 return pycompat.bytestr(repr(thing))
431 return pycompat.bytestr(repr(thing))
432
432
433
433
434 def _debugbundle2(ui, gen, all=None, **opts):
434 def _debugbundle2(ui, gen, all=None, **opts):
435 """lists the contents of a bundle2"""
435 """lists the contents of a bundle2"""
436 if not isinstance(gen, bundle2.unbundle20):
436 if not isinstance(gen, bundle2.unbundle20):
437 raise error.Abort(_(b'not a bundle2 file'))
437 raise error.Abort(_(b'not a bundle2 file'))
438 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
438 ui.write((b'Stream params: %s\n' % _quasirepr(gen.params)))
439 parttypes = opts.get('part_type', [])
439 parttypes = opts.get('part_type', [])
440 for part in gen.iterparts():
440 for part in gen.iterparts():
441 if parttypes and part.type not in parttypes:
441 if parttypes and part.type not in parttypes:
442 continue
442 continue
443 msg = b'%s -- %s (mandatory: %r)\n'
443 msg = b'%s -- %s (mandatory: %r)\n'
444 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
444 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
445 if part.type == b'changegroup':
445 if part.type == b'changegroup':
446 version = part.params.get(b'version', b'01')
446 version = part.params.get(b'version', b'01')
447 cg = changegroup.getunbundler(version, part, b'UN')
447 cg = changegroup.getunbundler(version, part, b'UN')
448 if not ui.quiet:
448 if not ui.quiet:
449 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
449 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
450 if part.type == b'obsmarkers':
450 if part.type == b'obsmarkers':
451 if not ui.quiet:
451 if not ui.quiet:
452 _debugobsmarkers(ui, part, indent=4, **opts)
452 _debugobsmarkers(ui, part, indent=4, **opts)
453 if part.type == b'phase-heads':
453 if part.type == b'phase-heads':
454 if not ui.quiet:
454 if not ui.quiet:
455 _debugphaseheads(ui, part, indent=4)
455 _debugphaseheads(ui, part, indent=4)
456
456
457
457
458 @command(
458 @command(
459 b'debugbundle',
459 b'debugbundle',
460 [
460 [
461 (b'a', b'all', None, _(b'show all details')),
461 (b'a', b'all', None, _(b'show all details')),
462 (b'', b'part-type', [], _(b'show only the named part type')),
462 (b'', b'part-type', [], _(b'show only the named part type')),
463 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
463 (b'', b'spec', None, _(b'print the bundlespec of the bundle')),
464 ],
464 ],
465 _(b'FILE'),
465 _(b'FILE'),
466 norepo=True,
466 norepo=True,
467 )
467 )
468 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
468 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
469 """lists the contents of a bundle"""
469 """lists the contents of a bundle"""
470 with hg.openpath(ui, bundlepath) as f:
470 with hg.openpath(ui, bundlepath) as f:
471 if spec:
471 if spec:
472 spec = exchange.getbundlespec(ui, f)
472 spec = exchange.getbundlespec(ui, f)
473 ui.write(b'%s\n' % spec)
473 ui.write(b'%s\n' % spec)
474 return
474 return
475
475
476 gen = exchange.readbundle(ui, f, bundlepath)
476 gen = exchange.readbundle(ui, f, bundlepath)
477 if isinstance(gen, bundle2.unbundle20):
477 if isinstance(gen, bundle2.unbundle20):
478 return _debugbundle2(ui, gen, all=all, **opts)
478 return _debugbundle2(ui, gen, all=all, **opts)
479 _debugchangegroup(ui, gen, all=all, **opts)
479 _debugchangegroup(ui, gen, all=all, **opts)
480
480
481
481
482 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
482 @command(b'debugcapabilities', [], _(b'PATH'), norepo=True)
483 def debugcapabilities(ui, path, **opts):
483 def debugcapabilities(ui, path, **opts):
484 """lists the capabilities of a remote peer"""
484 """lists the capabilities of a remote peer"""
485 opts = pycompat.byteskwargs(opts)
485 opts = pycompat.byteskwargs(opts)
486 peer = hg.peer(ui, opts, path)
486 peer = hg.peer(ui, opts, path)
487 try:
487 try:
488 caps = peer.capabilities()
488 caps = peer.capabilities()
489 ui.writenoi18n(b'Main capabilities:\n')
489 ui.writenoi18n(b'Main capabilities:\n')
490 for c in sorted(caps):
490 for c in sorted(caps):
491 ui.write(b' %s\n' % c)
491 ui.write(b' %s\n' % c)
492 b2caps = bundle2.bundle2caps(peer)
492 b2caps = bundle2.bundle2caps(peer)
493 if b2caps:
493 if b2caps:
494 ui.writenoi18n(b'Bundle2 capabilities:\n')
494 ui.writenoi18n(b'Bundle2 capabilities:\n')
495 for key, values in sorted(b2caps.items()):
495 for key, values in sorted(b2caps.items()):
496 ui.write(b' %s\n' % key)
496 ui.write(b' %s\n' % key)
497 for v in values:
497 for v in values:
498 ui.write(b' %s\n' % v)
498 ui.write(b' %s\n' % v)
499 finally:
499 finally:
500 peer.close()
500 peer.close()
501
501
502
502
503 @command(
503 @command(
504 b'debugchangedfiles',
504 b'debugchangedfiles',
505 [
505 [
506 (
506 (
507 b'',
507 b'',
508 b'compute',
508 b'compute',
509 False,
509 False,
510 b"compute information instead of reading it from storage",
510 b"compute information instead of reading it from storage",
511 ),
511 ),
512 ],
512 ],
513 b'REV',
513 b'REV',
514 )
514 )
515 def debugchangedfiles(ui, repo, rev, **opts):
515 def debugchangedfiles(ui, repo, rev, **opts):
516 """list the stored files changes for a revision"""
516 """list the stored files changes for a revision"""
517 ctx = logcmdutil.revsingle(repo, rev, None)
517 ctx = logcmdutil.revsingle(repo, rev, None)
518 files = None
518 files = None
519
519
520 if opts['compute']:
520 if opts['compute']:
521 files = metadata.compute_all_files_changes(ctx)
521 files = metadata.compute_all_files_changes(ctx)
522 else:
522 else:
523 sd = repo.changelog.sidedata(ctx.rev())
523 sd = repo.changelog.sidedata(ctx.rev())
524 files_block = sd.get(sidedata.SD_FILES)
524 files_block = sd.get(sidedata.SD_FILES)
525 if files_block is not None:
525 if files_block is not None:
526 files = metadata.decode_files_sidedata(sd)
526 files = metadata.decode_files_sidedata(sd)
527 if files is not None:
527 if files is not None:
528 for f in sorted(files.touched):
528 for f in sorted(files.touched):
529 if f in files.added:
529 if f in files.added:
530 action = b"added"
530 action = b"added"
531 elif f in files.removed:
531 elif f in files.removed:
532 action = b"removed"
532 action = b"removed"
533 elif f in files.merged:
533 elif f in files.merged:
534 action = b"merged"
534 action = b"merged"
535 elif f in files.salvaged:
535 elif f in files.salvaged:
536 action = b"salvaged"
536 action = b"salvaged"
537 else:
537 else:
538 action = b"touched"
538 action = b"touched"
539
539
540 copy_parent = b""
540 copy_parent = b""
541 copy_source = b""
541 copy_source = b""
542 if f in files.copied_from_p1:
542 if f in files.copied_from_p1:
543 copy_parent = b"p1"
543 copy_parent = b"p1"
544 copy_source = files.copied_from_p1[f]
544 copy_source = files.copied_from_p1[f]
545 elif f in files.copied_from_p2:
545 elif f in files.copied_from_p2:
546 copy_parent = b"p2"
546 copy_parent = b"p2"
547 copy_source = files.copied_from_p2[f]
547 copy_source = files.copied_from_p2[f]
548
548
549 data = (action, copy_parent, f, copy_source)
549 data = (action, copy_parent, f, copy_source)
550 template = b"%-8s %2s: %s, %s;\n"
550 template = b"%-8s %2s: %s, %s;\n"
551 ui.write(template % data)
551 ui.write(template % data)
552
552
553
553
554 @command(b'debugcheckstate', [], b'')
554 @command(b'debugcheckstate', [], b'')
555 def debugcheckstate(ui, repo):
555 def debugcheckstate(ui, repo):
556 """validate the correctness of the current dirstate"""
556 """validate the correctness of the current dirstate"""
557 parent1, parent2 = repo.dirstate.parents()
557 parent1, parent2 = repo.dirstate.parents()
558 m1 = repo[parent1].manifest()
558 m1 = repo[parent1].manifest()
559 m2 = repo[parent2].manifest()
559 m2 = repo[parent2].manifest()
560 errors = 0
560 errors = 0
561 for err in repo.dirstate.verify(m1, m2):
561 for err in repo.dirstate.verify(m1, m2):
562 ui.warn(err[0] % err[1:])
562 ui.warn(err[0] % err[1:])
563 errors += 1
563 errors += 1
564 if errors:
564 if errors:
565 errstr = _(b".hg/dirstate inconsistent with current parent's manifest")
565 errstr = _(b".hg/dirstate inconsistent with current parent's manifest")
566 raise error.Abort(errstr)
566 raise error.Abort(errstr)
567
567
568
568
569 @command(
569 @command(
570 b'debugcolor',
570 b'debugcolor',
571 [(b'', b'style', None, _(b'show all configured styles'))],
571 [(b'', b'style', None, _(b'show all configured styles'))],
572 b'hg debugcolor',
572 b'hg debugcolor',
573 )
573 )
574 def debugcolor(ui, repo, **opts):
574 def debugcolor(ui, repo, **opts):
575 """show available color, effects or style"""
575 """show available color, effects or style"""
576 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
576 ui.writenoi18n(b'color mode: %s\n' % stringutil.pprint(ui._colormode))
577 if opts.get('style'):
577 if opts.get('style'):
578 return _debugdisplaystyle(ui)
578 return _debugdisplaystyle(ui)
579 else:
579 else:
580 return _debugdisplaycolor(ui)
580 return _debugdisplaycolor(ui)
581
581
582
582
583 def _debugdisplaycolor(ui):
583 def _debugdisplaycolor(ui):
584 ui = ui.copy()
584 ui = ui.copy()
585 ui._styles.clear()
585 ui._styles.clear()
586 for effect in color._activeeffects(ui).keys():
586 for effect in color._activeeffects(ui).keys():
587 ui._styles[effect] = effect
587 ui._styles[effect] = effect
588 if ui._terminfoparams:
588 if ui._terminfoparams:
589 for k, v in ui.configitems(b'color'):
589 for k, v in ui.configitems(b'color'):
590 if k.startswith(b'color.'):
590 if k.startswith(b'color.'):
591 ui._styles[k] = k[6:]
591 ui._styles[k] = k[6:]
592 elif k.startswith(b'terminfo.'):
592 elif k.startswith(b'terminfo.'):
593 ui._styles[k] = k[9:]
593 ui._styles[k] = k[9:]
594 ui.write(_(b'available colors:\n'))
594 ui.write(_(b'available colors:\n'))
595 # sort label with a '_' after the other to group '_background' entry.
595 # sort label with a '_' after the other to group '_background' entry.
596 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
596 items = sorted(ui._styles.items(), key=lambda i: (b'_' in i[0], i[0], i[1]))
597 for colorname, label in items:
597 for colorname, label in items:
598 ui.write(b'%s\n' % colorname, label=label)
598 ui.write(b'%s\n' % colorname, label=label)
599
599
600
600
601 def _debugdisplaystyle(ui):
601 def _debugdisplaystyle(ui):
602 ui.write(_(b'available style:\n'))
602 ui.write(_(b'available style:\n'))
603 if not ui._styles:
603 if not ui._styles:
604 return
604 return
605 width = max(len(s) for s in ui._styles)
605 width = max(len(s) for s in ui._styles)
606 for label, effects in sorted(ui._styles.items()):
606 for label, effects in sorted(ui._styles.items()):
607 ui.write(b'%s' % label, label=label)
607 ui.write(b'%s' % label, label=label)
608 if effects:
608 if effects:
609 # 50
609 # 50
610 ui.write(b': ')
610 ui.write(b': ')
611 ui.write(b' ' * (max(0, width - len(label))))
611 ui.write(b' ' * (max(0, width - len(label))))
612 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
612 ui.write(b', '.join(ui.label(e, e) for e in effects.split()))
613 ui.write(b'\n')
613 ui.write(b'\n')
614
614
615
615
616 @command(b'debugcreatestreamclonebundle', [], b'FILE')
616 @command(b'debugcreatestreamclonebundle', [], b'FILE')
617 def debugcreatestreamclonebundle(ui, repo, fname):
617 def debugcreatestreamclonebundle(ui, repo, fname):
618 """create a stream clone bundle file
618 """create a stream clone bundle file
619
619
620 Stream bundles are special bundles that are essentially archives of
620 Stream bundles are special bundles that are essentially archives of
621 revlog files. They are commonly used for cloning very quickly.
621 revlog files. They are commonly used for cloning very quickly.
622 """
622 """
623 # TODO we may want to turn this into an abort when this functionality
623 # TODO we may want to turn this into an abort when this functionality
624 # is moved into `hg bundle`.
624 # is moved into `hg bundle`.
625 if phases.hassecret(repo):
625 if phases.hassecret(repo):
626 ui.warn(
626 ui.warn(
627 _(
627 _(
628 b'(warning: stream clone bundle will contain secret '
628 b'(warning: stream clone bundle will contain secret '
629 b'revisions)\n'
629 b'revisions)\n'
630 )
630 )
631 )
631 )
632
632
633 requirements, gen = streamclone.generatebundlev1(repo)
633 requirements, gen = streamclone.generatebundlev1(repo)
634 changegroup.writechunks(ui, gen, fname)
634 changegroup.writechunks(ui, gen, fname)
635
635
636 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
636 ui.write(_(b'bundle requirements: %s\n') % b', '.join(sorted(requirements)))
637
637
638
638
639 @command(
639 @command(
640 b'debugdag',
640 b'debugdag',
641 [
641 [
642 (b't', b'tags', None, _(b'use tags as labels')),
642 (b't', b'tags', None, _(b'use tags as labels')),
643 (b'b', b'branches', None, _(b'annotate with branch names')),
643 (b'b', b'branches', None, _(b'annotate with branch names')),
644 (b'', b'dots', None, _(b'use dots for runs')),
644 (b'', b'dots', None, _(b'use dots for runs')),
645 (b's', b'spaces', None, _(b'separate elements by spaces')),
645 (b's', b'spaces', None, _(b'separate elements by spaces')),
646 ],
646 ],
647 _(b'[OPTION]... [FILE [REV]...]'),
647 _(b'[OPTION]... [FILE [REV]...]'),
648 optionalrepo=True,
648 optionalrepo=True,
649 )
649 )
650 def debugdag(ui, repo, file_=None, *revs, **opts):
650 def debugdag(ui, repo, file_=None, *revs, **opts):
651 """format the changelog or an index DAG as a concise textual description
651 """format the changelog or an index DAG as a concise textual description
652
652
653 If you pass a revlog index, the revlog's DAG is emitted. If you list
653 If you pass a revlog index, the revlog's DAG is emitted. If you list
654 revision numbers, they get labeled in the output as rN.
654 revision numbers, they get labeled in the output as rN.
655
655
656 Otherwise, the changelog DAG of the current repo is emitted.
656 Otherwise, the changelog DAG of the current repo is emitted.
657 """
657 """
658 spaces = opts.get('spaces')
658 spaces = opts.get('spaces')
659 dots = opts.get('dots')
659 dots = opts.get('dots')
660 if file_:
660 if file_:
661 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
661 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), file_)
662 revs = {int(r) for r in revs}
662 revs = {int(r) for r in revs}
663
663
664 def events():
664 def events():
665 for r in rlog:
665 for r in rlog:
666 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
666 yield b'n', (r, list(p for p in rlog.parentrevs(r) if p != -1))
667 if r in revs:
667 if r in revs:
668 yield b'l', (r, b"r%i" % r)
668 yield b'l', (r, b"r%i" % r)
669
669
670 elif repo:
670 elif repo:
671 cl = repo.changelog
671 cl = repo.changelog
672 tags = opts.get('tags')
672 tags = opts.get('tags')
673 branches = opts.get('branches')
673 branches = opts.get('branches')
674 if tags:
674 if tags:
675 labels = {}
675 labels = {}
676 for l, n in repo.tags().items():
676 for l, n in repo.tags().items():
677 labels.setdefault(cl.rev(n), []).append(l)
677 labels.setdefault(cl.rev(n), []).append(l)
678
678
679 def events():
679 def events():
680 b = b"default"
680 b = b"default"
681 for r in cl:
681 for r in cl:
682 if branches:
682 if branches:
683 newb = cl.read(cl.node(r))[5][b'branch']
683 newb = cl.read(cl.node(r))[5][b'branch']
684 if newb != b:
684 if newb != b:
685 yield b'a', newb
685 yield b'a', newb
686 b = newb
686 b = newb
687 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
687 yield b'n', (r, list(p for p in cl.parentrevs(r) if p != -1))
688 if tags:
688 if tags:
689 ls = labels.get(r)
689 ls = labels.get(r)
690 if ls:
690 if ls:
691 for l in ls:
691 for l in ls:
692 yield b'l', (r, l)
692 yield b'l', (r, l)
693
693
694 else:
694 else:
695 raise error.Abort(_(b'need repo for changelog dag'))
695 raise error.Abort(_(b'need repo for changelog dag'))
696
696
697 for line in dagparser.dagtextlines(
697 for line in dagparser.dagtextlines(
698 events(),
698 events(),
699 addspaces=spaces,
699 addspaces=spaces,
700 wraplabels=True,
700 wraplabels=True,
701 wrapannotations=True,
701 wrapannotations=True,
702 wrapnonlinear=dots,
702 wrapnonlinear=dots,
703 usedots=dots,
703 usedots=dots,
704 maxlinewidth=70,
704 maxlinewidth=70,
705 ):
705 ):
706 ui.write(line)
706 ui.write(line)
707 ui.write(b"\n")
707 ui.write(b"\n")
708
708
709
709
710 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
710 @command(b'debugdata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
711 def debugdata(ui, repo, file_, rev=None, **opts):
711 def debugdata(ui, repo, file_, rev=None, **opts):
712 """dump the contents of a data file revision"""
712 """dump the contents of a data file revision"""
713 opts = pycompat.byteskwargs(opts)
713 opts = pycompat.byteskwargs(opts)
714 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
714 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
715 if rev is not None:
715 if rev is not None:
716 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
716 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
717 file_, rev = None, file_
717 file_, rev = None, file_
718 elif rev is None:
718 elif rev is None:
719 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
719 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
720 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
720 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
721 try:
721 try:
722 ui.write(r.rawdata(r.lookup(rev)))
722 ui.write(r.rawdata(r.lookup(rev)))
723 except KeyError:
723 except KeyError:
724 raise error.Abort(_(b'invalid revision identifier %s') % rev)
724 raise error.Abort(_(b'invalid revision identifier %s') % rev)
725
725
726
726
727 @command(
727 @command(
728 b'debugdate',
728 b'debugdate',
729 [(b'e', b'extended', None, _(b'try extended date formats'))],
729 [(b'e', b'extended', None, _(b'try extended date formats'))],
730 _(b'[-e] DATE [RANGE]'),
730 _(b'[-e] DATE [RANGE]'),
731 norepo=True,
731 norepo=True,
732 optionalrepo=True,
732 optionalrepo=True,
733 )
733 )
734 def debugdate(ui, date, range=None, **opts):
734 def debugdate(ui, date, range=None, **opts):
735 """parse and display a date"""
735 """parse and display a date"""
736 if opts["extended"]:
736 if opts["extended"]:
737 d = dateutil.parsedate(date, dateutil.extendeddateformats)
737 d = dateutil.parsedate(date, dateutil.extendeddateformats)
738 else:
738 else:
739 d = dateutil.parsedate(date)
739 d = dateutil.parsedate(date)
740 ui.writenoi18n(b"internal: %d %d\n" % d)
740 ui.writenoi18n(b"internal: %d %d\n" % d)
741 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
741 ui.writenoi18n(b"standard: %s\n" % dateutil.datestr(d))
742 if range:
742 if range:
743 m = dateutil.matchdate(range)
743 m = dateutil.matchdate(range)
744 ui.writenoi18n(b"match: %s\n" % m(d[0]))
744 ui.writenoi18n(b"match: %s\n" % m(d[0]))
745
745
746
746
747 @command(
747 @command(
748 b'debugdeltachain',
748 b'debugdeltachain',
749 cmdutil.debugrevlogopts + cmdutil.formatteropts,
749 cmdutil.debugrevlogopts + cmdutil.formatteropts,
750 _(b'-c|-m|FILE'),
750 _(b'-c|-m|FILE'),
751 optionalrepo=True,
751 optionalrepo=True,
752 )
752 )
753 def debugdeltachain(ui, repo, file_=None, **opts):
753 def debugdeltachain(ui, repo, file_=None, **opts):
754 """dump information about delta chains in a revlog
754 """dump information about delta chains in a revlog
755
755
756 Output can be templatized. Available template keywords are:
756 Output can be templatized. Available template keywords are:
757
757
758 :``rev``: revision number
758 :``rev``: revision number
759 :``p1``: parent 1 revision number (for reference)
759 :``p1``: parent 1 revision number (for reference)
760 :``p2``: parent 2 revision number (for reference)
760 :``p2``: parent 2 revision number (for reference)
761 :``chainid``: delta chain identifier (numbered by unique base)
761 :``chainid``: delta chain identifier (numbered by unique base)
762 :``chainlen``: delta chain length to this revision
762 :``chainlen``: delta chain length to this revision
763 :``prevrev``: previous revision in delta chain
763 :``prevrev``: previous revision in delta chain
764 :``deltatype``: role of delta / how it was computed
764 :``deltatype``: role of delta / how it was computed
765 - base: a full snapshot
765 - base: a full snapshot
766 - snap: an intermediate snapshot
766 - snap: an intermediate snapshot
767 - p1: a delta against the first parent
767 - p1: a delta against the first parent
768 - p2: a delta against the second parent
768 - p2: a delta against the second parent
769 - skip1: a delta against the same base as p1
769 - skip1: a delta against the same base as p1
770 (when p1 has empty delta
770 (when p1 has empty delta
771 - skip2: a delta against the same base as p2
771 - skip2: a delta against the same base as p2
772 (when p2 has empty delta
772 (when p2 has empty delta
773 - prev: a delta against the previous revision
773 - prev: a delta against the previous revision
774 - other: a delta against an arbitrary revision
774 - other: a delta against an arbitrary revision
775 :``compsize``: compressed size of revision
775 :``compsize``: compressed size of revision
776 :``uncompsize``: uncompressed size of revision
776 :``uncompsize``: uncompressed size of revision
777 :``chainsize``: total size of compressed revisions in chain
777 :``chainsize``: total size of compressed revisions in chain
778 :``chainratio``: total chain size divided by uncompressed revision size
778 :``chainratio``: total chain size divided by uncompressed revision size
779 (new delta chains typically start at ratio 2.00)
779 (new delta chains typically start at ratio 2.00)
780 :``lindist``: linear distance from base revision in delta chain to end
780 :``lindist``: linear distance from base revision in delta chain to end
781 of this revision
781 of this revision
782 :``extradist``: total size of revisions not part of this delta chain from
782 :``extradist``: total size of revisions not part of this delta chain from
783 base of delta chain to end of this revision; a measurement
783 base of delta chain to end of this revision; a measurement
784 of how much extra data we need to read/seek across to read
784 of how much extra data we need to read/seek across to read
785 the delta chain for this revision
785 the delta chain for this revision
786 :``extraratio``: extradist divided by chainsize; another representation of
786 :``extraratio``: extradist divided by chainsize; another representation of
787 how much unrelated data is needed to load this delta chain
787 how much unrelated data is needed to load this delta chain
788
788
789 If the repository is configured to use the sparse read, additional keywords
789 If the repository is configured to use the sparse read, additional keywords
790 are available:
790 are available:
791
791
792 :``readsize``: total size of data read from the disk for a revision
792 :``readsize``: total size of data read from the disk for a revision
793 (sum of the sizes of all the blocks)
793 (sum of the sizes of all the blocks)
794 :``largestblock``: size of the largest block of data read from the disk
794 :``largestblock``: size of the largest block of data read from the disk
795 :``readdensity``: density of useful bytes in the data read from the disk
795 :``readdensity``: density of useful bytes in the data read from the disk
796 :``srchunks``: in how many data hunks the whole revision would be read
796 :``srchunks``: in how many data hunks the whole revision would be read
797
797
798 The sparse read can be enabled with experimental.sparse-read = True
798 The sparse read can be enabled with experimental.sparse-read = True
799 """
799 """
800 opts = pycompat.byteskwargs(opts)
800 opts = pycompat.byteskwargs(opts)
801 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
801 r = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
802 index = r.index
802 index = r.index
803 start = r.start
803 start = r.start
804 length = r.length
804 length = r.length
805 generaldelta = r._generaldelta
805 generaldelta = r._generaldelta
806 withsparseread = getattr(r, '_withsparseread', False)
806 withsparseread = getattr(r, '_withsparseread', False)
807
807
808 # security to avoid crash on corrupted revlogs
808 # security to avoid crash on corrupted revlogs
809 total_revs = len(index)
809 total_revs = len(index)
810
810
811 def revinfo(rev):
811 def revinfo(rev):
812 e = index[rev]
812 e = index[rev]
813 compsize = e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
813 compsize = e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
814 uncompsize = e[revlog_constants.ENTRY_DATA_UNCOMPRESSED_LENGTH]
814 uncompsize = e[revlog_constants.ENTRY_DATA_UNCOMPRESSED_LENGTH]
815 chainsize = 0
815 chainsize = 0
816
816
817 base = e[revlog_constants.ENTRY_DELTA_BASE]
817 base = e[revlog_constants.ENTRY_DELTA_BASE]
818 p1 = e[revlog_constants.ENTRY_PARENT_1]
818 p1 = e[revlog_constants.ENTRY_PARENT_1]
819 p2 = e[revlog_constants.ENTRY_PARENT_2]
819 p2 = e[revlog_constants.ENTRY_PARENT_2]
820
820
821 # If the parents of a revision has an empty delta, we never try to delta
821 # If the parents of a revision has an empty delta, we never try to delta
822 # against that parent, but directly against the delta base of that
822 # against that parent, but directly against the delta base of that
823 # parent (recursively). It avoids adding a useless entry in the chain.
823 # parent (recursively). It avoids adding a useless entry in the chain.
824 #
824 #
825 # However we need to detect that as a special case for delta-type, that
825 # However we need to detect that as a special case for delta-type, that
826 # is not simply "other".
826 # is not simply "other".
827 p1_base = p1
827 p1_base = p1
828 if p1 != nullrev and p1 < total_revs:
828 if p1 != nullrev and p1 < total_revs:
829 e1 = index[p1]
829 e1 = index[p1]
830 while e1[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
830 while e1[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
831 new_base = e1[revlog_constants.ENTRY_DELTA_BASE]
831 new_base = e1[revlog_constants.ENTRY_DELTA_BASE]
832 if (
832 if (
833 new_base == p1_base
833 new_base == p1_base
834 or new_base == nullrev
834 or new_base == nullrev
835 or new_base >= total_revs
835 or new_base >= total_revs
836 ):
836 ):
837 break
837 break
838 p1_base = new_base
838 p1_base = new_base
839 e1 = index[p1_base]
839 e1 = index[p1_base]
840 p2_base = p2
840 p2_base = p2
841 if p2 != nullrev and p2 < total_revs:
841 if p2 != nullrev and p2 < total_revs:
842 e2 = index[p2]
842 e2 = index[p2]
843 while e2[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
843 while e2[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH] == 0:
844 new_base = e2[revlog_constants.ENTRY_DELTA_BASE]
844 new_base = e2[revlog_constants.ENTRY_DELTA_BASE]
845 if (
845 if (
846 new_base == p2_base
846 new_base == p2_base
847 or new_base == nullrev
847 or new_base == nullrev
848 or new_base >= total_revs
848 or new_base >= total_revs
849 ):
849 ):
850 break
850 break
851 p2_base = new_base
851 p2_base = new_base
852 e2 = index[p2_base]
852 e2 = index[p2_base]
853
853
854 if generaldelta:
854 if generaldelta:
855 if base == p1:
855 if base == p1:
856 deltatype = b'p1'
856 deltatype = b'p1'
857 elif base == p2:
857 elif base == p2:
858 deltatype = b'p2'
858 deltatype = b'p2'
859 elif base == rev:
859 elif base == rev:
860 deltatype = b'base'
860 deltatype = b'base'
861 elif base == p1_base:
861 elif base == p1_base:
862 deltatype = b'skip1'
862 deltatype = b'skip1'
863 elif base == p2_base:
863 elif base == p2_base:
864 deltatype = b'skip2'
864 deltatype = b'skip2'
865 elif r.issnapshot(rev):
865 elif r.issnapshot(rev):
866 deltatype = b'snap'
866 deltatype = b'snap'
867 elif base == rev - 1:
867 elif base == rev - 1:
868 deltatype = b'prev'
868 deltatype = b'prev'
869 else:
869 else:
870 deltatype = b'other'
870 deltatype = b'other'
871 else:
871 else:
872 if base == rev:
872 if base == rev:
873 deltatype = b'base'
873 deltatype = b'base'
874 else:
874 else:
875 deltatype = b'prev'
875 deltatype = b'prev'
876
876
877 chain = r._deltachain(rev)[0]
877 chain = r._deltachain(rev)[0]
878 for iterrev in chain:
878 for iterrev in chain:
879 e = index[iterrev]
879 e = index[iterrev]
880 chainsize += e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
880 chainsize += e[revlog_constants.ENTRY_DATA_COMPRESSED_LENGTH]
881
881
882 return p1, p2, compsize, uncompsize, deltatype, chain, chainsize
882 return p1, p2, compsize, uncompsize, deltatype, chain, chainsize
883
883
884 fm = ui.formatter(b'debugdeltachain', opts)
884 fm = ui.formatter(b'debugdeltachain', opts)
885
885
886 fm.plain(
886 fm.plain(
887 b' rev p1 p2 chain# chainlen prev delta '
887 b' rev p1 p2 chain# chainlen prev delta '
888 b'size rawsize chainsize ratio lindist extradist '
888 b'size rawsize chainsize ratio lindist extradist '
889 b'extraratio'
889 b'extraratio'
890 )
890 )
891 if withsparseread:
891 if withsparseread:
892 fm.plain(b' readsize largestblk rddensity srchunks')
892 fm.plain(b' readsize largestblk rddensity srchunks')
893 fm.plain(b'\n')
893 fm.plain(b'\n')
894
894
895 chainbases = {}
895 chainbases = {}
896 for rev in r:
896 for rev in r:
897 p1, p2, comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
897 p1, p2, comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
898 chainbase = chain[0]
898 chainbase = chain[0]
899 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
899 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
900 basestart = start(chainbase)
900 basestart = start(chainbase)
901 revstart = start(rev)
901 revstart = start(rev)
902 lineardist = revstart + comp - basestart
902 lineardist = revstart + comp - basestart
903 extradist = lineardist - chainsize
903 extradist = lineardist - chainsize
904 try:
904 try:
905 prevrev = chain[-2]
905 prevrev = chain[-2]
906 except IndexError:
906 except IndexError:
907 prevrev = -1
907 prevrev = -1
908
908
909 if uncomp != 0:
909 if uncomp != 0:
910 chainratio = float(chainsize) / float(uncomp)
910 chainratio = float(chainsize) / float(uncomp)
911 else:
911 else:
912 chainratio = chainsize
912 chainratio = chainsize
913
913
914 if chainsize != 0:
914 if chainsize != 0:
915 extraratio = float(extradist) / float(chainsize)
915 extraratio = float(extradist) / float(chainsize)
916 else:
916 else:
917 extraratio = extradist
917 extraratio = extradist
918
918
919 fm.startitem()
919 fm.startitem()
920 fm.write(
920 fm.write(
921 b'rev p1 p2 chainid chainlen prevrev deltatype compsize '
921 b'rev p1 p2 chainid chainlen prevrev deltatype compsize '
922 b'uncompsize chainsize chainratio lindist extradist '
922 b'uncompsize chainsize chainratio lindist extradist '
923 b'extraratio',
923 b'extraratio',
924 b'%7d %7d %7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
924 b'%7d %7d %7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
925 rev,
925 rev,
926 p1,
926 p1,
927 p2,
927 p2,
928 chainid,
928 chainid,
929 len(chain),
929 len(chain),
930 prevrev,
930 prevrev,
931 deltatype,
931 deltatype,
932 comp,
932 comp,
933 uncomp,
933 uncomp,
934 chainsize,
934 chainsize,
935 chainratio,
935 chainratio,
936 lineardist,
936 lineardist,
937 extradist,
937 extradist,
938 extraratio,
938 extraratio,
939 rev=rev,
939 rev=rev,
940 chainid=chainid,
940 chainid=chainid,
941 chainlen=len(chain),
941 chainlen=len(chain),
942 prevrev=prevrev,
942 prevrev=prevrev,
943 deltatype=deltatype,
943 deltatype=deltatype,
944 compsize=comp,
944 compsize=comp,
945 uncompsize=uncomp,
945 uncompsize=uncomp,
946 chainsize=chainsize,
946 chainsize=chainsize,
947 chainratio=chainratio,
947 chainratio=chainratio,
948 lindist=lineardist,
948 lindist=lineardist,
949 extradist=extradist,
949 extradist=extradist,
950 extraratio=extraratio,
950 extraratio=extraratio,
951 )
951 )
952 if withsparseread:
952 if withsparseread:
953 readsize = 0
953 readsize = 0
954 largestblock = 0
954 largestblock = 0
955 srchunks = 0
955 srchunks = 0
956
956
957 for revschunk in deltautil.slicechunk(r, chain):
957 for revschunk in deltautil.slicechunk(r, chain):
958 srchunks += 1
958 srchunks += 1
959 blkend = start(revschunk[-1]) + length(revschunk[-1])
959 blkend = start(revschunk[-1]) + length(revschunk[-1])
960 blksize = blkend - start(revschunk[0])
960 blksize = blkend - start(revschunk[0])
961
961
962 readsize += blksize
962 readsize += blksize
963 if largestblock < blksize:
963 if largestblock < blksize:
964 largestblock = blksize
964 largestblock = blksize
965
965
966 if readsize:
966 if readsize:
967 readdensity = float(chainsize) / float(readsize)
967 readdensity = float(chainsize) / float(readsize)
968 else:
968 else:
969 readdensity = 1
969 readdensity = 1
970
970
971 fm.write(
971 fm.write(
972 b'readsize largestblock readdensity srchunks',
972 b'readsize largestblock readdensity srchunks',
973 b' %10d %10d %9.5f %8d',
973 b' %10d %10d %9.5f %8d',
974 readsize,
974 readsize,
975 largestblock,
975 largestblock,
976 readdensity,
976 readdensity,
977 srchunks,
977 srchunks,
978 readsize=readsize,
978 readsize=readsize,
979 largestblock=largestblock,
979 largestblock=largestblock,
980 readdensity=readdensity,
980 readdensity=readdensity,
981 srchunks=srchunks,
981 srchunks=srchunks,
982 )
982 )
983
983
984 fm.plain(b'\n')
984 fm.plain(b'\n')
985
985
986 fm.end()
986 fm.end()
987
987
988
988
989 @command(
989 @command(
990 b'debug-delta-find',
990 b'debug-delta-find',
991 cmdutil.debugrevlogopts
991 cmdutil.debugrevlogopts
992 + cmdutil.formatteropts
992 + cmdutil.formatteropts
993 + [
993 + [
994 (
994 (
995 b'',
995 b'',
996 b'source',
996 b'source',
997 b'full',
997 b'full',
998 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
998 _(b'input data feed to the process (full, storage, p1, p2, prev)'),
999 ),
999 ),
1000 ],
1000 ],
1001 _(b'-c|-m|FILE REV'),
1001 _(b'-c|-m|FILE REV'),
1002 optionalrepo=True,
1002 optionalrepo=True,
1003 )
1003 )
1004 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
1004 def debugdeltafind(ui, repo, arg_1, arg_2=None, source=b'full', **opts):
1005 """display the computation to get to a valid delta for storing REV
1005 """display the computation to get to a valid delta for storing REV
1006
1006
1007 This command will replay the process used to find the "best" delta to store
1007 This command will replay the process used to find the "best" delta to store
1008 a revision and display information about all the steps used to get to that
1008 a revision and display information about all the steps used to get to that
1009 result.
1009 result.
1010
1010
1011 By default, the process is fed with a the full-text for the revision. This
1011 By default, the process is fed with a the full-text for the revision. This
1012 can be controlled with the --source flag.
1012 can be controlled with the --source flag.
1013
1013
1014 The revision use the revision number of the target storage (not changelog
1014 The revision use the revision number of the target storage (not changelog
1015 revision number).
1015 revision number).
1016
1016
1017 note: the process is initiated from a full text of the revision to store.
1017 note: the process is initiated from a full text of the revision to store.
1018 """
1018 """
1019 opts = pycompat.byteskwargs(opts)
1019 opts = pycompat.byteskwargs(opts)
1020 if arg_2 is None:
1020 if arg_2 is None:
1021 file_ = None
1021 file_ = None
1022 rev = arg_1
1022 rev = arg_1
1023 else:
1023 else:
1024 file_ = arg_1
1024 file_ = arg_1
1025 rev = arg_2
1025 rev = arg_2
1026
1026
1027 rev = int(rev)
1027 rev = int(rev)
1028
1028
1029 revlog = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
1029 revlog = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
1030 p1r, p2r = revlog.parentrevs(rev)
1030 p1r, p2r = revlog.parentrevs(rev)
1031
1031
1032 if source == b'full':
1032 if source == b'full':
1033 base_rev = nullrev
1033 base_rev = nullrev
1034 elif source == b'storage':
1034 elif source == b'storage':
1035 base_rev = revlog.deltaparent(rev)
1035 base_rev = revlog.deltaparent(rev)
1036 elif source == b'p1':
1036 elif source == b'p1':
1037 base_rev = p1r
1037 base_rev = p1r
1038 elif source == b'p2':
1038 elif source == b'p2':
1039 base_rev = p2r
1039 base_rev = p2r
1040 elif source == b'prev':
1040 elif source == b'prev':
1041 base_rev = rev - 1
1041 base_rev = rev - 1
1042 else:
1042 else:
1043 raise error.InputError(b"invalid --source value: %s" % source)
1043 raise error.InputError(b"invalid --source value: %s" % source)
1044
1044
1045 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
1045 revlog_debug.debug_delta_find(ui, revlog, rev, base_rev=base_rev)
1046
1046
1047
1047
1048 @command(
1048 @command(
1049 b'debugdirstate|debugstate',
1049 b'debugdirstate|debugstate',
1050 [
1050 [
1051 (
1051 (
1052 b'',
1052 b'',
1053 b'nodates',
1053 b'nodates',
1054 None,
1054 None,
1055 _(b'do not display the saved mtime (DEPRECATED)'),
1055 _(b'do not display the saved mtime (DEPRECATED)'),
1056 ),
1056 ),
1057 (b'', b'dates', True, _(b'display the saved mtime')),
1057 (b'', b'dates', True, _(b'display the saved mtime')),
1058 (b'', b'datesort', None, _(b'sort by saved mtime')),
1058 (b'', b'datesort', None, _(b'sort by saved mtime')),
1059 (
1059 (
1060 b'',
1060 b'',
1061 b'docket',
1061 b'docket',
1062 False,
1062 False,
1063 _(b'display the docket (metadata file) instead'),
1063 _(b'display the docket (metadata file) instead'),
1064 ),
1064 ),
1065 (
1065 (
1066 b'',
1066 b'',
1067 b'all',
1067 b'all',
1068 False,
1068 False,
1069 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
1069 _(b'display dirstate-v2 tree nodes that would not exist in v1'),
1070 ),
1070 ),
1071 ],
1071 ],
1072 _(b'[OPTION]...'),
1072 _(b'[OPTION]...'),
1073 )
1073 )
1074 def debugstate(ui, repo, **opts):
1074 def debugstate(ui, repo, **opts):
1075 """show the contents of the current dirstate"""
1075 """show the contents of the current dirstate"""
1076
1076
1077 if opts.get("docket"):
1077 if opts.get("docket"):
1078 if not repo.dirstate._use_dirstate_v2:
1078 if not repo.dirstate._use_dirstate_v2:
1079 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1079 raise error.Abort(_(b'dirstate v1 does not have a docket'))
1080
1080
1081 docket = repo.dirstate._map.docket
1081 docket = repo.dirstate._map.docket
1082 (
1082 (
1083 start_offset,
1083 start_offset,
1084 root_nodes,
1084 root_nodes,
1085 nodes_with_entry,
1085 nodes_with_entry,
1086 nodes_with_copy,
1086 nodes_with_copy,
1087 unused_bytes,
1087 unused_bytes,
1088 _unused,
1088 _unused,
1089 ignore_pattern,
1089 ignore_pattern,
1090 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1090 ) = dirstateutils.v2.TREE_METADATA.unpack(docket.tree_metadata)
1091
1091
1092 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1092 ui.write(_(b"size of dirstate data: %d\n") % docket.data_size)
1093 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1093 ui.write(_(b"data file uuid: %s\n") % docket.uuid)
1094 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1094 ui.write(_(b"start offset of root nodes: %d\n") % start_offset)
1095 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1095 ui.write(_(b"number of root nodes: %d\n") % root_nodes)
1096 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1096 ui.write(_(b"nodes with entries: %d\n") % nodes_with_entry)
1097 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1097 ui.write(_(b"nodes with copies: %d\n") % nodes_with_copy)
1098 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1098 ui.write(_(b"number of unused bytes: %d\n") % unused_bytes)
1099 ui.write(
1099 ui.write(
1100 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1100 _(b"ignore pattern hash: %s\n") % binascii.hexlify(ignore_pattern)
1101 )
1101 )
1102 return
1102 return
1103
1103
1104 nodates = not opts['dates']
1104 nodates = not opts['dates']
1105 if opts.get('nodates') is not None:
1105 if opts.get('nodates') is not None:
1106 nodates = True
1106 nodates = True
1107 datesort = opts.get('datesort')
1107 datesort = opts.get('datesort')
1108
1108
1109 if datesort:
1109 if datesort:
1110
1110
1111 def keyfunc(entry):
1111 def keyfunc(entry):
1112 filename, _state, _mode, _size, mtime = entry
1112 filename, _state, _mode, _size, mtime = entry
1113 return (mtime, filename)
1113 return (mtime, filename)
1114
1114
1115 else:
1115 else:
1116 keyfunc = None # sort by filename
1116 keyfunc = None # sort by filename
1117 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1117 entries = list(repo.dirstate._map.debug_iter(all=opts['all']))
1118 entries.sort(key=keyfunc)
1118 entries.sort(key=keyfunc)
1119 for entry in entries:
1119 for entry in entries:
1120 filename, state, mode, size, mtime = entry
1120 filename, state, mode, size, mtime = entry
1121 if mtime == -1:
1121 if mtime == -1:
1122 timestr = b'unset '
1122 timestr = b'unset '
1123 elif nodates:
1123 elif nodates:
1124 timestr = b'set '
1124 timestr = b'set '
1125 else:
1125 else:
1126 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1126 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(mtime))
1127 timestr = encoding.strtolocal(timestr)
1127 timestr = encoding.strtolocal(timestr)
1128 if mode & 0o20000:
1128 if mode & 0o20000:
1129 mode = b'lnk'
1129 mode = b'lnk'
1130 else:
1130 else:
1131 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1131 mode = b'%3o' % (mode & 0o777 & ~util.umask)
1132 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1132 ui.write(b"%c %s %10d %s%s\n" % (state, mode, size, timestr, filename))
1133 for f in repo.dirstate.copies():
1133 for f in repo.dirstate.copies():
1134 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1134 ui.write(_(b"copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1135
1135
1136
1136
1137 @command(
1137 @command(
1138 b'debugdirstateignorepatternshash',
1138 b'debugdirstateignorepatternshash',
1139 [],
1139 [],
1140 _(b''),
1140 _(b''),
1141 )
1141 )
1142 def debugdirstateignorepatternshash(ui, repo, **opts):
1142 def debugdirstateignorepatternshash(ui, repo, **opts):
1143 """show the hash of ignore patterns stored in dirstate if v2,
1143 """show the hash of ignore patterns stored in dirstate if v2,
1144 or nothing for dirstate-v2
1144 or nothing for dirstate-v2
1145 """
1145 """
1146 if repo.dirstate._use_dirstate_v2:
1146 if repo.dirstate._use_dirstate_v2:
1147 docket = repo.dirstate._map.docket
1147 docket = repo.dirstate._map.docket
1148 hash_len = 20 # 160 bits for SHA-1
1148 hash_len = 20 # 160 bits for SHA-1
1149 hash_bytes = docket.tree_metadata[-hash_len:]
1149 hash_bytes = docket.tree_metadata[-hash_len:]
1150 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1150 ui.write(binascii.hexlify(hash_bytes) + b'\n')
1151
1151
1152
1152
1153 @command(
1153 @command(
1154 b'debugdiscovery',
1154 b'debugdiscovery',
1155 [
1155 [
1156 (b'', b'old', None, _(b'use old-style discovery')),
1156 (b'', b'old', None, _(b'use old-style discovery')),
1157 (
1157 (
1158 b'',
1158 b'',
1159 b'nonheads',
1159 b'nonheads',
1160 None,
1160 None,
1161 _(b'use old-style discovery with non-heads included'),
1161 _(b'use old-style discovery with non-heads included'),
1162 ),
1162 ),
1163 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1163 (b'', b'rev', [], b'restrict discovery to this set of revs'),
1164 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1164 (b'', b'seed', b'12323', b'specify the random seed use for discovery'),
1165 (
1165 (
1166 b'',
1166 b'',
1167 b'local-as-revs',
1167 b'local-as-revs',
1168 b"",
1168 b"",
1169 b'treat local has having these revisions only',
1169 b'treat local has having these revisions only',
1170 ),
1170 ),
1171 (
1171 (
1172 b'',
1172 b'',
1173 b'remote-as-revs',
1173 b'remote-as-revs',
1174 b"",
1174 b"",
1175 b'use local as remote, with only these revisions',
1175 b'use local as remote, with only these revisions',
1176 ),
1176 ),
1177 ]
1177 ]
1178 + cmdutil.remoteopts
1178 + cmdutil.remoteopts
1179 + cmdutil.formatteropts,
1179 + cmdutil.formatteropts,
1180 _(b'[--rev REV] [OTHER]'),
1180 _(b'[--rev REV] [OTHER]'),
1181 )
1181 )
1182 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1182 def debugdiscovery(ui, repo, remoteurl=b"default", **opts):
1183 """runs the changeset discovery protocol in isolation
1183 """runs the changeset discovery protocol in isolation
1184
1184
1185 The local peer can be "replaced" by a subset of the local repository by
1185 The local peer can be "replaced" by a subset of the local repository by
1186 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1186 using the `--local-as-revs` flag. In the same way, the usual `remote` peer
1187 can be "replaced" by a subset of the local repository using the
1187 can be "replaced" by a subset of the local repository using the
1188 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1188 `--remote-as-revs` flag. This is useful to efficiently debug pathological
1189 discovery situations.
1189 discovery situations.
1190
1190
1191 The following developer oriented config are relevant for people playing with this command:
1191 The following developer oriented config are relevant for people playing with this command:
1192
1192
1193 * devel.discovery.exchange-heads=True
1193 * devel.discovery.exchange-heads=True
1194
1194
1195 If False, the discovery will not start with
1195 If False, the discovery will not start with
1196 remote head fetching and local head querying.
1196 remote head fetching and local head querying.
1197
1197
1198 * devel.discovery.grow-sample=True
1198 * devel.discovery.grow-sample=True
1199
1199
1200 If False, the sample size used in set discovery will not be increased
1200 If False, the sample size used in set discovery will not be increased
1201 through the process
1201 through the process
1202
1202
1203 * devel.discovery.grow-sample.dynamic=True
1203 * devel.discovery.grow-sample.dynamic=True
1204
1204
1205 When discovery.grow-sample.dynamic is True, the default, the sample size is
1205 When discovery.grow-sample.dynamic is True, the default, the sample size is
1206 adapted to the shape of the undecided set (it is set to the max of:
1206 adapted to the shape of the undecided set (it is set to the max of:
1207 <target-size>, len(roots(undecided)), len(heads(undecided)
1207 <target-size>, len(roots(undecided)), len(heads(undecided)
1208
1208
1209 * devel.discovery.grow-sample.rate=1.05
1209 * devel.discovery.grow-sample.rate=1.05
1210
1210
1211 the rate at which the sample grow
1211 the rate at which the sample grow
1212
1212
1213 * devel.discovery.randomize=True
1213 * devel.discovery.randomize=True
1214
1214
1215 If andom sampling during discovery are deterministic. It is meant for
1215 If andom sampling during discovery are deterministic. It is meant for
1216 integration tests.
1216 integration tests.
1217
1217
1218 * devel.discovery.sample-size=200
1218 * devel.discovery.sample-size=200
1219
1219
1220 Control the initial size of the discovery sample
1220 Control the initial size of the discovery sample
1221
1221
1222 * devel.discovery.sample-size.initial=100
1222 * devel.discovery.sample-size.initial=100
1223
1223
1224 Control the initial size of the discovery for initial change
1224 Control the initial size of the discovery for initial change
1225 """
1225 """
1226 opts = pycompat.byteskwargs(opts)
1226 opts = pycompat.byteskwargs(opts)
1227 unfi = repo.unfiltered()
1227 unfi = repo.unfiltered()
1228
1228
1229 # setup potential extra filtering
1229 # setup potential extra filtering
1230 local_revs = opts[b"local_as_revs"]
1230 local_revs = opts[b"local_as_revs"]
1231 remote_revs = opts[b"remote_as_revs"]
1231 remote_revs = opts[b"remote_as_revs"]
1232
1232
1233 # make sure tests are repeatable
1233 # make sure tests are repeatable
1234 random.seed(int(opts[b'seed']))
1234 random.seed(int(opts[b'seed']))
1235
1235
1236 if not remote_revs:
1236 if not remote_revs:
1237 path = urlutil.get_unique_pull_path_obj(
1237 path = urlutil.get_unique_pull_path_obj(
1238 b'debugdiscovery', ui, remoteurl
1238 b'debugdiscovery', ui, remoteurl
1239 )
1239 )
1240 branches = (path.branch, [])
1240 branches = (path.branch, [])
1241 remote = hg.peer(repo, opts, path)
1241 remote = hg.peer(repo, opts, path)
1242 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1242 ui.status(_(b'comparing with %s\n') % urlutil.hidepassword(path.loc))
1243 else:
1243 else:
1244 branches = (None, [])
1244 branches = (None, [])
1245 remote_filtered_revs = logcmdutil.revrange(
1245 remote_filtered_revs = logcmdutil.revrange(
1246 unfi, [b"not (::(%s))" % remote_revs]
1246 unfi, [b"not (::(%s))" % remote_revs]
1247 )
1247 )
1248 remote_filtered_revs = frozenset(remote_filtered_revs)
1248 remote_filtered_revs = frozenset(remote_filtered_revs)
1249
1249
1250 def remote_func(x):
1250 def remote_func(x):
1251 return remote_filtered_revs
1251 return remote_filtered_revs
1252
1252
1253 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1253 repoview.filtertable[b'debug-discovery-remote-filter'] = remote_func
1254
1254
1255 remote = repo.peer()
1255 remote = repo.peer()
1256 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1256 remote._repo = remote._repo.filtered(b'debug-discovery-remote-filter')
1257
1257
1258 if local_revs:
1258 if local_revs:
1259 local_filtered_revs = logcmdutil.revrange(
1259 local_filtered_revs = logcmdutil.revrange(
1260 unfi, [b"not (::(%s))" % local_revs]
1260 unfi, [b"not (::(%s))" % local_revs]
1261 )
1261 )
1262 local_filtered_revs = frozenset(local_filtered_revs)
1262 local_filtered_revs = frozenset(local_filtered_revs)
1263
1263
1264 def local_func(x):
1264 def local_func(x):
1265 return local_filtered_revs
1265 return local_filtered_revs
1266
1266
1267 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1267 repoview.filtertable[b'debug-discovery-local-filter'] = local_func
1268 repo = repo.filtered(b'debug-discovery-local-filter')
1268 repo = repo.filtered(b'debug-discovery-local-filter')
1269
1269
1270 data = {}
1270 data = {}
1271 if opts.get(b'old'):
1271 if opts.get(b'old'):
1272
1272
1273 def doit(pushedrevs, remoteheads, remote=remote):
1273 def doit(pushedrevs, remoteheads, remote=remote):
1274 if not util.safehasattr(remote, b'branches'):
1274 if not util.safehasattr(remote, b'branches'):
1275 # enable in-client legacy support
1275 # enable in-client legacy support
1276 remote = localrepo.locallegacypeer(remote.local())
1276 remote = localrepo.locallegacypeer(remote.local())
1277 if remote_revs:
1277 if remote_revs:
1278 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1278 r = remote._repo.filtered(b'debug-discovery-remote-filter')
1279 remote._repo = r
1279 remote._repo = r
1280 common, _in, hds = treediscovery.findcommonincoming(
1280 common, _in, hds = treediscovery.findcommonincoming(
1281 repo, remote, force=True, audit=data
1281 repo, remote, force=True, audit=data
1282 )
1282 )
1283 common = set(common)
1283 common = set(common)
1284 if not opts.get(b'nonheads'):
1284 if not opts.get(b'nonheads'):
1285 ui.writenoi18n(
1285 ui.writenoi18n(
1286 b"unpruned common: %s\n"
1286 b"unpruned common: %s\n"
1287 % b" ".join(sorted(short(n) for n in common))
1287 % b" ".join(sorted(short(n) for n in common))
1288 )
1288 )
1289
1289
1290 clnode = repo.changelog.node
1290 clnode = repo.changelog.node
1291 common = repo.revs(b'heads(::%ln)', common)
1291 common = repo.revs(b'heads(::%ln)', common)
1292 common = {clnode(r) for r in common}
1292 common = {clnode(r) for r in common}
1293 return common, hds
1293 return common, hds
1294
1294
1295 else:
1295 else:
1296
1296
1297 def doit(pushedrevs, remoteheads, remote=remote):
1297 def doit(pushedrevs, remoteheads, remote=remote):
1298 nodes = None
1298 nodes = None
1299 if pushedrevs:
1299 if pushedrevs:
1300 revs = logcmdutil.revrange(repo, pushedrevs)
1300 revs = logcmdutil.revrange(repo, pushedrevs)
1301 nodes = [repo[r].node() for r in revs]
1301 nodes = [repo[r].node() for r in revs]
1302 common, any, hds = setdiscovery.findcommonheads(
1302 common, any, hds = setdiscovery.findcommonheads(
1303 ui,
1303 ui,
1304 repo,
1304 repo,
1305 remote,
1305 remote,
1306 ancestorsof=nodes,
1306 ancestorsof=nodes,
1307 audit=data,
1307 audit=data,
1308 abortwhenunrelated=False,
1308 abortwhenunrelated=False,
1309 )
1309 )
1310 return common, hds
1310 return common, hds
1311
1311
1312 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1312 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
1313 localrevs = opts[b'rev']
1313 localrevs = opts[b'rev']
1314
1314
1315 fm = ui.formatter(b'debugdiscovery', opts)
1315 fm = ui.formatter(b'debugdiscovery', opts)
1316 if fm.strict_format:
1316 if fm.strict_format:
1317
1317
1318 @contextlib.contextmanager
1318 @contextlib.contextmanager
1319 def may_capture_output():
1319 def may_capture_output():
1320 ui.pushbuffer()
1320 ui.pushbuffer()
1321 yield
1321 yield
1322 data[b'output'] = ui.popbuffer()
1322 data[b'output'] = ui.popbuffer()
1323
1323
1324 else:
1324 else:
1325 may_capture_output = util.nullcontextmanager
1325 may_capture_output = util.nullcontextmanager
1326 with may_capture_output():
1326 with may_capture_output():
1327 with util.timedcm('debug-discovery') as t:
1327 with util.timedcm('debug-discovery') as t:
1328 common, hds = doit(localrevs, remoterevs)
1328 common, hds = doit(localrevs, remoterevs)
1329
1329
1330 # compute all statistics
1330 # compute all statistics
1331 if len(common) == 1 and repo.nullid in common:
1331 if len(common) == 1 and repo.nullid in common:
1332 common = set()
1332 common = set()
1333 heads_common = set(common)
1333 heads_common = set(common)
1334 heads_remote = set(hds)
1334 heads_remote = set(hds)
1335 heads_local = set(repo.heads())
1335 heads_local = set(repo.heads())
1336 # note: they cannot be a local or remote head that is in common and not
1336 # note: they cannot be a local or remote head that is in common and not
1337 # itself a head of common.
1337 # itself a head of common.
1338 heads_common_local = heads_common & heads_local
1338 heads_common_local = heads_common & heads_local
1339 heads_common_remote = heads_common & heads_remote
1339 heads_common_remote = heads_common & heads_remote
1340 heads_common_both = heads_common & heads_remote & heads_local
1340 heads_common_both = heads_common & heads_remote & heads_local
1341
1341
1342 all = repo.revs(b'all()')
1342 all = repo.revs(b'all()')
1343 common = repo.revs(b'::%ln', common)
1343 common = repo.revs(b'::%ln', common)
1344 roots_common = repo.revs(b'roots(::%ld)', common)
1344 roots_common = repo.revs(b'roots(::%ld)', common)
1345 missing = repo.revs(b'not ::%ld', common)
1345 missing = repo.revs(b'not ::%ld', common)
1346 heads_missing = repo.revs(b'heads(%ld)', missing)
1346 heads_missing = repo.revs(b'heads(%ld)', missing)
1347 roots_missing = repo.revs(b'roots(%ld)', missing)
1347 roots_missing = repo.revs(b'roots(%ld)', missing)
1348 assert len(common) + len(missing) == len(all)
1348 assert len(common) + len(missing) == len(all)
1349
1349
1350 initial_undecided = repo.revs(
1350 initial_undecided = repo.revs(
1351 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1351 b'not (::%ln or %ln::)', heads_common_remote, heads_common_local
1352 )
1352 )
1353 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1353 heads_initial_undecided = repo.revs(b'heads(%ld)', initial_undecided)
1354 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1354 roots_initial_undecided = repo.revs(b'roots(%ld)', initial_undecided)
1355 common_initial_undecided = initial_undecided & common
1355 common_initial_undecided = initial_undecided & common
1356 missing_initial_undecided = initial_undecided & missing
1356 missing_initial_undecided = initial_undecided & missing
1357
1357
1358 data[b'elapsed'] = t.elapsed
1358 data[b'elapsed'] = t.elapsed
1359 data[b'nb-common-heads'] = len(heads_common)
1359 data[b'nb-common-heads'] = len(heads_common)
1360 data[b'nb-common-heads-local'] = len(heads_common_local)
1360 data[b'nb-common-heads-local'] = len(heads_common_local)
1361 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1361 data[b'nb-common-heads-remote'] = len(heads_common_remote)
1362 data[b'nb-common-heads-both'] = len(heads_common_both)
1362 data[b'nb-common-heads-both'] = len(heads_common_both)
1363 data[b'nb-common-roots'] = len(roots_common)
1363 data[b'nb-common-roots'] = len(roots_common)
1364 data[b'nb-head-local'] = len(heads_local)
1364 data[b'nb-head-local'] = len(heads_local)
1365 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1365 data[b'nb-head-local-missing'] = len(heads_local) - len(heads_common_local)
1366 data[b'nb-head-remote'] = len(heads_remote)
1366 data[b'nb-head-remote'] = len(heads_remote)
1367 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1367 data[b'nb-head-remote-unknown'] = len(heads_remote) - len(
1368 heads_common_remote
1368 heads_common_remote
1369 )
1369 )
1370 data[b'nb-revs'] = len(all)
1370 data[b'nb-revs'] = len(all)
1371 data[b'nb-revs-common'] = len(common)
1371 data[b'nb-revs-common'] = len(common)
1372 data[b'nb-revs-missing'] = len(missing)
1372 data[b'nb-revs-missing'] = len(missing)
1373 data[b'nb-missing-heads'] = len(heads_missing)
1373 data[b'nb-missing-heads'] = len(heads_missing)
1374 data[b'nb-missing-roots'] = len(roots_missing)
1374 data[b'nb-missing-roots'] = len(roots_missing)
1375 data[b'nb-ini_und'] = len(initial_undecided)
1375 data[b'nb-ini_und'] = len(initial_undecided)
1376 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1376 data[b'nb-ini_und-heads'] = len(heads_initial_undecided)
1377 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1377 data[b'nb-ini_und-roots'] = len(roots_initial_undecided)
1378 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1378 data[b'nb-ini_und-common'] = len(common_initial_undecided)
1379 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1379 data[b'nb-ini_und-missing'] = len(missing_initial_undecided)
1380
1380
1381 fm.startitem()
1381 fm.startitem()
1382 fm.data(**pycompat.strkwargs(data))
1382 fm.data(**pycompat.strkwargs(data))
1383 # display discovery summary
1383 # display discovery summary
1384 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1384 fm.plain(b"elapsed time: %(elapsed)f seconds\n" % data)
1385 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1385 fm.plain(b"round-trips: %(total-roundtrips)9d\n" % data)
1386 if b'total-round-trips-heads' in data:
1386 if b'total-round-trips-heads' in data:
1387 fm.plain(
1387 fm.plain(
1388 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1388 b" round-trips-heads: %(total-round-trips-heads)9d\n" % data
1389 )
1389 )
1390 if b'total-round-trips-branches' in data:
1390 if b'total-round-trips-branches' in data:
1391 fm.plain(
1391 fm.plain(
1392 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1392 b" round-trips-branches: %(total-round-trips-branches)9d\n"
1393 % data
1393 % data
1394 )
1394 )
1395 if b'total-round-trips-between' in data:
1395 if b'total-round-trips-between' in data:
1396 fm.plain(
1396 fm.plain(
1397 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1397 b" round-trips-between: %(total-round-trips-between)9d\n" % data
1398 )
1398 )
1399 fm.plain(b"queries: %(total-queries)9d\n" % data)
1399 fm.plain(b"queries: %(total-queries)9d\n" % data)
1400 if b'total-queries-branches' in data:
1400 if b'total-queries-branches' in data:
1401 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1401 fm.plain(b" queries-branches: %(total-queries-branches)9d\n" % data)
1402 if b'total-queries-between' in data:
1402 if b'total-queries-between' in data:
1403 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1403 fm.plain(b" queries-between: %(total-queries-between)9d\n" % data)
1404 fm.plain(b"heads summary:\n")
1404 fm.plain(b"heads summary:\n")
1405 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1405 fm.plain(b" total common heads: %(nb-common-heads)9d\n" % data)
1406 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1406 fm.plain(b" also local heads: %(nb-common-heads-local)9d\n" % data)
1407 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1407 fm.plain(b" also remote heads: %(nb-common-heads-remote)9d\n" % data)
1408 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1408 fm.plain(b" both: %(nb-common-heads-both)9d\n" % data)
1409 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1409 fm.plain(b" local heads: %(nb-head-local)9d\n" % data)
1410 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1410 fm.plain(b" common: %(nb-common-heads-local)9d\n" % data)
1411 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1411 fm.plain(b" missing: %(nb-head-local-missing)9d\n" % data)
1412 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1412 fm.plain(b" remote heads: %(nb-head-remote)9d\n" % data)
1413 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1413 fm.plain(b" common: %(nb-common-heads-remote)9d\n" % data)
1414 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1414 fm.plain(b" unknown: %(nb-head-remote-unknown)9d\n" % data)
1415 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1415 fm.plain(b"local changesets: %(nb-revs)9d\n" % data)
1416 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1416 fm.plain(b" common: %(nb-revs-common)9d\n" % data)
1417 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1417 fm.plain(b" heads: %(nb-common-heads)9d\n" % data)
1418 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1418 fm.plain(b" roots: %(nb-common-roots)9d\n" % data)
1419 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1419 fm.plain(b" missing: %(nb-revs-missing)9d\n" % data)
1420 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1420 fm.plain(b" heads: %(nb-missing-heads)9d\n" % data)
1421 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1421 fm.plain(b" roots: %(nb-missing-roots)9d\n" % data)
1422 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1422 fm.plain(b" first undecided set: %(nb-ini_und)9d\n" % data)
1423 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1423 fm.plain(b" heads: %(nb-ini_und-heads)9d\n" % data)
1424 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1424 fm.plain(b" roots: %(nb-ini_und-roots)9d\n" % data)
1425 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1425 fm.plain(b" common: %(nb-ini_und-common)9d\n" % data)
1426 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1426 fm.plain(b" missing: %(nb-ini_und-missing)9d\n" % data)
1427
1427
1428 if ui.verbose:
1428 if ui.verbose:
1429 fm.plain(
1429 fm.plain(
1430 b"common heads: %s\n"
1430 b"common heads: %s\n"
1431 % b" ".join(sorted(short(n) for n in heads_common))
1431 % b" ".join(sorted(short(n) for n in heads_common))
1432 )
1432 )
1433 fm.end()
1433 fm.end()
1434
1434
1435
1435
1436 _chunksize = 4 << 10
1436 _chunksize = 4 << 10
1437
1437
1438
1438
1439 @command(
1439 @command(
1440 b'debugdownload',
1440 b'debugdownload',
1441 [
1441 [
1442 (b'o', b'output', b'', _(b'path')),
1442 (b'o', b'output', b'', _(b'path')),
1443 ],
1443 ],
1444 optionalrepo=True,
1444 optionalrepo=True,
1445 )
1445 )
1446 def debugdownload(ui, repo, url, output=None, **opts):
1446 def debugdownload(ui, repo, url, output=None, **opts):
1447 """download a resource using Mercurial logic and config"""
1447 """download a resource using Mercurial logic and config"""
1448 fh = urlmod.open(ui, url, output)
1448 fh = urlmod.open(ui, url, output)
1449
1449
1450 dest = ui
1450 dest = ui
1451 if output:
1451 if output:
1452 dest = open(output, b"wb", _chunksize)
1452 dest = open(output, b"wb", _chunksize)
1453 try:
1453 try:
1454 data = fh.read(_chunksize)
1454 data = fh.read(_chunksize)
1455 while data:
1455 while data:
1456 dest.write(data)
1456 dest.write(data)
1457 data = fh.read(_chunksize)
1457 data = fh.read(_chunksize)
1458 finally:
1458 finally:
1459 if output:
1459 if output:
1460 dest.close()
1460 dest.close()
1461
1461
1462
1462
1463 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1463 @command(b'debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
1464 def debugextensions(ui, repo, **opts):
1464 def debugextensions(ui, repo, **opts):
1465 '''show information about active extensions'''
1465 '''show information about active extensions'''
1466 opts = pycompat.byteskwargs(opts)
1466 opts = pycompat.byteskwargs(opts)
1467 exts = extensions.extensions(ui)
1467 exts = extensions.extensions(ui)
1468 hgver = util.version()
1468 hgver = util.version()
1469 fm = ui.formatter(b'debugextensions', opts)
1469 fm = ui.formatter(b'debugextensions', opts)
1470 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1470 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
1471 isinternal = extensions.ismoduleinternal(extmod)
1471 isinternal = extensions.ismoduleinternal(extmod)
1472 extsource = None
1472 extsource = None
1473
1473
1474 if util.safehasattr(extmod, '__file__'):
1474 if util.safehasattr(extmod, '__file__'):
1475 extsource = pycompat.fsencode(extmod.__file__)
1475 extsource = pycompat.fsencode(extmod.__file__)
1476 elif getattr(sys, 'oxidized', False):
1476 elif getattr(sys, 'oxidized', False):
1477 extsource = pycompat.sysexecutable
1477 extsource = pycompat.sysexecutable
1478 if isinternal:
1478 if isinternal:
1479 exttestedwith = [] # never expose magic string to users
1479 exttestedwith = [] # never expose magic string to users
1480 else:
1480 else:
1481 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1481 exttestedwith = getattr(extmod, 'testedwith', b'').split()
1482 extbuglink = getattr(extmod, 'buglink', None)
1482 extbuglink = getattr(extmod, 'buglink', None)
1483
1483
1484 fm.startitem()
1484 fm.startitem()
1485
1485
1486 if ui.quiet or ui.verbose:
1486 if ui.quiet or ui.verbose:
1487 fm.write(b'name', b'%s\n', extname)
1487 fm.write(b'name', b'%s\n', extname)
1488 else:
1488 else:
1489 fm.write(b'name', b'%s', extname)
1489 fm.write(b'name', b'%s', extname)
1490 if isinternal or hgver in exttestedwith:
1490 if isinternal or hgver in exttestedwith:
1491 fm.plain(b'\n')
1491 fm.plain(b'\n')
1492 elif not exttestedwith:
1492 elif not exttestedwith:
1493 fm.plain(_(b' (untested!)\n'))
1493 fm.plain(_(b' (untested!)\n'))
1494 else:
1494 else:
1495 lasttestedversion = exttestedwith[-1]
1495 lasttestedversion = exttestedwith[-1]
1496 fm.plain(b' (%s!)\n' % lasttestedversion)
1496 fm.plain(b' (%s!)\n' % lasttestedversion)
1497
1497
1498 fm.condwrite(
1498 fm.condwrite(
1499 ui.verbose and extsource,
1499 ui.verbose and extsource,
1500 b'source',
1500 b'source',
1501 _(b' location: %s\n'),
1501 _(b' location: %s\n'),
1502 extsource or b"",
1502 extsource or b"",
1503 )
1503 )
1504
1504
1505 if ui.verbose:
1505 if ui.verbose:
1506 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1506 fm.plain(_(b' bundled: %s\n') % [b'no', b'yes'][isinternal])
1507 fm.data(bundled=isinternal)
1507 fm.data(bundled=isinternal)
1508
1508
1509 fm.condwrite(
1509 fm.condwrite(
1510 ui.verbose and exttestedwith,
1510 ui.verbose and exttestedwith,
1511 b'testedwith',
1511 b'testedwith',
1512 _(b' tested with: %s\n'),
1512 _(b' tested with: %s\n'),
1513 fm.formatlist(exttestedwith, name=b'ver'),
1513 fm.formatlist(exttestedwith, name=b'ver'),
1514 )
1514 )
1515
1515
1516 fm.condwrite(
1516 fm.condwrite(
1517 ui.verbose and extbuglink,
1517 ui.verbose and extbuglink,
1518 b'buglink',
1518 b'buglink',
1519 _(b' bug reporting: %s\n'),
1519 _(b' bug reporting: %s\n'),
1520 extbuglink or b"",
1520 extbuglink or b"",
1521 )
1521 )
1522
1522
1523 fm.end()
1523 fm.end()
1524
1524
1525
1525
1526 @command(
1526 @command(
1527 b'debugfileset',
1527 b'debugfileset',
1528 [
1528 [
1529 (
1529 (
1530 b'r',
1530 b'r',
1531 b'rev',
1531 b'rev',
1532 b'',
1532 b'',
1533 _(b'apply the filespec on this revision'),
1533 _(b'apply the filespec on this revision'),
1534 _(b'REV'),
1534 _(b'REV'),
1535 ),
1535 ),
1536 (
1536 (
1537 b'',
1537 b'',
1538 b'all-files',
1538 b'all-files',
1539 False,
1539 False,
1540 _(b'test files from all revisions and working directory'),
1540 _(b'test files from all revisions and working directory'),
1541 ),
1541 ),
1542 (
1542 (
1543 b's',
1543 b's',
1544 b'show-matcher',
1544 b'show-matcher',
1545 None,
1545 None,
1546 _(b'print internal representation of matcher'),
1546 _(b'print internal representation of matcher'),
1547 ),
1547 ),
1548 (
1548 (
1549 b'p',
1549 b'p',
1550 b'show-stage',
1550 b'show-stage',
1551 [],
1551 [],
1552 _(b'print parsed tree at the given stage'),
1552 _(b'print parsed tree at the given stage'),
1553 _(b'NAME'),
1553 _(b'NAME'),
1554 ),
1554 ),
1555 ],
1555 ],
1556 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1556 _(b'[-r REV] [--all-files] [OPTION]... FILESPEC'),
1557 )
1557 )
1558 def debugfileset(ui, repo, expr, **opts):
1558 def debugfileset(ui, repo, expr, **opts):
1559 '''parse and apply a fileset specification'''
1559 '''parse and apply a fileset specification'''
1560 from . import fileset
1560 from . import fileset
1561
1561
1562 fileset.symbols # force import of fileset so we have predicates to optimize
1562 fileset.symbols # force import of fileset so we have predicates to optimize
1563 opts = pycompat.byteskwargs(opts)
1563 opts = pycompat.byteskwargs(opts)
1564 ctx = logcmdutil.revsingle(repo, opts.get(b'rev'), None)
1564 ctx = logcmdutil.revsingle(repo, opts.get(b'rev'), None)
1565
1565
1566 stages = [
1566 stages = [
1567 (b'parsed', pycompat.identity),
1567 (b'parsed', pycompat.identity),
1568 (b'analyzed', filesetlang.analyze),
1568 (b'analyzed', filesetlang.analyze),
1569 (b'optimized', filesetlang.optimize),
1569 (b'optimized', filesetlang.optimize),
1570 ]
1570 ]
1571 stagenames = {n for n, f in stages}
1571 stagenames = {n for n, f in stages}
1572
1572
1573 showalways = set()
1573 showalways = set()
1574 if ui.verbose and not opts[b'show_stage']:
1574 if ui.verbose and not opts[b'show_stage']:
1575 # show parsed tree by --verbose (deprecated)
1575 # show parsed tree by --verbose (deprecated)
1576 showalways.add(b'parsed')
1576 showalways.add(b'parsed')
1577 if opts[b'show_stage'] == [b'all']:
1577 if opts[b'show_stage'] == [b'all']:
1578 showalways.update(stagenames)
1578 showalways.update(stagenames)
1579 else:
1579 else:
1580 for n in opts[b'show_stage']:
1580 for n in opts[b'show_stage']:
1581 if n not in stagenames:
1581 if n not in stagenames:
1582 raise error.Abort(_(b'invalid stage name: %s') % n)
1582 raise error.Abort(_(b'invalid stage name: %s') % n)
1583 showalways.update(opts[b'show_stage'])
1583 showalways.update(opts[b'show_stage'])
1584
1584
1585 tree = filesetlang.parse(expr)
1585 tree = filesetlang.parse(expr)
1586 for n, f in stages:
1586 for n, f in stages:
1587 tree = f(tree)
1587 tree = f(tree)
1588 if n in showalways:
1588 if n in showalways:
1589 if opts[b'show_stage'] or n != b'parsed':
1589 if opts[b'show_stage'] or n != b'parsed':
1590 ui.write(b"* %s:\n" % n)
1590 ui.write(b"* %s:\n" % n)
1591 ui.write(filesetlang.prettyformat(tree), b"\n")
1591 ui.write(filesetlang.prettyformat(tree), b"\n")
1592
1592
1593 files = set()
1593 files = set()
1594 if opts[b'all_files']:
1594 if opts[b'all_files']:
1595 for r in repo:
1595 for r in repo:
1596 c = repo[r]
1596 c = repo[r]
1597 files.update(c.files())
1597 files.update(c.files())
1598 files.update(c.substate)
1598 files.update(c.substate)
1599 if opts[b'all_files'] or ctx.rev() is None:
1599 if opts[b'all_files'] or ctx.rev() is None:
1600 wctx = repo[None]
1600 wctx = repo[None]
1601 files.update(
1601 files.update(
1602 repo.dirstate.walk(
1602 repo.dirstate.walk(
1603 scmutil.matchall(repo),
1603 scmutil.matchall(repo),
1604 subrepos=list(wctx.substate),
1604 subrepos=list(wctx.substate),
1605 unknown=True,
1605 unknown=True,
1606 ignored=True,
1606 ignored=True,
1607 )
1607 )
1608 )
1608 )
1609 files.update(wctx.substate)
1609 files.update(wctx.substate)
1610 else:
1610 else:
1611 files.update(ctx.files())
1611 files.update(ctx.files())
1612 files.update(ctx.substate)
1612 files.update(ctx.substate)
1613
1613
1614 m = ctx.matchfileset(repo.getcwd(), expr)
1614 m = ctx.matchfileset(repo.getcwd(), expr)
1615 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1615 if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
1616 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1616 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
1617 for f in sorted(files):
1617 for f in sorted(files):
1618 if not m(f):
1618 if not m(f):
1619 continue
1619 continue
1620 ui.write(b"%s\n" % f)
1620 ui.write(b"%s\n" % f)
1621
1621
1622
1622
1623 @command(
1623 @command(
1624 b"debug-repair-issue6528",
1624 b"debug-repair-issue6528",
1625 [
1625 [
1626 (
1626 (
1627 b'',
1627 b'',
1628 b'to-report',
1628 b'to-report',
1629 b'',
1629 b'',
1630 _(b'build a report of affected revisions to this file'),
1630 _(b'build a report of affected revisions to this file'),
1631 _(b'FILE'),
1631 _(b'FILE'),
1632 ),
1632 ),
1633 (
1633 (
1634 b'',
1634 b'',
1635 b'from-report',
1635 b'from-report',
1636 b'',
1636 b'',
1637 _(b'repair revisions listed in this report file'),
1637 _(b'repair revisions listed in this report file'),
1638 _(b'FILE'),
1638 _(b'FILE'),
1639 ),
1639 ),
1640 (
1640 (
1641 b'',
1641 b'',
1642 b'paranoid',
1642 b'paranoid',
1643 False,
1643 False,
1644 _(b'check that both detection methods do the same thing'),
1644 _(b'check that both detection methods do the same thing'),
1645 ),
1645 ),
1646 ]
1646 ]
1647 + cmdutil.dryrunopts,
1647 + cmdutil.dryrunopts,
1648 )
1648 )
1649 def debug_repair_issue6528(ui, repo, **opts):
1649 def debug_repair_issue6528(ui, repo, **opts):
1650 """find affected revisions and repair them. See issue6528 for more details.
1650 """find affected revisions and repair them. See issue6528 for more details.
1651
1651
1652 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1652 The `--to-report` and `--from-report` flags allow you to cache and reuse the
1653 computation of affected revisions for a given repository across clones.
1653 computation of affected revisions for a given repository across clones.
1654 The report format is line-based (with empty lines ignored):
1654 The report format is line-based (with empty lines ignored):
1655
1655
1656 ```
1656 ```
1657 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1657 <ascii-hex of the affected revision>,... <unencoded filelog index filename>
1658 ```
1658 ```
1659
1659
1660 There can be multiple broken revisions per filelog, they are separated by
1660 There can be multiple broken revisions per filelog, they are separated by
1661 a comma with no spaces. The only space is between the revision(s) and the
1661 a comma with no spaces. The only space is between the revision(s) and the
1662 filename.
1662 filename.
1663
1663
1664 Note that this does *not* mean that this repairs future affected revisions,
1664 Note that this does *not* mean that this repairs future affected revisions,
1665 that needs a separate fix at the exchange level that was introduced in
1665 that needs a separate fix at the exchange level that was introduced in
1666 Mercurial 5.9.1.
1666 Mercurial 5.9.1.
1667
1667
1668 There is a `--paranoid` flag to test that the fast implementation is correct
1668 There is a `--paranoid` flag to test that the fast implementation is correct
1669 by checking it against the slow implementation. Since this matter is quite
1669 by checking it against the slow implementation. Since this matter is quite
1670 urgent and testing every edge-case is probably quite costly, we use this
1670 urgent and testing every edge-case is probably quite costly, we use this
1671 method to test on large repositories as a fuzzing method of sorts.
1671 method to test on large repositories as a fuzzing method of sorts.
1672 """
1672 """
1673 cmdutil.check_incompatible_arguments(
1673 cmdutil.check_incompatible_arguments(
1674 opts, 'to_report', ['from_report', 'dry_run']
1674 opts, 'to_report', ['from_report', 'dry_run']
1675 )
1675 )
1676 dry_run = opts.get('dry_run')
1676 dry_run = opts.get('dry_run')
1677 to_report = opts.get('to_report')
1677 to_report = opts.get('to_report')
1678 from_report = opts.get('from_report')
1678 from_report = opts.get('from_report')
1679 paranoid = opts.get('paranoid')
1679 paranoid = opts.get('paranoid')
1680 # TODO maybe add filelog pattern and revision pattern parameters to help
1680 # TODO maybe add filelog pattern and revision pattern parameters to help
1681 # narrow down the search for users that know what they're looking for?
1681 # narrow down the search for users that know what they're looking for?
1682
1682
1683 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1683 if requirements.REVLOGV1_REQUIREMENT not in repo.requirements:
1684 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1684 msg = b"can only repair revlogv1 repositories, v2 is not affected"
1685 raise error.Abort(_(msg))
1685 raise error.Abort(_(msg))
1686
1686
1687 rewrite.repair_issue6528(
1687 rewrite.repair_issue6528(
1688 ui,
1688 ui,
1689 repo,
1689 repo,
1690 dry_run=dry_run,
1690 dry_run=dry_run,
1691 to_report=to_report,
1691 to_report=to_report,
1692 from_report=from_report,
1692 from_report=from_report,
1693 paranoid=paranoid,
1693 paranoid=paranoid,
1694 )
1694 )
1695
1695
1696
1696
1697 @command(b'debugformat', [] + cmdutil.formatteropts)
1697 @command(b'debugformat', [] + cmdutil.formatteropts)
1698 def debugformat(ui, repo, **opts):
1698 def debugformat(ui, repo, **opts):
1699 """display format information about the current repository
1699 """display format information about the current repository
1700
1700
1701 Use --verbose to get extra information about current config value and
1701 Use --verbose to get extra information about current config value and
1702 Mercurial default."""
1702 Mercurial default."""
1703 opts = pycompat.byteskwargs(opts)
1703 opts = pycompat.byteskwargs(opts)
1704 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1704 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
1705 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1705 maxvariantlength = max(len(b'format-variant'), maxvariantlength)
1706
1706
1707 def makeformatname(name):
1707 def makeformatname(name):
1708 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1708 return b'%s:' + (b' ' * (maxvariantlength - len(name)))
1709
1709
1710 fm = ui.formatter(b'debugformat', opts)
1710 fm = ui.formatter(b'debugformat', opts)
1711 if fm.isplain():
1711 if fm.isplain():
1712
1712
1713 def formatvalue(value):
1713 def formatvalue(value):
1714 if util.safehasattr(value, b'startswith'):
1714 if util.safehasattr(value, b'startswith'):
1715 return value
1715 return value
1716 if value:
1716 if value:
1717 return b'yes'
1717 return b'yes'
1718 else:
1718 else:
1719 return b'no'
1719 return b'no'
1720
1720
1721 else:
1721 else:
1722 formatvalue = pycompat.identity
1722 formatvalue = pycompat.identity
1723
1723
1724 fm.plain(b'format-variant')
1724 fm.plain(b'format-variant')
1725 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1725 fm.plain(b' ' * (maxvariantlength - len(b'format-variant')))
1726 fm.plain(b' repo')
1726 fm.plain(b' repo')
1727 if ui.verbose:
1727 if ui.verbose:
1728 fm.plain(b' config default')
1728 fm.plain(b' config default')
1729 fm.plain(b'\n')
1729 fm.plain(b'\n')
1730 for fv in upgrade.allformatvariant:
1730 for fv in upgrade.allformatvariant:
1731 fm.startitem()
1731 fm.startitem()
1732 repovalue = fv.fromrepo(repo)
1732 repovalue = fv.fromrepo(repo)
1733 configvalue = fv.fromconfig(repo)
1733 configvalue = fv.fromconfig(repo)
1734
1734
1735 if repovalue != configvalue:
1735 if repovalue != configvalue:
1736 namelabel = b'formatvariant.name.mismatchconfig'
1736 namelabel = b'formatvariant.name.mismatchconfig'
1737 repolabel = b'formatvariant.repo.mismatchconfig'
1737 repolabel = b'formatvariant.repo.mismatchconfig'
1738 elif repovalue != fv.default:
1738 elif repovalue != fv.default:
1739 namelabel = b'formatvariant.name.mismatchdefault'
1739 namelabel = b'formatvariant.name.mismatchdefault'
1740 repolabel = b'formatvariant.repo.mismatchdefault'
1740 repolabel = b'formatvariant.repo.mismatchdefault'
1741 else:
1741 else:
1742 namelabel = b'formatvariant.name.uptodate'
1742 namelabel = b'formatvariant.name.uptodate'
1743 repolabel = b'formatvariant.repo.uptodate'
1743 repolabel = b'formatvariant.repo.uptodate'
1744
1744
1745 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1745 fm.write(b'name', makeformatname(fv.name), fv.name, label=namelabel)
1746 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1746 fm.write(b'repo', b' %3s', formatvalue(repovalue), label=repolabel)
1747 if fv.default != configvalue:
1747 if fv.default != configvalue:
1748 configlabel = b'formatvariant.config.special'
1748 configlabel = b'formatvariant.config.special'
1749 else:
1749 else:
1750 configlabel = b'formatvariant.config.default'
1750 configlabel = b'formatvariant.config.default'
1751 fm.condwrite(
1751 fm.condwrite(
1752 ui.verbose,
1752 ui.verbose,
1753 b'config',
1753 b'config',
1754 b' %6s',
1754 b' %6s',
1755 formatvalue(configvalue),
1755 formatvalue(configvalue),
1756 label=configlabel,
1756 label=configlabel,
1757 )
1757 )
1758 fm.condwrite(
1758 fm.condwrite(
1759 ui.verbose,
1759 ui.verbose,
1760 b'default',
1760 b'default',
1761 b' %7s',
1761 b' %7s',
1762 formatvalue(fv.default),
1762 formatvalue(fv.default),
1763 label=b'formatvariant.default',
1763 label=b'formatvariant.default',
1764 )
1764 )
1765 fm.plain(b'\n')
1765 fm.plain(b'\n')
1766 fm.end()
1766 fm.end()
1767
1767
1768
1768
1769 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1769 @command(b'debugfsinfo', [], _(b'[PATH]'), norepo=True)
1770 def debugfsinfo(ui, path=b"."):
1770 def debugfsinfo(ui, path=b"."):
1771 """show information detected about current filesystem"""
1771 """show information detected about current filesystem"""
1772 ui.writenoi18n(b'path: %s\n' % path)
1772 ui.writenoi18n(b'path: %s\n' % path)
1773 ui.writenoi18n(
1773 ui.writenoi18n(
1774 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1774 b'mounted on: %s\n' % (util.getfsmountpoint(path) or b'(unknown)')
1775 )
1775 )
1776 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1776 ui.writenoi18n(b'exec: %s\n' % (util.checkexec(path) and b'yes' or b'no'))
1777 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1777 ui.writenoi18n(b'fstype: %s\n' % (util.getfstype(path) or b'(unknown)'))
1778 ui.writenoi18n(
1778 ui.writenoi18n(
1779 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1779 b'symlink: %s\n' % (util.checklink(path) and b'yes' or b'no')
1780 )
1780 )
1781 ui.writenoi18n(
1781 ui.writenoi18n(
1782 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1782 b'hardlink: %s\n' % (util.checknlink(path) and b'yes' or b'no')
1783 )
1783 )
1784 casesensitive = b'(unknown)'
1784 casesensitive = b'(unknown)'
1785 try:
1785 try:
1786 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1786 with pycompat.namedtempfile(prefix=b'.debugfsinfo', dir=path) as f:
1787 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1787 casesensitive = util.fscasesensitive(f.name) and b'yes' or b'no'
1788 except OSError:
1788 except OSError:
1789 pass
1789 pass
1790 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1790 ui.writenoi18n(b'case-sensitive: %s\n' % casesensitive)
1791
1791
1792
1792
1793 @command(
1793 @command(
1794 b'debuggetbundle',
1794 b'debuggetbundle',
1795 [
1795 [
1796 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1796 (b'H', b'head', [], _(b'id of head node'), _(b'ID')),
1797 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1797 (b'C', b'common', [], _(b'id of common node'), _(b'ID')),
1798 (
1798 (
1799 b't',
1799 b't',
1800 b'type',
1800 b'type',
1801 b'bzip2',
1801 b'bzip2',
1802 _(b'bundle compression type to use'),
1802 _(b'bundle compression type to use'),
1803 _(b'TYPE'),
1803 _(b'TYPE'),
1804 ),
1804 ),
1805 ],
1805 ],
1806 _(b'REPO FILE [-H|-C ID]...'),
1806 _(b'REPO FILE [-H|-C ID]...'),
1807 norepo=True,
1807 norepo=True,
1808 )
1808 )
1809 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1809 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1810 """retrieves a bundle from a repo
1810 """retrieves a bundle from a repo
1811
1811
1812 Every ID must be a full-length hex node id string. Saves the bundle to the
1812 Every ID must be a full-length hex node id string. Saves the bundle to the
1813 given file.
1813 given file.
1814 """
1814 """
1815 opts = pycompat.byteskwargs(opts)
1815 opts = pycompat.byteskwargs(opts)
1816 repo = hg.peer(ui, opts, repopath)
1816 repo = hg.peer(ui, opts, repopath)
1817 if not repo.capable(b'getbundle'):
1817 if not repo.capable(b'getbundle'):
1818 raise error.Abort(b"getbundle() not supported by target repository")
1818 raise error.Abort(b"getbundle() not supported by target repository")
1819 args = {}
1819 args = {}
1820 if common:
1820 if common:
1821 args['common'] = [bin(s) for s in common]
1821 args['common'] = [bin(s) for s in common]
1822 if head:
1822 if head:
1823 args['heads'] = [bin(s) for s in head]
1823 args['heads'] = [bin(s) for s in head]
1824 # TODO: get desired bundlecaps from command line.
1824 # TODO: get desired bundlecaps from command line.
1825 args['bundlecaps'] = None
1825 args['bundlecaps'] = None
1826 bundle = repo.getbundle(b'debug', **args)
1826 bundle = repo.getbundle(b'debug', **args)
1827
1827
1828 bundletype = opts.get(b'type', b'bzip2').lower()
1828 bundletype = opts.get(b'type', b'bzip2').lower()
1829 btypes = {
1829 btypes = {
1830 b'none': b'HG10UN',
1830 b'none': b'HG10UN',
1831 b'bzip2': b'HG10BZ',
1831 b'bzip2': b'HG10BZ',
1832 b'gzip': b'HG10GZ',
1832 b'gzip': b'HG10GZ',
1833 b'bundle2': b'HG20',
1833 b'bundle2': b'HG20',
1834 }
1834 }
1835 bundletype = btypes.get(bundletype)
1835 bundletype = btypes.get(bundletype)
1836 if bundletype not in bundle2.bundletypes:
1836 if bundletype not in bundle2.bundletypes:
1837 raise error.Abort(_(b'unknown bundle type specified with --type'))
1837 raise error.Abort(_(b'unknown bundle type specified with --type'))
1838 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1838 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1839
1839
1840
1840
1841 @command(b'debugignore', [], b'[FILE]')
1841 @command(b'debugignore', [], b'[FILE]')
1842 def debugignore(ui, repo, *files, **opts):
1842 def debugignore(ui, repo, *files, **opts):
1843 """display the combined ignore pattern and information about ignored files
1843 """display the combined ignore pattern and information about ignored files
1844
1844
1845 With no argument display the combined ignore pattern.
1845 With no argument display the combined ignore pattern.
1846
1846
1847 Given space separated file names, shows if the given file is ignored and
1847 Given space separated file names, shows if the given file is ignored and
1848 if so, show the ignore rule (file and line number) that matched it.
1848 if so, show the ignore rule (file and line number) that matched it.
1849 """
1849 """
1850 ignore = repo.dirstate._ignore
1850 ignore = repo.dirstate._ignore
1851 if not files:
1851 if not files:
1852 # Show all the patterns
1852 # Show all the patterns
1853 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1853 ui.write(b"%s\n" % pycompat.byterepr(ignore))
1854 else:
1854 else:
1855 m = scmutil.match(repo[None], pats=files)
1855 m = scmutil.match(repo[None], pats=files)
1856 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1856 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1857 for f in m.files():
1857 for f in m.files():
1858 nf = util.normpath(f)
1858 nf = util.normpath(f)
1859 ignored = None
1859 ignored = None
1860 ignoredata = None
1860 ignoredata = None
1861 if nf != b'.':
1861 if nf != b'.':
1862 if ignore(nf):
1862 if ignore(nf):
1863 ignored = nf
1863 ignored = nf
1864 ignoredata = repo.dirstate._ignorefileandline(nf)
1864 ignoredata = repo.dirstate._ignorefileandline(nf)
1865 else:
1865 else:
1866 for p in pathutil.finddirs(nf):
1866 for p in pathutil.finddirs(nf):
1867 if ignore(p):
1867 if ignore(p):
1868 ignored = p
1868 ignored = p
1869 ignoredata = repo.dirstate._ignorefileandline(p)
1869 ignoredata = repo.dirstate._ignorefileandline(p)
1870 break
1870 break
1871 if ignored:
1871 if ignored:
1872 if ignored == nf:
1872 if ignored == nf:
1873 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1873 ui.write(_(b"%s is ignored\n") % uipathfn(f))
1874 else:
1874 else:
1875 ui.write(
1875 ui.write(
1876 _(
1876 _(
1877 b"%s is ignored because of "
1877 b"%s is ignored because of "
1878 b"containing directory %s\n"
1878 b"containing directory %s\n"
1879 )
1879 )
1880 % (uipathfn(f), ignored)
1880 % (uipathfn(f), ignored)
1881 )
1881 )
1882 ignorefile, lineno, line = ignoredata
1882 ignorefile, lineno, line = ignoredata
1883 ui.write(
1883 ui.write(
1884 _(b"(ignore rule in %s, line %d: '%s')\n")
1884 _(b"(ignore rule in %s, line %d: '%s')\n")
1885 % (ignorefile, lineno, line)
1885 % (ignorefile, lineno, line)
1886 )
1886 )
1887 else:
1887 else:
1888 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1888 ui.write(_(b"%s is not ignored\n") % uipathfn(f))
1889
1889
1890
1890
1891 @command(
1891 @command(
1892 b'debug-revlog-index|debugindex',
1892 b'debug-revlog-index|debugindex',
1893 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1893 cmdutil.debugrevlogopts + cmdutil.formatteropts,
1894 _(b'-c|-m|FILE'),
1894 _(b'-c|-m|FILE'),
1895 )
1895 )
1896 def debugindex(ui, repo, file_=None, **opts):
1896 def debugindex(ui, repo, file_=None, **opts):
1897 """dump index data for a revlog"""
1897 """dump index data for a revlog"""
1898 opts = pycompat.byteskwargs(opts)
1898 opts = pycompat.byteskwargs(opts)
1899 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1899 store = cmdutil.openstorage(repo, b'debugindex', file_, opts)
1900
1900
1901 fm = ui.formatter(b'debugindex', opts)
1901 fm = ui.formatter(b'debugindex', opts)
1902
1902
1903 revlog = getattr(store, b'_revlog', store)
1903 revlog = getattr(store, b'_revlog', store)
1904
1904
1905 return revlog_debug.debug_index(
1905 return revlog_debug.debug_index(
1906 ui,
1906 ui,
1907 repo,
1907 repo,
1908 formatter=fm,
1908 formatter=fm,
1909 revlog=revlog,
1909 revlog=revlog,
1910 full_node=ui.debugflag,
1910 full_node=ui.debugflag,
1911 )
1911 )
1912
1912
1913
1913
1914 @command(
1914 @command(
1915 b'debugindexdot',
1915 b'debugindexdot',
1916 cmdutil.debugrevlogopts,
1916 cmdutil.debugrevlogopts,
1917 _(b'-c|-m|FILE'),
1917 _(b'-c|-m|FILE'),
1918 optionalrepo=True,
1918 optionalrepo=True,
1919 )
1919 )
1920 def debugindexdot(ui, repo, file_=None, **opts):
1920 def debugindexdot(ui, repo, file_=None, **opts):
1921 """dump an index DAG as a graphviz dot file"""
1921 """dump an index DAG as a graphviz dot file"""
1922 opts = pycompat.byteskwargs(opts)
1922 opts = pycompat.byteskwargs(opts)
1923 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1923 r = cmdutil.openstorage(repo, b'debugindexdot', file_, opts)
1924 ui.writenoi18n(b"digraph G {\n")
1924 ui.writenoi18n(b"digraph G {\n")
1925 for i in r:
1925 for i in r:
1926 node = r.node(i)
1926 node = r.node(i)
1927 pp = r.parents(node)
1927 pp = r.parents(node)
1928 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1928 ui.write(b"\t%d -> %d\n" % (r.rev(pp[0]), i))
1929 if pp[1] != repo.nullid:
1929 if pp[1] != repo.nullid:
1930 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1930 ui.write(b"\t%d -> %d\n" % (r.rev(pp[1]), i))
1931 ui.write(b"}\n")
1931 ui.write(b"}\n")
1932
1932
1933
1933
1934 @command(b'debugindexstats', [])
1934 @command(b'debugindexstats', [])
1935 def debugindexstats(ui, repo):
1935 def debugindexstats(ui, repo):
1936 """show stats related to the changelog index"""
1936 """show stats related to the changelog index"""
1937 repo.changelog.shortest(repo.nullid, 1)
1937 repo.changelog.shortest(repo.nullid, 1)
1938 index = repo.changelog.index
1938 index = repo.changelog.index
1939 if not util.safehasattr(index, b'stats'):
1939 if not util.safehasattr(index, b'stats'):
1940 raise error.Abort(_(b'debugindexstats only works with native code'))
1940 raise error.Abort(_(b'debugindexstats only works with native code'))
1941 for k, v in sorted(index.stats().items()):
1941 for k, v in sorted(index.stats().items()):
1942 ui.write(b'%s: %d\n' % (k, v))
1942 ui.write(b'%s: %d\n' % (k, v))
1943
1943
1944
1944
1945 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1945 @command(b'debuginstall', [] + cmdutil.formatteropts, b'', norepo=True)
1946 def debuginstall(ui, **opts):
1946 def debuginstall(ui, **opts):
1947 """test Mercurial installation
1947 """test Mercurial installation
1948
1948
1949 Returns 0 on success.
1949 Returns 0 on success.
1950 """
1950 """
1951 opts = pycompat.byteskwargs(opts)
1951 opts = pycompat.byteskwargs(opts)
1952
1952
1953 problems = 0
1953 problems = 0
1954
1954
1955 fm = ui.formatter(b'debuginstall', opts)
1955 fm = ui.formatter(b'debuginstall', opts)
1956 fm.startitem()
1956 fm.startitem()
1957
1957
1958 # encoding might be unknown or wrong. don't translate these messages.
1958 # encoding might be unknown or wrong. don't translate these messages.
1959 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1959 fm.write(b'encoding', b"checking encoding (%s)...\n", encoding.encoding)
1960 err = None
1960 err = None
1961 try:
1961 try:
1962 codecs.lookup(pycompat.sysstr(encoding.encoding))
1962 codecs.lookup(pycompat.sysstr(encoding.encoding))
1963 except LookupError as inst:
1963 except LookupError as inst:
1964 err = stringutil.forcebytestr(inst)
1964 err = stringutil.forcebytestr(inst)
1965 problems += 1
1965 problems += 1
1966 fm.condwrite(
1966 fm.condwrite(
1967 err,
1967 err,
1968 b'encodingerror',
1968 b'encodingerror',
1969 b" %s\n (check that your locale is properly set)\n",
1969 b" %s\n (check that your locale is properly set)\n",
1970 err,
1970 err,
1971 )
1971 )
1972
1972
1973 # Python
1973 # Python
1974 pythonlib = None
1974 pythonlib = None
1975 if util.safehasattr(os, '__file__'):
1975 if util.safehasattr(os, '__file__'):
1976 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1976 pythonlib = os.path.dirname(pycompat.fsencode(os.__file__))
1977 elif getattr(sys, 'oxidized', False):
1977 elif getattr(sys, 'oxidized', False):
1978 pythonlib = pycompat.sysexecutable
1978 pythonlib = pycompat.sysexecutable
1979
1979
1980 fm.write(
1980 fm.write(
1981 b'pythonexe',
1981 b'pythonexe',
1982 _(b"checking Python executable (%s)\n"),
1982 _(b"checking Python executable (%s)\n"),
1983 pycompat.sysexecutable or _(b"unknown"),
1983 pycompat.sysexecutable or _(b"unknown"),
1984 )
1984 )
1985 fm.write(
1985 fm.write(
1986 b'pythonimplementation',
1986 b'pythonimplementation',
1987 _(b"checking Python implementation (%s)\n"),
1987 _(b"checking Python implementation (%s)\n"),
1988 pycompat.sysbytes(platform.python_implementation()),
1988 pycompat.sysbytes(platform.python_implementation()),
1989 )
1989 )
1990 fm.write(
1990 fm.write(
1991 b'pythonver',
1991 b'pythonver',
1992 _(b"checking Python version (%s)\n"),
1992 _(b"checking Python version (%s)\n"),
1993 (b"%d.%d.%d" % sys.version_info[:3]),
1993 (b"%d.%d.%d" % sys.version_info[:3]),
1994 )
1994 )
1995 fm.write(
1995 fm.write(
1996 b'pythonlib',
1996 b'pythonlib',
1997 _(b"checking Python lib (%s)...\n"),
1997 _(b"checking Python lib (%s)...\n"),
1998 pythonlib or _(b"unknown"),
1998 pythonlib or _(b"unknown"),
1999 )
1999 )
2000
2000
2001 try:
2001 try:
2002 from . import rustext # pytype: disable=import-error
2002 from . import rustext # pytype: disable=import-error
2003
2003
2004 rustext.__doc__ # trigger lazy import
2004 rustext.__doc__ # trigger lazy import
2005 except ImportError:
2005 except ImportError:
2006 rustext = None
2006 rustext = None
2007
2007
2008 security = set(sslutil.supportedprotocols)
2008 security = set(sslutil.supportedprotocols)
2009 if sslutil.hassni:
2009 if sslutil.hassni:
2010 security.add(b'sni')
2010 security.add(b'sni')
2011
2011
2012 fm.write(
2012 fm.write(
2013 b'pythonsecurity',
2013 b'pythonsecurity',
2014 _(b"checking Python security support (%s)\n"),
2014 _(b"checking Python security support (%s)\n"),
2015 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
2015 fm.formatlist(sorted(security), name=b'protocol', fmt=b'%s', sep=b','),
2016 )
2016 )
2017
2017
2018 # These are warnings, not errors. So don't increment problem count. This
2018 # These are warnings, not errors. So don't increment problem count. This
2019 # may change in the future.
2019 # may change in the future.
2020 if b'tls1.2' not in security:
2020 if b'tls1.2' not in security:
2021 fm.plain(
2021 fm.plain(
2022 _(
2022 _(
2023 b' TLS 1.2 not supported by Python install; '
2023 b' TLS 1.2 not supported by Python install; '
2024 b'network connections lack modern security\n'
2024 b'network connections lack modern security\n'
2025 )
2025 )
2026 )
2026 )
2027 if b'sni' not in security:
2027 if b'sni' not in security:
2028 fm.plain(
2028 fm.plain(
2029 _(
2029 _(
2030 b' SNI not supported by Python install; may have '
2030 b' SNI not supported by Python install; may have '
2031 b'connectivity issues with some servers\n'
2031 b'connectivity issues with some servers\n'
2032 )
2032 )
2033 )
2033 )
2034
2034
2035 fm.plain(
2035 fm.plain(
2036 _(
2036 _(
2037 b"checking Rust extensions (%s)\n"
2037 b"checking Rust extensions (%s)\n"
2038 % (b'missing' if rustext is None else b'installed')
2038 % (b'missing' if rustext is None else b'installed')
2039 ),
2039 ),
2040 )
2040 )
2041
2041
2042 # TODO print CA cert info
2042 # TODO print CA cert info
2043
2043
2044 # hg version
2044 # hg version
2045 hgver = util.version()
2045 hgver = util.version()
2046 fm.write(
2046 fm.write(
2047 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
2047 b'hgver', _(b"checking Mercurial version (%s)\n"), hgver.split(b'+')[0]
2048 )
2048 )
2049 fm.write(
2049 fm.write(
2050 b'hgverextra',
2050 b'hgverextra',
2051 _(b"checking Mercurial custom build (%s)\n"),
2051 _(b"checking Mercurial custom build (%s)\n"),
2052 b'+'.join(hgver.split(b'+')[1:]),
2052 b'+'.join(hgver.split(b'+')[1:]),
2053 )
2053 )
2054
2054
2055 # compiled modules
2055 # compiled modules
2056 hgmodules = None
2056 hgmodules = None
2057 if util.safehasattr(sys.modules[__name__], '__file__'):
2057 if util.safehasattr(sys.modules[__name__], '__file__'):
2058 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
2058 hgmodules = os.path.dirname(pycompat.fsencode(__file__))
2059 elif getattr(sys, 'oxidized', False):
2059 elif getattr(sys, 'oxidized', False):
2060 hgmodules = pycompat.sysexecutable
2060 hgmodules = pycompat.sysexecutable
2061
2061
2062 fm.write(
2062 fm.write(
2063 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
2063 b'hgmodulepolicy', _(b"checking module policy (%s)\n"), policy.policy
2064 )
2064 )
2065 fm.write(
2065 fm.write(
2066 b'hgmodules',
2066 b'hgmodules',
2067 _(b"checking installed modules (%s)...\n"),
2067 _(b"checking installed modules (%s)...\n"),
2068 hgmodules or _(b"unknown"),
2068 hgmodules or _(b"unknown"),
2069 )
2069 )
2070
2070
2071 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
2071 rustandc = policy.policy in (b'rust+c', b'rust+c-allow')
2072 rustext = rustandc # for now, that's the only case
2072 rustext = rustandc # for now, that's the only case
2073 cext = policy.policy in (b'c', b'allow') or rustandc
2073 cext = policy.policy in (b'c', b'allow') or rustandc
2074 nopure = cext or rustext
2074 nopure = cext or rustext
2075 if nopure:
2075 if nopure:
2076 err = None
2076 err = None
2077 try:
2077 try:
2078 if cext:
2078 if cext:
2079 from .cext import ( # pytype: disable=import-error
2079 from .cext import ( # pytype: disable=import-error
2080 base85,
2080 base85,
2081 bdiff,
2081 bdiff,
2082 mpatch,
2082 mpatch,
2083 osutil,
2083 osutil,
2084 )
2084 )
2085
2085
2086 # quiet pyflakes
2086 # quiet pyflakes
2087 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2087 dir(bdiff), dir(mpatch), dir(base85), dir(osutil)
2088 if rustext:
2088 if rustext:
2089 from .rustext import ( # pytype: disable=import-error
2089 from .rustext import ( # pytype: disable=import-error
2090 ancestor,
2090 ancestor,
2091 dirstate,
2091 dirstate,
2092 )
2092 )
2093
2093
2094 dir(ancestor), dir(dirstate) # quiet pyflakes
2094 dir(ancestor), dir(dirstate) # quiet pyflakes
2095 except Exception as inst:
2095 except Exception as inst:
2096 err = stringutil.forcebytestr(inst)
2096 err = stringutil.forcebytestr(inst)
2097 problems += 1
2097 problems += 1
2098 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2098 fm.condwrite(err, b'extensionserror', b" %s\n", err)
2099
2099
2100 compengines = util.compengines._engines.values()
2100 compengines = util.compengines._engines.values()
2101 fm.write(
2101 fm.write(
2102 b'compengines',
2102 b'compengines',
2103 _(b'checking registered compression engines (%s)\n'),
2103 _(b'checking registered compression engines (%s)\n'),
2104 fm.formatlist(
2104 fm.formatlist(
2105 sorted(e.name() for e in compengines),
2105 sorted(e.name() for e in compengines),
2106 name=b'compengine',
2106 name=b'compengine',
2107 fmt=b'%s',
2107 fmt=b'%s',
2108 sep=b', ',
2108 sep=b', ',
2109 ),
2109 ),
2110 )
2110 )
2111 fm.write(
2111 fm.write(
2112 b'compenginesavail',
2112 b'compenginesavail',
2113 _(b'checking available compression engines (%s)\n'),
2113 _(b'checking available compression engines (%s)\n'),
2114 fm.formatlist(
2114 fm.formatlist(
2115 sorted(e.name() for e in compengines if e.available()),
2115 sorted(e.name() for e in compengines if e.available()),
2116 name=b'compengine',
2116 name=b'compengine',
2117 fmt=b'%s',
2117 fmt=b'%s',
2118 sep=b', ',
2118 sep=b', ',
2119 ),
2119 ),
2120 )
2120 )
2121 wirecompengines = compression.compengines.supportedwireengines(
2121 wirecompengines = compression.compengines.supportedwireengines(
2122 compression.SERVERROLE
2122 compression.SERVERROLE
2123 )
2123 )
2124 fm.write(
2124 fm.write(
2125 b'compenginesserver',
2125 b'compenginesserver',
2126 _(
2126 _(
2127 b'checking available compression engines '
2127 b'checking available compression engines '
2128 b'for wire protocol (%s)\n'
2128 b'for wire protocol (%s)\n'
2129 ),
2129 ),
2130 fm.formatlist(
2130 fm.formatlist(
2131 [e.name() for e in wirecompengines if e.wireprotosupport()],
2131 [e.name() for e in wirecompengines if e.wireprotosupport()],
2132 name=b'compengine',
2132 name=b'compengine',
2133 fmt=b'%s',
2133 fmt=b'%s',
2134 sep=b', ',
2134 sep=b', ',
2135 ),
2135 ),
2136 )
2136 )
2137 re2 = b'missing'
2137 re2 = b'missing'
2138 if util._re2:
2138 if util._re2:
2139 re2 = b'available'
2139 re2 = b'available'
2140 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2140 fm.plain(_(b'checking "re2" regexp engine (%s)\n') % re2)
2141 fm.data(re2=bool(util._re2))
2141 fm.data(re2=bool(util._re2))
2142
2142
2143 # templates
2143 # templates
2144 p = templater.templatedir()
2144 p = templater.templatedir()
2145 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2145 fm.write(b'templatedirs', b'checking templates (%s)...\n', p or b'')
2146 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2146 fm.condwrite(not p, b'', _(b" no template directories found\n"))
2147 if p:
2147 if p:
2148 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2148 (m, fp) = templater.try_open_template(b"map-cmdline.default")
2149 if m:
2149 if m:
2150 # template found, check if it is working
2150 # template found, check if it is working
2151 err = None
2151 err = None
2152 try:
2152 try:
2153 templater.templater.frommapfile(m)
2153 templater.templater.frommapfile(m)
2154 except Exception as inst:
2154 except Exception as inst:
2155 err = stringutil.forcebytestr(inst)
2155 err = stringutil.forcebytestr(inst)
2156 p = None
2156 p = None
2157 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2157 fm.condwrite(err, b'defaulttemplateerror', b" %s\n", err)
2158 else:
2158 else:
2159 p = None
2159 p = None
2160 fm.condwrite(
2160 fm.condwrite(
2161 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2161 p, b'defaulttemplate', _(b"checking default template (%s)\n"), m
2162 )
2162 )
2163 fm.condwrite(
2163 fm.condwrite(
2164 not m,
2164 not m,
2165 b'defaulttemplatenotfound',
2165 b'defaulttemplatenotfound',
2166 _(b" template '%s' not found\n"),
2166 _(b" template '%s' not found\n"),
2167 b"default",
2167 b"default",
2168 )
2168 )
2169 if not p:
2169 if not p:
2170 problems += 1
2170 problems += 1
2171 fm.condwrite(
2171 fm.condwrite(
2172 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2172 not p, b'', _(b" (templates seem to have been installed incorrectly)\n")
2173 )
2173 )
2174
2174
2175 # editor
2175 # editor
2176 editor = ui.geteditor()
2176 editor = ui.geteditor()
2177 editor = util.expandpath(editor)
2177 editor = util.expandpath(editor)
2178 editorbin = procutil.shellsplit(editor)[0]
2178 editorbin = procutil.shellsplit(editor)[0]
2179 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2179 fm.write(b'editor', _(b"checking commit editor... (%s)\n"), editorbin)
2180 cmdpath = procutil.findexe(editorbin)
2180 cmdpath = procutil.findexe(editorbin)
2181 fm.condwrite(
2181 fm.condwrite(
2182 not cmdpath and editor == b'vi',
2182 not cmdpath and editor == b'vi',
2183 b'vinotfound',
2183 b'vinotfound',
2184 _(
2184 _(
2185 b" No commit editor set and can't find %s in PATH\n"
2185 b" No commit editor set and can't find %s in PATH\n"
2186 b" (specify a commit editor in your configuration"
2186 b" (specify a commit editor in your configuration"
2187 b" file)\n"
2187 b" file)\n"
2188 ),
2188 ),
2189 not cmdpath and editor == b'vi' and editorbin,
2189 not cmdpath and editor == b'vi' and editorbin,
2190 )
2190 )
2191 fm.condwrite(
2191 fm.condwrite(
2192 not cmdpath and editor != b'vi',
2192 not cmdpath and editor != b'vi',
2193 b'editornotfound',
2193 b'editornotfound',
2194 _(
2194 _(
2195 b" Can't find editor '%s' in PATH\n"
2195 b" Can't find editor '%s' in PATH\n"
2196 b" (specify a commit editor in your configuration"
2196 b" (specify a commit editor in your configuration"
2197 b" file)\n"
2197 b" file)\n"
2198 ),
2198 ),
2199 not cmdpath and editorbin,
2199 not cmdpath and editorbin,
2200 )
2200 )
2201 if not cmdpath and editor != b'vi':
2201 if not cmdpath and editor != b'vi':
2202 problems += 1
2202 problems += 1
2203
2203
2204 # check username
2204 # check username
2205 username = None
2205 username = None
2206 err = None
2206 err = None
2207 try:
2207 try:
2208 username = ui.username()
2208 username = ui.username()
2209 except error.Abort as e:
2209 except error.Abort as e:
2210 err = e.message
2210 err = e.message
2211 problems += 1
2211 problems += 1
2212
2212
2213 fm.condwrite(
2213 fm.condwrite(
2214 username, b'username', _(b"checking username (%s)\n"), username
2214 username, b'username', _(b"checking username (%s)\n"), username
2215 )
2215 )
2216 fm.condwrite(
2216 fm.condwrite(
2217 err,
2217 err,
2218 b'usernameerror',
2218 b'usernameerror',
2219 _(
2219 _(
2220 b"checking username...\n %s\n"
2220 b"checking username...\n %s\n"
2221 b" (specify a username in your configuration file)\n"
2221 b" (specify a username in your configuration file)\n"
2222 ),
2222 ),
2223 err,
2223 err,
2224 )
2224 )
2225
2225
2226 for name, mod in extensions.extensions():
2226 for name, mod in extensions.extensions():
2227 handler = getattr(mod, 'debuginstall', None)
2227 handler = getattr(mod, 'debuginstall', None)
2228 if handler is not None:
2228 if handler is not None:
2229 problems += handler(ui, fm)
2229 problems += handler(ui, fm)
2230
2230
2231 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2231 fm.condwrite(not problems, b'', _(b"no problems detected\n"))
2232 if not problems:
2232 if not problems:
2233 fm.data(problems=problems)
2233 fm.data(problems=problems)
2234 fm.condwrite(
2234 fm.condwrite(
2235 problems,
2235 problems,
2236 b'problems',
2236 b'problems',
2237 _(b"%d problems detected, please check your install!\n"),
2237 _(b"%d problems detected, please check your install!\n"),
2238 problems,
2238 problems,
2239 )
2239 )
2240 fm.end()
2240 fm.end()
2241
2241
2242 return problems
2242 return problems
2243
2243
2244
2244
2245 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2245 @command(b'debugknown', [], _(b'REPO ID...'), norepo=True)
2246 def debugknown(ui, repopath, *ids, **opts):
2246 def debugknown(ui, repopath, *ids, **opts):
2247 """test whether node ids are known to a repo
2247 """test whether node ids are known to a repo
2248
2248
2249 Every ID must be a full-length hex node id string. Returns a list of 0s
2249 Every ID must be a full-length hex node id string. Returns a list of 0s
2250 and 1s indicating unknown/known.
2250 and 1s indicating unknown/known.
2251 """
2251 """
2252 opts = pycompat.byteskwargs(opts)
2252 opts = pycompat.byteskwargs(opts)
2253 repo = hg.peer(ui, opts, repopath)
2253 repo = hg.peer(ui, opts, repopath)
2254 if not repo.capable(b'known'):
2254 if not repo.capable(b'known'):
2255 raise error.Abort(b"known() not supported by target repository")
2255 raise error.Abort(b"known() not supported by target repository")
2256 flags = repo.known([bin(s) for s in ids])
2256 flags = repo.known([bin(s) for s in ids])
2257 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2257 ui.write(b"%s\n" % (b"".join([f and b"1" or b"0" for f in flags])))
2258
2258
2259
2259
2260 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2260 @command(b'debuglabelcomplete', [], _(b'LABEL...'))
2261 def debuglabelcomplete(ui, repo, *args):
2261 def debuglabelcomplete(ui, repo, *args):
2262 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2262 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2263 debugnamecomplete(ui, repo, *args)
2263 debugnamecomplete(ui, repo, *args)
2264
2264
2265
2265
2266 @command(
2266 @command(
2267 b'debuglocks',
2267 b'debuglocks',
2268 [
2268 [
2269 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2269 (b'L', b'force-free-lock', None, _(b'free the store lock (DANGEROUS)')),
2270 (
2270 (
2271 b'W',
2271 b'W',
2272 b'force-free-wlock',
2272 b'force-free-wlock',
2273 None,
2273 None,
2274 _(b'free the working state lock (DANGEROUS)'),
2274 _(b'free the working state lock (DANGEROUS)'),
2275 ),
2275 ),
2276 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2276 (b's', b'set-lock', None, _(b'set the store lock until stopped')),
2277 (
2277 (
2278 b'S',
2278 b'S',
2279 b'set-wlock',
2279 b'set-wlock',
2280 None,
2280 None,
2281 _(b'set the working state lock until stopped'),
2281 _(b'set the working state lock until stopped'),
2282 ),
2282 ),
2283 ],
2283 ],
2284 _(b'[OPTION]...'),
2284 _(b'[OPTION]...'),
2285 )
2285 )
2286 def debuglocks(ui, repo, **opts):
2286 def debuglocks(ui, repo, **opts):
2287 """show or modify state of locks
2287 """show or modify state of locks
2288
2288
2289 By default, this command will show which locks are held. This
2289 By default, this command will show which locks are held. This
2290 includes the user and process holding the lock, the amount of time
2290 includes the user and process holding the lock, the amount of time
2291 the lock has been held, and the machine name where the process is
2291 the lock has been held, and the machine name where the process is
2292 running if it's not local.
2292 running if it's not local.
2293
2293
2294 Locks protect the integrity of Mercurial's data, so should be
2294 Locks protect the integrity of Mercurial's data, so should be
2295 treated with care. System crashes or other interruptions may cause
2295 treated with care. System crashes or other interruptions may cause
2296 locks to not be properly released, though Mercurial will usually
2296 locks to not be properly released, though Mercurial will usually
2297 detect and remove such stale locks automatically.
2297 detect and remove such stale locks automatically.
2298
2298
2299 However, detecting stale locks may not always be possible (for
2299 However, detecting stale locks may not always be possible (for
2300 instance, on a shared filesystem). Removing locks may also be
2300 instance, on a shared filesystem). Removing locks may also be
2301 blocked by filesystem permissions.
2301 blocked by filesystem permissions.
2302
2302
2303 Setting a lock will prevent other commands from changing the data.
2303 Setting a lock will prevent other commands from changing the data.
2304 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2304 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
2305 The set locks are removed when the command exits.
2305 The set locks are removed when the command exits.
2306
2306
2307 Returns 0 if no locks are held.
2307 Returns 0 if no locks are held.
2308
2308
2309 """
2309 """
2310
2310
2311 if opts.get('force_free_lock'):
2311 if opts.get('force_free_lock'):
2312 repo.svfs.tryunlink(b'lock')
2312 repo.svfs.tryunlink(b'lock')
2313 if opts.get('force_free_wlock'):
2313 if opts.get('force_free_wlock'):
2314 repo.vfs.tryunlink(b'wlock')
2314 repo.vfs.tryunlink(b'wlock')
2315 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2315 if opts.get('force_free_lock') or opts.get('force_free_wlock'):
2316 return 0
2316 return 0
2317
2317
2318 locks = []
2318 locks = []
2319 try:
2319 try:
2320 if opts.get('set_wlock'):
2320 if opts.get('set_wlock'):
2321 try:
2321 try:
2322 locks.append(repo.wlock(False))
2322 locks.append(repo.wlock(False))
2323 except error.LockHeld:
2323 except error.LockHeld:
2324 raise error.Abort(_(b'wlock is already held'))
2324 raise error.Abort(_(b'wlock is already held'))
2325 if opts.get('set_lock'):
2325 if opts.get('set_lock'):
2326 try:
2326 try:
2327 locks.append(repo.lock(False))
2327 locks.append(repo.lock(False))
2328 except error.LockHeld:
2328 except error.LockHeld:
2329 raise error.Abort(_(b'lock is already held'))
2329 raise error.Abort(_(b'lock is already held'))
2330 if len(locks):
2330 if len(locks):
2331 try:
2331 try:
2332 if ui.interactive():
2332 if ui.interactive():
2333 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2333 prompt = _(b"ready to release the lock (y)? $$ &Yes")
2334 ui.promptchoice(prompt)
2334 ui.promptchoice(prompt)
2335 else:
2335 else:
2336 msg = b"%d locks held, waiting for signal\n"
2336 msg = b"%d locks held, waiting for signal\n"
2337 msg %= len(locks)
2337 msg %= len(locks)
2338 ui.status(msg)
2338 ui.status(msg)
2339 while True: # XXX wait for a signal
2339 while True: # XXX wait for a signal
2340 time.sleep(0.1)
2340 time.sleep(0.1)
2341 except KeyboardInterrupt:
2341 except KeyboardInterrupt:
2342 msg = b"signal-received releasing locks\n"
2342 msg = b"signal-received releasing locks\n"
2343 ui.status(msg)
2343 ui.status(msg)
2344 return 0
2344 return 0
2345 finally:
2345 finally:
2346 release(*locks)
2346 release(*locks)
2347
2347
2348 now = time.time()
2348 now = time.time()
2349 held = 0
2349 held = 0
2350
2350
2351 def report(vfs, name, method):
2351 def report(vfs, name, method):
2352 # this causes stale locks to get reaped for more accurate reporting
2352 # this causes stale locks to get reaped for more accurate reporting
2353 try:
2353 try:
2354 l = method(False)
2354 l = method(False)
2355 except error.LockHeld:
2355 except error.LockHeld:
2356 l = None
2356 l = None
2357
2357
2358 if l:
2358 if l:
2359 l.release()
2359 l.release()
2360 else:
2360 else:
2361 try:
2361 try:
2362 st = vfs.lstat(name)
2362 st = vfs.lstat(name)
2363 age = now - st[stat.ST_MTIME]
2363 age = now - st[stat.ST_MTIME]
2364 user = util.username(st.st_uid)
2364 user = util.username(st.st_uid)
2365 locker = vfs.readlock(name)
2365 locker = vfs.readlock(name)
2366 if b":" in locker:
2366 if b":" in locker:
2367 host, pid = locker.split(b':')
2367 host, pid = locker.split(b':')
2368 if host == socket.gethostname():
2368 if host == socket.gethostname():
2369 locker = b'user %s, process %s' % (user or b'None', pid)
2369 locker = b'user %s, process %s' % (user or b'None', pid)
2370 else:
2370 else:
2371 locker = b'user %s, process %s, host %s' % (
2371 locker = b'user %s, process %s, host %s' % (
2372 user or b'None',
2372 user or b'None',
2373 pid,
2373 pid,
2374 host,
2374 host,
2375 )
2375 )
2376 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2376 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
2377 return 1
2377 return 1
2378 except FileNotFoundError:
2378 except FileNotFoundError:
2379 pass
2379 pass
2380
2380
2381 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2381 ui.writenoi18n(b"%-6s free\n" % (name + b":"))
2382 return 0
2382 return 0
2383
2383
2384 held += report(repo.svfs, b"lock", repo.lock)
2384 held += report(repo.svfs, b"lock", repo.lock)
2385 held += report(repo.vfs, b"wlock", repo.wlock)
2385 held += report(repo.vfs, b"wlock", repo.wlock)
2386
2386
2387 return held
2387 return held
2388
2388
2389
2389
2390 @command(
2390 @command(
2391 b'debugmanifestfulltextcache',
2391 b'debugmanifestfulltextcache',
2392 [
2392 [
2393 (b'', b'clear', False, _(b'clear the cache')),
2393 (b'', b'clear', False, _(b'clear the cache')),
2394 (
2394 (
2395 b'a',
2395 b'a',
2396 b'add',
2396 b'add',
2397 [],
2397 [],
2398 _(b'add the given manifest nodes to the cache'),
2398 _(b'add the given manifest nodes to the cache'),
2399 _(b'NODE'),
2399 _(b'NODE'),
2400 ),
2400 ),
2401 ],
2401 ],
2402 b'',
2402 b'',
2403 )
2403 )
2404 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2404 def debugmanifestfulltextcache(ui, repo, add=(), **opts):
2405 """show, clear or amend the contents of the manifest fulltext cache"""
2405 """show, clear or amend the contents of the manifest fulltext cache"""
2406
2406
2407 def getcache():
2407 def getcache():
2408 r = repo.manifestlog.getstorage(b'')
2408 r = repo.manifestlog.getstorage(b'')
2409 try:
2409 try:
2410 return r._fulltextcache
2410 return r._fulltextcache
2411 except AttributeError:
2411 except AttributeError:
2412 msg = _(
2412 msg = _(
2413 b"Current revlog implementation doesn't appear to have a "
2413 b"Current revlog implementation doesn't appear to have a "
2414 b"manifest fulltext cache\n"
2414 b"manifest fulltext cache\n"
2415 )
2415 )
2416 raise error.Abort(msg)
2416 raise error.Abort(msg)
2417
2417
2418 if opts.get('clear'):
2418 if opts.get('clear'):
2419 with repo.wlock():
2419 with repo.wlock():
2420 cache = getcache()
2420 cache = getcache()
2421 cache.clear(clear_persisted_data=True)
2421 cache.clear(clear_persisted_data=True)
2422 return
2422 return
2423
2423
2424 if add:
2424 if add:
2425 with repo.wlock():
2425 with repo.wlock():
2426 m = repo.manifestlog
2426 m = repo.manifestlog
2427 store = m.getstorage(b'')
2427 store = m.getstorage(b'')
2428 for n in add:
2428 for n in add:
2429 try:
2429 try:
2430 manifest = m[store.lookup(n)]
2430 manifest = m[store.lookup(n)]
2431 except error.LookupError as e:
2431 except error.LookupError as e:
2432 raise error.Abort(
2432 raise error.Abort(
2433 bytes(e), hint=b"Check your manifest node id"
2433 bytes(e), hint=b"Check your manifest node id"
2434 )
2434 )
2435 manifest.read() # stores revisision in cache too
2435 manifest.read() # stores revisision in cache too
2436 return
2436 return
2437
2437
2438 cache = getcache()
2438 cache = getcache()
2439 if not len(cache):
2439 if not len(cache):
2440 ui.write(_(b'cache empty\n'))
2440 ui.write(_(b'cache empty\n'))
2441 else:
2441 else:
2442 ui.write(
2442 ui.write(
2443 _(
2443 _(
2444 b'cache contains %d manifest entries, in order of most to '
2444 b'cache contains %d manifest entries, in order of most to '
2445 b'least recent:\n'
2445 b'least recent:\n'
2446 )
2446 )
2447 % (len(cache),)
2447 % (len(cache),)
2448 )
2448 )
2449 totalsize = 0
2449 totalsize = 0
2450 for nodeid in cache:
2450 for nodeid in cache:
2451 # Use cache.get to not update the LRU order
2451 # Use cache.get to not update the LRU order
2452 data = cache.peek(nodeid)
2452 data = cache.peek(nodeid)
2453 size = len(data)
2453 size = len(data)
2454 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2454 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
2455 ui.write(
2455 ui.write(
2456 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2456 _(b'id: %s, size %s\n') % (hex(nodeid), util.bytecount(size))
2457 )
2457 )
2458 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2458 ondisk = cache._opener.stat(b'manifestfulltextcache').st_size
2459 ui.write(
2459 ui.write(
2460 _(b'total cache data size %s, on-disk %s\n')
2460 _(b'total cache data size %s, on-disk %s\n')
2461 % (util.bytecount(totalsize), util.bytecount(ondisk))
2461 % (util.bytecount(totalsize), util.bytecount(ondisk))
2462 )
2462 )
2463
2463
2464
2464
2465 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2465 @command(b'debugmergestate', [] + cmdutil.templateopts, b'')
2466 def debugmergestate(ui, repo, *args, **opts):
2466 def debugmergestate(ui, repo, *args, **opts):
2467 """print merge state
2467 """print merge state
2468
2468
2469 Use --verbose to print out information about whether v1 or v2 merge state
2469 Use --verbose to print out information about whether v1 or v2 merge state
2470 was chosen."""
2470 was chosen."""
2471
2471
2472 if ui.verbose:
2472 if ui.verbose:
2473 ms = mergestatemod.mergestate(repo)
2473 ms = mergestatemod.mergestate(repo)
2474
2474
2475 # sort so that reasonable information is on top
2475 # sort so that reasonable information is on top
2476 v1records = ms._readrecordsv1()
2476 v1records = ms._readrecordsv1()
2477 v2records = ms._readrecordsv2()
2477 v2records = ms._readrecordsv2()
2478
2478
2479 if not v1records and not v2records:
2479 if not v1records and not v2records:
2480 pass
2480 pass
2481 elif not v2records:
2481 elif not v2records:
2482 ui.writenoi18n(b'no version 2 merge state\n')
2482 ui.writenoi18n(b'no version 2 merge state\n')
2483 elif ms._v1v2match(v1records, v2records):
2483 elif ms._v1v2match(v1records, v2records):
2484 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2484 ui.writenoi18n(b'v1 and v2 states match: using v2\n')
2485 else:
2485 else:
2486 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2486 ui.writenoi18n(b'v1 and v2 states mismatch: using v1\n')
2487
2487
2488 opts = pycompat.byteskwargs(opts)
2488 opts = pycompat.byteskwargs(opts)
2489 if not opts[b'template']:
2489 if not opts[b'template']:
2490 opts[b'template'] = (
2490 opts[b'template'] = (
2491 b'{if(commits, "", "no merge state found\n")}'
2491 b'{if(commits, "", "no merge state found\n")}'
2492 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2492 b'{commits % "{name}{if(label, " ({label})")}: {node}\n"}'
2493 b'{files % "file: {path} (state \\"{state}\\")\n'
2493 b'{files % "file: {path} (state \\"{state}\\")\n'
2494 b'{if(local_path, "'
2494 b'{if(local_path, "'
2495 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2495 b' local path: {local_path} (hash {local_key}, flags \\"{local_flags}\\")\n'
2496 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2496 b' ancestor path: {ancestor_path} (node {ancestor_node})\n'
2497 b' other path: {other_path} (node {other_node})\n'
2497 b' other path: {other_path} (node {other_node})\n'
2498 b'")}'
2498 b'")}'
2499 b'{if(rename_side, "'
2499 b'{if(rename_side, "'
2500 b' rename side: {rename_side}\n'
2500 b' rename side: {rename_side}\n'
2501 b' renamed path: {renamed_path}\n'
2501 b' renamed path: {renamed_path}\n'
2502 b'")}'
2502 b'")}'
2503 b'{extras % " extra: {key} = {value}\n"}'
2503 b'{extras % " extra: {key} = {value}\n"}'
2504 b'"}'
2504 b'"}'
2505 b'{extras % "extra: {file} ({key} = {value})\n"}'
2505 b'{extras % "extra: {file} ({key} = {value})\n"}'
2506 )
2506 )
2507
2507
2508 ms = mergestatemod.mergestate.read(repo)
2508 ms = mergestatemod.mergestate.read(repo)
2509
2509
2510 fm = ui.formatter(b'debugmergestate', opts)
2510 fm = ui.formatter(b'debugmergestate', opts)
2511 fm.startitem()
2511 fm.startitem()
2512
2512
2513 fm_commits = fm.nested(b'commits')
2513 fm_commits = fm.nested(b'commits')
2514 if ms.active():
2514 if ms.active():
2515 for name, node, label_index in (
2515 for name, node, label_index in (
2516 (b'local', ms.local, 0),
2516 (b'local', ms.local, 0),
2517 (b'other', ms.other, 1),
2517 (b'other', ms.other, 1),
2518 ):
2518 ):
2519 fm_commits.startitem()
2519 fm_commits.startitem()
2520 fm_commits.data(name=name)
2520 fm_commits.data(name=name)
2521 fm_commits.data(node=hex(node))
2521 fm_commits.data(node=hex(node))
2522 if ms._labels and len(ms._labels) > label_index:
2522 if ms._labels and len(ms._labels) > label_index:
2523 fm_commits.data(label=ms._labels[label_index])
2523 fm_commits.data(label=ms._labels[label_index])
2524 fm_commits.end()
2524 fm_commits.end()
2525
2525
2526 fm_files = fm.nested(b'files')
2526 fm_files = fm.nested(b'files')
2527 if ms.active():
2527 if ms.active():
2528 for f in ms:
2528 for f in ms:
2529 fm_files.startitem()
2529 fm_files.startitem()
2530 fm_files.data(path=f)
2530 fm_files.data(path=f)
2531 state = ms._state[f]
2531 state = ms._state[f]
2532 fm_files.data(state=state[0])
2532 fm_files.data(state=state[0])
2533 if state[0] in (
2533 if state[0] in (
2534 mergestatemod.MERGE_RECORD_UNRESOLVED,
2534 mergestatemod.MERGE_RECORD_UNRESOLVED,
2535 mergestatemod.MERGE_RECORD_RESOLVED,
2535 mergestatemod.MERGE_RECORD_RESOLVED,
2536 ):
2536 ):
2537 fm_files.data(local_key=state[1])
2537 fm_files.data(local_key=state[1])
2538 fm_files.data(local_path=state[2])
2538 fm_files.data(local_path=state[2])
2539 fm_files.data(ancestor_path=state[3])
2539 fm_files.data(ancestor_path=state[3])
2540 fm_files.data(ancestor_node=state[4])
2540 fm_files.data(ancestor_node=state[4])
2541 fm_files.data(other_path=state[5])
2541 fm_files.data(other_path=state[5])
2542 fm_files.data(other_node=state[6])
2542 fm_files.data(other_node=state[6])
2543 fm_files.data(local_flags=state[7])
2543 fm_files.data(local_flags=state[7])
2544 elif state[0] in (
2544 elif state[0] in (
2545 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2545 mergestatemod.MERGE_RECORD_UNRESOLVED_PATH,
2546 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2546 mergestatemod.MERGE_RECORD_RESOLVED_PATH,
2547 ):
2547 ):
2548 fm_files.data(renamed_path=state[1])
2548 fm_files.data(renamed_path=state[1])
2549 fm_files.data(rename_side=state[2])
2549 fm_files.data(rename_side=state[2])
2550 fm_extras = fm_files.nested(b'extras')
2550 fm_extras = fm_files.nested(b'extras')
2551 for k, v in sorted(ms.extras(f).items()):
2551 for k, v in sorted(ms.extras(f).items()):
2552 fm_extras.startitem()
2552 fm_extras.startitem()
2553 fm_extras.data(key=k)
2553 fm_extras.data(key=k)
2554 fm_extras.data(value=v)
2554 fm_extras.data(value=v)
2555 fm_extras.end()
2555 fm_extras.end()
2556
2556
2557 fm_files.end()
2557 fm_files.end()
2558
2558
2559 fm_extras = fm.nested(b'extras')
2559 fm_extras = fm.nested(b'extras')
2560 for f, d in sorted(ms.allextras().items()):
2560 for f, d in sorted(ms.allextras().items()):
2561 if f in ms:
2561 if f in ms:
2562 # If file is in mergestate, we have already processed it's extras
2562 # If file is in mergestate, we have already processed it's extras
2563 continue
2563 continue
2564 for k, v in d.items():
2564 for k, v in d.items():
2565 fm_extras.startitem()
2565 fm_extras.startitem()
2566 fm_extras.data(file=f)
2566 fm_extras.data(file=f)
2567 fm_extras.data(key=k)
2567 fm_extras.data(key=k)
2568 fm_extras.data(value=v)
2568 fm_extras.data(value=v)
2569 fm_extras.end()
2569 fm_extras.end()
2570
2570
2571 fm.end()
2571 fm.end()
2572
2572
2573
2573
2574 @command(b'debugnamecomplete', [], _(b'NAME...'))
2574 @command(b'debugnamecomplete', [], _(b'NAME...'))
2575 def debugnamecomplete(ui, repo, *args):
2575 def debugnamecomplete(ui, repo, *args):
2576 '''complete "names" - tags, open branch names, bookmark names'''
2576 '''complete "names" - tags, open branch names, bookmark names'''
2577
2577
2578 names = set()
2578 names = set()
2579 # since we previously only listed open branches, we will handle that
2579 # since we previously only listed open branches, we will handle that
2580 # specially (after this for loop)
2580 # specially (after this for loop)
2581 for name, ns in repo.names.items():
2581 for name, ns in repo.names.items():
2582 if name != b'branches':
2582 if name != b'branches':
2583 names.update(ns.listnames(repo))
2583 names.update(ns.listnames(repo))
2584 names.update(
2584 names.update(
2585 tag
2585 tag
2586 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2586 for (tag, heads, tip, closed) in repo.branchmap().iterbranches()
2587 if not closed
2587 if not closed
2588 )
2588 )
2589 completions = set()
2589 completions = set()
2590 if not args:
2590 if not args:
2591 args = [b'']
2591 args = [b'']
2592 for a in args:
2592 for a in args:
2593 completions.update(n for n in names if n.startswith(a))
2593 completions.update(n for n in names if n.startswith(a))
2594 ui.write(b'\n'.join(sorted(completions)))
2594 ui.write(b'\n'.join(sorted(completions)))
2595 ui.write(b'\n')
2595 ui.write(b'\n')
2596
2596
2597
2597
2598 @command(
2598 @command(
2599 b'debugnodemap',
2599 b'debugnodemap',
2600 [
2600 [
2601 (
2601 (
2602 b'',
2602 b'',
2603 b'dump-new',
2603 b'dump-new',
2604 False,
2604 False,
2605 _(b'write a (new) persistent binary nodemap on stdout'),
2605 _(b'write a (new) persistent binary nodemap on stdout'),
2606 ),
2606 ),
2607 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2607 (b'', b'dump-disk', False, _(b'dump on-disk data on stdout')),
2608 (
2608 (
2609 b'',
2609 b'',
2610 b'check',
2610 b'check',
2611 False,
2611 False,
2612 _(b'check that the data on disk data are correct.'),
2612 _(b'check that the data on disk data are correct.'),
2613 ),
2613 ),
2614 (
2614 (
2615 b'',
2615 b'',
2616 b'metadata',
2616 b'metadata',
2617 False,
2617 False,
2618 _(b'display the on disk meta data for the nodemap'),
2618 _(b'display the on disk meta data for the nodemap'),
2619 ),
2619 ),
2620 ],
2620 ],
2621 )
2621 )
2622 def debugnodemap(ui, repo, **opts):
2622 def debugnodemap(ui, repo, **opts):
2623 """write and inspect on disk nodemap"""
2623 """write and inspect on disk nodemap"""
2624 if opts['dump_new']:
2624 if opts['dump_new']:
2625 unfi = repo.unfiltered()
2625 unfi = repo.unfiltered()
2626 cl = unfi.changelog
2626 cl = unfi.changelog
2627 if util.safehasattr(cl.index, "nodemap_data_all"):
2627 if util.safehasattr(cl.index, "nodemap_data_all"):
2628 data = cl.index.nodemap_data_all()
2628 data = cl.index.nodemap_data_all()
2629 else:
2629 else:
2630 data = nodemap.persistent_data(cl.index)
2630 data = nodemap.persistent_data(cl.index)
2631 ui.write(data)
2631 ui.write(data)
2632 elif opts['dump_disk']:
2632 elif opts['dump_disk']:
2633 unfi = repo.unfiltered()
2633 unfi = repo.unfiltered()
2634 cl = unfi.changelog
2634 cl = unfi.changelog
2635 nm_data = nodemap.persisted_data(cl)
2635 nm_data = nodemap.persisted_data(cl)
2636 if nm_data is not None:
2636 if nm_data is not None:
2637 docket, data = nm_data
2637 docket, data = nm_data
2638 ui.write(data[:])
2638 ui.write(data[:])
2639 elif opts['check']:
2639 elif opts['check']:
2640 unfi = repo.unfiltered()
2640 unfi = repo.unfiltered()
2641 cl = unfi.changelog
2641 cl = unfi.changelog
2642 nm_data = nodemap.persisted_data(cl)
2642 nm_data = nodemap.persisted_data(cl)
2643 if nm_data is not None:
2643 if nm_data is not None:
2644 docket, data = nm_data
2644 docket, data = nm_data
2645 return nodemap.check_data(ui, cl.index, data)
2645 return nodemap.check_data(ui, cl.index, data)
2646 elif opts['metadata']:
2646 elif opts['metadata']:
2647 unfi = repo.unfiltered()
2647 unfi = repo.unfiltered()
2648 cl = unfi.changelog
2648 cl = unfi.changelog
2649 nm_data = nodemap.persisted_data(cl)
2649 nm_data = nodemap.persisted_data(cl)
2650 if nm_data is not None:
2650 if nm_data is not None:
2651 docket, data = nm_data
2651 docket, data = nm_data
2652 ui.write((b"uid: %s\n") % docket.uid)
2652 ui.write((b"uid: %s\n") % docket.uid)
2653 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2653 ui.write((b"tip-rev: %d\n") % docket.tip_rev)
2654 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2654 ui.write((b"tip-node: %s\n") % hex(docket.tip_node))
2655 ui.write((b"data-length: %d\n") % docket.data_length)
2655 ui.write((b"data-length: %d\n") % docket.data_length)
2656 ui.write((b"data-unused: %d\n") % docket.data_unused)
2656 ui.write((b"data-unused: %d\n") % docket.data_unused)
2657 unused_perc = docket.data_unused * 100.0 / docket.data_length
2657 unused_perc = docket.data_unused * 100.0 / docket.data_length
2658 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2658 ui.write((b"data-unused: %2.3f%%\n") % unused_perc)
2659
2659
2660
2660
2661 @command(
2661 @command(
2662 b'debugobsolete',
2662 b'debugobsolete',
2663 [
2663 [
2664 (b'', b'flags', 0, _(b'markers flag')),
2664 (b'', b'flags', 0, _(b'markers flag')),
2665 (
2665 (
2666 b'',
2666 b'',
2667 b'record-parents',
2667 b'record-parents',
2668 False,
2668 False,
2669 _(b'record parent information for the precursor'),
2669 _(b'record parent information for the precursor'),
2670 ),
2670 ),
2671 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2671 (b'r', b'rev', [], _(b'display markers relevant to REV')),
2672 (
2672 (
2673 b'',
2673 b'',
2674 b'exclusive',
2674 b'exclusive',
2675 False,
2675 False,
2676 _(b'restrict display to markers only relevant to REV'),
2676 _(b'restrict display to markers only relevant to REV'),
2677 ),
2677 ),
2678 (b'', b'index', False, _(b'display index of the marker')),
2678 (b'', b'index', False, _(b'display index of the marker')),
2679 (b'', b'delete', [], _(b'delete markers specified by indices')),
2679 (b'', b'delete', [], _(b'delete markers specified by indices')),
2680 ]
2680 ]
2681 + cmdutil.commitopts2
2681 + cmdutil.commitopts2
2682 + cmdutil.formatteropts,
2682 + cmdutil.formatteropts,
2683 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2683 _(b'[OBSOLETED [REPLACEMENT ...]]'),
2684 )
2684 )
2685 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2685 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2686 """create arbitrary obsolete marker
2686 """create arbitrary obsolete marker
2687
2687
2688 With no arguments, displays the list of obsolescence markers."""
2688 With no arguments, displays the list of obsolescence markers."""
2689
2689
2690 opts = pycompat.byteskwargs(opts)
2690 opts = pycompat.byteskwargs(opts)
2691
2691
2692 def parsenodeid(s):
2692 def parsenodeid(s):
2693 try:
2693 try:
2694 # We do not use revsingle/revrange functions here to accept
2694 # We do not use revsingle/revrange functions here to accept
2695 # arbitrary node identifiers, possibly not present in the
2695 # arbitrary node identifiers, possibly not present in the
2696 # local repository.
2696 # local repository.
2697 n = bin(s)
2697 n = bin(s)
2698 if len(n) != repo.nodeconstants.nodelen:
2698 if len(n) != repo.nodeconstants.nodelen:
2699 raise ValueError
2699 raise ValueError
2700 return n
2700 return n
2701 except ValueError:
2701 except ValueError:
2702 raise error.InputError(
2702 raise error.InputError(
2703 b'changeset references must be full hexadecimal '
2703 b'changeset references must be full hexadecimal '
2704 b'node identifiers'
2704 b'node identifiers'
2705 )
2705 )
2706
2706
2707 if opts.get(b'delete'):
2707 if opts.get(b'delete'):
2708 indices = []
2708 indices = []
2709 for v in opts.get(b'delete'):
2709 for v in opts.get(b'delete'):
2710 try:
2710 try:
2711 indices.append(int(v))
2711 indices.append(int(v))
2712 except ValueError:
2712 except ValueError:
2713 raise error.InputError(
2713 raise error.InputError(
2714 _(b'invalid index value: %r') % v,
2714 _(b'invalid index value: %r') % v,
2715 hint=_(b'use integers for indices'),
2715 hint=_(b'use integers for indices'),
2716 )
2716 )
2717
2717
2718 if repo.currenttransaction():
2718 if repo.currenttransaction():
2719 raise error.Abort(
2719 raise error.Abort(
2720 _(b'cannot delete obsmarkers in the middle of transaction.')
2720 _(b'cannot delete obsmarkers in the middle of transaction.')
2721 )
2721 )
2722
2722
2723 with repo.lock():
2723 with repo.lock():
2724 n = repair.deleteobsmarkers(repo.obsstore, indices)
2724 n = repair.deleteobsmarkers(repo.obsstore, indices)
2725 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2725 ui.write(_(b'deleted %i obsolescence markers\n') % n)
2726
2726
2727 return
2727 return
2728
2728
2729 if precursor is not None:
2729 if precursor is not None:
2730 if opts[b'rev']:
2730 if opts[b'rev']:
2731 raise error.InputError(
2731 raise error.InputError(
2732 b'cannot select revision when creating marker'
2732 b'cannot select revision when creating marker'
2733 )
2733 )
2734 metadata = {}
2734 metadata = {}
2735 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2735 metadata[b'user'] = encoding.fromlocal(opts[b'user'] or ui.username())
2736 succs = tuple(parsenodeid(succ) for succ in successors)
2736 succs = tuple(parsenodeid(succ) for succ in successors)
2737 l = repo.lock()
2737 l = repo.lock()
2738 try:
2738 try:
2739 tr = repo.transaction(b'debugobsolete')
2739 tr = repo.transaction(b'debugobsolete')
2740 try:
2740 try:
2741 date = opts.get(b'date')
2741 date = opts.get(b'date')
2742 if date:
2742 if date:
2743 date = dateutil.parsedate(date)
2743 date = dateutil.parsedate(date)
2744 else:
2744 else:
2745 date = None
2745 date = None
2746 prec = parsenodeid(precursor)
2746 prec = parsenodeid(precursor)
2747 parents = None
2747 parents = None
2748 if opts[b'record_parents']:
2748 if opts[b'record_parents']:
2749 if prec not in repo.unfiltered():
2749 if prec not in repo.unfiltered():
2750 raise error.Abort(
2750 raise error.Abort(
2751 b'cannot used --record-parents on '
2751 b'cannot used --record-parents on '
2752 b'unknown changesets'
2752 b'unknown changesets'
2753 )
2753 )
2754 parents = repo.unfiltered()[prec].parents()
2754 parents = repo.unfiltered()[prec].parents()
2755 parents = tuple(p.node() for p in parents)
2755 parents = tuple(p.node() for p in parents)
2756 repo.obsstore.create(
2756 repo.obsstore.create(
2757 tr,
2757 tr,
2758 prec,
2758 prec,
2759 succs,
2759 succs,
2760 opts[b'flags'],
2760 opts[b'flags'],
2761 parents=parents,
2761 parents=parents,
2762 date=date,
2762 date=date,
2763 metadata=metadata,
2763 metadata=metadata,
2764 ui=ui,
2764 ui=ui,
2765 )
2765 )
2766 tr.close()
2766 tr.close()
2767 except ValueError as exc:
2767 except ValueError as exc:
2768 raise error.Abort(
2768 raise error.Abort(
2769 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2769 _(b'bad obsmarker input: %s') % stringutil.forcebytestr(exc)
2770 )
2770 )
2771 finally:
2771 finally:
2772 tr.release()
2772 tr.release()
2773 finally:
2773 finally:
2774 l.release()
2774 l.release()
2775 else:
2775 else:
2776 if opts[b'rev']:
2776 if opts[b'rev']:
2777 revs = logcmdutil.revrange(repo, opts[b'rev'])
2777 revs = logcmdutil.revrange(repo, opts[b'rev'])
2778 nodes = [repo[r].node() for r in revs]
2778 nodes = [repo[r].node() for r in revs]
2779 markers = list(
2779 markers = list(
2780 obsutil.getmarkers(
2780 obsutil.getmarkers(
2781 repo, nodes=nodes, exclusive=opts[b'exclusive']
2781 repo, nodes=nodes, exclusive=opts[b'exclusive']
2782 )
2782 )
2783 )
2783 )
2784 markers.sort(key=lambda x: x._data)
2784 markers.sort(key=lambda x: x._data)
2785 else:
2785 else:
2786 markers = obsutil.getmarkers(repo)
2786 markers = obsutil.getmarkers(repo)
2787
2787
2788 markerstoiter = markers
2788 markerstoiter = markers
2789 isrelevant = lambda m: True
2789 isrelevant = lambda m: True
2790 if opts.get(b'rev') and opts.get(b'index'):
2790 if opts.get(b'rev') and opts.get(b'index'):
2791 markerstoiter = obsutil.getmarkers(repo)
2791 markerstoiter = obsutil.getmarkers(repo)
2792 markerset = set(markers)
2792 markerset = set(markers)
2793 isrelevant = lambda m: m in markerset
2793 isrelevant = lambda m: m in markerset
2794
2794
2795 fm = ui.formatter(b'debugobsolete', opts)
2795 fm = ui.formatter(b'debugobsolete', opts)
2796 for i, m in enumerate(markerstoiter):
2796 for i, m in enumerate(markerstoiter):
2797 if not isrelevant(m):
2797 if not isrelevant(m):
2798 # marker can be irrelevant when we're iterating over a set
2798 # marker can be irrelevant when we're iterating over a set
2799 # of markers (markerstoiter) which is bigger than the set
2799 # of markers (markerstoiter) which is bigger than the set
2800 # of markers we want to display (markers)
2800 # of markers we want to display (markers)
2801 # this can happen if both --index and --rev options are
2801 # this can happen if both --index and --rev options are
2802 # provided and thus we need to iterate over all of the markers
2802 # provided and thus we need to iterate over all of the markers
2803 # to get the correct indices, but only display the ones that
2803 # to get the correct indices, but only display the ones that
2804 # are relevant to --rev value
2804 # are relevant to --rev value
2805 continue
2805 continue
2806 fm.startitem()
2806 fm.startitem()
2807 ind = i if opts.get(b'index') else None
2807 ind = i if opts.get(b'index') else None
2808 cmdutil.showmarker(fm, m, index=ind)
2808 cmdutil.showmarker(fm, m, index=ind)
2809 fm.end()
2809 fm.end()
2810
2810
2811
2811
2812 @command(
2812 @command(
2813 b'debugp1copies',
2813 b'debugp1copies',
2814 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2814 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2815 _(b'[-r REV]'),
2815 _(b'[-r REV]'),
2816 )
2816 )
2817 def debugp1copies(ui, repo, **opts):
2817 def debugp1copies(ui, repo, **opts):
2818 """dump copy information compared to p1"""
2818 """dump copy information compared to p1"""
2819
2819
2820 opts = pycompat.byteskwargs(opts)
2820 opts = pycompat.byteskwargs(opts)
2821 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2821 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2822 for dst, src in ctx.p1copies().items():
2822 for dst, src in ctx.p1copies().items():
2823 ui.write(b'%s -> %s\n' % (src, dst))
2823 ui.write(b'%s -> %s\n' % (src, dst))
2824
2824
2825
2825
2826 @command(
2826 @command(
2827 b'debugp2copies',
2827 b'debugp2copies',
2828 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2828 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
2829 _(b'[-r REV]'),
2829 _(b'[-r REV]'),
2830 )
2830 )
2831 def debugp2copies(ui, repo, **opts):
2831 def debugp2copies(ui, repo, **opts):
2832 """dump copy information compared to p2"""
2832 """dump copy information compared to p2"""
2833
2833
2834 opts = pycompat.byteskwargs(opts)
2834 opts = pycompat.byteskwargs(opts)
2835 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2835 ctx = scmutil.revsingle(repo, opts.get(b'rev'), default=None)
2836 for dst, src in ctx.p2copies().items():
2836 for dst, src in ctx.p2copies().items():
2837 ui.write(b'%s -> %s\n' % (src, dst))
2837 ui.write(b'%s -> %s\n' % (src, dst))
2838
2838
2839
2839
2840 @command(
2840 @command(
2841 b'debugpathcomplete',
2841 b'debugpathcomplete',
2842 [
2842 [
2843 (b'f', b'full', None, _(b'complete an entire path')),
2843 (b'f', b'full', None, _(b'complete an entire path')),
2844 (b'n', b'normal', None, _(b'show only normal files')),
2844 (b'n', b'normal', None, _(b'show only normal files')),
2845 (b'a', b'added', None, _(b'show only added files')),
2845 (b'a', b'added', None, _(b'show only added files')),
2846 (b'r', b'removed', None, _(b'show only removed files')),
2846 (b'r', b'removed', None, _(b'show only removed files')),
2847 ],
2847 ],
2848 _(b'FILESPEC...'),
2848 _(b'FILESPEC...'),
2849 )
2849 )
2850 def debugpathcomplete(ui, repo, *specs, **opts):
2850 def debugpathcomplete(ui, repo, *specs, **opts):
2851 """complete part or all of a tracked path
2851 """complete part or all of a tracked path
2852
2852
2853 This command supports shells that offer path name completion. It
2853 This command supports shells that offer path name completion. It
2854 currently completes only files already known to the dirstate.
2854 currently completes only files already known to the dirstate.
2855
2855
2856 Completion extends only to the next path segment unless
2856 Completion extends only to the next path segment unless
2857 --full is specified, in which case entire paths are used."""
2857 --full is specified, in which case entire paths are used."""
2858
2858
2859 def complete(path, acceptable):
2859 def complete(path, acceptable):
2860 dirstate = repo.dirstate
2860 dirstate = repo.dirstate
2861 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2861 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
2862 rootdir = repo.root + pycompat.ossep
2862 rootdir = repo.root + pycompat.ossep
2863 if spec != repo.root and not spec.startswith(rootdir):
2863 if spec != repo.root and not spec.startswith(rootdir):
2864 return [], []
2864 return [], []
2865 if os.path.isdir(spec):
2865 if os.path.isdir(spec):
2866 spec += b'/'
2866 spec += b'/'
2867 spec = spec[len(rootdir) :]
2867 spec = spec[len(rootdir) :]
2868 fixpaths = pycompat.ossep != b'/'
2868 fixpaths = pycompat.ossep != b'/'
2869 if fixpaths:
2869 if fixpaths:
2870 spec = spec.replace(pycompat.ossep, b'/')
2870 spec = spec.replace(pycompat.ossep, b'/')
2871 speclen = len(spec)
2871 speclen = len(spec)
2872 fullpaths = opts['full']
2872 fullpaths = opts['full']
2873 files, dirs = set(), set()
2873 files, dirs = set(), set()
2874 adddir, addfile = dirs.add, files.add
2874 adddir, addfile = dirs.add, files.add
2875 for f, st in dirstate.items():
2875 for f, st in dirstate.items():
2876 if f.startswith(spec) and st.state in acceptable:
2876 if f.startswith(spec) and st.state in acceptable:
2877 if fixpaths:
2877 if fixpaths:
2878 f = f.replace(b'/', pycompat.ossep)
2878 f = f.replace(b'/', pycompat.ossep)
2879 if fullpaths:
2879 if fullpaths:
2880 addfile(f)
2880 addfile(f)
2881 continue
2881 continue
2882 s = f.find(pycompat.ossep, speclen)
2882 s = f.find(pycompat.ossep, speclen)
2883 if s >= 0:
2883 if s >= 0:
2884 adddir(f[:s])
2884 adddir(f[:s])
2885 else:
2885 else:
2886 addfile(f)
2886 addfile(f)
2887 return files, dirs
2887 return files, dirs
2888
2888
2889 acceptable = b''
2889 acceptable = b''
2890 if opts['normal']:
2890 if opts['normal']:
2891 acceptable += b'nm'
2891 acceptable += b'nm'
2892 if opts['added']:
2892 if opts['added']:
2893 acceptable += b'a'
2893 acceptable += b'a'
2894 if opts['removed']:
2894 if opts['removed']:
2895 acceptable += b'r'
2895 acceptable += b'r'
2896 cwd = repo.getcwd()
2896 cwd = repo.getcwd()
2897 if not specs:
2897 if not specs:
2898 specs = [b'.']
2898 specs = [b'.']
2899
2899
2900 files, dirs = set(), set()
2900 files, dirs = set(), set()
2901 for spec in specs:
2901 for spec in specs:
2902 f, d = complete(spec, acceptable or b'nmar')
2902 f, d = complete(spec, acceptable or b'nmar')
2903 files.update(f)
2903 files.update(f)
2904 dirs.update(d)
2904 dirs.update(d)
2905 files.update(dirs)
2905 files.update(dirs)
2906 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2906 ui.write(b'\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2907 ui.write(b'\n')
2907 ui.write(b'\n')
2908
2908
2909
2909
2910 @command(
2910 @command(
2911 b'debugpathcopies',
2911 b'debugpathcopies',
2912 cmdutil.walkopts,
2912 cmdutil.walkopts,
2913 b'hg debugpathcopies REV1 REV2 [FILE]',
2913 b'hg debugpathcopies REV1 REV2 [FILE]',
2914 inferrepo=True,
2914 inferrepo=True,
2915 )
2915 )
2916 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2916 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
2917 """show copies between two revisions"""
2917 """show copies between two revisions"""
2918 ctx1 = scmutil.revsingle(repo, rev1)
2918 ctx1 = scmutil.revsingle(repo, rev1)
2919 ctx2 = scmutil.revsingle(repo, rev2)
2919 ctx2 = scmutil.revsingle(repo, rev2)
2920 m = scmutil.match(ctx1, pats, opts)
2920 m = scmutil.match(ctx1, pats, opts)
2921 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2921 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
2922 ui.write(b'%s -> %s\n' % (src, dst))
2922 ui.write(b'%s -> %s\n' % (src, dst))
2923
2923
2924
2924
2925 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2925 @command(b'debugpeer', [], _(b'PATH'), norepo=True)
2926 def debugpeer(ui, path):
2926 def debugpeer(ui, path):
2927 """establish a connection to a peer repository"""
2927 """establish a connection to a peer repository"""
2928 # Always enable peer request logging. Requires --debug to display
2928 # Always enable peer request logging. Requires --debug to display
2929 # though.
2929 # though.
2930 overrides = {
2930 overrides = {
2931 (b'devel', b'debug.peer-request'): True,
2931 (b'devel', b'debug.peer-request'): True,
2932 }
2932 }
2933
2933
2934 with ui.configoverride(overrides):
2934 with ui.configoverride(overrides):
2935 peer = hg.peer(ui, {}, path)
2935 peer = hg.peer(ui, {}, path)
2936
2936
2937 try:
2937 try:
2938 local = peer.local() is not None
2938 local = peer.local() is not None
2939 canpush = peer.canpush()
2939 canpush = peer.canpush()
2940
2940
2941 ui.write(_(b'url: %s\n') % peer.url())
2941 ui.write(_(b'url: %s\n') % peer.url())
2942 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2942 ui.write(_(b'local: %s\n') % (_(b'yes') if local else _(b'no')))
2943 ui.write(
2943 ui.write(
2944 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2944 _(b'pushable: %s\n') % (_(b'yes') if canpush else _(b'no'))
2945 )
2945 )
2946 finally:
2946 finally:
2947 peer.close()
2947 peer.close()
2948
2948
2949
2949
2950 @command(
2950 @command(
2951 b'debugpickmergetool',
2951 b'debugpickmergetool',
2952 [
2952 [
2953 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2953 (b'r', b'rev', b'', _(b'check for files in this revision'), _(b'REV')),
2954 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2954 (b'', b'changedelete', None, _(b'emulate merging change and delete')),
2955 ]
2955 ]
2956 + cmdutil.walkopts
2956 + cmdutil.walkopts
2957 + cmdutil.mergetoolopts,
2957 + cmdutil.mergetoolopts,
2958 _(b'[PATTERN]...'),
2958 _(b'[PATTERN]...'),
2959 inferrepo=True,
2959 inferrepo=True,
2960 )
2960 )
2961 def debugpickmergetool(ui, repo, *pats, **opts):
2961 def debugpickmergetool(ui, repo, *pats, **opts):
2962 """examine which merge tool is chosen for specified file
2962 """examine which merge tool is chosen for specified file
2963
2963
2964 As described in :hg:`help merge-tools`, Mercurial examines
2964 As described in :hg:`help merge-tools`, Mercurial examines
2965 configurations below in this order to decide which merge tool is
2965 configurations below in this order to decide which merge tool is
2966 chosen for specified file.
2966 chosen for specified file.
2967
2967
2968 1. ``--tool`` option
2968 1. ``--tool`` option
2969 2. ``HGMERGE`` environment variable
2969 2. ``HGMERGE`` environment variable
2970 3. configurations in ``merge-patterns`` section
2970 3. configurations in ``merge-patterns`` section
2971 4. configuration of ``ui.merge``
2971 4. configuration of ``ui.merge``
2972 5. configurations in ``merge-tools`` section
2972 5. configurations in ``merge-tools`` section
2973 6. ``hgmerge`` tool (for historical reason only)
2973 6. ``hgmerge`` tool (for historical reason only)
2974 7. default tool for fallback (``:merge`` or ``:prompt``)
2974 7. default tool for fallback (``:merge`` or ``:prompt``)
2975
2975
2976 This command writes out examination result in the style below::
2976 This command writes out examination result in the style below::
2977
2977
2978 FILE = MERGETOOL
2978 FILE = MERGETOOL
2979
2979
2980 By default, all files known in the first parent context of the
2980 By default, all files known in the first parent context of the
2981 working directory are examined. Use file patterns and/or -I/-X
2981 working directory are examined. Use file patterns and/or -I/-X
2982 options to limit target files. -r/--rev is also useful to examine
2982 options to limit target files. -r/--rev is also useful to examine
2983 files in another context without actual updating to it.
2983 files in another context without actual updating to it.
2984
2984
2985 With --debug, this command shows warning messages while matching
2985 With --debug, this command shows warning messages while matching
2986 against ``merge-patterns`` and so on, too. It is recommended to
2986 against ``merge-patterns`` and so on, too. It is recommended to
2987 use this option with explicit file patterns and/or -I/-X options,
2987 use this option with explicit file patterns and/or -I/-X options,
2988 because this option increases amount of output per file according
2988 because this option increases amount of output per file according
2989 to configurations in hgrc.
2989 to configurations in hgrc.
2990
2990
2991 With -v/--verbose, this command shows configurations below at
2991 With -v/--verbose, this command shows configurations below at
2992 first (only if specified).
2992 first (only if specified).
2993
2993
2994 - ``--tool`` option
2994 - ``--tool`` option
2995 - ``HGMERGE`` environment variable
2995 - ``HGMERGE`` environment variable
2996 - configuration of ``ui.merge``
2996 - configuration of ``ui.merge``
2997
2997
2998 If merge tool is chosen before matching against
2998 If merge tool is chosen before matching against
2999 ``merge-patterns``, this command can't show any helpful
2999 ``merge-patterns``, this command can't show any helpful
3000 information, even with --debug. In such case, information above is
3000 information, even with --debug. In such case, information above is
3001 useful to know why a merge tool is chosen.
3001 useful to know why a merge tool is chosen.
3002 """
3002 """
3003 opts = pycompat.byteskwargs(opts)
3003 opts = pycompat.byteskwargs(opts)
3004 overrides = {}
3004 overrides = {}
3005 if opts[b'tool']:
3005 if opts[b'tool']:
3006 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
3006 overrides[(b'ui', b'forcemerge')] = opts[b'tool']
3007 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
3007 ui.notenoi18n(b'with --tool %r\n' % (pycompat.bytestr(opts[b'tool'])))
3008
3008
3009 with ui.configoverride(overrides, b'debugmergepatterns'):
3009 with ui.configoverride(overrides, b'debugmergepatterns'):
3010 hgmerge = encoding.environ.get(b"HGMERGE")
3010 hgmerge = encoding.environ.get(b"HGMERGE")
3011 if hgmerge is not None:
3011 if hgmerge is not None:
3012 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
3012 ui.notenoi18n(b'with HGMERGE=%r\n' % (pycompat.bytestr(hgmerge)))
3013 uimerge = ui.config(b"ui", b"merge")
3013 uimerge = ui.config(b"ui", b"merge")
3014 if uimerge:
3014 if uimerge:
3015 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
3015 ui.notenoi18n(b'with ui.merge=%r\n' % (pycompat.bytestr(uimerge)))
3016
3016
3017 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3017 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3018 m = scmutil.match(ctx, pats, opts)
3018 m = scmutil.match(ctx, pats, opts)
3019 changedelete = opts[b'changedelete']
3019 changedelete = opts[b'changedelete']
3020 for path in ctx.walk(m):
3020 for path in ctx.walk(m):
3021 fctx = ctx[path]
3021 fctx = ctx[path]
3022 with ui.silent(
3022 with ui.silent(
3023 error=True
3023 error=True
3024 ) if not ui.debugflag else util.nullcontextmanager():
3024 ) if not ui.debugflag else util.nullcontextmanager():
3025 tool, toolpath = filemerge._picktool(
3025 tool, toolpath = filemerge._picktool(
3026 repo,
3026 repo,
3027 ui,
3027 ui,
3028 path,
3028 path,
3029 fctx.isbinary(),
3029 fctx.isbinary(),
3030 b'l' in fctx.flags(),
3030 b'l' in fctx.flags(),
3031 changedelete,
3031 changedelete,
3032 )
3032 )
3033 ui.write(b'%s = %s\n' % (path, tool))
3033 ui.write(b'%s = %s\n' % (path, tool))
3034
3034
3035
3035
3036 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3036 @command(b'debugpushkey', [], _(b'REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3037 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3037 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3038 """access the pushkey key/value protocol
3038 """access the pushkey key/value protocol
3039
3039
3040 With two args, list the keys in the given namespace.
3040 With two args, list the keys in the given namespace.
3041
3041
3042 With five args, set a key to new if it currently is set to old.
3042 With five args, set a key to new if it currently is set to old.
3043 Reports success or failure.
3043 Reports success or failure.
3044 """
3044 """
3045
3045
3046 target = hg.peer(ui, {}, repopath)
3046 target = hg.peer(ui, {}, repopath)
3047 try:
3047 try:
3048 if keyinfo:
3048 if keyinfo:
3049 key, old, new = keyinfo
3049 key, old, new = keyinfo
3050 with target.commandexecutor() as e:
3050 with target.commandexecutor() as e:
3051 r = e.callcommand(
3051 r = e.callcommand(
3052 b'pushkey',
3052 b'pushkey',
3053 {
3053 {
3054 b'namespace': namespace,
3054 b'namespace': namespace,
3055 b'key': key,
3055 b'key': key,
3056 b'old': old,
3056 b'old': old,
3057 b'new': new,
3057 b'new': new,
3058 },
3058 },
3059 ).result()
3059 ).result()
3060
3060
3061 ui.status(pycompat.bytestr(r) + b'\n')
3061 ui.status(pycompat.bytestr(r) + b'\n')
3062 return not r
3062 return not r
3063 else:
3063 else:
3064 for k, v in sorted(target.listkeys(namespace).items()):
3064 for k, v in sorted(target.listkeys(namespace).items()):
3065 ui.write(
3065 ui.write(
3066 b"%s\t%s\n"
3066 b"%s\t%s\n"
3067 % (stringutil.escapestr(k), stringutil.escapestr(v))
3067 % (stringutil.escapestr(k), stringutil.escapestr(v))
3068 )
3068 )
3069 finally:
3069 finally:
3070 target.close()
3070 target.close()
3071
3071
3072
3072
3073 @command(b'debugpvec', [], _(b'A B'))
3073 @command(b'debugpvec', [], _(b'A B'))
3074 def debugpvec(ui, repo, a, b=None):
3074 def debugpvec(ui, repo, a, b=None):
3075 ca = scmutil.revsingle(repo, a)
3075 ca = scmutil.revsingle(repo, a)
3076 cb = scmutil.revsingle(repo, b)
3076 cb = scmutil.revsingle(repo, b)
3077 pa = pvec.ctxpvec(ca)
3077 pa = pvec.ctxpvec(ca)
3078 pb = pvec.ctxpvec(cb)
3078 pb = pvec.ctxpvec(cb)
3079 if pa == pb:
3079 if pa == pb:
3080 rel = b"="
3080 rel = b"="
3081 elif pa > pb:
3081 elif pa > pb:
3082 rel = b">"
3082 rel = b">"
3083 elif pa < pb:
3083 elif pa < pb:
3084 rel = b"<"
3084 rel = b"<"
3085 elif pa | pb:
3085 elif pa | pb:
3086 rel = b"|"
3086 rel = b"|"
3087 ui.write(_(b"a: %s\n") % pa)
3087 ui.write(_(b"a: %s\n") % pa)
3088 ui.write(_(b"b: %s\n") % pb)
3088 ui.write(_(b"b: %s\n") % pb)
3089 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3089 ui.write(_(b"depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3090 ui.write(
3090 ui.write(
3091 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3091 _(b"delta: %d hdist: %d distance: %d relation: %s\n")
3092 % (
3092 % (
3093 abs(pa._depth - pb._depth),
3093 abs(pa._depth - pb._depth),
3094 pvec._hamming(pa._vec, pb._vec),
3094 pvec._hamming(pa._vec, pb._vec),
3095 pa.distance(pb),
3095 pa.distance(pb),
3096 rel,
3096 rel,
3097 )
3097 )
3098 )
3098 )
3099
3099
3100
3100
3101 @command(
3101 @command(
3102 b'debugrebuilddirstate|debugrebuildstate',
3102 b'debugrebuilddirstate|debugrebuildstate',
3103 [
3103 [
3104 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3104 (b'r', b'rev', b'', _(b'revision to rebuild to'), _(b'REV')),
3105 (
3105 (
3106 b'',
3106 b'',
3107 b'minimal',
3107 b'minimal',
3108 None,
3108 None,
3109 _(
3109 _(
3110 b'only rebuild files that are inconsistent with '
3110 b'only rebuild files that are inconsistent with '
3111 b'the working copy parent'
3111 b'the working copy parent'
3112 ),
3112 ),
3113 ),
3113 ),
3114 ],
3114 ],
3115 _(b'[-r REV]'),
3115 _(b'[-r REV]'),
3116 )
3116 )
3117 def debugrebuilddirstate(ui, repo, rev, **opts):
3117 def debugrebuilddirstate(ui, repo, rev, **opts):
3118 """rebuild the dirstate as it would look like for the given revision
3118 """rebuild the dirstate as it would look like for the given revision
3119
3119
3120 If no revision is specified the first current parent will be used.
3120 If no revision is specified the first current parent will be used.
3121
3121
3122 The dirstate will be set to the files of the given revision.
3122 The dirstate will be set to the files of the given revision.
3123 The actual working directory content or existing dirstate
3123 The actual working directory content or existing dirstate
3124 information such as adds or removes is not considered.
3124 information such as adds or removes is not considered.
3125
3125
3126 ``minimal`` will only rebuild the dirstate status for files that claim to be
3126 ``minimal`` will only rebuild the dirstate status for files that claim to be
3127 tracked but are not in the parent manifest, or that exist in the parent
3127 tracked but are not in the parent manifest, or that exist in the parent
3128 manifest but are not in the dirstate. It will not change adds, removes, or
3128 manifest but are not in the dirstate. It will not change adds, removes, or
3129 modified files that are in the working copy parent.
3129 modified files that are in the working copy parent.
3130
3130
3131 One use of this command is to make the next :hg:`status` invocation
3131 One use of this command is to make the next :hg:`status` invocation
3132 check the actual file content.
3132 check the actual file content.
3133 """
3133 """
3134 ctx = scmutil.revsingle(repo, rev)
3134 ctx = scmutil.revsingle(repo, rev)
3135 with repo.wlock():
3135 with repo.wlock():
3136 dirstate = repo.dirstate
3136 dirstate = repo.dirstate
3137 changedfiles = None
3137 changedfiles = None
3138 # See command doc for what minimal does.
3138 # See command doc for what minimal does.
3139 if opts.get('minimal'):
3139 if opts.get('minimal'):
3140 manifestfiles = set(ctx.manifest().keys())
3140 manifestfiles = set(ctx.manifest().keys())
3141 dirstatefiles = set(dirstate)
3141 dirstatefiles = set(dirstate)
3142 manifestonly = manifestfiles - dirstatefiles
3142 manifestonly = manifestfiles - dirstatefiles
3143 dsonly = dirstatefiles - manifestfiles
3143 dsonly = dirstatefiles - manifestfiles
3144 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3144 dsnotadded = {f for f in dsonly if not dirstate.get_entry(f).added}
3145 changedfiles = manifestonly | dsnotadded
3145 changedfiles = manifestonly | dsnotadded
3146
3146
3147 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3147 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3148
3148
3149
3149
3150 @command(
3150 @command(
3151 b'debugrebuildfncache',
3151 b'debugrebuildfncache',
3152 [
3152 [
3153 (
3153 (
3154 b'',
3154 b'',
3155 b'only-data',
3155 b'only-data',
3156 False,
3156 False,
3157 _(b'only look for wrong .d files (much faster)'),
3157 _(b'only look for wrong .d files (much faster)'),
3158 )
3158 )
3159 ],
3159 ],
3160 b'',
3160 b'',
3161 )
3161 )
3162 def debugrebuildfncache(ui, repo, **opts):
3162 def debugrebuildfncache(ui, repo, **opts):
3163 """rebuild the fncache file"""
3163 """rebuild the fncache file"""
3164 opts = pycompat.byteskwargs(opts)
3164 opts = pycompat.byteskwargs(opts)
3165 repair.rebuildfncache(ui, repo, opts.get(b"only_data"))
3165 repair.rebuildfncache(ui, repo, opts.get(b"only_data"))
3166
3166
3167
3167
3168 @command(
3168 @command(
3169 b'debugrename',
3169 b'debugrename',
3170 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3170 [(b'r', b'rev', b'', _(b'revision to debug'), _(b'REV'))],
3171 _(b'[-r REV] [FILE]...'),
3171 _(b'[-r REV] [FILE]...'),
3172 )
3172 )
3173 def debugrename(ui, repo, *pats, **opts):
3173 def debugrename(ui, repo, *pats, **opts):
3174 """dump rename information"""
3174 """dump rename information"""
3175
3175
3176 opts = pycompat.byteskwargs(opts)
3176 opts = pycompat.byteskwargs(opts)
3177 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3177 ctx = scmutil.revsingle(repo, opts.get(b'rev'))
3178 m = scmutil.match(ctx, pats, opts)
3178 m = scmutil.match(ctx, pats, opts)
3179 for abs in ctx.walk(m):
3179 for abs in ctx.walk(m):
3180 fctx = ctx[abs]
3180 fctx = ctx[abs]
3181 o = fctx.filelog().renamed(fctx.filenode())
3181 o = fctx.filelog().renamed(fctx.filenode())
3182 rel = repo.pathto(abs)
3182 rel = repo.pathto(abs)
3183 if o:
3183 if o:
3184 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3184 ui.write(_(b"%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3185 else:
3185 else:
3186 ui.write(_(b"%s not renamed\n") % rel)
3186 ui.write(_(b"%s not renamed\n") % rel)
3187
3187
3188
3188
3189 @command(b'debugrequires|debugrequirements', [], b'')
3189 @command(b'debugrequires|debugrequirements', [], b'')
3190 def debugrequirements(ui, repo):
3190 def debugrequirements(ui, repo):
3191 """print the current repo requirements"""
3191 """print the current repo requirements"""
3192 for r in sorted(repo.requirements):
3192 for r in sorted(repo.requirements):
3193 ui.write(b"%s\n" % r)
3193 ui.write(b"%s\n" % r)
3194
3194
3195
3195
3196 @command(
3196 @command(
3197 b'debugrevlog',
3197 b'debugrevlog',
3198 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3198 cmdutil.debugrevlogopts + [(b'd', b'dump', False, _(b'dump index data'))],
3199 _(b'-c|-m|FILE'),
3199 _(b'-c|-m|FILE'),
3200 optionalrepo=True,
3200 optionalrepo=True,
3201 )
3201 )
3202 def debugrevlog(ui, repo, file_=None, **opts):
3202 def debugrevlog(ui, repo, file_=None, **opts):
3203 """show data and statistics about a revlog"""
3203 """show data and statistics about a revlog"""
3204 opts = pycompat.byteskwargs(opts)
3204 opts = pycompat.byteskwargs(opts)
3205 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
3205 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
3206
3206
3207 if opts.get(b"dump"):
3207 if opts.get(b"dump"):
3208 revlog_debug.dump(ui, r)
3208 revlog_debug.dump(ui, r)
3209 else:
3209 else:
3210 revlog_debug.debug_revlog(ui, r)
3210 revlog_debug.debug_revlog(ui, r)
3211 return 0
3211 return 0
3212
3212
3213
3213
3214 @command(
3214 @command(
3215 b'debugrevlogindex',
3215 b'debugrevlogindex',
3216 cmdutil.debugrevlogopts
3216 cmdutil.debugrevlogopts
3217 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3217 + [(b'f', b'format', 0, _(b'revlog format'), _(b'FORMAT'))],
3218 _(b'[-f FORMAT] -c|-m|FILE'),
3218 _(b'[-f FORMAT] -c|-m|FILE'),
3219 optionalrepo=True,
3219 optionalrepo=True,
3220 )
3220 )
3221 def debugrevlogindex(ui, repo, file_=None, **opts):
3221 def debugrevlogindex(ui, repo, file_=None, **opts):
3222 """dump the contents of a revlog index"""
3222 """dump the contents of a revlog index"""
3223 opts = pycompat.byteskwargs(opts)
3223 opts = pycompat.byteskwargs(opts)
3224 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
3224 r = cmdutil.openrevlog(repo, b'debugrevlogindex', file_, opts)
3225 format = opts.get(b'format', 0)
3225 format = opts.get(b'format', 0)
3226 if format not in (0, 1):
3226 if format not in (0, 1):
3227 raise error.Abort(_(b"unknown format %d") % format)
3227 raise error.Abort(_(b"unknown format %d") % format)
3228
3228
3229 if ui.debugflag:
3229 if ui.debugflag:
3230 shortfn = hex
3230 shortfn = hex
3231 else:
3231 else:
3232 shortfn = short
3232 shortfn = short
3233
3233
3234 # There might not be anything in r, so have a sane default
3234 # There might not be anything in r, so have a sane default
3235 idlen = 12
3235 idlen = 12
3236 for i in r:
3236 for i in r:
3237 idlen = len(shortfn(r.node(i)))
3237 idlen = len(shortfn(r.node(i)))
3238 break
3238 break
3239
3239
3240 if format == 0:
3240 if format == 0:
3241 if ui.verbose:
3241 if ui.verbose:
3242 ui.writenoi18n(
3242 ui.writenoi18n(
3243 b" rev offset length linkrev %s %s p2\n"
3243 b" rev offset length linkrev %s %s p2\n"
3244 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3244 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3245 )
3245 )
3246 else:
3246 else:
3247 ui.writenoi18n(
3247 ui.writenoi18n(
3248 b" rev linkrev %s %s p2\n"
3248 b" rev linkrev %s %s p2\n"
3249 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3249 % (b"nodeid".ljust(idlen), b"p1".ljust(idlen))
3250 )
3250 )
3251 elif format == 1:
3251 elif format == 1:
3252 if ui.verbose:
3252 if ui.verbose:
3253 ui.writenoi18n(
3253 ui.writenoi18n(
3254 (
3254 (
3255 b" rev flag offset length size link p1"
3255 b" rev flag offset length size link p1"
3256 b" p2 %s\n"
3256 b" p2 %s\n"
3257 )
3257 )
3258 % b"nodeid".rjust(idlen)
3258 % b"nodeid".rjust(idlen)
3259 )
3259 )
3260 else:
3260 else:
3261 ui.writenoi18n(
3261 ui.writenoi18n(
3262 b" rev flag size link p1 p2 %s\n"
3262 b" rev flag size link p1 p2 %s\n"
3263 % b"nodeid".rjust(idlen)
3263 % b"nodeid".rjust(idlen)
3264 )
3264 )
3265
3265
3266 for i in r:
3266 for i in r:
3267 node = r.node(i)
3267 node = r.node(i)
3268 if format == 0:
3268 if format == 0:
3269 try:
3269 try:
3270 pp = r.parents(node)
3270 pp = r.parents(node)
3271 except Exception:
3271 except Exception:
3272 pp = [repo.nullid, repo.nullid]
3272 pp = [repo.nullid, repo.nullid]
3273 if ui.verbose:
3273 if ui.verbose:
3274 ui.write(
3274 ui.write(
3275 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3275 b"% 6d % 9d % 7d % 7d %s %s %s\n"
3276 % (
3276 % (
3277 i,
3277 i,
3278 r.start(i),
3278 r.start(i),
3279 r.length(i),
3279 r.length(i),
3280 r.linkrev(i),
3280 r.linkrev(i),
3281 shortfn(node),
3281 shortfn(node),
3282 shortfn(pp[0]),
3282 shortfn(pp[0]),
3283 shortfn(pp[1]),
3283 shortfn(pp[1]),
3284 )
3284 )
3285 )
3285 )
3286 else:
3286 else:
3287 ui.write(
3287 ui.write(
3288 b"% 6d % 7d %s %s %s\n"
3288 b"% 6d % 7d %s %s %s\n"
3289 % (
3289 % (
3290 i,
3290 i,
3291 r.linkrev(i),
3291 r.linkrev(i),
3292 shortfn(node),
3292 shortfn(node),
3293 shortfn(pp[0]),
3293 shortfn(pp[0]),
3294 shortfn(pp[1]),
3294 shortfn(pp[1]),
3295 )
3295 )
3296 )
3296 )
3297 elif format == 1:
3297 elif format == 1:
3298 pr = r.parentrevs(i)
3298 pr = r.parentrevs(i)
3299 if ui.verbose:
3299 if ui.verbose:
3300 ui.write(
3300 ui.write(
3301 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3301 b"% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n"
3302 % (
3302 % (
3303 i,
3303 i,
3304 r.flags(i),
3304 r.flags(i),
3305 r.start(i),
3305 r.start(i),
3306 r.length(i),
3306 r.length(i),
3307 r.rawsize(i),
3307 r.rawsize(i),
3308 r.linkrev(i),
3308 r.linkrev(i),
3309 pr[0],
3309 pr[0],
3310 pr[1],
3310 pr[1],
3311 shortfn(node),
3311 shortfn(node),
3312 )
3312 )
3313 )
3313 )
3314 else:
3314 else:
3315 ui.write(
3315 ui.write(
3316 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3316 b"% 6d %04x % 8d % 6d % 6d % 6d %s\n"
3317 % (
3317 % (
3318 i,
3318 i,
3319 r.flags(i),
3319 r.flags(i),
3320 r.rawsize(i),
3320 r.rawsize(i),
3321 r.linkrev(i),
3321 r.linkrev(i),
3322 pr[0],
3322 pr[0],
3323 pr[1],
3323 pr[1],
3324 shortfn(node),
3324 shortfn(node),
3325 )
3325 )
3326 )
3326 )
3327
3327
3328
3328
3329 @command(
3329 @command(
3330 b'debugrevspec',
3330 b'debugrevspec',
3331 [
3331 [
3332 (
3332 (
3333 b'',
3333 b'',
3334 b'optimize',
3334 b'optimize',
3335 None,
3335 None,
3336 _(b'print parsed tree after optimizing (DEPRECATED)'),
3336 _(b'print parsed tree after optimizing (DEPRECATED)'),
3337 ),
3337 ),
3338 (
3338 (
3339 b'',
3339 b'',
3340 b'show-revs',
3340 b'show-revs',
3341 True,
3341 True,
3342 _(b'print list of result revisions (default)'),
3342 _(b'print list of result revisions (default)'),
3343 ),
3343 ),
3344 (
3344 (
3345 b's',
3345 b's',
3346 b'show-set',
3346 b'show-set',
3347 None,
3347 None,
3348 _(b'print internal representation of result set'),
3348 _(b'print internal representation of result set'),
3349 ),
3349 ),
3350 (
3350 (
3351 b'p',
3351 b'p',
3352 b'show-stage',
3352 b'show-stage',
3353 [],
3353 [],
3354 _(b'print parsed tree at the given stage'),
3354 _(b'print parsed tree at the given stage'),
3355 _(b'NAME'),
3355 _(b'NAME'),
3356 ),
3356 ),
3357 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3357 (b'', b'no-optimized', False, _(b'evaluate tree without optimization')),
3358 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3358 (b'', b'verify-optimized', False, _(b'verify optimized result')),
3359 ],
3359 ],
3360 b'REVSPEC',
3360 b'REVSPEC',
3361 )
3361 )
3362 def debugrevspec(ui, repo, expr, **opts):
3362 def debugrevspec(ui, repo, expr, **opts):
3363 """parse and apply a revision specification
3363 """parse and apply a revision specification
3364
3364
3365 Use -p/--show-stage option to print the parsed tree at the given stages.
3365 Use -p/--show-stage option to print the parsed tree at the given stages.
3366 Use -p all to print tree at every stage.
3366 Use -p all to print tree at every stage.
3367
3367
3368 Use --no-show-revs option with -s or -p to print only the set
3368 Use --no-show-revs option with -s or -p to print only the set
3369 representation or the parsed tree respectively.
3369 representation or the parsed tree respectively.
3370
3370
3371 Use --verify-optimized to compare the optimized result with the unoptimized
3371 Use --verify-optimized to compare the optimized result with the unoptimized
3372 one. Returns 1 if the optimized result differs.
3372 one. Returns 1 if the optimized result differs.
3373 """
3373 """
3374 opts = pycompat.byteskwargs(opts)
3374 opts = pycompat.byteskwargs(opts)
3375 aliases = ui.configitems(b'revsetalias')
3375 aliases = ui.configitems(b'revsetalias')
3376 stages = [
3376 stages = [
3377 (b'parsed', lambda tree: tree),
3377 (b'parsed', lambda tree: tree),
3378 (
3378 (
3379 b'expanded',
3379 b'expanded',
3380 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3380 lambda tree: revsetlang.expandaliases(tree, aliases, ui.warn),
3381 ),
3381 ),
3382 (b'concatenated', revsetlang.foldconcat),
3382 (b'concatenated', revsetlang.foldconcat),
3383 (b'analyzed', revsetlang.analyze),
3383 (b'analyzed', revsetlang.analyze),
3384 (b'optimized', revsetlang.optimize),
3384 (b'optimized', revsetlang.optimize),
3385 ]
3385 ]
3386 if opts[b'no_optimized']:
3386 if opts[b'no_optimized']:
3387 stages = stages[:-1]
3387 stages = stages[:-1]
3388 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3388 if opts[b'verify_optimized'] and opts[b'no_optimized']:
3389 raise error.Abort(
3389 raise error.Abort(
3390 _(b'cannot use --verify-optimized with --no-optimized')
3390 _(b'cannot use --verify-optimized with --no-optimized')
3391 )
3391 )
3392 stagenames = {n for n, f in stages}
3392 stagenames = {n for n, f in stages}
3393
3393
3394 showalways = set()
3394 showalways = set()
3395 showchanged = set()
3395 showchanged = set()
3396 if ui.verbose and not opts[b'show_stage']:
3396 if ui.verbose and not opts[b'show_stage']:
3397 # show parsed tree by --verbose (deprecated)
3397 # show parsed tree by --verbose (deprecated)
3398 showalways.add(b'parsed')
3398 showalways.add(b'parsed')
3399 showchanged.update([b'expanded', b'concatenated'])
3399 showchanged.update([b'expanded', b'concatenated'])
3400 if opts[b'optimize']:
3400 if opts[b'optimize']:
3401 showalways.add(b'optimized')
3401 showalways.add(b'optimized')
3402 if opts[b'show_stage'] and opts[b'optimize']:
3402 if opts[b'show_stage'] and opts[b'optimize']:
3403 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3403 raise error.Abort(_(b'cannot use --optimize with --show-stage'))
3404 if opts[b'show_stage'] == [b'all']:
3404 if opts[b'show_stage'] == [b'all']:
3405 showalways.update(stagenames)
3405 showalways.update(stagenames)
3406 else:
3406 else:
3407 for n in opts[b'show_stage']:
3407 for n in opts[b'show_stage']:
3408 if n not in stagenames:
3408 if n not in stagenames:
3409 raise error.Abort(_(b'invalid stage name: %s') % n)
3409 raise error.Abort(_(b'invalid stage name: %s') % n)
3410 showalways.update(opts[b'show_stage'])
3410 showalways.update(opts[b'show_stage'])
3411
3411
3412 treebystage = {}
3412 treebystage = {}
3413 printedtree = None
3413 printedtree = None
3414 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3414 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
3415 for n, f in stages:
3415 for n, f in stages:
3416 treebystage[n] = tree = f(tree)
3416 treebystage[n] = tree = f(tree)
3417 if n in showalways or (n in showchanged and tree != printedtree):
3417 if n in showalways or (n in showchanged and tree != printedtree):
3418 if opts[b'show_stage'] or n != b'parsed':
3418 if opts[b'show_stage'] or n != b'parsed':
3419 ui.write(b"* %s:\n" % n)
3419 ui.write(b"* %s:\n" % n)
3420 ui.write(revsetlang.prettyformat(tree), b"\n")
3420 ui.write(revsetlang.prettyformat(tree), b"\n")
3421 printedtree = tree
3421 printedtree = tree
3422
3422
3423 if opts[b'verify_optimized']:
3423 if opts[b'verify_optimized']:
3424 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3424 arevs = revset.makematcher(treebystage[b'analyzed'])(repo)
3425 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3425 brevs = revset.makematcher(treebystage[b'optimized'])(repo)
3426 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3426 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3427 ui.writenoi18n(
3427 ui.writenoi18n(
3428 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3428 b"* analyzed set:\n", stringutil.prettyrepr(arevs), b"\n"
3429 )
3429 )
3430 ui.writenoi18n(
3430 ui.writenoi18n(
3431 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3431 b"* optimized set:\n", stringutil.prettyrepr(brevs), b"\n"
3432 )
3432 )
3433 arevs = list(arevs)
3433 arevs = list(arevs)
3434 brevs = list(brevs)
3434 brevs = list(brevs)
3435 if arevs == brevs:
3435 if arevs == brevs:
3436 return 0
3436 return 0
3437 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3437 ui.writenoi18n(b'--- analyzed\n', label=b'diff.file_a')
3438 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3438 ui.writenoi18n(b'+++ optimized\n', label=b'diff.file_b')
3439 sm = difflib.SequenceMatcher(None, arevs, brevs)
3439 sm = difflib.SequenceMatcher(None, arevs, brevs)
3440 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3440 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3441 if tag in ('delete', 'replace'):
3441 if tag in ('delete', 'replace'):
3442 for c in arevs[alo:ahi]:
3442 for c in arevs[alo:ahi]:
3443 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3443 ui.write(b'-%d\n' % c, label=b'diff.deleted')
3444 if tag in ('insert', 'replace'):
3444 if tag in ('insert', 'replace'):
3445 for c in brevs[blo:bhi]:
3445 for c in brevs[blo:bhi]:
3446 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3446 ui.write(b'+%d\n' % c, label=b'diff.inserted')
3447 if tag == 'equal':
3447 if tag == 'equal':
3448 for c in arevs[alo:ahi]:
3448 for c in arevs[alo:ahi]:
3449 ui.write(b' %d\n' % c)
3449 ui.write(b' %d\n' % c)
3450 return 1
3450 return 1
3451
3451
3452 func = revset.makematcher(tree)
3452 func = revset.makematcher(tree)
3453 revs = func(repo)
3453 revs = func(repo)
3454 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3454 if opts[b'show_set'] or (opts[b'show_set'] is None and ui.verbose):
3455 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3455 ui.writenoi18n(b"* set:\n", stringutil.prettyrepr(revs), b"\n")
3456 if not opts[b'show_revs']:
3456 if not opts[b'show_revs']:
3457 return
3457 return
3458 for c in revs:
3458 for c in revs:
3459 ui.write(b"%d\n" % c)
3459 ui.write(b"%d\n" % c)
3460
3460
3461
3461
3462 @command(
3462 @command(
3463 b'debugserve',
3463 b'debugserve',
3464 [
3464 [
3465 (
3465 (
3466 b'',
3466 b'',
3467 b'sshstdio',
3467 b'sshstdio',
3468 False,
3468 False,
3469 _(b'run an SSH server bound to process handles'),
3469 _(b'run an SSH server bound to process handles'),
3470 ),
3470 ),
3471 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3471 (b'', b'logiofd', b'', _(b'file descriptor to log server I/O to')),
3472 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3472 (b'', b'logiofile', b'', _(b'file to log server I/O to')),
3473 ],
3473 ],
3474 b'',
3474 b'',
3475 )
3475 )
3476 def debugserve(ui, repo, **opts):
3476 def debugserve(ui, repo, **opts):
3477 """run a server with advanced settings
3477 """run a server with advanced settings
3478
3478
3479 This command is similar to :hg:`serve`. It exists partially as a
3479 This command is similar to :hg:`serve`. It exists partially as a
3480 workaround to the fact that ``hg serve --stdio`` must have specific
3480 workaround to the fact that ``hg serve --stdio`` must have specific
3481 arguments for security reasons.
3481 arguments for security reasons.
3482 """
3482 """
3483 opts = pycompat.byteskwargs(opts)
3483 opts = pycompat.byteskwargs(opts)
3484
3484
3485 if not opts[b'sshstdio']:
3485 if not opts[b'sshstdio']:
3486 raise error.Abort(_(b'only --sshstdio is currently supported'))
3486 raise error.Abort(_(b'only --sshstdio is currently supported'))
3487
3487
3488 logfh = None
3488 logfh = None
3489
3489
3490 if opts[b'logiofd'] and opts[b'logiofile']:
3490 if opts[b'logiofd'] and opts[b'logiofile']:
3491 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3491 raise error.Abort(_(b'cannot use both --logiofd and --logiofile'))
3492
3492
3493 if opts[b'logiofd']:
3493 if opts[b'logiofd']:
3494 # Ideally we would be line buffered. But line buffering in binary
3494 # Ideally we would be line buffered. But line buffering in binary
3495 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3495 # mode isn't supported and emits a warning in Python 3.8+. Disabling
3496 # buffering could have performance impacts. But since this isn't
3496 # buffering could have performance impacts. But since this isn't
3497 # performance critical code, it should be fine.
3497 # performance critical code, it should be fine.
3498 try:
3498 try:
3499 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3499 logfh = os.fdopen(int(opts[b'logiofd']), 'ab', 0)
3500 except OSError as e:
3500 except OSError as e:
3501 if e.errno != errno.ESPIPE:
3501 if e.errno != errno.ESPIPE:
3502 raise
3502 raise
3503 # can't seek a pipe, so `ab` mode fails on py3
3503 # can't seek a pipe, so `ab` mode fails on py3
3504 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3504 logfh = os.fdopen(int(opts[b'logiofd']), 'wb', 0)
3505 elif opts[b'logiofile']:
3505 elif opts[b'logiofile']:
3506 logfh = open(opts[b'logiofile'], b'ab', 0)
3506 logfh = open(opts[b'logiofile'], b'ab', 0)
3507
3507
3508 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3508 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
3509 s.serve_forever()
3509 s.serve_forever()
3510
3510
3511
3511
3512 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3512 @command(b'debugsetparents', [], _(b'REV1 [REV2]'))
3513 def debugsetparents(ui, repo, rev1, rev2=None):
3513 def debugsetparents(ui, repo, rev1, rev2=None):
3514 """manually set the parents of the current working directory (DANGEROUS)
3514 """manually set the parents of the current working directory (DANGEROUS)
3515
3515
3516 This command is not what you are looking for and should not be used. Using
3516 This command is not what you are looking for and should not be used. Using
3517 this command will most certainly results in slight corruption of the file
3517 this command will most certainly results in slight corruption of the file
3518 level histories withing your repository. DO NOT USE THIS COMMAND.
3518 level histories withing your repository. DO NOT USE THIS COMMAND.
3519
3519
3520 The command update the p1 and p2 field in the dirstate, and not touching
3520 The command update the p1 and p2 field in the dirstate, and not touching
3521 anything else. This useful for writing repository conversion tools, but
3521 anything else. This useful for writing repository conversion tools, but
3522 should be used with extreme care. For example, neither the working
3522 should be used with extreme care. For example, neither the working
3523 directory nor the dirstate is updated, so file status may be incorrect
3523 directory nor the dirstate is updated, so file status may be incorrect
3524 after running this command. Only used if you are one of the few people that
3524 after running this command. Only used if you are one of the few people that
3525 deeply unstand both conversion tools and file level histories. If you are
3525 deeply unstand both conversion tools and file level histories. If you are
3526 reading this help, you are not one of this people (most of them sailed west
3526 reading this help, you are not one of this people (most of them sailed west
3527 from Mithlond anyway.
3527 from Mithlond anyway.
3528
3528
3529 So one last time DO NOT USE THIS COMMAND.
3529 So one last time DO NOT USE THIS COMMAND.
3530
3530
3531 Returns 0 on success.
3531 Returns 0 on success.
3532 """
3532 """
3533
3533
3534 node1 = scmutil.revsingle(repo, rev1).node()
3534 node1 = scmutil.revsingle(repo, rev1).node()
3535 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3535 node2 = scmutil.revsingle(repo, rev2, b'null').node()
3536
3536
3537 with repo.wlock():
3537 with repo.wlock():
3538 repo.setparents(node1, node2)
3538 repo.setparents(node1, node2)
3539
3539
3540
3540
3541 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3541 @command(b'debugsidedata', cmdutil.debugrevlogopts, _(b'-c|-m|FILE REV'))
3542 def debugsidedata(ui, repo, file_, rev=None, **opts):
3542 def debugsidedata(ui, repo, file_, rev=None, **opts):
3543 """dump the side data for a cl/manifest/file revision
3543 """dump the side data for a cl/manifest/file revision
3544
3544
3545 Use --verbose to dump the sidedata content."""
3545 Use --verbose to dump the sidedata content."""
3546 opts = pycompat.byteskwargs(opts)
3546 opts = pycompat.byteskwargs(opts)
3547 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3547 if opts.get(b'changelog') or opts.get(b'manifest') or opts.get(b'dir'):
3548 if rev is not None:
3548 if rev is not None:
3549 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3549 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3550 file_, rev = None, file_
3550 file_, rev = None, file_
3551 elif rev is None:
3551 elif rev is None:
3552 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3552 raise error.CommandError(b'debugdata', _(b'invalid arguments'))
3553 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3553 r = cmdutil.openstorage(repo, b'debugdata', file_, opts)
3554 r = getattr(r, '_revlog', r)
3554 r = getattr(r, '_revlog', r)
3555 try:
3555 try:
3556 sidedata = r.sidedata(r.lookup(rev))
3556 sidedata = r.sidedata(r.lookup(rev))
3557 except KeyError:
3557 except KeyError:
3558 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3558 raise error.Abort(_(b'invalid revision identifier %s') % rev)
3559 if sidedata:
3559 if sidedata:
3560 sidedata = list(sidedata.items())
3560 sidedata = list(sidedata.items())
3561 sidedata.sort()
3561 sidedata.sort()
3562 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3562 ui.writenoi18n(b'%d sidedata entries\n' % len(sidedata))
3563 for key, value in sidedata:
3563 for key, value in sidedata:
3564 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3564 ui.writenoi18n(b' entry-%04o size %d\n' % (key, len(value)))
3565 if ui.verbose:
3565 if ui.verbose:
3566 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3566 ui.writenoi18n(b' %s\n' % stringutil.pprint(value))
3567
3567
3568
3568
3569 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3569 @command(b'debugssl', [], b'[SOURCE]', optionalrepo=True)
3570 def debugssl(ui, repo, source=None, **opts):
3570 def debugssl(ui, repo, source=None, **opts):
3571 """test a secure connection to a server
3571 """test a secure connection to a server
3572
3572
3573 This builds the certificate chain for the server on Windows, installing the
3573 This builds the certificate chain for the server on Windows, installing the
3574 missing intermediates and trusted root via Windows Update if necessary. It
3574 missing intermediates and trusted root via Windows Update if necessary. It
3575 does nothing on other platforms.
3575 does nothing on other platforms.
3576
3576
3577 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3577 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
3578 that server is used. See :hg:`help urls` for more information.
3578 that server is used. See :hg:`help urls` for more information.
3579
3579
3580 If the update succeeds, retry the original operation. Otherwise, the cause
3580 If the update succeeds, retry the original operation. Otherwise, the cause
3581 of the SSL error is likely another issue.
3581 of the SSL error is likely another issue.
3582 """
3582 """
3583 if not pycompat.iswindows:
3583 if not pycompat.iswindows:
3584 raise error.Abort(
3584 raise error.Abort(
3585 _(b'certificate chain building is only possible on Windows')
3585 _(b'certificate chain building is only possible on Windows')
3586 )
3586 )
3587
3587
3588 if not source:
3588 if not source:
3589 if not repo:
3589 if not repo:
3590 raise error.Abort(
3590 raise error.Abort(
3591 _(
3591 _(
3592 b"there is no Mercurial repository here, and no "
3592 b"there is no Mercurial repository here, and no "
3593 b"server specified"
3593 b"server specified"
3594 )
3594 )
3595 )
3595 )
3596 source = b"default"
3596 source = b"default"
3597
3597
3598 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3598 path = urlutil.get_unique_pull_path_obj(b'debugssl', ui, source)
3599 url = path.url
3599 url = path.url
3600
3600
3601 defaultport = {b'https': 443, b'ssh': 22}
3601 defaultport = {b'https': 443, b'ssh': 22}
3602 if url.scheme in defaultport:
3602 if url.scheme in defaultport:
3603 try:
3603 try:
3604 addr = (url.host, int(url.port or defaultport[url.scheme]))
3604 addr = (url.host, int(url.port or defaultport[url.scheme]))
3605 except ValueError:
3605 except ValueError:
3606 raise error.Abort(_(b"malformed port number in URL"))
3606 raise error.Abort(_(b"malformed port number in URL"))
3607 else:
3607 else:
3608 raise error.Abort(_(b"only https and ssh connections are supported"))
3608 raise error.Abort(_(b"only https and ssh connections are supported"))
3609
3609
3610 from . import win32
3610 from . import win32
3611
3611
3612 s = ssl.wrap_socket(
3612 s = ssl.wrap_socket(
3613 socket.socket(),
3613 socket.socket(),
3614 ssl_version=ssl.PROTOCOL_TLS,
3614 ssl_version=ssl.PROTOCOL_TLS,
3615 cert_reqs=ssl.CERT_NONE,
3615 cert_reqs=ssl.CERT_NONE,
3616 ca_certs=None,
3616 ca_certs=None,
3617 )
3617 )
3618
3618
3619 try:
3619 try:
3620 s.connect(addr)
3620 s.connect(addr)
3621 cert = s.getpeercert(True)
3621 cert = s.getpeercert(True)
3622
3622
3623 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3623 ui.status(_(b'checking the certificate chain for %s\n') % url.host)
3624
3624
3625 complete = win32.checkcertificatechain(cert, build=False)
3625 complete = win32.checkcertificatechain(cert, build=False)
3626
3626
3627 if not complete:
3627 if not complete:
3628 ui.status(_(b'certificate chain is incomplete, updating... '))
3628 ui.status(_(b'certificate chain is incomplete, updating... '))
3629
3629
3630 if not win32.checkcertificatechain(cert):
3630 if not win32.checkcertificatechain(cert):
3631 ui.status(_(b'failed.\n'))
3631 ui.status(_(b'failed.\n'))
3632 else:
3632 else:
3633 ui.status(_(b'done.\n'))
3633 ui.status(_(b'done.\n'))
3634 else:
3634 else:
3635 ui.status(_(b'full certificate chain is available\n'))
3635 ui.status(_(b'full certificate chain is available\n'))
3636 finally:
3636 finally:
3637 s.close()
3637 s.close()
3638
3638
3639
3639
3640 @command(
3640 @command(
3641 b"debugbackupbundle",
3641 b"debugbackupbundle",
3642 [
3642 [
3643 (
3643 (
3644 b"",
3644 b"",
3645 b"recover",
3645 b"recover",
3646 b"",
3646 b"",
3647 b"brings the specified changeset back into the repository",
3647 b"brings the specified changeset back into the repository",
3648 )
3648 )
3649 ]
3649 ]
3650 + cmdutil.logopts,
3650 + cmdutil.logopts,
3651 _(b"hg debugbackupbundle [--recover HASH]"),
3651 _(b"hg debugbackupbundle [--recover HASH]"),
3652 )
3652 )
3653 def debugbackupbundle(ui, repo, *pats, **opts):
3653 def debugbackupbundle(ui, repo, *pats, **opts):
3654 """lists the changesets available in backup bundles
3654 """lists the changesets available in backup bundles
3655
3655
3656 Without any arguments, this command prints a list of the changesets in each
3656 Without any arguments, this command prints a list of the changesets in each
3657 backup bundle.
3657 backup bundle.
3658
3658
3659 --recover takes a changeset hash and unbundles the first bundle that
3659 --recover takes a changeset hash and unbundles the first bundle that
3660 contains that hash, which puts that changeset back in your repository.
3660 contains that hash, which puts that changeset back in your repository.
3661
3661
3662 --verbose will print the entire commit message and the bundle path for that
3662 --verbose will print the entire commit message and the bundle path for that
3663 backup.
3663 backup.
3664 """
3664 """
3665 backups = list(
3665 backups = list(
3666 filter(
3666 filter(
3667 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3667 os.path.isfile, glob.glob(repo.vfs.join(b"strip-backup") + b"/*.hg")
3668 )
3668 )
3669 )
3669 )
3670 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3670 backups.sort(key=lambda x: os.path.getmtime(x), reverse=True)
3671
3671
3672 opts = pycompat.byteskwargs(opts)
3672 opts = pycompat.byteskwargs(opts)
3673 opts[b"bundle"] = b""
3673 opts[b"bundle"] = b""
3674 opts[b"force"] = None
3674 opts[b"force"] = None
3675 limit = logcmdutil.getlimit(opts)
3675 limit = logcmdutil.getlimit(opts)
3676
3676
3677 def display(other, chlist, displayer):
3677 def display(other, chlist, displayer):
3678 if opts.get(b"newest_first"):
3678 if opts.get(b"newest_first"):
3679 chlist.reverse()
3679 chlist.reverse()
3680 count = 0
3680 count = 0
3681 for n in chlist:
3681 for n in chlist:
3682 if limit is not None and count >= limit:
3682 if limit is not None and count >= limit:
3683 break
3683 break
3684 parents = [
3684 parents = [
3685 True for p in other.changelog.parents(n) if p != repo.nullid
3685 True for p in other.changelog.parents(n) if p != repo.nullid
3686 ]
3686 ]
3687 if opts.get(b"no_merges") and len(parents) == 2:
3687 if opts.get(b"no_merges") and len(parents) == 2:
3688 continue
3688 continue
3689 count += 1
3689 count += 1
3690 displayer.show(other[n])
3690 displayer.show(other[n])
3691
3691
3692 recovernode = opts.get(b"recover")
3692 recovernode = opts.get(b"recover")
3693 if recovernode:
3693 if recovernode:
3694 if scmutil.isrevsymbol(repo, recovernode):
3694 if scmutil.isrevsymbol(repo, recovernode):
3695 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3695 ui.warn(_(b"%s already exists in the repo\n") % recovernode)
3696 return
3696 return
3697 elif backups:
3697 elif backups:
3698 msg = _(
3698 msg = _(
3699 b"Recover changesets using: hg debugbackupbundle --recover "
3699 b"Recover changesets using: hg debugbackupbundle --recover "
3700 b"<changeset hash>\n\nAvailable backup changesets:"
3700 b"<changeset hash>\n\nAvailable backup changesets:"
3701 )
3701 )
3702 ui.status(msg, label=b"status.removed")
3702 ui.status(msg, label=b"status.removed")
3703 else:
3703 else:
3704 ui.status(_(b"no backup changesets found\n"))
3704 ui.status(_(b"no backup changesets found\n"))
3705 return
3705 return
3706
3706
3707 for backup in backups:
3707 for backup in backups:
3708 # Much of this is copied from the hg incoming logic
3708 # Much of this is copied from the hg incoming logic
3709 source = os.path.relpath(backup, encoding.getcwd())
3709 source = os.path.relpath(backup, encoding.getcwd())
3710 path = urlutil.get_unique_pull_path_obj(
3710 path = urlutil.get_unique_pull_path_obj(
3711 b'debugbackupbundle',
3711 b'debugbackupbundle',
3712 ui,
3712 ui,
3713 source,
3713 source,
3714 )
3714 )
3715 try:
3715 try:
3716 other = hg.peer(repo, opts, path)
3716 other = hg.peer(repo, opts, path)
3717 except error.LookupError as ex:
3717 except error.LookupError as ex:
3718 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3718 msg = _(b"\nwarning: unable to open bundle %s") % path.loc
3719 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3719 hint = _(b"\n(missing parent rev %s)\n") % short(ex.name)
3720 ui.warn(msg, hint=hint)
3720 ui.warn(msg, hint=hint)
3721 continue
3721 continue
3722 branches = (path.branch, opts.get(b'branch', []))
3722 branches = (path.branch, opts.get(b'branch', []))
3723 revs, checkout = hg.addbranchrevs(
3723 revs, checkout = hg.addbranchrevs(
3724 repo, other, branches, opts.get(b"rev")
3724 repo, other, branches, opts.get(b"rev")
3725 )
3725 )
3726
3726
3727 if revs:
3727 if revs:
3728 revs = [other.lookup(rev) for rev in revs]
3728 revs = [other.lookup(rev) for rev in revs]
3729
3729
3730 with ui.silent():
3730 with ui.silent():
3731 try:
3731 try:
3732 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3732 other, chlist, cleanupfn = bundlerepo.getremotechanges(
3733 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
3733 ui, repo, other, revs, opts[b"bundle"], opts[b"force"]
3734 )
3734 )
3735 except error.LookupError:
3735 except error.LookupError:
3736 continue
3736 continue
3737
3737
3738 try:
3738 try:
3739 if not chlist:
3739 if not chlist:
3740 continue
3740 continue
3741 if recovernode:
3741 if recovernode:
3742 with repo.lock(), repo.transaction(b"unbundle") as tr:
3742 with repo.lock(), repo.transaction(b"unbundle") as tr:
3743 if scmutil.isrevsymbol(other, recovernode):
3743 if scmutil.isrevsymbol(other, recovernode):
3744 ui.status(_(b"Unbundling %s\n") % (recovernode))
3744 ui.status(_(b"Unbundling %s\n") % (recovernode))
3745 f = hg.openpath(ui, path.loc)
3745 f = hg.openpath(ui, path.loc)
3746 gen = exchange.readbundle(ui, f, path.loc)
3746 gen = exchange.readbundle(ui, f, path.loc)
3747 if isinstance(gen, bundle2.unbundle20):
3747 if isinstance(gen, bundle2.unbundle20):
3748 bundle2.applybundle(
3748 bundle2.applybundle(
3749 repo,
3749 repo,
3750 gen,
3750 gen,
3751 tr,
3751 tr,
3752 source=b"unbundle",
3752 source=b"unbundle",
3753 url=b"bundle:" + path.loc,
3753 url=b"bundle:" + path.loc,
3754 )
3754 )
3755 else:
3755 else:
3756 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3756 gen.apply(repo, b"unbundle", b"bundle:" + path.loc)
3757 break
3757 break
3758 else:
3758 else:
3759 backupdate = encoding.strtolocal(
3759 backupdate = encoding.strtolocal(
3760 time.strftime(
3760 time.strftime(
3761 "%a %H:%M, %Y-%m-%d",
3761 "%a %H:%M, %Y-%m-%d",
3762 time.localtime(os.path.getmtime(path.loc)),
3762 time.localtime(os.path.getmtime(path.loc)),
3763 )
3763 )
3764 )
3764 )
3765 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3765 ui.status(b"\n%s\n" % (backupdate.ljust(50)))
3766 if ui.verbose:
3766 if ui.verbose:
3767 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3767 ui.status(b"%s%s\n" % (b"bundle:".ljust(13), path.loc))
3768 else:
3768 else:
3769 opts[
3769 opts[
3770 b"template"
3770 b"template"
3771 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3771 ] = b"{label('status.modified', node|short)} {desc|firstline}\n"
3772 displayer = logcmdutil.changesetdisplayer(
3772 displayer = logcmdutil.changesetdisplayer(
3773 ui, other, opts, False
3773 ui, other, opts, False
3774 )
3774 )
3775 display(other, chlist, displayer)
3775 display(other, chlist, displayer)
3776 displayer.close()
3776 displayer.close()
3777 finally:
3777 finally:
3778 cleanupfn()
3778 cleanupfn()
3779
3779
3780
3780
3781 @command(
3781 @command(
3782 b'debugsub',
3782 b'debugsub',
3783 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3783 [(b'r', b'rev', b'', _(b'revision to check'), _(b'REV'))],
3784 _(b'[-r REV] [REV]'),
3784 _(b'[-r REV] [REV]'),
3785 )
3785 )
3786 def debugsub(ui, repo, rev=None):
3786 def debugsub(ui, repo, rev=None):
3787 ctx = scmutil.revsingle(repo, rev, None)
3787 ctx = scmutil.revsingle(repo, rev, None)
3788 for k, v in sorted(ctx.substate.items()):
3788 for k, v in sorted(ctx.substate.items()):
3789 ui.writenoi18n(b'path %s\n' % k)
3789 ui.writenoi18n(b'path %s\n' % k)
3790 ui.writenoi18n(b' source %s\n' % v[0])
3790 ui.writenoi18n(b' source %s\n' % v[0])
3791 ui.writenoi18n(b' revision %s\n' % v[1])
3791 ui.writenoi18n(b' revision %s\n' % v[1])
3792
3792
3793
3793
3794 @command(b'debugshell', optionalrepo=True)
3794 @command(b'debugshell', optionalrepo=True)
3795 def debugshell(ui, repo):
3795 def debugshell(ui, repo):
3796 """run an interactive Python interpreter
3796 """run an interactive Python interpreter
3797
3797
3798 The local namespace is provided with a reference to the ui and
3798 The local namespace is provided with a reference to the ui and
3799 the repo instance (if available).
3799 the repo instance (if available).
3800 """
3800 """
3801 import code
3801 import code
3802
3802
3803 imported_objects = {
3803 imported_objects = {
3804 'ui': ui,
3804 'ui': ui,
3805 'repo': repo,
3805 'repo': repo,
3806 }
3806 }
3807
3807
3808 code.interact(local=imported_objects)
3808 code.interact(local=imported_objects)
3809
3809
3810
3810
3811 @command(
3811 @command(
3812 b'debug-revlog-stats',
3813 [
3814 (b'c', b'changelog', None, _(b'Display changelog statistics')),
3815 (b'm', b'manifest', None, _(b'Display manifest statistics')),
3816 (b'f', b'filelogs', None, _(b'Display filelogs statistics')),
3817 ]
3818 + cmdutil.formatteropts,
3819 )
3820 def debug_revlog_stats(ui, repo, **opts):
3821 """display statistics about revlogs in the store"""
3822 opts = pycompat.byteskwargs(opts)
3823 changelog = opts[b"changelog"]
3824 manifest = opts[b"manifest"]
3825 filelogs = opts[b"filelogs"]
3826
3827 if changelog is None and manifest is None and filelogs is None:
3828 changelog = True
3829 manifest = True
3830 filelogs = True
3831
3832 repo = repo.unfiltered()
3833 fm = ui.formatter(b'debug-revlog-stats', opts)
3834 revlog_debug.debug_revlog_stats(repo, fm, changelog, manifest, filelogs)
3835 fm.end()
3836
3837
3838 @command(
3812 b'debugsuccessorssets',
3839 b'debugsuccessorssets',
3813 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3840 [(b'', b'closest', False, _(b'return closest successors sets only'))],
3814 _(b'[REV]'),
3841 _(b'[REV]'),
3815 )
3842 )
3816 def debugsuccessorssets(ui, repo, *revs, **opts):
3843 def debugsuccessorssets(ui, repo, *revs, **opts):
3817 """show set of successors for revision
3844 """show set of successors for revision
3818
3845
3819 A successors set of changeset A is a consistent group of revisions that
3846 A successors set of changeset A is a consistent group of revisions that
3820 succeed A. It contains non-obsolete changesets only unless closests
3847 succeed A. It contains non-obsolete changesets only unless closests
3821 successors set is set.
3848 successors set is set.
3822
3849
3823 In most cases a changeset A has a single successors set containing a single
3850 In most cases a changeset A has a single successors set containing a single
3824 successor (changeset A replaced by A').
3851 successor (changeset A replaced by A').
3825
3852
3826 A changeset that is made obsolete with no successors are called "pruned".
3853 A changeset that is made obsolete with no successors are called "pruned".
3827 Such changesets have no successors sets at all.
3854 Such changesets have no successors sets at all.
3828
3855
3829 A changeset that has been "split" will have a successors set containing
3856 A changeset that has been "split" will have a successors set containing
3830 more than one successor.
3857 more than one successor.
3831
3858
3832 A changeset that has been rewritten in multiple different ways is called
3859 A changeset that has been rewritten in multiple different ways is called
3833 "divergent". Such changesets have multiple successor sets (each of which
3860 "divergent". Such changesets have multiple successor sets (each of which
3834 may also be split, i.e. have multiple successors).
3861 may also be split, i.e. have multiple successors).
3835
3862
3836 Results are displayed as follows::
3863 Results are displayed as follows::
3837
3864
3838 <rev1>
3865 <rev1>
3839 <successors-1A>
3866 <successors-1A>
3840 <rev2>
3867 <rev2>
3841 <successors-2A>
3868 <successors-2A>
3842 <successors-2B1> <successors-2B2> <successors-2B3>
3869 <successors-2B1> <successors-2B2> <successors-2B3>
3843
3870
3844 Here rev2 has two possible (i.e. divergent) successors sets. The first
3871 Here rev2 has two possible (i.e. divergent) successors sets. The first
3845 holds one element, whereas the second holds three (i.e. the changeset has
3872 holds one element, whereas the second holds three (i.e. the changeset has
3846 been split).
3873 been split).
3847 """
3874 """
3848 # passed to successorssets caching computation from one call to another
3875 # passed to successorssets caching computation from one call to another
3849 cache = {}
3876 cache = {}
3850 ctx2str = bytes
3877 ctx2str = bytes
3851 node2str = short
3878 node2str = short
3852 for rev in logcmdutil.revrange(repo, revs):
3879 for rev in logcmdutil.revrange(repo, revs):
3853 ctx = repo[rev]
3880 ctx = repo[rev]
3854 ui.write(b'%s\n' % ctx2str(ctx))
3881 ui.write(b'%s\n' % ctx2str(ctx))
3855 for succsset in obsutil.successorssets(
3882 for succsset in obsutil.successorssets(
3856 repo, ctx.node(), closest=opts['closest'], cache=cache
3883 repo, ctx.node(), closest=opts['closest'], cache=cache
3857 ):
3884 ):
3858 if succsset:
3885 if succsset:
3859 ui.write(b' ')
3886 ui.write(b' ')
3860 ui.write(node2str(succsset[0]))
3887 ui.write(node2str(succsset[0]))
3861 for node in succsset[1:]:
3888 for node in succsset[1:]:
3862 ui.write(b' ')
3889 ui.write(b' ')
3863 ui.write(node2str(node))
3890 ui.write(node2str(node))
3864 ui.write(b'\n')
3891 ui.write(b'\n')
3865
3892
3866
3893
3867 @command(b'debugtagscache', [])
3894 @command(b'debugtagscache', [])
3868 def debugtagscache(ui, repo):
3895 def debugtagscache(ui, repo):
3869 """display the contents of .hg/cache/hgtagsfnodes1"""
3896 """display the contents of .hg/cache/hgtagsfnodes1"""
3870 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3897 cache = tagsmod.hgtagsfnodescache(repo.unfiltered())
3871 flog = repo.file(b'.hgtags')
3898 flog = repo.file(b'.hgtags')
3872 for r in repo:
3899 for r in repo:
3873 node = repo[r].node()
3900 node = repo[r].node()
3874 tagsnode = cache.getfnode(node, computemissing=False)
3901 tagsnode = cache.getfnode(node, computemissing=False)
3875 if tagsnode:
3902 if tagsnode:
3876 tagsnodedisplay = hex(tagsnode)
3903 tagsnodedisplay = hex(tagsnode)
3877 if not flog.hasnode(tagsnode):
3904 if not flog.hasnode(tagsnode):
3878 tagsnodedisplay += b' (unknown node)'
3905 tagsnodedisplay += b' (unknown node)'
3879 elif tagsnode is None:
3906 elif tagsnode is None:
3880 tagsnodedisplay = b'missing'
3907 tagsnodedisplay = b'missing'
3881 else:
3908 else:
3882 tagsnodedisplay = b'invalid'
3909 tagsnodedisplay = b'invalid'
3883
3910
3884 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3911 ui.write(b'%d %s %s\n' % (r, hex(node), tagsnodedisplay))
3885
3912
3886
3913
3887 @command(
3914 @command(
3888 b'debugtemplate',
3915 b'debugtemplate',
3889 [
3916 [
3890 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3917 (b'r', b'rev', [], _(b'apply template on changesets'), _(b'REV')),
3891 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3918 (b'D', b'define', [], _(b'define template keyword'), _(b'KEY=VALUE')),
3892 ],
3919 ],
3893 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3920 _(b'[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
3894 optionalrepo=True,
3921 optionalrepo=True,
3895 )
3922 )
3896 def debugtemplate(ui, repo, tmpl, **opts):
3923 def debugtemplate(ui, repo, tmpl, **opts):
3897 """parse and apply a template
3924 """parse and apply a template
3898
3925
3899 If -r/--rev is given, the template is processed as a log template and
3926 If -r/--rev is given, the template is processed as a log template and
3900 applied to the given changesets. Otherwise, it is processed as a generic
3927 applied to the given changesets. Otherwise, it is processed as a generic
3901 template.
3928 template.
3902
3929
3903 Use --verbose to print the parsed tree.
3930 Use --verbose to print the parsed tree.
3904 """
3931 """
3905 revs = None
3932 revs = None
3906 if opts['rev']:
3933 if opts['rev']:
3907 if repo is None:
3934 if repo is None:
3908 raise error.RepoError(
3935 raise error.RepoError(
3909 _(b'there is no Mercurial repository here (.hg not found)')
3936 _(b'there is no Mercurial repository here (.hg not found)')
3910 )
3937 )
3911 revs = logcmdutil.revrange(repo, opts['rev'])
3938 revs = logcmdutil.revrange(repo, opts['rev'])
3912
3939
3913 props = {}
3940 props = {}
3914 for d in opts['define']:
3941 for d in opts['define']:
3915 try:
3942 try:
3916 k, v = (e.strip() for e in d.split(b'=', 1))
3943 k, v = (e.strip() for e in d.split(b'=', 1))
3917 if not k or k == b'ui':
3944 if not k or k == b'ui':
3918 raise ValueError
3945 raise ValueError
3919 props[k] = v
3946 props[k] = v
3920 except ValueError:
3947 except ValueError:
3921 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3948 raise error.Abort(_(b'malformed keyword definition: %s') % d)
3922
3949
3923 if ui.verbose:
3950 if ui.verbose:
3924 aliases = ui.configitems(b'templatealias')
3951 aliases = ui.configitems(b'templatealias')
3925 tree = templater.parse(tmpl)
3952 tree = templater.parse(tmpl)
3926 ui.note(templater.prettyformat(tree), b'\n')
3953 ui.note(templater.prettyformat(tree), b'\n')
3927 newtree = templater.expandaliases(tree, aliases)
3954 newtree = templater.expandaliases(tree, aliases)
3928 if newtree != tree:
3955 if newtree != tree:
3929 ui.notenoi18n(
3956 ui.notenoi18n(
3930 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3957 b"* expanded:\n", templater.prettyformat(newtree), b'\n'
3931 )
3958 )
3932
3959
3933 if revs is None:
3960 if revs is None:
3934 tres = formatter.templateresources(ui, repo)
3961 tres = formatter.templateresources(ui, repo)
3935 t = formatter.maketemplater(ui, tmpl, resources=tres)
3962 t = formatter.maketemplater(ui, tmpl, resources=tres)
3936 if ui.verbose:
3963 if ui.verbose:
3937 kwds, funcs = t.symbolsuseddefault()
3964 kwds, funcs = t.symbolsuseddefault()
3938 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3965 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3939 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3966 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3940 ui.write(t.renderdefault(props))
3967 ui.write(t.renderdefault(props))
3941 else:
3968 else:
3942 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3969 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
3943 if ui.verbose:
3970 if ui.verbose:
3944 kwds, funcs = displayer.t.symbolsuseddefault()
3971 kwds, funcs = displayer.t.symbolsuseddefault()
3945 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3972 ui.writenoi18n(b"* keywords: %s\n" % b', '.join(sorted(kwds)))
3946 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3973 ui.writenoi18n(b"* functions: %s\n" % b', '.join(sorted(funcs)))
3947 for r in revs:
3974 for r in revs:
3948 displayer.show(repo[r], **pycompat.strkwargs(props))
3975 displayer.show(repo[r], **pycompat.strkwargs(props))
3949 displayer.close()
3976 displayer.close()
3950
3977
3951
3978
3952 @command(
3979 @command(
3953 b'debuguigetpass',
3980 b'debuguigetpass',
3954 [
3981 [
3955 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3982 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3956 ],
3983 ],
3957 _(b'[-p TEXT]'),
3984 _(b'[-p TEXT]'),
3958 norepo=True,
3985 norepo=True,
3959 )
3986 )
3960 def debuguigetpass(ui, prompt=b''):
3987 def debuguigetpass(ui, prompt=b''):
3961 """show prompt to type password"""
3988 """show prompt to type password"""
3962 r = ui.getpass(prompt)
3989 r = ui.getpass(prompt)
3963 if r is None:
3990 if r is None:
3964 r = b"<default response>"
3991 r = b"<default response>"
3965 ui.writenoi18n(b'response: %s\n' % r)
3992 ui.writenoi18n(b'response: %s\n' % r)
3966
3993
3967
3994
3968 @command(
3995 @command(
3969 b'debuguiprompt',
3996 b'debuguiprompt',
3970 [
3997 [
3971 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3998 (b'p', b'prompt', b'', _(b'prompt text'), _(b'TEXT')),
3972 ],
3999 ],
3973 _(b'[-p TEXT]'),
4000 _(b'[-p TEXT]'),
3974 norepo=True,
4001 norepo=True,
3975 )
4002 )
3976 def debuguiprompt(ui, prompt=b''):
4003 def debuguiprompt(ui, prompt=b''):
3977 """show plain prompt"""
4004 """show plain prompt"""
3978 r = ui.prompt(prompt)
4005 r = ui.prompt(prompt)
3979 ui.writenoi18n(b'response: %s\n' % r)
4006 ui.writenoi18n(b'response: %s\n' % r)
3980
4007
3981
4008
3982 @command(b'debugupdatecaches', [])
4009 @command(b'debugupdatecaches', [])
3983 def debugupdatecaches(ui, repo, *pats, **opts):
4010 def debugupdatecaches(ui, repo, *pats, **opts):
3984 """warm all known caches in the repository"""
4011 """warm all known caches in the repository"""
3985 with repo.wlock(), repo.lock():
4012 with repo.wlock(), repo.lock():
3986 repo.updatecaches(caches=repository.CACHES_ALL)
4013 repo.updatecaches(caches=repository.CACHES_ALL)
3987
4014
3988
4015
3989 @command(
4016 @command(
3990 b'debugupgraderepo',
4017 b'debugupgraderepo',
3991 [
4018 [
3992 (
4019 (
3993 b'o',
4020 b'o',
3994 b'optimize',
4021 b'optimize',
3995 [],
4022 [],
3996 _(b'extra optimization to perform'),
4023 _(b'extra optimization to perform'),
3997 _(b'NAME'),
4024 _(b'NAME'),
3998 ),
4025 ),
3999 (b'', b'run', False, _(b'performs an upgrade')),
4026 (b'', b'run', False, _(b'performs an upgrade')),
4000 (b'', b'backup', True, _(b'keep the old repository content around')),
4027 (b'', b'backup', True, _(b'keep the old repository content around')),
4001 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4028 (b'', b'changelog', None, _(b'select the changelog for upgrade')),
4002 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4029 (b'', b'manifest', None, _(b'select the manifest for upgrade')),
4003 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4030 (b'', b'filelogs', None, _(b'select all filelogs for upgrade')),
4004 ],
4031 ],
4005 )
4032 )
4006 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4033 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True, **opts):
4007 """upgrade a repository to use different features
4034 """upgrade a repository to use different features
4008
4035
4009 If no arguments are specified, the repository is evaluated for upgrade
4036 If no arguments are specified, the repository is evaluated for upgrade
4010 and a list of problems and potential optimizations is printed.
4037 and a list of problems and potential optimizations is printed.
4011
4038
4012 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4039 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
4013 can be influenced via additional arguments. More details will be provided
4040 can be influenced via additional arguments. More details will be provided
4014 by the command output when run without ``--run``.
4041 by the command output when run without ``--run``.
4015
4042
4016 During the upgrade, the repository will be locked and no writes will be
4043 During the upgrade, the repository will be locked and no writes will be
4017 allowed.
4044 allowed.
4018
4045
4019 At the end of the upgrade, the repository may not be readable while new
4046 At the end of the upgrade, the repository may not be readable while new
4020 repository data is swapped in. This window will be as long as it takes to
4047 repository data is swapped in. This window will be as long as it takes to
4021 rename some directories inside the ``.hg`` directory. On most machines, this
4048 rename some directories inside the ``.hg`` directory. On most machines, this
4022 should complete almost instantaneously and the chances of a consumer being
4049 should complete almost instantaneously and the chances of a consumer being
4023 unable to access the repository should be low.
4050 unable to access the repository should be low.
4024
4051
4025 By default, all revlogs will be upgraded. You can restrict this using flags
4052 By default, all revlogs will be upgraded. You can restrict this using flags
4026 such as `--manifest`:
4053 such as `--manifest`:
4027
4054
4028 * `--manifest`: only optimize the manifest
4055 * `--manifest`: only optimize the manifest
4029 * `--no-manifest`: optimize all revlog but the manifest
4056 * `--no-manifest`: optimize all revlog but the manifest
4030 * `--changelog`: optimize the changelog only
4057 * `--changelog`: optimize the changelog only
4031 * `--no-changelog --no-manifest`: optimize filelogs only
4058 * `--no-changelog --no-manifest`: optimize filelogs only
4032 * `--filelogs`: optimize the filelogs only
4059 * `--filelogs`: optimize the filelogs only
4033 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4060 * `--no-changelog --no-manifest --no-filelogs`: skip all revlog optimizations
4034 """
4061 """
4035 return upgrade.upgraderepo(
4062 return upgrade.upgraderepo(
4036 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4063 ui, repo, run=run, optimize=set(optimize), backup=backup, **opts
4037 )
4064 )
4038
4065
4039
4066
4040 @command(
4067 @command(
4041 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4068 b'debugwalk', cmdutil.walkopts, _(b'[OPTION]... [FILE]...'), inferrepo=True
4042 )
4069 )
4043 def debugwalk(ui, repo, *pats, **opts):
4070 def debugwalk(ui, repo, *pats, **opts):
4044 """show how files match on given patterns"""
4071 """show how files match on given patterns"""
4045 opts = pycompat.byteskwargs(opts)
4072 opts = pycompat.byteskwargs(opts)
4046 m = scmutil.match(repo[None], pats, opts)
4073 m = scmutil.match(repo[None], pats, opts)
4047 if ui.verbose:
4074 if ui.verbose:
4048 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4075 ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
4049 items = list(repo[None].walk(m))
4076 items = list(repo[None].walk(m))
4050 if not items:
4077 if not items:
4051 return
4078 return
4052 f = lambda fn: fn
4079 f = lambda fn: fn
4053 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4080 if ui.configbool(b'ui', b'slash') and pycompat.ossep != b'/':
4054 f = lambda fn: util.normpath(fn)
4081 f = lambda fn: util.normpath(fn)
4055 fmt = b'f %%-%ds %%-%ds %%s' % (
4082 fmt = b'f %%-%ds %%-%ds %%s' % (
4056 max([len(abs) for abs in items]),
4083 max([len(abs) for abs in items]),
4057 max([len(repo.pathto(abs)) for abs in items]),
4084 max([len(repo.pathto(abs)) for abs in items]),
4058 )
4085 )
4059 for abs in items:
4086 for abs in items:
4060 line = fmt % (
4087 line = fmt % (
4061 abs,
4088 abs,
4062 f(repo.pathto(abs)),
4089 f(repo.pathto(abs)),
4063 m.exact(abs) and b'exact' or b'',
4090 m.exact(abs) and b'exact' or b'',
4064 )
4091 )
4065 ui.write(b"%s\n" % line.rstrip())
4092 ui.write(b"%s\n" % line.rstrip())
4066
4093
4067
4094
4068 @command(b'debugwhyunstable', [], _(b'REV'))
4095 @command(b'debugwhyunstable', [], _(b'REV'))
4069 def debugwhyunstable(ui, repo, rev):
4096 def debugwhyunstable(ui, repo, rev):
4070 """explain instabilities of a changeset"""
4097 """explain instabilities of a changeset"""
4071 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4098 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
4072 dnodes = b''
4099 dnodes = b''
4073 if entry.get(b'divergentnodes'):
4100 if entry.get(b'divergentnodes'):
4074 dnodes = (
4101 dnodes = (
4075 b' '.join(
4102 b' '.join(
4076 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4103 b'%s (%s)' % (ctx.hex(), ctx.phasestr())
4077 for ctx in entry[b'divergentnodes']
4104 for ctx in entry[b'divergentnodes']
4078 )
4105 )
4079 + b' '
4106 + b' '
4080 )
4107 )
4081 ui.write(
4108 ui.write(
4082 b'%s: %s%s %s\n'
4109 b'%s: %s%s %s\n'
4083 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4110 % (entry[b'instability'], dnodes, entry[b'reason'], entry[b'node'])
4084 )
4111 )
4085
4112
4086
4113
4087 @command(
4114 @command(
4088 b'debugwireargs',
4115 b'debugwireargs',
4089 [
4116 [
4090 (b'', b'three', b'', b'three'),
4117 (b'', b'three', b'', b'three'),
4091 (b'', b'four', b'', b'four'),
4118 (b'', b'four', b'', b'four'),
4092 (b'', b'five', b'', b'five'),
4119 (b'', b'five', b'', b'five'),
4093 ]
4120 ]
4094 + cmdutil.remoteopts,
4121 + cmdutil.remoteopts,
4095 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4122 _(b'REPO [OPTIONS]... [ONE [TWO]]'),
4096 norepo=True,
4123 norepo=True,
4097 )
4124 )
4098 def debugwireargs(ui, repopath, *vals, **opts):
4125 def debugwireargs(ui, repopath, *vals, **opts):
4099 opts = pycompat.byteskwargs(opts)
4126 opts = pycompat.byteskwargs(opts)
4100 repo = hg.peer(ui, opts, repopath)
4127 repo = hg.peer(ui, opts, repopath)
4101 try:
4128 try:
4102 for opt in cmdutil.remoteopts:
4129 for opt in cmdutil.remoteopts:
4103 del opts[opt[1]]
4130 del opts[opt[1]]
4104 args = {}
4131 args = {}
4105 for k, v in opts.items():
4132 for k, v in opts.items():
4106 if v:
4133 if v:
4107 args[k] = v
4134 args[k] = v
4108 args = pycompat.strkwargs(args)
4135 args = pycompat.strkwargs(args)
4109 # run twice to check that we don't mess up the stream for the next command
4136 # run twice to check that we don't mess up the stream for the next command
4110 res1 = repo.debugwireargs(*vals, **args)
4137 res1 = repo.debugwireargs(*vals, **args)
4111 res2 = repo.debugwireargs(*vals, **args)
4138 res2 = repo.debugwireargs(*vals, **args)
4112 ui.write(b"%s\n" % res1)
4139 ui.write(b"%s\n" % res1)
4113 if res1 != res2:
4140 if res1 != res2:
4114 ui.warn(b"%s\n" % res2)
4141 ui.warn(b"%s\n" % res2)
4115 finally:
4142 finally:
4116 repo.close()
4143 repo.close()
4117
4144
4118
4145
4119 def _parsewirelangblocks(fh):
4146 def _parsewirelangblocks(fh):
4120 activeaction = None
4147 activeaction = None
4121 blocklines = []
4148 blocklines = []
4122 lastindent = 0
4149 lastindent = 0
4123
4150
4124 for line in fh:
4151 for line in fh:
4125 line = line.rstrip()
4152 line = line.rstrip()
4126 if not line:
4153 if not line:
4127 continue
4154 continue
4128
4155
4129 if line.startswith(b'#'):
4156 if line.startswith(b'#'):
4130 continue
4157 continue
4131
4158
4132 if not line.startswith(b' '):
4159 if not line.startswith(b' '):
4133 # New block. Flush previous one.
4160 # New block. Flush previous one.
4134 if activeaction:
4161 if activeaction:
4135 yield activeaction, blocklines
4162 yield activeaction, blocklines
4136
4163
4137 activeaction = line
4164 activeaction = line
4138 blocklines = []
4165 blocklines = []
4139 lastindent = 0
4166 lastindent = 0
4140 continue
4167 continue
4141
4168
4142 # Else we start with an indent.
4169 # Else we start with an indent.
4143
4170
4144 if not activeaction:
4171 if not activeaction:
4145 raise error.Abort(_(b'indented line outside of block'))
4172 raise error.Abort(_(b'indented line outside of block'))
4146
4173
4147 indent = len(line) - len(line.lstrip())
4174 indent = len(line) - len(line.lstrip())
4148
4175
4149 # If this line is indented more than the last line, concatenate it.
4176 # If this line is indented more than the last line, concatenate it.
4150 if indent > lastindent and blocklines:
4177 if indent > lastindent and blocklines:
4151 blocklines[-1] += line.lstrip()
4178 blocklines[-1] += line.lstrip()
4152 else:
4179 else:
4153 blocklines.append(line)
4180 blocklines.append(line)
4154 lastindent = indent
4181 lastindent = indent
4155
4182
4156 # Flush last block.
4183 # Flush last block.
4157 if activeaction:
4184 if activeaction:
4158 yield activeaction, blocklines
4185 yield activeaction, blocklines
4159
4186
4160
4187
4161 @command(
4188 @command(
4162 b'debugwireproto',
4189 b'debugwireproto',
4163 [
4190 [
4164 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4191 (b'', b'localssh', False, _(b'start an SSH server for this repo')),
4165 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4192 (b'', b'peer', b'', _(b'construct a specific version of the peer')),
4166 (
4193 (
4167 b'',
4194 b'',
4168 b'noreadstderr',
4195 b'noreadstderr',
4169 False,
4196 False,
4170 _(b'do not read from stderr of the remote'),
4197 _(b'do not read from stderr of the remote'),
4171 ),
4198 ),
4172 (
4199 (
4173 b'',
4200 b'',
4174 b'nologhandshake',
4201 b'nologhandshake',
4175 False,
4202 False,
4176 _(b'do not log I/O related to the peer handshake'),
4203 _(b'do not log I/O related to the peer handshake'),
4177 ),
4204 ),
4178 ]
4205 ]
4179 + cmdutil.remoteopts,
4206 + cmdutil.remoteopts,
4180 _(b'[PATH]'),
4207 _(b'[PATH]'),
4181 optionalrepo=True,
4208 optionalrepo=True,
4182 )
4209 )
4183 def debugwireproto(ui, repo, path=None, **opts):
4210 def debugwireproto(ui, repo, path=None, **opts):
4184 """send wire protocol commands to a server
4211 """send wire protocol commands to a server
4185
4212
4186 This command can be used to issue wire protocol commands to remote
4213 This command can be used to issue wire protocol commands to remote
4187 peers and to debug the raw data being exchanged.
4214 peers and to debug the raw data being exchanged.
4188
4215
4189 ``--localssh`` will start an SSH server against the current repository
4216 ``--localssh`` will start an SSH server against the current repository
4190 and connect to that. By default, the connection will perform a handshake
4217 and connect to that. By default, the connection will perform a handshake
4191 and establish an appropriate peer instance.
4218 and establish an appropriate peer instance.
4192
4219
4193 ``--peer`` can be used to bypass the handshake protocol and construct a
4220 ``--peer`` can be used to bypass the handshake protocol and construct a
4194 peer instance using the specified class type. Valid values are ``raw``,
4221 peer instance using the specified class type. Valid values are ``raw``,
4195 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4222 ``ssh1``. ``raw`` instances only allow sending raw data payloads and
4196 don't support higher-level command actions.
4223 don't support higher-level command actions.
4197
4224
4198 ``--noreadstderr`` can be used to disable automatic reading from stderr
4225 ``--noreadstderr`` can be used to disable automatic reading from stderr
4199 of the peer (for SSH connections only). Disabling automatic reading of
4226 of the peer (for SSH connections only). Disabling automatic reading of
4200 stderr is useful for making output more deterministic.
4227 stderr is useful for making output more deterministic.
4201
4228
4202 Commands are issued via a mini language which is specified via stdin.
4229 Commands are issued via a mini language which is specified via stdin.
4203 The language consists of individual actions to perform. An action is
4230 The language consists of individual actions to perform. An action is
4204 defined by a block. A block is defined as a line with no leading
4231 defined by a block. A block is defined as a line with no leading
4205 space followed by 0 or more lines with leading space. Blocks are
4232 space followed by 0 or more lines with leading space. Blocks are
4206 effectively a high-level command with additional metadata.
4233 effectively a high-level command with additional metadata.
4207
4234
4208 Lines beginning with ``#`` are ignored.
4235 Lines beginning with ``#`` are ignored.
4209
4236
4210 The following sections denote available actions.
4237 The following sections denote available actions.
4211
4238
4212 raw
4239 raw
4213 ---
4240 ---
4214
4241
4215 Send raw data to the server.
4242 Send raw data to the server.
4216
4243
4217 The block payload contains the raw data to send as one atomic send
4244 The block payload contains the raw data to send as one atomic send
4218 operation. The data may not actually be delivered in a single system
4245 operation. The data may not actually be delivered in a single system
4219 call: it depends on the abilities of the transport being used.
4246 call: it depends on the abilities of the transport being used.
4220
4247
4221 Each line in the block is de-indented and concatenated. Then, that
4248 Each line in the block is de-indented and concatenated. Then, that
4222 value is evaluated as a Python b'' literal. This allows the use of
4249 value is evaluated as a Python b'' literal. This allows the use of
4223 backslash escaping, etc.
4250 backslash escaping, etc.
4224
4251
4225 raw+
4252 raw+
4226 ----
4253 ----
4227
4254
4228 Behaves like ``raw`` except flushes output afterwards.
4255 Behaves like ``raw`` except flushes output afterwards.
4229
4256
4230 command <X>
4257 command <X>
4231 -----------
4258 -----------
4232
4259
4233 Send a request to run a named command, whose name follows the ``command``
4260 Send a request to run a named command, whose name follows the ``command``
4234 string.
4261 string.
4235
4262
4236 Arguments to the command are defined as lines in this block. The format of
4263 Arguments to the command are defined as lines in this block. The format of
4237 each line is ``<key> <value>``. e.g.::
4264 each line is ``<key> <value>``. e.g.::
4238
4265
4239 command listkeys
4266 command listkeys
4240 namespace bookmarks
4267 namespace bookmarks
4241
4268
4242 If the value begins with ``eval:``, it will be interpreted as a Python
4269 If the value begins with ``eval:``, it will be interpreted as a Python
4243 literal expression. Otherwise values are interpreted as Python b'' literals.
4270 literal expression. Otherwise values are interpreted as Python b'' literals.
4244 This allows sending complex types and encoding special byte sequences via
4271 This allows sending complex types and encoding special byte sequences via
4245 backslash escaping.
4272 backslash escaping.
4246
4273
4247 The following arguments have special meaning:
4274 The following arguments have special meaning:
4248
4275
4249 ``PUSHFILE``
4276 ``PUSHFILE``
4250 When defined, the *push* mechanism of the peer will be used instead
4277 When defined, the *push* mechanism of the peer will be used instead
4251 of the static request-response mechanism and the content of the
4278 of the static request-response mechanism and the content of the
4252 file specified in the value of this argument will be sent as the
4279 file specified in the value of this argument will be sent as the
4253 command payload.
4280 command payload.
4254
4281
4255 This can be used to submit a local bundle file to the remote.
4282 This can be used to submit a local bundle file to the remote.
4256
4283
4257 batchbegin
4284 batchbegin
4258 ----------
4285 ----------
4259
4286
4260 Instruct the peer to begin a batched send.
4287 Instruct the peer to begin a batched send.
4261
4288
4262 All ``command`` blocks are queued for execution until the next
4289 All ``command`` blocks are queued for execution until the next
4263 ``batchsubmit`` block.
4290 ``batchsubmit`` block.
4264
4291
4265 batchsubmit
4292 batchsubmit
4266 -----------
4293 -----------
4267
4294
4268 Submit previously queued ``command`` blocks as a batch request.
4295 Submit previously queued ``command`` blocks as a batch request.
4269
4296
4270 This action MUST be paired with a ``batchbegin`` action.
4297 This action MUST be paired with a ``batchbegin`` action.
4271
4298
4272 httprequest <method> <path>
4299 httprequest <method> <path>
4273 ---------------------------
4300 ---------------------------
4274
4301
4275 (HTTP peer only)
4302 (HTTP peer only)
4276
4303
4277 Send an HTTP request to the peer.
4304 Send an HTTP request to the peer.
4278
4305
4279 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4306 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
4280
4307
4281 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4308 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
4282 headers to add to the request. e.g. ``Accept: foo``.
4309 headers to add to the request. e.g. ``Accept: foo``.
4283
4310
4284 The following arguments are special:
4311 The following arguments are special:
4285
4312
4286 ``BODYFILE``
4313 ``BODYFILE``
4287 The content of the file defined as the value to this argument will be
4314 The content of the file defined as the value to this argument will be
4288 transferred verbatim as the HTTP request body.
4315 transferred verbatim as the HTTP request body.
4289
4316
4290 ``frame <type> <flags> <payload>``
4317 ``frame <type> <flags> <payload>``
4291 Send a unified protocol frame as part of the request body.
4318 Send a unified protocol frame as part of the request body.
4292
4319
4293 All frames will be collected and sent as the body to the HTTP
4320 All frames will be collected and sent as the body to the HTTP
4294 request.
4321 request.
4295
4322
4296 close
4323 close
4297 -----
4324 -----
4298
4325
4299 Close the connection to the server.
4326 Close the connection to the server.
4300
4327
4301 flush
4328 flush
4302 -----
4329 -----
4303
4330
4304 Flush data written to the server.
4331 Flush data written to the server.
4305
4332
4306 readavailable
4333 readavailable
4307 -------------
4334 -------------
4308
4335
4309 Close the write end of the connection and read all available data from
4336 Close the write end of the connection and read all available data from
4310 the server.
4337 the server.
4311
4338
4312 If the connection to the server encompasses multiple pipes, we poll both
4339 If the connection to the server encompasses multiple pipes, we poll both
4313 pipes and read available data.
4340 pipes and read available data.
4314
4341
4315 readline
4342 readline
4316 --------
4343 --------
4317
4344
4318 Read a line of output from the server. If there are multiple output
4345 Read a line of output from the server. If there are multiple output
4319 pipes, reads only the main pipe.
4346 pipes, reads only the main pipe.
4320
4347
4321 ereadline
4348 ereadline
4322 ---------
4349 ---------
4323
4350
4324 Like ``readline``, but read from the stderr pipe, if available.
4351 Like ``readline``, but read from the stderr pipe, if available.
4325
4352
4326 read <X>
4353 read <X>
4327 --------
4354 --------
4328
4355
4329 ``read()`` N bytes from the server's main output pipe.
4356 ``read()`` N bytes from the server's main output pipe.
4330
4357
4331 eread <X>
4358 eread <X>
4332 ---------
4359 ---------
4333
4360
4334 ``read()`` N bytes from the server's stderr pipe, if available.
4361 ``read()`` N bytes from the server's stderr pipe, if available.
4335
4362
4336 Specifying Unified Frame-Based Protocol Frames
4363 Specifying Unified Frame-Based Protocol Frames
4337 ----------------------------------------------
4364 ----------------------------------------------
4338
4365
4339 It is possible to emit a *Unified Frame-Based Protocol* by using special
4366 It is possible to emit a *Unified Frame-Based Protocol* by using special
4340 syntax.
4367 syntax.
4341
4368
4342 A frame is composed as a type, flags, and payload. These can be parsed
4369 A frame is composed as a type, flags, and payload. These can be parsed
4343 from a string of the form:
4370 from a string of the form:
4344
4371
4345 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4372 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
4346
4373
4347 ``request-id`` and ``stream-id`` are integers defining the request and
4374 ``request-id`` and ``stream-id`` are integers defining the request and
4348 stream identifiers.
4375 stream identifiers.
4349
4376
4350 ``type`` can be an integer value for the frame type or the string name
4377 ``type`` can be an integer value for the frame type or the string name
4351 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4378 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
4352 ``command-name``.
4379 ``command-name``.
4353
4380
4354 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4381 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
4355 components. Each component (and there can be just one) can be an integer
4382 components. Each component (and there can be just one) can be an integer
4356 or a flag name for stream flags or frame flags, respectively. Values are
4383 or a flag name for stream flags or frame flags, respectively. Values are
4357 resolved to integers and then bitwise OR'd together.
4384 resolved to integers and then bitwise OR'd together.
4358
4385
4359 ``payload`` represents the raw frame payload. If it begins with
4386 ``payload`` represents the raw frame payload. If it begins with
4360 ``cbor:``, the following string is evaluated as Python code and the
4387 ``cbor:``, the following string is evaluated as Python code and the
4361 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4388 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
4362 as a Python byte string literal.
4389 as a Python byte string literal.
4363 """
4390 """
4364 opts = pycompat.byteskwargs(opts)
4391 opts = pycompat.byteskwargs(opts)
4365
4392
4366 if opts[b'localssh'] and not repo:
4393 if opts[b'localssh'] and not repo:
4367 raise error.Abort(_(b'--localssh requires a repository'))
4394 raise error.Abort(_(b'--localssh requires a repository'))
4368
4395
4369 if opts[b'peer'] and opts[b'peer'] not in (
4396 if opts[b'peer'] and opts[b'peer'] not in (
4370 b'raw',
4397 b'raw',
4371 b'ssh1',
4398 b'ssh1',
4372 ):
4399 ):
4373 raise error.Abort(
4400 raise error.Abort(
4374 _(b'invalid value for --peer'),
4401 _(b'invalid value for --peer'),
4375 hint=_(b'valid values are "raw" and "ssh1"'),
4402 hint=_(b'valid values are "raw" and "ssh1"'),
4376 )
4403 )
4377
4404
4378 if path and opts[b'localssh']:
4405 if path and opts[b'localssh']:
4379 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4406 raise error.Abort(_(b'cannot specify --localssh with an explicit path'))
4380
4407
4381 if ui.interactive():
4408 if ui.interactive():
4382 ui.write(_(b'(waiting for commands on stdin)\n'))
4409 ui.write(_(b'(waiting for commands on stdin)\n'))
4383
4410
4384 blocks = list(_parsewirelangblocks(ui.fin))
4411 blocks = list(_parsewirelangblocks(ui.fin))
4385
4412
4386 proc = None
4413 proc = None
4387 stdin = None
4414 stdin = None
4388 stdout = None
4415 stdout = None
4389 stderr = None
4416 stderr = None
4390 opener = None
4417 opener = None
4391
4418
4392 if opts[b'localssh']:
4419 if opts[b'localssh']:
4393 # We start the SSH server in its own process so there is process
4420 # We start the SSH server in its own process so there is process
4394 # separation. This prevents a whole class of potential bugs around
4421 # separation. This prevents a whole class of potential bugs around
4395 # shared state from interfering with server operation.
4422 # shared state from interfering with server operation.
4396 args = procutil.hgcmd() + [
4423 args = procutil.hgcmd() + [
4397 b'-R',
4424 b'-R',
4398 repo.root,
4425 repo.root,
4399 b'debugserve',
4426 b'debugserve',
4400 b'--sshstdio',
4427 b'--sshstdio',
4401 ]
4428 ]
4402 proc = subprocess.Popen(
4429 proc = subprocess.Popen(
4403 pycompat.rapply(procutil.tonativestr, args),
4430 pycompat.rapply(procutil.tonativestr, args),
4404 stdin=subprocess.PIPE,
4431 stdin=subprocess.PIPE,
4405 stdout=subprocess.PIPE,
4432 stdout=subprocess.PIPE,
4406 stderr=subprocess.PIPE,
4433 stderr=subprocess.PIPE,
4407 bufsize=0,
4434 bufsize=0,
4408 )
4435 )
4409
4436
4410 stdin = proc.stdin
4437 stdin = proc.stdin
4411 stdout = proc.stdout
4438 stdout = proc.stdout
4412 stderr = proc.stderr
4439 stderr = proc.stderr
4413
4440
4414 # We turn the pipes into observers so we can log I/O.
4441 # We turn the pipes into observers so we can log I/O.
4415 if ui.verbose or opts[b'peer'] == b'raw':
4442 if ui.verbose or opts[b'peer'] == b'raw':
4416 stdin = util.makeloggingfileobject(
4443 stdin = util.makeloggingfileobject(
4417 ui, proc.stdin, b'i', logdata=True
4444 ui, proc.stdin, b'i', logdata=True
4418 )
4445 )
4419 stdout = util.makeloggingfileobject(
4446 stdout = util.makeloggingfileobject(
4420 ui, proc.stdout, b'o', logdata=True
4447 ui, proc.stdout, b'o', logdata=True
4421 )
4448 )
4422 stderr = util.makeloggingfileobject(
4449 stderr = util.makeloggingfileobject(
4423 ui, proc.stderr, b'e', logdata=True
4450 ui, proc.stderr, b'e', logdata=True
4424 )
4451 )
4425
4452
4426 # --localssh also implies the peer connection settings.
4453 # --localssh also implies the peer connection settings.
4427
4454
4428 url = b'ssh://localserver'
4455 url = b'ssh://localserver'
4429 autoreadstderr = not opts[b'noreadstderr']
4456 autoreadstderr = not opts[b'noreadstderr']
4430
4457
4431 if opts[b'peer'] == b'ssh1':
4458 if opts[b'peer'] == b'ssh1':
4432 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4459 ui.write(_(b'creating ssh peer for wire protocol version 1\n'))
4433 peer = sshpeer.sshv1peer(
4460 peer = sshpeer.sshv1peer(
4434 ui,
4461 ui,
4435 url,
4462 url,
4436 proc,
4463 proc,
4437 stdin,
4464 stdin,
4438 stdout,
4465 stdout,
4439 stderr,
4466 stderr,
4440 None,
4467 None,
4441 autoreadstderr=autoreadstderr,
4468 autoreadstderr=autoreadstderr,
4442 )
4469 )
4443 elif opts[b'peer'] == b'raw':
4470 elif opts[b'peer'] == b'raw':
4444 ui.write(_(b'using raw connection to peer\n'))
4471 ui.write(_(b'using raw connection to peer\n'))
4445 peer = None
4472 peer = None
4446 else:
4473 else:
4447 ui.write(_(b'creating ssh peer from handshake results\n'))
4474 ui.write(_(b'creating ssh peer from handshake results\n'))
4448 peer = sshpeer.makepeer(
4475 peer = sshpeer.makepeer(
4449 ui,
4476 ui,
4450 url,
4477 url,
4451 proc,
4478 proc,
4452 stdin,
4479 stdin,
4453 stdout,
4480 stdout,
4454 stderr,
4481 stderr,
4455 autoreadstderr=autoreadstderr,
4482 autoreadstderr=autoreadstderr,
4456 )
4483 )
4457
4484
4458 elif path:
4485 elif path:
4459 # We bypass hg.peer() so we can proxy the sockets.
4486 # We bypass hg.peer() so we can proxy the sockets.
4460 # TODO consider not doing this because we skip
4487 # TODO consider not doing this because we skip
4461 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4488 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
4462 u = urlutil.url(path)
4489 u = urlutil.url(path)
4463 if u.scheme != b'http':
4490 if u.scheme != b'http':
4464 raise error.Abort(_(b'only http:// paths are currently supported'))
4491 raise error.Abort(_(b'only http:// paths are currently supported'))
4465
4492
4466 url, authinfo = u.authinfo()
4493 url, authinfo = u.authinfo()
4467 openerargs = {
4494 openerargs = {
4468 'useragent': b'Mercurial debugwireproto',
4495 'useragent': b'Mercurial debugwireproto',
4469 }
4496 }
4470
4497
4471 # Turn pipes/sockets into observers so we can log I/O.
4498 # Turn pipes/sockets into observers so we can log I/O.
4472 if ui.verbose:
4499 if ui.verbose:
4473 openerargs.update(
4500 openerargs.update(
4474 {
4501 {
4475 'loggingfh': ui,
4502 'loggingfh': ui,
4476 'loggingname': b's',
4503 'loggingname': b's',
4477 'loggingopts': {
4504 'loggingopts': {
4478 'logdata': True,
4505 'logdata': True,
4479 'logdataapis': False,
4506 'logdataapis': False,
4480 },
4507 },
4481 }
4508 }
4482 )
4509 )
4483
4510
4484 if ui.debugflag:
4511 if ui.debugflag:
4485 openerargs['loggingopts']['logdataapis'] = True
4512 openerargs['loggingopts']['logdataapis'] = True
4486
4513
4487 # Don't send default headers when in raw mode. This allows us to
4514 # Don't send default headers when in raw mode. This allows us to
4488 # bypass most of the behavior of our URL handling code so we can
4515 # bypass most of the behavior of our URL handling code so we can
4489 # have near complete control over what's sent on the wire.
4516 # have near complete control over what's sent on the wire.
4490 if opts[b'peer'] == b'raw':
4517 if opts[b'peer'] == b'raw':
4491 openerargs['sendaccept'] = False
4518 openerargs['sendaccept'] = False
4492
4519
4493 opener = urlmod.opener(ui, authinfo, **openerargs)
4520 opener = urlmod.opener(ui, authinfo, **openerargs)
4494
4521
4495 if opts[b'peer'] == b'raw':
4522 if opts[b'peer'] == b'raw':
4496 ui.write(_(b'using raw connection to peer\n'))
4523 ui.write(_(b'using raw connection to peer\n'))
4497 peer = None
4524 peer = None
4498 elif opts[b'peer']:
4525 elif opts[b'peer']:
4499 raise error.Abort(
4526 raise error.Abort(
4500 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4527 _(b'--peer %s not supported with HTTP peers') % opts[b'peer']
4501 )
4528 )
4502 else:
4529 else:
4503 peer_path = urlutil.try_path(ui, path)
4530 peer_path = urlutil.try_path(ui, path)
4504 peer = httppeer.makepeer(ui, peer_path, opener=opener)
4531 peer = httppeer.makepeer(ui, peer_path, opener=opener)
4505
4532
4506 # We /could/ populate stdin/stdout with sock.makefile()...
4533 # We /could/ populate stdin/stdout with sock.makefile()...
4507 else:
4534 else:
4508 raise error.Abort(_(b'unsupported connection configuration'))
4535 raise error.Abort(_(b'unsupported connection configuration'))
4509
4536
4510 batchedcommands = None
4537 batchedcommands = None
4511
4538
4512 # Now perform actions based on the parsed wire language instructions.
4539 # Now perform actions based on the parsed wire language instructions.
4513 for action, lines in blocks:
4540 for action, lines in blocks:
4514 if action in (b'raw', b'raw+'):
4541 if action in (b'raw', b'raw+'):
4515 if not stdin:
4542 if not stdin:
4516 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4543 raise error.Abort(_(b'cannot call raw/raw+ on this peer'))
4517
4544
4518 # Concatenate the data together.
4545 # Concatenate the data together.
4519 data = b''.join(l.lstrip() for l in lines)
4546 data = b''.join(l.lstrip() for l in lines)
4520 data = stringutil.unescapestr(data)
4547 data = stringutil.unescapestr(data)
4521 stdin.write(data)
4548 stdin.write(data)
4522
4549
4523 if action == b'raw+':
4550 if action == b'raw+':
4524 stdin.flush()
4551 stdin.flush()
4525 elif action == b'flush':
4552 elif action == b'flush':
4526 if not stdin:
4553 if not stdin:
4527 raise error.Abort(_(b'cannot call flush on this peer'))
4554 raise error.Abort(_(b'cannot call flush on this peer'))
4528 stdin.flush()
4555 stdin.flush()
4529 elif action.startswith(b'command'):
4556 elif action.startswith(b'command'):
4530 if not peer:
4557 if not peer:
4531 raise error.Abort(
4558 raise error.Abort(
4532 _(
4559 _(
4533 b'cannot send commands unless peer instance '
4560 b'cannot send commands unless peer instance '
4534 b'is available'
4561 b'is available'
4535 )
4562 )
4536 )
4563 )
4537
4564
4538 command = action.split(b' ', 1)[1]
4565 command = action.split(b' ', 1)[1]
4539
4566
4540 args = {}
4567 args = {}
4541 for line in lines:
4568 for line in lines:
4542 # We need to allow empty values.
4569 # We need to allow empty values.
4543 fields = line.lstrip().split(b' ', 1)
4570 fields = line.lstrip().split(b' ', 1)
4544 if len(fields) == 1:
4571 if len(fields) == 1:
4545 key = fields[0]
4572 key = fields[0]
4546 value = b''
4573 value = b''
4547 else:
4574 else:
4548 key, value = fields
4575 key, value = fields
4549
4576
4550 if value.startswith(b'eval:'):
4577 if value.startswith(b'eval:'):
4551 value = stringutil.evalpythonliteral(value[5:])
4578 value = stringutil.evalpythonliteral(value[5:])
4552 else:
4579 else:
4553 value = stringutil.unescapestr(value)
4580 value = stringutil.unescapestr(value)
4554
4581
4555 args[key] = value
4582 args[key] = value
4556
4583
4557 if batchedcommands is not None:
4584 if batchedcommands is not None:
4558 batchedcommands.append((command, args))
4585 batchedcommands.append((command, args))
4559 continue
4586 continue
4560
4587
4561 ui.status(_(b'sending %s command\n') % command)
4588 ui.status(_(b'sending %s command\n') % command)
4562
4589
4563 if b'PUSHFILE' in args:
4590 if b'PUSHFILE' in args:
4564 with open(args[b'PUSHFILE'], 'rb') as fh:
4591 with open(args[b'PUSHFILE'], 'rb') as fh:
4565 del args[b'PUSHFILE']
4592 del args[b'PUSHFILE']
4566 res, output = peer._callpush(
4593 res, output = peer._callpush(
4567 command, fh, **pycompat.strkwargs(args)
4594 command, fh, **pycompat.strkwargs(args)
4568 )
4595 )
4569 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4596 ui.status(_(b'result: %s\n') % stringutil.escapestr(res))
4570 ui.status(
4597 ui.status(
4571 _(b'remote output: %s\n') % stringutil.escapestr(output)
4598 _(b'remote output: %s\n') % stringutil.escapestr(output)
4572 )
4599 )
4573 else:
4600 else:
4574 with peer.commandexecutor() as e:
4601 with peer.commandexecutor() as e:
4575 res = e.callcommand(command, args).result()
4602 res = e.callcommand(command, args).result()
4576
4603
4577 ui.status(
4604 ui.status(
4578 _(b'response: %s\n')
4605 _(b'response: %s\n')
4579 % stringutil.pprint(res, bprefix=True, indent=2)
4606 % stringutil.pprint(res, bprefix=True, indent=2)
4580 )
4607 )
4581
4608
4582 elif action == b'batchbegin':
4609 elif action == b'batchbegin':
4583 if batchedcommands is not None:
4610 if batchedcommands is not None:
4584 raise error.Abort(_(b'nested batchbegin not allowed'))
4611 raise error.Abort(_(b'nested batchbegin not allowed'))
4585
4612
4586 batchedcommands = []
4613 batchedcommands = []
4587 elif action == b'batchsubmit':
4614 elif action == b'batchsubmit':
4588 # There is a batching API we could go through. But it would be
4615 # There is a batching API we could go through. But it would be
4589 # difficult to normalize requests into function calls. It is easier
4616 # difficult to normalize requests into function calls. It is easier
4590 # to bypass this layer and normalize to commands + args.
4617 # to bypass this layer and normalize to commands + args.
4591 ui.status(
4618 ui.status(
4592 _(b'sending batch with %d sub-commands\n')
4619 _(b'sending batch with %d sub-commands\n')
4593 % len(batchedcommands)
4620 % len(batchedcommands)
4594 )
4621 )
4595 assert peer is not None
4622 assert peer is not None
4596 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4623 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
4597 ui.status(
4624 ui.status(
4598 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4625 _(b'response #%d: %s\n') % (i, stringutil.escapestr(chunk))
4599 )
4626 )
4600
4627
4601 batchedcommands = None
4628 batchedcommands = None
4602
4629
4603 elif action.startswith(b'httprequest '):
4630 elif action.startswith(b'httprequest '):
4604 if not opener:
4631 if not opener:
4605 raise error.Abort(
4632 raise error.Abort(
4606 _(b'cannot use httprequest without an HTTP peer')
4633 _(b'cannot use httprequest without an HTTP peer')
4607 )
4634 )
4608
4635
4609 request = action.split(b' ', 2)
4636 request = action.split(b' ', 2)
4610 if len(request) != 3:
4637 if len(request) != 3:
4611 raise error.Abort(
4638 raise error.Abort(
4612 _(
4639 _(
4613 b'invalid httprequest: expected format is '
4640 b'invalid httprequest: expected format is '
4614 b'"httprequest <method> <path>'
4641 b'"httprequest <method> <path>'
4615 )
4642 )
4616 )
4643 )
4617
4644
4618 method, httppath = request[1:]
4645 method, httppath = request[1:]
4619 headers = {}
4646 headers = {}
4620 body = None
4647 body = None
4621 frames = []
4648 frames = []
4622 for line in lines:
4649 for line in lines:
4623 line = line.lstrip()
4650 line = line.lstrip()
4624 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4651 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
4625 if m:
4652 if m:
4626 # Headers need to use native strings.
4653 # Headers need to use native strings.
4627 key = pycompat.strurl(m.group(1))
4654 key = pycompat.strurl(m.group(1))
4628 value = pycompat.strurl(m.group(2))
4655 value = pycompat.strurl(m.group(2))
4629 headers[key] = value
4656 headers[key] = value
4630 continue
4657 continue
4631
4658
4632 if line.startswith(b'BODYFILE '):
4659 if line.startswith(b'BODYFILE '):
4633 with open(line.split(b' ', 1), b'rb') as fh:
4660 with open(line.split(b' ', 1), b'rb') as fh:
4634 body = fh.read()
4661 body = fh.read()
4635 elif line.startswith(b'frame '):
4662 elif line.startswith(b'frame '):
4636 frame = wireprotoframing.makeframefromhumanstring(
4663 frame = wireprotoframing.makeframefromhumanstring(
4637 line[len(b'frame ') :]
4664 line[len(b'frame ') :]
4638 )
4665 )
4639
4666
4640 frames.append(frame)
4667 frames.append(frame)
4641 else:
4668 else:
4642 raise error.Abort(
4669 raise error.Abort(
4643 _(b'unknown argument to httprequest: %s') % line
4670 _(b'unknown argument to httprequest: %s') % line
4644 )
4671 )
4645
4672
4646 url = path + httppath
4673 url = path + httppath
4647
4674
4648 if frames:
4675 if frames:
4649 body = b''.join(bytes(f) for f in frames)
4676 body = b''.join(bytes(f) for f in frames)
4650
4677
4651 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4678 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
4652
4679
4653 # urllib.Request insists on using has_data() as a proxy for
4680 # urllib.Request insists on using has_data() as a proxy for
4654 # determining the request method. Override that to use our
4681 # determining the request method. Override that to use our
4655 # explicitly requested method.
4682 # explicitly requested method.
4656 req.get_method = lambda: pycompat.sysstr(method)
4683 req.get_method = lambda: pycompat.sysstr(method)
4657
4684
4658 try:
4685 try:
4659 res = opener.open(req)
4686 res = opener.open(req)
4660 body = res.read()
4687 body = res.read()
4661 except util.urlerr.urlerror as e:
4688 except util.urlerr.urlerror as e:
4662 # read() method must be called, but only exists in Python 2
4689 # read() method must be called, but only exists in Python 2
4663 getattr(e, 'read', lambda: None)()
4690 getattr(e, 'read', lambda: None)()
4664 continue
4691 continue
4665
4692
4666 ct = res.headers.get('Content-Type')
4693 ct = res.headers.get('Content-Type')
4667 if ct == 'application/mercurial-cbor':
4694 if ct == 'application/mercurial-cbor':
4668 ui.write(
4695 ui.write(
4669 _(b'cbor> %s\n')
4696 _(b'cbor> %s\n')
4670 % stringutil.pprint(
4697 % stringutil.pprint(
4671 cborutil.decodeall(body), bprefix=True, indent=2
4698 cborutil.decodeall(body), bprefix=True, indent=2
4672 )
4699 )
4673 )
4700 )
4674
4701
4675 elif action == b'close':
4702 elif action == b'close':
4676 assert peer is not None
4703 assert peer is not None
4677 peer.close()
4704 peer.close()
4678 elif action == b'readavailable':
4705 elif action == b'readavailable':
4679 if not stdout or not stderr:
4706 if not stdout or not stderr:
4680 raise error.Abort(
4707 raise error.Abort(
4681 _(b'readavailable not available on this peer')
4708 _(b'readavailable not available on this peer')
4682 )
4709 )
4683
4710
4684 stdin.close()
4711 stdin.close()
4685 stdout.read()
4712 stdout.read()
4686 stderr.read()
4713 stderr.read()
4687
4714
4688 elif action == b'readline':
4715 elif action == b'readline':
4689 if not stdout:
4716 if not stdout:
4690 raise error.Abort(_(b'readline not available on this peer'))
4717 raise error.Abort(_(b'readline not available on this peer'))
4691 stdout.readline()
4718 stdout.readline()
4692 elif action == b'ereadline':
4719 elif action == b'ereadline':
4693 if not stderr:
4720 if not stderr:
4694 raise error.Abort(_(b'ereadline not available on this peer'))
4721 raise error.Abort(_(b'ereadline not available on this peer'))
4695 stderr.readline()
4722 stderr.readline()
4696 elif action.startswith(b'read '):
4723 elif action.startswith(b'read '):
4697 count = int(action.split(b' ', 1)[1])
4724 count = int(action.split(b' ', 1)[1])
4698 if not stdout:
4725 if not stdout:
4699 raise error.Abort(_(b'read not available on this peer'))
4726 raise error.Abort(_(b'read not available on this peer'))
4700 stdout.read(count)
4727 stdout.read(count)
4701 elif action.startswith(b'eread '):
4728 elif action.startswith(b'eread '):
4702 count = int(action.split(b' ', 1)[1])
4729 count = int(action.split(b' ', 1)[1])
4703 if not stderr:
4730 if not stderr:
4704 raise error.Abort(_(b'eread not available on this peer'))
4731 raise error.Abort(_(b'eread not available on this peer'))
4705 stderr.read(count)
4732 stderr.read(count)
4706 else:
4733 else:
4707 raise error.Abort(_(b'unknown action: %s') % action)
4734 raise error.Abort(_(b'unknown action: %s') % action)
4708
4735
4709 if batchedcommands is not None:
4736 if batchedcommands is not None:
4710 raise error.Abort(_(b'unclosed "batchbegin" request'))
4737 raise error.Abort(_(b'unclosed "batchbegin" request'))
4711
4738
4712 if peer:
4739 if peer:
4713 peer.close()
4740 peer.close()
4714
4741
4715 if proc:
4742 if proc:
4716 proc.kill()
4743 proc.kill()
@@ -1,663 +1,721
1 # revlogutils/debug.py - utility used for revlog debuging
1 # revlogutils/debug.py - utility used for revlog debuging
2 #
2 #
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
3 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
4 # Copyright 2022 Octobus <contact@octobus.net>
4 # Copyright 2022 Octobus <contact@octobus.net>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 import collections
9 import collections
10 import string
10 import string
11
11
12 from .. import (
12 from .. import (
13 mdiff,
13 mdiff,
14 node as nodemod,
14 node as nodemod,
15 revlogutils,
15 revlogutils,
16 util,
16 util,
17 )
17 )
18
18
19 from . import (
19 from . import (
20 constants,
20 constants,
21 deltas as deltautil,
21 deltas as deltautil,
22 )
22 )
23
23
24 INDEX_ENTRY_DEBUG_COLUMN = []
24 INDEX_ENTRY_DEBUG_COLUMN = []
25
25
26 NODE_SIZE = object()
26 NODE_SIZE = object()
27
27
28
28
29 class _column_base:
29 class _column_base:
30 """constains the definition of a revlog column
30 """constains the definition of a revlog column
31
31
32 name: the column header,
32 name: the column header,
33 value_func: the function called to get a value,
33 value_func: the function called to get a value,
34 size: the width of the column,
34 size: the width of the column,
35 verbose_only: only include the column in verbose mode.
35 verbose_only: only include the column in verbose mode.
36 """
36 """
37
37
38 def __init__(self, name, value_func, size=None, verbose=False):
38 def __init__(self, name, value_func, size=None, verbose=False):
39 self.name = name
39 self.name = name
40 self.value_func = value_func
40 self.value_func = value_func
41 if size is not NODE_SIZE:
41 if size is not NODE_SIZE:
42 if size is None:
42 if size is None:
43 size = 8 # arbitrary default
43 size = 8 # arbitrary default
44 size = max(len(name), size)
44 size = max(len(name), size)
45 self._size = size
45 self._size = size
46 self.verbose_only = verbose
46 self.verbose_only = verbose
47
47
48 def get_size(self, node_size):
48 def get_size(self, node_size):
49 if self._size is NODE_SIZE:
49 if self._size is NODE_SIZE:
50 return node_size
50 return node_size
51 else:
51 else:
52 return self._size
52 return self._size
53
53
54
54
55 def debug_column(name, size=None, verbose=False):
55 def debug_column(name, size=None, verbose=False):
56 """decorated function is registered as a column
56 """decorated function is registered as a column
57
57
58 name: the name of the column,
58 name: the name of the column,
59 size: the expected size of the column.
59 size: the expected size of the column.
60 """
60 """
61
61
62 def register(func):
62 def register(func):
63 entry = _column_base(
63 entry = _column_base(
64 name=name,
64 name=name,
65 value_func=func,
65 value_func=func,
66 size=size,
66 size=size,
67 verbose=verbose,
67 verbose=verbose,
68 )
68 )
69 INDEX_ENTRY_DEBUG_COLUMN.append(entry)
69 INDEX_ENTRY_DEBUG_COLUMN.append(entry)
70 return entry
70 return entry
71
71
72 return register
72 return register
73
73
74
74
75 @debug_column(b"rev", size=6)
75 @debug_column(b"rev", size=6)
76 def _rev(index, rev, entry, hexfn):
76 def _rev(index, rev, entry, hexfn):
77 return b"%d" % rev
77 return b"%d" % rev
78
78
79
79
80 @debug_column(b"rank", size=6, verbose=True)
80 @debug_column(b"rank", size=6, verbose=True)
81 def rank(index, rev, entry, hexfn):
81 def rank(index, rev, entry, hexfn):
82 return b"%d" % entry[constants.ENTRY_RANK]
82 return b"%d" % entry[constants.ENTRY_RANK]
83
83
84
84
85 @debug_column(b"linkrev", size=6)
85 @debug_column(b"linkrev", size=6)
86 def _linkrev(index, rev, entry, hexfn):
86 def _linkrev(index, rev, entry, hexfn):
87 return b"%d" % entry[constants.ENTRY_LINK_REV]
87 return b"%d" % entry[constants.ENTRY_LINK_REV]
88
88
89
89
90 @debug_column(b"nodeid", size=NODE_SIZE)
90 @debug_column(b"nodeid", size=NODE_SIZE)
91 def _nodeid(index, rev, entry, hexfn):
91 def _nodeid(index, rev, entry, hexfn):
92 return hexfn(entry[constants.ENTRY_NODE_ID])
92 return hexfn(entry[constants.ENTRY_NODE_ID])
93
93
94
94
95 @debug_column(b"p1-rev", size=6, verbose=True)
95 @debug_column(b"p1-rev", size=6, verbose=True)
96 def _p1_rev(index, rev, entry, hexfn):
96 def _p1_rev(index, rev, entry, hexfn):
97 return b"%d" % entry[constants.ENTRY_PARENT_1]
97 return b"%d" % entry[constants.ENTRY_PARENT_1]
98
98
99
99
100 @debug_column(b"p1-nodeid", size=NODE_SIZE)
100 @debug_column(b"p1-nodeid", size=NODE_SIZE)
101 def _p1_node(index, rev, entry, hexfn):
101 def _p1_node(index, rev, entry, hexfn):
102 parent = entry[constants.ENTRY_PARENT_1]
102 parent = entry[constants.ENTRY_PARENT_1]
103 p_entry = index[parent]
103 p_entry = index[parent]
104 return hexfn(p_entry[constants.ENTRY_NODE_ID])
104 return hexfn(p_entry[constants.ENTRY_NODE_ID])
105
105
106
106
107 @debug_column(b"p2-rev", size=6, verbose=True)
107 @debug_column(b"p2-rev", size=6, verbose=True)
108 def _p2_rev(index, rev, entry, hexfn):
108 def _p2_rev(index, rev, entry, hexfn):
109 return b"%d" % entry[constants.ENTRY_PARENT_2]
109 return b"%d" % entry[constants.ENTRY_PARENT_2]
110
110
111
111
112 @debug_column(b"p2-nodeid", size=NODE_SIZE)
112 @debug_column(b"p2-nodeid", size=NODE_SIZE)
113 def _p2_node(index, rev, entry, hexfn):
113 def _p2_node(index, rev, entry, hexfn):
114 parent = entry[constants.ENTRY_PARENT_2]
114 parent = entry[constants.ENTRY_PARENT_2]
115 p_entry = index[parent]
115 p_entry = index[parent]
116 return hexfn(p_entry[constants.ENTRY_NODE_ID])
116 return hexfn(p_entry[constants.ENTRY_NODE_ID])
117
117
118
118
119 @debug_column(b"full-size", size=20, verbose=True)
119 @debug_column(b"full-size", size=20, verbose=True)
120 def full_size(index, rev, entry, hexfn):
120 def full_size(index, rev, entry, hexfn):
121 return b"%d" % entry[constants.ENTRY_DATA_UNCOMPRESSED_LENGTH]
121 return b"%d" % entry[constants.ENTRY_DATA_UNCOMPRESSED_LENGTH]
122
122
123
123
124 @debug_column(b"delta-base", size=6, verbose=True)
124 @debug_column(b"delta-base", size=6, verbose=True)
125 def delta_base(index, rev, entry, hexfn):
125 def delta_base(index, rev, entry, hexfn):
126 return b"%d" % entry[constants.ENTRY_DELTA_BASE]
126 return b"%d" % entry[constants.ENTRY_DELTA_BASE]
127
127
128
128
129 @debug_column(b"flags", size=2, verbose=True)
129 @debug_column(b"flags", size=2, verbose=True)
130 def flags(index, rev, entry, hexfn):
130 def flags(index, rev, entry, hexfn):
131 field = entry[constants.ENTRY_DATA_OFFSET]
131 field = entry[constants.ENTRY_DATA_OFFSET]
132 field &= 0xFFFF
132 field &= 0xFFFF
133 return b"%d" % field
133 return b"%d" % field
134
134
135
135
136 @debug_column(b"comp-mode", size=4, verbose=True)
136 @debug_column(b"comp-mode", size=4, verbose=True)
137 def compression_mode(index, rev, entry, hexfn):
137 def compression_mode(index, rev, entry, hexfn):
138 return b"%d" % entry[constants.ENTRY_DATA_COMPRESSION_MODE]
138 return b"%d" % entry[constants.ENTRY_DATA_COMPRESSION_MODE]
139
139
140
140
141 @debug_column(b"data-offset", size=20, verbose=True)
141 @debug_column(b"data-offset", size=20, verbose=True)
142 def data_offset(index, rev, entry, hexfn):
142 def data_offset(index, rev, entry, hexfn):
143 field = entry[constants.ENTRY_DATA_OFFSET]
143 field = entry[constants.ENTRY_DATA_OFFSET]
144 field >>= 16
144 field >>= 16
145 return b"%d" % field
145 return b"%d" % field
146
146
147
147
148 @debug_column(b"chunk-size", size=10, verbose=True)
148 @debug_column(b"chunk-size", size=10, verbose=True)
149 def data_chunk_size(index, rev, entry, hexfn):
149 def data_chunk_size(index, rev, entry, hexfn):
150 return b"%d" % entry[constants.ENTRY_DATA_COMPRESSED_LENGTH]
150 return b"%d" % entry[constants.ENTRY_DATA_COMPRESSED_LENGTH]
151
151
152
152
153 @debug_column(b"sd-comp-mode", size=7, verbose=True)
153 @debug_column(b"sd-comp-mode", size=7, verbose=True)
154 def sidedata_compression_mode(index, rev, entry, hexfn):
154 def sidedata_compression_mode(index, rev, entry, hexfn):
155 compression = entry[constants.ENTRY_SIDEDATA_COMPRESSION_MODE]
155 compression = entry[constants.ENTRY_SIDEDATA_COMPRESSION_MODE]
156 if compression == constants.COMP_MODE_PLAIN:
156 if compression == constants.COMP_MODE_PLAIN:
157 return b"plain"
157 return b"plain"
158 elif compression == constants.COMP_MODE_DEFAULT:
158 elif compression == constants.COMP_MODE_DEFAULT:
159 return b"default"
159 return b"default"
160 elif compression == constants.COMP_MODE_INLINE:
160 elif compression == constants.COMP_MODE_INLINE:
161 return b"inline"
161 return b"inline"
162 else:
162 else:
163 return b"%d" % compression
163 return b"%d" % compression
164
164
165
165
166 @debug_column(b"sidedata-offset", size=20, verbose=True)
166 @debug_column(b"sidedata-offset", size=20, verbose=True)
167 def sidedata_offset(index, rev, entry, hexfn):
167 def sidedata_offset(index, rev, entry, hexfn):
168 return b"%d" % entry[constants.ENTRY_SIDEDATA_OFFSET]
168 return b"%d" % entry[constants.ENTRY_SIDEDATA_OFFSET]
169
169
170
170
171 @debug_column(b"sd-chunk-size", size=10, verbose=True)
171 @debug_column(b"sd-chunk-size", size=10, verbose=True)
172 def sidedata_chunk_size(index, rev, entry, hexfn):
172 def sidedata_chunk_size(index, rev, entry, hexfn):
173 return b"%d" % entry[constants.ENTRY_SIDEDATA_COMPRESSED_LENGTH]
173 return b"%d" % entry[constants.ENTRY_SIDEDATA_COMPRESSED_LENGTH]
174
174
175
175
176 def debug_index(
176 def debug_index(
177 ui,
177 ui,
178 repo,
178 repo,
179 formatter,
179 formatter,
180 revlog,
180 revlog,
181 full_node,
181 full_node,
182 ):
182 ):
183 """display index data for a revlog"""
183 """display index data for a revlog"""
184 if full_node:
184 if full_node:
185 hexfn = nodemod.hex
185 hexfn = nodemod.hex
186 else:
186 else:
187 hexfn = nodemod.short
187 hexfn = nodemod.short
188
188
189 idlen = 12
189 idlen = 12
190 for i in revlog:
190 for i in revlog:
191 idlen = len(hexfn(revlog.node(i)))
191 idlen = len(hexfn(revlog.node(i)))
192 break
192 break
193
193
194 fm = formatter
194 fm = formatter
195
195
196 header_pieces = []
196 header_pieces = []
197 for column in INDEX_ENTRY_DEBUG_COLUMN:
197 for column in INDEX_ENTRY_DEBUG_COLUMN:
198 if column.verbose_only and not ui.verbose:
198 if column.verbose_only and not ui.verbose:
199 continue
199 continue
200 size = column.get_size(idlen)
200 size = column.get_size(idlen)
201 name = column.name
201 name = column.name
202 header_pieces.append(name.rjust(size))
202 header_pieces.append(name.rjust(size))
203
203
204 fm.plain(b' '.join(header_pieces) + b'\n')
204 fm.plain(b' '.join(header_pieces) + b'\n')
205
205
206 index = revlog.index
206 index = revlog.index
207
207
208 for rev in revlog:
208 for rev in revlog:
209 fm.startitem()
209 fm.startitem()
210 entry = index[rev]
210 entry = index[rev]
211 first = True
211 first = True
212 for column in INDEX_ENTRY_DEBUG_COLUMN:
212 for column in INDEX_ENTRY_DEBUG_COLUMN:
213 if column.verbose_only and not ui.verbose:
213 if column.verbose_only and not ui.verbose:
214 continue
214 continue
215 if not first:
215 if not first:
216 fm.plain(b' ')
216 fm.plain(b' ')
217 first = False
217 first = False
218
218
219 size = column.get_size(idlen)
219 size = column.get_size(idlen)
220 value = column.value_func(index, rev, entry, hexfn)
220 value = column.value_func(index, rev, entry, hexfn)
221 display = b"%%%ds" % size
221 display = b"%%%ds" % size
222 fm.write(column.name, display, value)
222 fm.write(column.name, display, value)
223 fm.plain(b'\n')
223 fm.plain(b'\n')
224
224
225 fm.end()
225 fm.end()
226
226
227
227
228 def dump(ui, revlog):
228 def dump(ui, revlog):
229 """perform the work for `hg debugrevlog --dump"""
229 """perform the work for `hg debugrevlog --dump"""
230 # XXX seems redundant with debug index ?
230 # XXX seems redundant with debug index ?
231 r = revlog
231 r = revlog
232 numrevs = len(r)
232 numrevs = len(r)
233 ui.write(
233 ui.write(
234 (
234 (
235 b"# rev p1rev p2rev start end deltastart base p1 p2"
235 b"# rev p1rev p2rev start end deltastart base p1 p2"
236 b" rawsize totalsize compression heads chainlen\n"
236 b" rawsize totalsize compression heads chainlen\n"
237 )
237 )
238 )
238 )
239 ts = 0
239 ts = 0
240 heads = set()
240 heads = set()
241
241
242 for rev in range(numrevs):
242 for rev in range(numrevs):
243 dbase = r.deltaparent(rev)
243 dbase = r.deltaparent(rev)
244 if dbase == -1:
244 if dbase == -1:
245 dbase = rev
245 dbase = rev
246 cbase = r.chainbase(rev)
246 cbase = r.chainbase(rev)
247 clen = r.chainlen(rev)
247 clen = r.chainlen(rev)
248 p1, p2 = r.parentrevs(rev)
248 p1, p2 = r.parentrevs(rev)
249 rs = r.rawsize(rev)
249 rs = r.rawsize(rev)
250 ts = ts + rs
250 ts = ts + rs
251 heads -= set(r.parentrevs(rev))
251 heads -= set(r.parentrevs(rev))
252 heads.add(rev)
252 heads.add(rev)
253 try:
253 try:
254 compression = ts / r.end(rev)
254 compression = ts / r.end(rev)
255 except ZeroDivisionError:
255 except ZeroDivisionError:
256 compression = 0
256 compression = 0
257 ui.write(
257 ui.write(
258 b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
258 b"%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
259 b"%11d %5d %8d\n"
259 b"%11d %5d %8d\n"
260 % (
260 % (
261 rev,
261 rev,
262 p1,
262 p1,
263 p2,
263 p2,
264 r.start(rev),
264 r.start(rev),
265 r.end(rev),
265 r.end(rev),
266 r.start(dbase),
266 r.start(dbase),
267 r.start(cbase),
267 r.start(cbase),
268 r.start(p1),
268 r.start(p1),
269 r.start(p2),
269 r.start(p2),
270 rs,
270 rs,
271 ts,
271 ts,
272 compression,
272 compression,
273 len(heads),
273 len(heads),
274 clen,
274 clen,
275 )
275 )
276 )
276 )
277
277
278
278
279 def debug_revlog(ui, revlog):
279 def debug_revlog(ui, revlog):
280 """code for `hg debugrevlog`"""
280 """code for `hg debugrevlog`"""
281 r = revlog
281 r = revlog
282 format = r._format_version
282 format = r._format_version
283 v = r._format_flags
283 v = r._format_flags
284 flags = []
284 flags = []
285 gdelta = False
285 gdelta = False
286 if v & constants.FLAG_INLINE_DATA:
286 if v & constants.FLAG_INLINE_DATA:
287 flags.append(b'inline')
287 flags.append(b'inline')
288 if v & constants.FLAG_GENERALDELTA:
288 if v & constants.FLAG_GENERALDELTA:
289 gdelta = True
289 gdelta = True
290 flags.append(b'generaldelta')
290 flags.append(b'generaldelta')
291 if not flags:
291 if not flags:
292 flags = [b'(none)']
292 flags = [b'(none)']
293
293
294 ### the total size of stored content if incompressed.
294 ### the total size of stored content if incompressed.
295 full_text_total_size = 0
295 full_text_total_size = 0
296 ### tracks merge vs single parent
296 ### tracks merge vs single parent
297 nummerges = 0
297 nummerges = 0
298
298
299 ### tracks ways the "delta" are build
299 ### tracks ways the "delta" are build
300 # nodelta
300 # nodelta
301 numempty = 0
301 numempty = 0
302 numemptytext = 0
302 numemptytext = 0
303 numemptydelta = 0
303 numemptydelta = 0
304 # full file content
304 # full file content
305 numfull = 0
305 numfull = 0
306 # intermediate snapshot against a prior snapshot
306 # intermediate snapshot against a prior snapshot
307 numsemi = 0
307 numsemi = 0
308 # snapshot count per depth
308 # snapshot count per depth
309 numsnapdepth = collections.defaultdict(lambda: 0)
309 numsnapdepth = collections.defaultdict(lambda: 0)
310 # number of snapshots with a non-ancestor delta
310 # number of snapshots with a non-ancestor delta
311 numsnapdepth_nad = collections.defaultdict(lambda: 0)
311 numsnapdepth_nad = collections.defaultdict(lambda: 0)
312 # delta against previous revision
312 # delta against previous revision
313 numprev = 0
313 numprev = 0
314 # delta against prev, where prev is a non-ancestor
314 # delta against prev, where prev is a non-ancestor
315 numprev_nad = 0
315 numprev_nad = 0
316 # delta against first or second parent (not prev)
316 # delta against first or second parent (not prev)
317 nump1 = 0
317 nump1 = 0
318 nump2 = 0
318 nump2 = 0
319 # delta against neither prev nor parents
319 # delta against neither prev nor parents
320 numother = 0
320 numother = 0
321 # delta against other that is a non-ancestor
321 # delta against other that is a non-ancestor
322 numother_nad = 0
322 numother_nad = 0
323 # delta against prev that are also first or second parent
323 # delta against prev that are also first or second parent
324 # (details of `numprev`)
324 # (details of `numprev`)
325 nump1prev = 0
325 nump1prev = 0
326 nump2prev = 0
326 nump2prev = 0
327
327
328 # data about delta chain of each revs
328 # data about delta chain of each revs
329 chainlengths = []
329 chainlengths = []
330 chainbases = []
330 chainbases = []
331 chainspans = []
331 chainspans = []
332
332
333 # data about each revision
333 # data about each revision
334 datasize = [None, 0, 0]
334 datasize = [None, 0, 0]
335 fullsize = [None, 0, 0]
335 fullsize = [None, 0, 0]
336 semisize = [None, 0, 0]
336 semisize = [None, 0, 0]
337 # snapshot count per depth
337 # snapshot count per depth
338 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
338 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
339 deltasize = [None, 0, 0]
339 deltasize = [None, 0, 0]
340 chunktypecounts = {}
340 chunktypecounts = {}
341 chunktypesizes = {}
341 chunktypesizes = {}
342
342
343 def addsize(size, l):
343 def addsize(size, l):
344 if l[0] is None or size < l[0]:
344 if l[0] is None or size < l[0]:
345 l[0] = size
345 l[0] = size
346 if size > l[1]:
346 if size > l[1]:
347 l[1] = size
347 l[1] = size
348 l[2] += size
348 l[2] += size
349
349
350 numrevs = len(r)
350 numrevs = len(r)
351 for rev in range(numrevs):
351 for rev in range(numrevs):
352 p1, p2 = r.parentrevs(rev)
352 p1, p2 = r.parentrevs(rev)
353 delta = r.deltaparent(rev)
353 delta = r.deltaparent(rev)
354 if format > 0:
354 if format > 0:
355 s = r.rawsize(rev)
355 s = r.rawsize(rev)
356 full_text_total_size += s
356 full_text_total_size += s
357 addsize(s, datasize)
357 addsize(s, datasize)
358 if p2 != nodemod.nullrev:
358 if p2 != nodemod.nullrev:
359 nummerges += 1
359 nummerges += 1
360 size = r.length(rev)
360 size = r.length(rev)
361 if delta == nodemod.nullrev:
361 if delta == nodemod.nullrev:
362 chainlengths.append(0)
362 chainlengths.append(0)
363 chainbases.append(r.start(rev))
363 chainbases.append(r.start(rev))
364 chainspans.append(size)
364 chainspans.append(size)
365 if size == 0:
365 if size == 0:
366 numempty += 1
366 numempty += 1
367 numemptytext += 1
367 numemptytext += 1
368 else:
368 else:
369 numfull += 1
369 numfull += 1
370 numsnapdepth[0] += 1
370 numsnapdepth[0] += 1
371 addsize(size, fullsize)
371 addsize(size, fullsize)
372 addsize(size, snapsizedepth[0])
372 addsize(size, snapsizedepth[0])
373 else:
373 else:
374 nad = (
374 nad = (
375 delta != p1 and delta != p2 and not r.isancestorrev(delta, rev)
375 delta != p1 and delta != p2 and not r.isancestorrev(delta, rev)
376 )
376 )
377 chainlengths.append(chainlengths[delta] + 1)
377 chainlengths.append(chainlengths[delta] + 1)
378 baseaddr = chainbases[delta]
378 baseaddr = chainbases[delta]
379 revaddr = r.start(rev)
379 revaddr = r.start(rev)
380 chainbases.append(baseaddr)
380 chainbases.append(baseaddr)
381 chainspans.append((revaddr - baseaddr) + size)
381 chainspans.append((revaddr - baseaddr) + size)
382 if size == 0:
382 if size == 0:
383 numempty += 1
383 numempty += 1
384 numemptydelta += 1
384 numemptydelta += 1
385 elif r.issnapshot(rev):
385 elif r.issnapshot(rev):
386 addsize(size, semisize)
386 addsize(size, semisize)
387 numsemi += 1
387 numsemi += 1
388 depth = r.snapshotdepth(rev)
388 depth = r.snapshotdepth(rev)
389 numsnapdepth[depth] += 1
389 numsnapdepth[depth] += 1
390 if nad:
390 if nad:
391 numsnapdepth_nad[depth] += 1
391 numsnapdepth_nad[depth] += 1
392 addsize(size, snapsizedepth[depth])
392 addsize(size, snapsizedepth[depth])
393 else:
393 else:
394 addsize(size, deltasize)
394 addsize(size, deltasize)
395 if delta == rev - 1:
395 if delta == rev - 1:
396 numprev += 1
396 numprev += 1
397 if delta == p1:
397 if delta == p1:
398 nump1prev += 1
398 nump1prev += 1
399 elif delta == p2:
399 elif delta == p2:
400 nump2prev += 1
400 nump2prev += 1
401 elif nad:
401 elif nad:
402 numprev_nad += 1
402 numprev_nad += 1
403 elif delta == p1:
403 elif delta == p1:
404 nump1 += 1
404 nump1 += 1
405 elif delta == p2:
405 elif delta == p2:
406 nump2 += 1
406 nump2 += 1
407 elif delta != nodemod.nullrev:
407 elif delta != nodemod.nullrev:
408 numother += 1
408 numother += 1
409 numother_nad += 1
409 numother_nad += 1
410
410
411 # Obtain data on the raw chunks in the revlog.
411 # Obtain data on the raw chunks in the revlog.
412 if util.safehasattr(r, '_getsegmentforrevs'):
412 if util.safehasattr(r, '_getsegmentforrevs'):
413 segment = r._getsegmentforrevs(rev, rev)[1]
413 segment = r._getsegmentforrevs(rev, rev)[1]
414 else:
414 else:
415 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
415 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
416 if segment:
416 if segment:
417 chunktype = bytes(segment[0:1])
417 chunktype = bytes(segment[0:1])
418 else:
418 else:
419 chunktype = b'empty'
419 chunktype = b'empty'
420
420
421 if chunktype not in chunktypecounts:
421 if chunktype not in chunktypecounts:
422 chunktypecounts[chunktype] = 0
422 chunktypecounts[chunktype] = 0
423 chunktypesizes[chunktype] = 0
423 chunktypesizes[chunktype] = 0
424
424
425 chunktypecounts[chunktype] += 1
425 chunktypecounts[chunktype] += 1
426 chunktypesizes[chunktype] += size
426 chunktypesizes[chunktype] += size
427
427
428 # Adjust size min value for empty cases
428 # Adjust size min value for empty cases
429 for size in (datasize, fullsize, semisize, deltasize):
429 for size in (datasize, fullsize, semisize, deltasize):
430 if size[0] is None:
430 if size[0] is None:
431 size[0] = 0
431 size[0] = 0
432
432
433 numdeltas = numrevs - numfull - numempty - numsemi
433 numdeltas = numrevs - numfull - numempty - numsemi
434 numoprev = numprev - nump1prev - nump2prev - numprev_nad
434 numoprev = numprev - nump1prev - nump2prev - numprev_nad
435 num_other_ancestors = numother - numother_nad
435 num_other_ancestors = numother - numother_nad
436 totalrawsize = datasize[2]
436 totalrawsize = datasize[2]
437 datasize[2] /= numrevs
437 datasize[2] /= numrevs
438 fulltotal = fullsize[2]
438 fulltotal = fullsize[2]
439 if numfull == 0:
439 if numfull == 0:
440 fullsize[2] = 0
440 fullsize[2] = 0
441 else:
441 else:
442 fullsize[2] /= numfull
442 fullsize[2] /= numfull
443 semitotal = semisize[2]
443 semitotal = semisize[2]
444 snaptotal = {}
444 snaptotal = {}
445 if numsemi > 0:
445 if numsemi > 0:
446 semisize[2] /= numsemi
446 semisize[2] /= numsemi
447 for depth in snapsizedepth:
447 for depth in snapsizedepth:
448 snaptotal[depth] = snapsizedepth[depth][2]
448 snaptotal[depth] = snapsizedepth[depth][2]
449 snapsizedepth[depth][2] /= numsnapdepth[depth]
449 snapsizedepth[depth][2] /= numsnapdepth[depth]
450
450
451 deltatotal = deltasize[2]
451 deltatotal = deltasize[2]
452 if numdeltas > 0:
452 if numdeltas > 0:
453 deltasize[2] /= numdeltas
453 deltasize[2] /= numdeltas
454 totalsize = fulltotal + semitotal + deltatotal
454 totalsize = fulltotal + semitotal + deltatotal
455 avgchainlen = sum(chainlengths) / numrevs
455 avgchainlen = sum(chainlengths) / numrevs
456 maxchainlen = max(chainlengths)
456 maxchainlen = max(chainlengths)
457 maxchainspan = max(chainspans)
457 maxchainspan = max(chainspans)
458 compratio = 1
458 compratio = 1
459 if totalsize:
459 if totalsize:
460 compratio = totalrawsize / totalsize
460 compratio = totalrawsize / totalsize
461
461
462 basedfmtstr = b'%%%dd\n'
462 basedfmtstr = b'%%%dd\n'
463 basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
463 basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
464
464
465 def dfmtstr(max):
465 def dfmtstr(max):
466 return basedfmtstr % len(str(max))
466 return basedfmtstr % len(str(max))
467
467
468 def pcfmtstr(max, padding=0):
468 def pcfmtstr(max, padding=0):
469 return basepcfmtstr % (len(str(max)), b' ' * padding)
469 return basepcfmtstr % (len(str(max)), b' ' * padding)
470
470
471 def pcfmt(value, total):
471 def pcfmt(value, total):
472 if total:
472 if total:
473 return (value, 100 * float(value) / total)
473 return (value, 100 * float(value) / total)
474 else:
474 else:
475 return value, 100.0
475 return value, 100.0
476
476
477 ui.writenoi18n(b'format : %d\n' % format)
477 ui.writenoi18n(b'format : %d\n' % format)
478 ui.writenoi18n(b'flags : %s\n' % b', '.join(flags))
478 ui.writenoi18n(b'flags : %s\n' % b', '.join(flags))
479
479
480 ui.write(b'\n')
480 ui.write(b'\n')
481 fmt = pcfmtstr(totalsize)
481 fmt = pcfmtstr(totalsize)
482 fmt2 = dfmtstr(totalsize)
482 fmt2 = dfmtstr(totalsize)
483 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
483 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
484 ui.writenoi18n(b' merges : ' + fmt % pcfmt(nummerges, numrevs))
484 ui.writenoi18n(b' merges : ' + fmt % pcfmt(nummerges, numrevs))
485 ui.writenoi18n(
485 ui.writenoi18n(
486 b' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs)
486 b' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs)
487 )
487 )
488 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
488 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
489 ui.writenoi18n(b' empty : ' + fmt % pcfmt(numempty, numrevs))
489 ui.writenoi18n(b' empty : ' + fmt % pcfmt(numempty, numrevs))
490 ui.writenoi18n(
490 ui.writenoi18n(
491 b' text : '
491 b' text : '
492 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
492 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
493 )
493 )
494 ui.writenoi18n(
494 ui.writenoi18n(
495 b' delta : '
495 b' delta : '
496 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
496 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
497 )
497 )
498 ui.writenoi18n(
498 ui.writenoi18n(
499 b' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs)
499 b' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs)
500 )
500 )
501 for depth in sorted(numsnapdepth):
501 for depth in sorted(numsnapdepth):
502 base = b' lvl-%-3d : ' % depth
502 base = b' lvl-%-3d : ' % depth
503 count = fmt % pcfmt(numsnapdepth[depth], numrevs)
503 count = fmt % pcfmt(numsnapdepth[depth], numrevs)
504 pieces = [base, count]
504 pieces = [base, count]
505 if numsnapdepth_nad[depth]:
505 if numsnapdepth_nad[depth]:
506 pieces[-1] = count = count[:-1] # drop the final '\n'
506 pieces[-1] = count = count[:-1] # drop the final '\n'
507 more = b' non-ancestor-bases: '
507 more = b' non-ancestor-bases: '
508 anc_count = fmt
508 anc_count = fmt
509 anc_count %= pcfmt(numsnapdepth_nad[depth], numsnapdepth[depth])
509 anc_count %= pcfmt(numsnapdepth_nad[depth], numsnapdepth[depth])
510 pieces.append(more)
510 pieces.append(more)
511 pieces.append(anc_count)
511 pieces.append(anc_count)
512 ui.write(b''.join(pieces))
512 ui.write(b''.join(pieces))
513 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
513 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
514 ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
514 ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
515 ui.writenoi18n(
515 ui.writenoi18n(
516 b' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
516 b' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
517 )
517 )
518 for depth in sorted(numsnapdepth):
518 for depth in sorted(numsnapdepth):
519 ui.write(
519 ui.write(
520 (b' lvl-%-3d : ' % depth)
520 (b' lvl-%-3d : ' % depth)
521 + fmt % pcfmt(snaptotal[depth], totalsize)
521 + fmt % pcfmt(snaptotal[depth], totalsize)
522 )
522 )
523 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
523 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
524
524
525 letters = string.ascii_letters.encode('ascii')
525 letters = string.ascii_letters.encode('ascii')
526
526
527 def fmtchunktype(chunktype):
527 def fmtchunktype(chunktype):
528 if chunktype == b'empty':
528 if chunktype == b'empty':
529 return b' %s : ' % chunktype
529 return b' %s : ' % chunktype
530 elif chunktype in letters:
530 elif chunktype in letters:
531 return b' 0x%s (%s) : ' % (nodemod.hex(chunktype), chunktype)
531 return b' 0x%s (%s) : ' % (nodemod.hex(chunktype), chunktype)
532 else:
532 else:
533 return b' 0x%s : ' % nodemod.hex(chunktype)
533 return b' 0x%s : ' % nodemod.hex(chunktype)
534
534
535 ui.write(b'\n')
535 ui.write(b'\n')
536 ui.writenoi18n(b'chunks : ' + fmt2 % numrevs)
536 ui.writenoi18n(b'chunks : ' + fmt2 % numrevs)
537 for chunktype in sorted(chunktypecounts):
537 for chunktype in sorted(chunktypecounts):
538 ui.write(fmtchunktype(chunktype))
538 ui.write(fmtchunktype(chunktype))
539 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
539 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
540 ui.writenoi18n(b'chunks size : ' + fmt2 % totalsize)
540 ui.writenoi18n(b'chunks size : ' + fmt2 % totalsize)
541 for chunktype in sorted(chunktypecounts):
541 for chunktype in sorted(chunktypecounts):
542 ui.write(fmtchunktype(chunktype))
542 ui.write(fmtchunktype(chunktype))
543 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
543 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
544
544
545 ui.write(b'\n')
545 ui.write(b'\n')
546 b_total = b"%d" % full_text_total_size
546 b_total = b"%d" % full_text_total_size
547 p_total = []
547 p_total = []
548 while len(b_total) > 3:
548 while len(b_total) > 3:
549 p_total.append(b_total[-3:])
549 p_total.append(b_total[-3:])
550 b_total = b_total[:-3]
550 b_total = b_total[:-3]
551 p_total.append(b_total)
551 p_total.append(b_total)
552 p_total.reverse()
552 p_total.reverse()
553 b_total = b' '.join(p_total)
553 b_total = b' '.join(p_total)
554
554
555 ui.write(b'\n')
555 ui.write(b'\n')
556 ui.writenoi18n(b'total-stored-content: %s bytes\n' % b_total)
556 ui.writenoi18n(b'total-stored-content: %s bytes\n' % b_total)
557 ui.write(b'\n')
557 ui.write(b'\n')
558 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
558 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
559 ui.writenoi18n(b'avg chain length : ' + fmt % avgchainlen)
559 ui.writenoi18n(b'avg chain length : ' + fmt % avgchainlen)
560 ui.writenoi18n(b'max chain length : ' + fmt % maxchainlen)
560 ui.writenoi18n(b'max chain length : ' + fmt % maxchainlen)
561 ui.writenoi18n(b'max chain reach : ' + fmt % maxchainspan)
561 ui.writenoi18n(b'max chain reach : ' + fmt % maxchainspan)
562 ui.writenoi18n(b'compression ratio : ' + fmt % compratio)
562 ui.writenoi18n(b'compression ratio : ' + fmt % compratio)
563
563
564 if format > 0:
564 if format > 0:
565 ui.write(b'\n')
565 ui.write(b'\n')
566 ui.writenoi18n(
566 ui.writenoi18n(
567 b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
567 b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
568 % tuple(datasize)
568 % tuple(datasize)
569 )
569 )
570 ui.writenoi18n(
570 ui.writenoi18n(
571 b'full revision size (min/max/avg) : %d / %d / %d\n'
571 b'full revision size (min/max/avg) : %d / %d / %d\n'
572 % tuple(fullsize)
572 % tuple(fullsize)
573 )
573 )
574 ui.writenoi18n(
574 ui.writenoi18n(
575 b'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
575 b'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
576 % tuple(semisize)
576 % tuple(semisize)
577 )
577 )
578 for depth in sorted(snapsizedepth):
578 for depth in sorted(snapsizedepth):
579 if depth == 0:
579 if depth == 0:
580 continue
580 continue
581 ui.writenoi18n(
581 ui.writenoi18n(
582 b' level-%-3d (min/max/avg) : %d / %d / %d\n'
582 b' level-%-3d (min/max/avg) : %d / %d / %d\n'
583 % ((depth,) + tuple(snapsizedepth[depth]))
583 % ((depth,) + tuple(snapsizedepth[depth]))
584 )
584 )
585 ui.writenoi18n(
585 ui.writenoi18n(
586 b'delta size (min/max/avg) : %d / %d / %d\n'
586 b'delta size (min/max/avg) : %d / %d / %d\n'
587 % tuple(deltasize)
587 % tuple(deltasize)
588 )
588 )
589
589
590 if numdeltas > 0:
590 if numdeltas > 0:
591 ui.write(b'\n')
591 ui.write(b'\n')
592 fmt = pcfmtstr(numdeltas)
592 fmt = pcfmtstr(numdeltas)
593 fmt2 = pcfmtstr(numdeltas, 4)
593 fmt2 = pcfmtstr(numdeltas, 4)
594 ui.writenoi18n(
594 ui.writenoi18n(
595 b'deltas against prev : ' + fmt % pcfmt(numprev, numdeltas)
595 b'deltas against prev : ' + fmt % pcfmt(numprev, numdeltas)
596 )
596 )
597 if numprev > 0:
597 if numprev > 0:
598 ui.writenoi18n(
598 ui.writenoi18n(
599 b' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
599 b' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
600 )
600 )
601 ui.writenoi18n(
601 ui.writenoi18n(
602 b' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
602 b' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
603 )
603 )
604 ui.writenoi18n(
604 ui.writenoi18n(
605 b' other-ancestor : ' + fmt2 % pcfmt(numoprev, numprev)
605 b' other-ancestor : ' + fmt2 % pcfmt(numoprev, numprev)
606 )
606 )
607 ui.writenoi18n(
607 ui.writenoi18n(
608 b' unrelated : ' + fmt2 % pcfmt(numoprev, numprev)
608 b' unrelated : ' + fmt2 % pcfmt(numoprev, numprev)
609 )
609 )
610 if gdelta:
610 if gdelta:
611 ui.writenoi18n(
611 ui.writenoi18n(
612 b'deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas)
612 b'deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas)
613 )
613 )
614 ui.writenoi18n(
614 ui.writenoi18n(
615 b'deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas)
615 b'deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas)
616 )
616 )
617 ui.writenoi18n(
617 ui.writenoi18n(
618 b'deltas against ancs : '
618 b'deltas against ancs : '
619 + fmt % pcfmt(num_other_ancestors, numdeltas)
619 + fmt % pcfmt(num_other_ancestors, numdeltas)
620 )
620 )
621 ui.writenoi18n(
621 ui.writenoi18n(
622 b'deltas against other : '
622 b'deltas against other : '
623 + fmt % pcfmt(numother_nad, numdeltas)
623 + fmt % pcfmt(numother_nad, numdeltas)
624 )
624 )
625
625
626
626
627 def debug_delta_find(ui, revlog, rev, base_rev=nodemod.nullrev):
627 def debug_delta_find(ui, revlog, rev, base_rev=nodemod.nullrev):
628 """display the search process for a delta"""
628 """display the search process for a delta"""
629 deltacomputer = deltautil.deltacomputer(
629 deltacomputer = deltautil.deltacomputer(
630 revlog,
630 revlog,
631 write_debug=ui.write,
631 write_debug=ui.write,
632 debug_search=not ui.quiet,
632 debug_search=not ui.quiet,
633 )
633 )
634
634
635 node = revlog.node(rev)
635 node = revlog.node(rev)
636 p1r, p2r = revlog.parentrevs(rev)
636 p1r, p2r = revlog.parentrevs(rev)
637 p1 = revlog.node(p1r)
637 p1 = revlog.node(p1r)
638 p2 = revlog.node(p2r)
638 p2 = revlog.node(p2r)
639 full_text = revlog.revision(rev)
639 full_text = revlog.revision(rev)
640 btext = [full_text]
640 btext = [full_text]
641 textlen = len(btext[0])
641 textlen = len(btext[0])
642 cachedelta = None
642 cachedelta = None
643 flags = revlog.flags(rev)
643 flags = revlog.flags(rev)
644
644
645 if base_rev != nodemod.nullrev:
645 if base_rev != nodemod.nullrev:
646 base_text = revlog.revision(base_rev)
646 base_text = revlog.revision(base_rev)
647 delta = mdiff.textdiff(base_text, full_text)
647 delta = mdiff.textdiff(base_text, full_text)
648
648
649 cachedelta = (base_rev, delta, constants.DELTA_BASE_REUSE_TRY)
649 cachedelta = (base_rev, delta, constants.DELTA_BASE_REUSE_TRY)
650 btext = [None]
650 btext = [None]
651
651
652 revinfo = revlogutils.revisioninfo(
652 revinfo = revlogutils.revisioninfo(
653 node,
653 node,
654 p1,
654 p1,
655 p2,
655 p2,
656 btext,
656 btext,
657 textlen,
657 textlen,
658 cachedelta,
658 cachedelta,
659 flags,
659 flags,
660 )
660 )
661
661
662 fh = revlog._datafp()
662 fh = revlog._datafp()
663 deltacomputer.finddeltainfo(revinfo, fh, target_rev=rev)
663 deltacomputer.finddeltainfo(revinfo, fh, target_rev=rev)
664
665
666 def _get_revlogs(repo, changelog: bool, manifest: bool, filelogs: bool):
667 """yield revlogs from this repository"""
668 if changelog:
669 yield repo.changelog
670
671 if manifest:
672 # XXX: Handle tree manifest
673 root_mf = repo.manifestlog.getstorage(b'')
674 assert not root_mf._treeondisk
675 yield root_mf._revlog
676
677 if filelogs:
678 files = set()
679 for rev in repo:
680 ctx = repo[rev]
681 files |= set(ctx.files())
682
683 for f in sorted(files):
684 yield repo.file(f)._revlog
685
686
687 def debug_revlog_stats(
688 repo, fm, changelog: bool, manifest: bool, filelogs: bool
689 ):
690 """Format revlog statistics for debugging purposes
691
692 fm: the output formatter.
693 """
694 fm.plain(b'rev-count data-size inl type target \n')
695
696 for rlog in _get_revlogs(repo, changelog, manifest, filelogs):
697 fm.startitem()
698 nb_rev = len(rlog)
699 inline = rlog._inline
700 data_size = rlog._get_data_offset(nb_rev - 1)
701
702 target = rlog.target
703 revlog_type = b'unknown'
704 revlog_target = b''
705 if target[0] == constants.KIND_CHANGELOG:
706 revlog_type = b'changelog'
707 elif target[0] == constants.KIND_MANIFESTLOG:
708 revlog_type = b'manifest'
709 revlog_target = target[1]
710 elif target[0] == constants.KIND_FILELOG:
711 revlog_type = b'file'
712 revlog_target = target[1]
713
714 fm.write(b'revlog.rev-count', b'%9d', nb_rev)
715 fm.write(b'revlog.data-size', b'%12d', data_size)
716
717 fm.write(b'revlog.inline', b' %-3s', b'yes' if inline else b'no')
718 fm.write(b'revlog.type', b' %-9s', revlog_type)
719 fm.write(b'revlog.target', b' %s', revlog_target)
720
721 fm.plain(b'\n')
@@ -1,449 +1,451
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 abort
3 abort
4 add
4 add
5 addremove
5 addremove
6 annotate
6 annotate
7 archive
7 archive
8 backout
8 backout
9 bisect
9 bisect
10 bookmarks
10 bookmarks
11 branch
11 branch
12 branches
12 branches
13 bundle
13 bundle
14 cat
14 cat
15 clone
15 clone
16 commit
16 commit
17 config
17 config
18 continue
18 continue
19 copy
19 copy
20 diff
20 diff
21 export
21 export
22 files
22 files
23 forget
23 forget
24 graft
24 graft
25 grep
25 grep
26 heads
26 heads
27 help
27 help
28 identify
28 identify
29 import
29 import
30 incoming
30 incoming
31 init
31 init
32 locate
32 locate
33 log
33 log
34 manifest
34 manifest
35 merge
35 merge
36 outgoing
36 outgoing
37 parents
37 parents
38 paths
38 paths
39 phase
39 phase
40 pull
40 pull
41 purge
41 purge
42 push
42 push
43 recover
43 recover
44 remove
44 remove
45 rename
45 rename
46 resolve
46 resolve
47 revert
47 revert
48 rollback
48 rollback
49 root
49 root
50 serve
50 serve
51 shelve
51 shelve
52 status
52 status
53 summary
53 summary
54 tag
54 tag
55 tags
55 tags
56 tip
56 tip
57 unbundle
57 unbundle
58 unshelve
58 unshelve
59 update
59 update
60 verify
60 verify
61 version
61 version
62
62
63 Show all commands that start with "a"
63 Show all commands that start with "a"
64 $ hg debugcomplete a
64 $ hg debugcomplete a
65 abort
65 abort
66 add
66 add
67 addremove
67 addremove
68 annotate
68 annotate
69 archive
69 archive
70
70
71 Do not show debug commands if there are other candidates
71 Do not show debug commands if there are other candidates
72 $ hg debugcomplete d
72 $ hg debugcomplete d
73 diff
73 diff
74
74
75 Show debug commands if there are no other candidates
75 Show debug commands if there are no other candidates
76 $ hg debugcomplete debug
76 $ hg debugcomplete debug
77 debug-delta-find
77 debug-delta-find
78 debug-repair-issue6528
78 debug-repair-issue6528
79 debug-revlog-index
79 debug-revlog-index
80 debug-revlog-stats
80 debugancestor
81 debugancestor
81 debugantivirusrunning
82 debugantivirusrunning
82 debugapplystreamclonebundle
83 debugapplystreamclonebundle
83 debugbackupbundle
84 debugbackupbundle
84 debugbuilddag
85 debugbuilddag
85 debugbundle
86 debugbundle
86 debugcapabilities
87 debugcapabilities
87 debugchangedfiles
88 debugchangedfiles
88 debugcheckstate
89 debugcheckstate
89 debugcolor
90 debugcolor
90 debugcommands
91 debugcommands
91 debugcomplete
92 debugcomplete
92 debugconfig
93 debugconfig
93 debugcreatestreamclonebundle
94 debugcreatestreamclonebundle
94 debugdag
95 debugdag
95 debugdata
96 debugdata
96 debugdate
97 debugdate
97 debugdeltachain
98 debugdeltachain
98 debugdirstate
99 debugdirstate
99 debugdirstateignorepatternshash
100 debugdirstateignorepatternshash
100 debugdiscovery
101 debugdiscovery
101 debugdownload
102 debugdownload
102 debugextensions
103 debugextensions
103 debugfileset
104 debugfileset
104 debugformat
105 debugformat
105 debugfsinfo
106 debugfsinfo
106 debuggetbundle
107 debuggetbundle
107 debugignore
108 debugignore
108 debugindexdot
109 debugindexdot
109 debugindexstats
110 debugindexstats
110 debuginstall
111 debuginstall
111 debugknown
112 debugknown
112 debuglabelcomplete
113 debuglabelcomplete
113 debuglocks
114 debuglocks
114 debugmanifestfulltextcache
115 debugmanifestfulltextcache
115 debugmergestate
116 debugmergestate
116 debugnamecomplete
117 debugnamecomplete
117 debugnodemap
118 debugnodemap
118 debugobsolete
119 debugobsolete
119 debugp1copies
120 debugp1copies
120 debugp2copies
121 debugp2copies
121 debugpathcomplete
122 debugpathcomplete
122 debugpathcopies
123 debugpathcopies
123 debugpeer
124 debugpeer
124 debugpickmergetool
125 debugpickmergetool
125 debugpushkey
126 debugpushkey
126 debugpvec
127 debugpvec
127 debugrebuilddirstate
128 debugrebuilddirstate
128 debugrebuildfncache
129 debugrebuildfncache
129 debugrename
130 debugrename
130 debugrequires
131 debugrequires
131 debugrevlog
132 debugrevlog
132 debugrevlogindex
133 debugrevlogindex
133 debugrevspec
134 debugrevspec
134 debugserve
135 debugserve
135 debugsetparents
136 debugsetparents
136 debugshell
137 debugshell
137 debugsidedata
138 debugsidedata
138 debugssl
139 debugssl
139 debugstrip
140 debugstrip
140 debugsub
141 debugsub
141 debugsuccessorssets
142 debugsuccessorssets
142 debugtagscache
143 debugtagscache
143 debugtemplate
144 debugtemplate
144 debuguigetpass
145 debuguigetpass
145 debuguiprompt
146 debuguiprompt
146 debugupdatecaches
147 debugupdatecaches
147 debugupgraderepo
148 debugupgraderepo
148 debugwalk
149 debugwalk
149 debugwhyunstable
150 debugwhyunstable
150 debugwireargs
151 debugwireargs
151 debugwireproto
152 debugwireproto
152
153
153 Do not show the alias of a debug command if there are other candidates
154 Do not show the alias of a debug command if there are other candidates
154 (this should hide rawcommit)
155 (this should hide rawcommit)
155 $ hg debugcomplete r
156 $ hg debugcomplete r
156 recover
157 recover
157 remove
158 remove
158 rename
159 rename
159 resolve
160 resolve
160 revert
161 revert
161 rollback
162 rollback
162 root
163 root
163 Show the alias of a debug command if there are no other candidates
164 Show the alias of a debug command if there are no other candidates
164 $ hg debugcomplete rawc
165 $ hg debugcomplete rawc
165
166
166
167
167 Show the global options
168 Show the global options
168 $ hg debugcomplete --options | sort
169 $ hg debugcomplete --options | sort
169 --color
170 --color
170 --config
171 --config
171 --cwd
172 --cwd
172 --debug
173 --debug
173 --debugger
174 --debugger
174 --encoding
175 --encoding
175 --encodingmode
176 --encodingmode
176 --help
177 --help
177 --hidden
178 --hidden
178 --noninteractive
179 --noninteractive
179 --pager
180 --pager
180 --profile
181 --profile
181 --quiet
182 --quiet
182 --repository
183 --repository
183 --time
184 --time
184 --traceback
185 --traceback
185 --verbose
186 --verbose
186 --version
187 --version
187 -R
188 -R
188 -h
189 -h
189 -q
190 -q
190 -v
191 -v
191 -y
192 -y
192
193
193 Show the options for the "serve" command
194 Show the options for the "serve" command
194 $ hg debugcomplete --options serve | sort
195 $ hg debugcomplete --options serve | sort
195 --accesslog
196 --accesslog
196 --address
197 --address
197 --certificate
198 --certificate
198 --cmdserver
199 --cmdserver
199 --color
200 --color
200 --config
201 --config
201 --cwd
202 --cwd
202 --daemon
203 --daemon
203 --daemon-postexec
204 --daemon-postexec
204 --debug
205 --debug
205 --debugger
206 --debugger
206 --encoding
207 --encoding
207 --encodingmode
208 --encodingmode
208 --errorlog
209 --errorlog
209 --help
210 --help
210 --hidden
211 --hidden
211 --ipv6
212 --ipv6
212 --name
213 --name
213 --noninteractive
214 --noninteractive
214 --pager
215 --pager
215 --pid-file
216 --pid-file
216 --port
217 --port
217 --prefix
218 --prefix
218 --print-url
219 --print-url
219 --profile
220 --profile
220 --quiet
221 --quiet
221 --repository
222 --repository
222 --stdio
223 --stdio
223 --style
224 --style
224 --subrepos
225 --subrepos
225 --templates
226 --templates
226 --time
227 --time
227 --traceback
228 --traceback
228 --verbose
229 --verbose
229 --version
230 --version
230 --web-conf
231 --web-conf
231 -6
232 -6
232 -A
233 -A
233 -E
234 -E
234 -R
235 -R
235 -S
236 -S
236 -a
237 -a
237 -d
238 -d
238 -h
239 -h
239 -n
240 -n
240 -p
241 -p
241 -q
242 -q
242 -t
243 -t
243 -v
244 -v
244 -y
245 -y
245
246
246 Show an error if we use --options with an ambiguous abbreviation
247 Show an error if we use --options with an ambiguous abbreviation
247 $ hg debugcomplete --options s
248 $ hg debugcomplete --options s
248 hg: command 's' is ambiguous:
249 hg: command 's' is ambiguous:
249 serve shelve showconfig status summary
250 serve shelve showconfig status summary
250 [10]
251 [10]
251
252
252 Show all commands + options
253 Show all commands + options
253 $ hg debugcommands
254 $ hg debugcommands
254 abort: dry-run
255 abort: dry-run
255 add: include, exclude, subrepos, dry-run
256 add: include, exclude, subrepos, dry-run
256 addremove: similarity, subrepos, include, exclude, dry-run
257 addremove: similarity, subrepos, include, exclude, dry-run
257 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
258 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, skip, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, include, exclude, template
258 archive: no-decode, prefix, rev, type, subrepos, include, exclude
259 archive: no-decode, prefix, rev, type, subrepos, include, exclude
259 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
260 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
260 bisect: reset, good, bad, skip, extend, command, noupdate
261 bisect: reset, good, bad, skip, extend, command, noupdate
261 bookmarks: force, rev, delete, rename, inactive, list, template
262 bookmarks: force, rev, delete, rename, inactive, list, template
262 branch: force, clean, rev
263 branch: force, clean, rev
263 branches: active, closed, rev, template
264 branches: active, closed, rev, template
264 bundle: exact, force, rev, branch, base, all, type, ssh, remotecmd, insecure
265 bundle: exact, force, rev, branch, base, all, type, ssh, remotecmd, insecure
265 cat: output, rev, decode, include, exclude, template
266 cat: output, rev, decode, include, exclude, template
266 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
267 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
267 commit: addremove, close-branch, amend, secret, draft, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
268 commit: addremove, close-branch, amend, secret, draft, edit, force-close-branch, interactive, include, exclude, message, logfile, date, user, subrepos
268 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
269 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
269 continue: dry-run
270 continue: dry-run
270 copy: forget, after, at-rev, force, include, exclude, dry-run
271 copy: forget, after, at-rev, force, include, exclude, dry-run
271 debug-delta-find: changelog, manifest, dir, template, source
272 debug-delta-find: changelog, manifest, dir, template, source
272 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
273 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
273 debug-revlog-index: changelog, manifest, dir, template
274 debug-revlog-index: changelog, manifest, dir, template
275 debug-revlog-stats: changelog, manifest, filelogs, template
274 debugancestor:
276 debugancestor:
275 debugantivirusrunning:
277 debugantivirusrunning:
276 debugapplystreamclonebundle:
278 debugapplystreamclonebundle:
277 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
279 debugbackupbundle: recover, patch, git, limit, no-merges, stat, graph, style, template
278 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
280 debugbuilddag: mergeable-file, overwritten-file, new-file, from-existing
279 debugbundle: all, part-type, spec
281 debugbundle: all, part-type, spec
280 debugcapabilities:
282 debugcapabilities:
281 debugchangedfiles: compute
283 debugchangedfiles: compute
282 debugcheckstate:
284 debugcheckstate:
283 debugcolor: style
285 debugcolor: style
284 debugcommands:
286 debugcommands:
285 debugcomplete: options
287 debugcomplete: options
286 debugcreatestreamclonebundle:
288 debugcreatestreamclonebundle:
287 debugdag: tags, branches, dots, spaces
289 debugdag: tags, branches, dots, spaces
288 debugdata: changelog, manifest, dir
290 debugdata: changelog, manifest, dir
289 debugdate: extended
291 debugdate: extended
290 debugdeltachain: changelog, manifest, dir, template
292 debugdeltachain: changelog, manifest, dir, template
291 debugdirstateignorepatternshash:
293 debugdirstateignorepatternshash:
292 debugdirstate: nodates, dates, datesort, docket, all
294 debugdirstate: nodates, dates, datesort, docket, all
293 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
295 debugdiscovery: old, nonheads, rev, seed, local-as-revs, remote-as-revs, ssh, remotecmd, insecure, template
294 debugdownload: output
296 debugdownload: output
295 debugextensions: template
297 debugextensions: template
296 debugfileset: rev, all-files, show-matcher, show-stage
298 debugfileset: rev, all-files, show-matcher, show-stage
297 debugformat: template
299 debugformat: template
298 debugfsinfo:
300 debugfsinfo:
299 debuggetbundle: head, common, type
301 debuggetbundle: head, common, type
300 debugignore:
302 debugignore:
301 debugindexdot: changelog, manifest, dir
303 debugindexdot: changelog, manifest, dir
302 debugindexstats:
304 debugindexstats:
303 debuginstall: template
305 debuginstall: template
304 debugknown:
306 debugknown:
305 debuglabelcomplete:
307 debuglabelcomplete:
306 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
308 debuglocks: force-free-lock, force-free-wlock, set-lock, set-wlock
307 debugmanifestfulltextcache: clear, add
309 debugmanifestfulltextcache: clear, add
308 debugmergestate: style, template
310 debugmergestate: style, template
309 debugnamecomplete:
311 debugnamecomplete:
310 debugnodemap: dump-new, dump-disk, check, metadata
312 debugnodemap: dump-new, dump-disk, check, metadata
311 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
313 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
312 debugp1copies: rev
314 debugp1copies: rev
313 debugp2copies: rev
315 debugp2copies: rev
314 debugpathcomplete: full, normal, added, removed
316 debugpathcomplete: full, normal, added, removed
315 debugpathcopies: include, exclude
317 debugpathcopies: include, exclude
316 debugpeer:
318 debugpeer:
317 debugpickmergetool: rev, changedelete, include, exclude, tool
319 debugpickmergetool: rev, changedelete, include, exclude, tool
318 debugpushkey:
320 debugpushkey:
319 debugpvec:
321 debugpvec:
320 debugrebuilddirstate: rev, minimal
322 debugrebuilddirstate: rev, minimal
321 debugrebuildfncache: only-data
323 debugrebuildfncache: only-data
322 debugrename: rev
324 debugrename: rev
323 debugrequires:
325 debugrequires:
324 debugrevlog: changelog, manifest, dir, dump
326 debugrevlog: changelog, manifest, dir, dump
325 debugrevlogindex: changelog, manifest, dir, format
327 debugrevlogindex: changelog, manifest, dir, format
326 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
328 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
327 debugserve: sshstdio, logiofd, logiofile
329 debugserve: sshstdio, logiofd, logiofile
328 debugsetparents:
330 debugsetparents:
329 debugshell:
331 debugshell:
330 debugsidedata: changelog, manifest, dir
332 debugsidedata: changelog, manifest, dir
331 debugssl:
333 debugssl:
332 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
334 debugstrip: rev, force, no-backup, nobackup, , keep, bookmark, soft
333 debugsub: rev
335 debugsub: rev
334 debugsuccessorssets: closest
336 debugsuccessorssets: closest
335 debugtagscache:
337 debugtagscache:
336 debugtemplate: rev, define
338 debugtemplate: rev, define
337 debuguigetpass: prompt
339 debuguigetpass: prompt
338 debuguiprompt: prompt
340 debuguiprompt: prompt
339 debugupdatecaches:
341 debugupdatecaches:
340 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
342 debugupgraderepo: optimize, run, backup, changelog, manifest, filelogs
341 debugwalk: include, exclude
343 debugwalk: include, exclude
342 debugwhyunstable:
344 debugwhyunstable:
343 debugwireargs: three, four, five, ssh, remotecmd, insecure
345 debugwireargs: three, four, five, ssh, remotecmd, insecure
344 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
346 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
345 diff: rev, from, to, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
347 diff: rev, from, to, change, text, git, binary, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, ignore-space-at-eol, unified, stat, root, include, exclude, subrepos
346 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
348 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
347 files: rev, print0, include, exclude, template, subrepos
349 files: rev, print0, include, exclude, template, subrepos
348 forget: interactive, include, exclude, dry-run
350 forget: interactive, include, exclude, dry-run
349 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
351 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
350 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
352 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
351 heads: rev, topo, active, closed, style, template
353 heads: rev, topo, active, closed, style, template
352 help: extension, command, keyword, system
354 help: extension, command, keyword, system
353 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
355 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
354 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
356 import: strip, base, secret, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
355 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
357 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
356 init: ssh, remotecmd, insecure
358 init: ssh, remotecmd, insecure
357 locate: rev, print0, fullpath, include, exclude
359 locate: rev, print0, fullpath, include, exclude
358 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
360 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, bookmark, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
359 manifest: rev, all, template
361 manifest: rev, all, template
360 merge: force, rev, preview, abort, tool
362 merge: force, rev, preview, abort, tool
361 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
363 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
362 parents: rev, style, template
364 parents: rev, style, template
363 paths: template
365 paths: template
364 phase: public, draft, secret, force, rev
366 phase: public, draft, secret, force, rev
365 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
367 pull: update, force, confirm, rev, bookmark, branch, ssh, remotecmd, insecure
366 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
368 purge: abort-on-err, all, ignored, dirs, files, print, print0, confirm, include, exclude
367 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
369 push: force, rev, bookmark, all-bookmarks, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
368 recover: verify
370 recover: verify
369 remove: after, force, subrepos, include, exclude, dry-run
371 remove: after, force, subrepos, include, exclude, dry-run
370 rename: forget, after, at-rev, force, include, exclude, dry-run
372 rename: forget, after, at-rev, force, include, exclude, dry-run
371 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
373 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
372 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
374 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
373 rollback: dry-run, force
375 rollback: dry-run, force
374 root: template
376 root: template
375 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
377 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, print-url, subrepos
376 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
378 shelve: addremove, unknown, cleanup, date, delete, edit, keep, list, message, name, patch, interactive, stat, include, exclude
377 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
379 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
378 summary: remote
380 summary: remote
379 tag: force, local, rev, remove, edit, message, date, user
381 tag: force, local, rev, remove, edit, message, date, user
380 tags: template
382 tags: template
381 tip: patch, git, style, template
383 tip: patch, git, style, template
382 unbundle: update
384 unbundle: update
383 unshelve: abort, continue, interactive, keep, name, tool, date
385 unshelve: abort, continue, interactive, keep, name, tool, date
384 update: clean, check, merge, date, rev, tool
386 update: clean, check, merge, date, rev, tool
385 verify: full
387 verify: full
386 version: template
388 version: template
387
389
388 $ hg init a
390 $ hg init a
389 $ cd a
391 $ cd a
390 $ echo fee > fee
392 $ echo fee > fee
391 $ hg ci -q -Amfee
393 $ hg ci -q -Amfee
392 $ hg tag fee
394 $ hg tag fee
393 $ mkdir fie
395 $ mkdir fie
394 $ echo dead > fie/dead
396 $ echo dead > fie/dead
395 $ echo live > fie/live
397 $ echo live > fie/live
396 $ hg bookmark fo
398 $ hg bookmark fo
397 $ hg branch -q fie
399 $ hg branch -q fie
398 $ hg ci -q -Amfie
400 $ hg ci -q -Amfie
399 $ echo fo > fo
401 $ echo fo > fo
400 $ hg branch -qf default
402 $ hg branch -qf default
401 $ hg ci -q -Amfo
403 $ hg ci -q -Amfo
402 $ echo Fum > Fum
404 $ echo Fum > Fum
403 $ hg ci -q -AmFum
405 $ hg ci -q -AmFum
404 $ hg bookmark Fum
406 $ hg bookmark Fum
405
407
406 Test debugpathcomplete
408 Test debugpathcomplete
407
409
408 $ hg debugpathcomplete f
410 $ hg debugpathcomplete f
409 fee
411 fee
410 fie
412 fie
411 fo
413 fo
412 $ hg debugpathcomplete -f f
414 $ hg debugpathcomplete -f f
413 fee
415 fee
414 fie/dead
416 fie/dead
415 fie/live
417 fie/live
416 fo
418 fo
417
419
418 $ hg rm Fum
420 $ hg rm Fum
419 $ hg debugpathcomplete -r F
421 $ hg debugpathcomplete -r F
420 Fum
422 Fum
421
423
422 Test debugnamecomplete
424 Test debugnamecomplete
423
425
424 $ hg debugnamecomplete
426 $ hg debugnamecomplete
425 Fum
427 Fum
426 default
428 default
427 fee
429 fee
428 fie
430 fie
429 fo
431 fo
430 tip
432 tip
431 $ hg debugnamecomplete f
433 $ hg debugnamecomplete f
432 fee
434 fee
433 fie
435 fie
434 fo
436 fo
435
437
436 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
438 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
437 used for completions in some shells.
439 used for completions in some shells.
438
440
439 $ hg debuglabelcomplete
441 $ hg debuglabelcomplete
440 Fum
442 Fum
441 default
443 default
442 fee
444 fee
443 fie
445 fie
444 fo
446 fo
445 tip
447 tip
446 $ hg debuglabelcomplete f
448 $ hg debuglabelcomplete f
447 fee
449 fee
448 fie
450 fie
449 fo
451 fo
@@ -1,4072 +1,4074
1 Short help:
1 Short help:
2
2
3 $ hg
3 $ hg
4 Mercurial Distributed SCM
4 Mercurial Distributed SCM
5
5
6 basic commands:
6 basic commands:
7
7
8 add add the specified files on the next commit
8 add add the specified files on the next commit
9 annotate show changeset information by line for each file
9 annotate show changeset information by line for each file
10 clone make a copy of an existing repository
10 clone make a copy of an existing repository
11 commit commit the specified files or all outstanding changes
11 commit commit the specified files or all outstanding changes
12 diff diff repository (or selected files)
12 diff diff repository (or selected files)
13 export dump the header and diffs for one or more changesets
13 export dump the header and diffs for one or more changesets
14 forget forget the specified files on the next commit
14 forget forget the specified files on the next commit
15 init create a new repository in the given directory
15 init create a new repository in the given directory
16 log show revision history of entire repository or files
16 log show revision history of entire repository or files
17 merge merge another revision into working directory
17 merge merge another revision into working directory
18 pull pull changes from the specified source
18 pull pull changes from the specified source
19 push push changes to the specified destination
19 push push changes to the specified destination
20 remove remove the specified files on the next commit
20 remove remove the specified files on the next commit
21 serve start stand-alone webserver
21 serve start stand-alone webserver
22 status show changed files in the working directory
22 status show changed files in the working directory
23 summary summarize working directory state
23 summary summarize working directory state
24 update update working directory (or switch revisions)
24 update update working directory (or switch revisions)
25
25
26 (use 'hg help' for the full list of commands or 'hg -v' for details)
26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27
27
28 $ hg -q
28 $ hg -q
29 add add the specified files on the next commit
29 add add the specified files on the next commit
30 annotate show changeset information by line for each file
30 annotate show changeset information by line for each file
31 clone make a copy of an existing repository
31 clone make a copy of an existing repository
32 commit commit the specified files or all outstanding changes
32 commit commit the specified files or all outstanding changes
33 diff diff repository (or selected files)
33 diff diff repository (or selected files)
34 export dump the header and diffs for one or more changesets
34 export dump the header and diffs for one or more changesets
35 forget forget the specified files on the next commit
35 forget forget the specified files on the next commit
36 init create a new repository in the given directory
36 init create a new repository in the given directory
37 log show revision history of entire repository or files
37 log show revision history of entire repository or files
38 merge merge another revision into working directory
38 merge merge another revision into working directory
39 pull pull changes from the specified source
39 pull pull changes from the specified source
40 push push changes to the specified destination
40 push push changes to the specified destination
41 remove remove the specified files on the next commit
41 remove remove the specified files on the next commit
42 serve start stand-alone webserver
42 serve start stand-alone webserver
43 status show changed files in the working directory
43 status show changed files in the working directory
44 summary summarize working directory state
44 summary summarize working directory state
45 update update working directory (or switch revisions)
45 update update working directory (or switch revisions)
46
46
47 Extra extensions will be printed in help output in a non-reliable order since
47 Extra extensions will be printed in help output in a non-reliable order since
48 the extension is unknown.
48 the extension is unknown.
49 #if no-extraextensions
49 #if no-extraextensions
50
50
51 $ hg help
51 $ hg help
52 Mercurial Distributed SCM
52 Mercurial Distributed SCM
53
53
54 list of commands:
54 list of commands:
55
55
56 Repository creation:
56 Repository creation:
57
57
58 clone make a copy of an existing repository
58 clone make a copy of an existing repository
59 init create a new repository in the given directory
59 init create a new repository in the given directory
60
60
61 Remote repository management:
61 Remote repository management:
62
62
63 incoming show new changesets found in source
63 incoming show new changesets found in source
64 outgoing show changesets not found in the destination
64 outgoing show changesets not found in the destination
65 paths show aliases for remote repositories
65 paths show aliases for remote repositories
66 pull pull changes from the specified source
66 pull pull changes from the specified source
67 push push changes to the specified destination
67 push push changes to the specified destination
68 serve start stand-alone webserver
68 serve start stand-alone webserver
69
69
70 Change creation:
70 Change creation:
71
71
72 commit commit the specified files or all outstanding changes
72 commit commit the specified files or all outstanding changes
73
73
74 Change manipulation:
74 Change manipulation:
75
75
76 backout reverse effect of earlier changeset
76 backout reverse effect of earlier changeset
77 graft copy changes from other branches onto the current branch
77 graft copy changes from other branches onto the current branch
78 merge merge another revision into working directory
78 merge merge another revision into working directory
79
79
80 Change organization:
80 Change organization:
81
81
82 bookmarks create a new bookmark or list existing bookmarks
82 bookmarks create a new bookmark or list existing bookmarks
83 branch set or show the current branch name
83 branch set or show the current branch name
84 branches list repository named branches
84 branches list repository named branches
85 phase set or show the current phase name
85 phase set or show the current phase name
86 tag add one or more tags for the current or given revision
86 tag add one or more tags for the current or given revision
87 tags list repository tags
87 tags list repository tags
88
88
89 File content management:
89 File content management:
90
90
91 annotate show changeset information by line for each file
91 annotate show changeset information by line for each file
92 cat output the current or given revision of files
92 cat output the current or given revision of files
93 copy mark files as copied for the next commit
93 copy mark files as copied for the next commit
94 diff diff repository (or selected files)
94 diff diff repository (or selected files)
95 grep search for a pattern in specified files
95 grep search for a pattern in specified files
96
96
97 Change navigation:
97 Change navigation:
98
98
99 bisect subdivision search of changesets
99 bisect subdivision search of changesets
100 heads show branch heads
100 heads show branch heads
101 identify identify the working directory or specified revision
101 identify identify the working directory or specified revision
102 log show revision history of entire repository or files
102 log show revision history of entire repository or files
103
103
104 Working directory management:
104 Working directory management:
105
105
106 add add the specified files on the next commit
106 add add the specified files on the next commit
107 addremove add all new files, delete all missing files
107 addremove add all new files, delete all missing files
108 files list tracked files
108 files list tracked files
109 forget forget the specified files on the next commit
109 forget forget the specified files on the next commit
110 purge removes files not tracked by Mercurial
110 purge removes files not tracked by Mercurial
111 remove remove the specified files on the next commit
111 remove remove the specified files on the next commit
112 rename rename files; equivalent of copy + remove
112 rename rename files; equivalent of copy + remove
113 resolve redo merges or set/view the merge status of files
113 resolve redo merges or set/view the merge status of files
114 revert restore files to their checkout state
114 revert restore files to their checkout state
115 root print the root (top) of the current working directory
115 root print the root (top) of the current working directory
116 shelve save and set aside changes from the working directory
116 shelve save and set aside changes from the working directory
117 status show changed files in the working directory
117 status show changed files in the working directory
118 summary summarize working directory state
118 summary summarize working directory state
119 unshelve restore a shelved change to the working directory
119 unshelve restore a shelved change to the working directory
120 update update working directory (or switch revisions)
120 update update working directory (or switch revisions)
121
121
122 Change import/export:
122 Change import/export:
123
123
124 archive create an unversioned archive of a repository revision
124 archive create an unversioned archive of a repository revision
125 bundle create a bundle file
125 bundle create a bundle file
126 export dump the header and diffs for one or more changesets
126 export dump the header and diffs for one or more changesets
127 import import an ordered set of patches
127 import import an ordered set of patches
128 unbundle apply one or more bundle files
128 unbundle apply one or more bundle files
129
129
130 Repository maintenance:
130 Repository maintenance:
131
131
132 manifest output the current or given revision of the project manifest
132 manifest output the current or given revision of the project manifest
133 recover roll back an interrupted transaction
133 recover roll back an interrupted transaction
134 verify verify the integrity of the repository
134 verify verify the integrity of the repository
135
135
136 Help:
136 Help:
137
137
138 config show combined config settings from all hgrc files
138 config show combined config settings from all hgrc files
139 help show help for a given topic or a help overview
139 help show help for a given topic or a help overview
140 version output version and copyright information
140 version output version and copyright information
141
141
142 additional help topics:
142 additional help topics:
143
143
144 Mercurial identifiers:
144 Mercurial identifiers:
145
145
146 filesets Specifying File Sets
146 filesets Specifying File Sets
147 hgignore Syntax for Mercurial Ignore Files
147 hgignore Syntax for Mercurial Ignore Files
148 patterns File Name Patterns
148 patterns File Name Patterns
149 revisions Specifying Revisions
149 revisions Specifying Revisions
150 urls URL Paths
150 urls URL Paths
151
151
152 Mercurial output:
152 Mercurial output:
153
153
154 color Colorizing Outputs
154 color Colorizing Outputs
155 dates Date Formats
155 dates Date Formats
156 diffs Diff Formats
156 diffs Diff Formats
157 templating Template Usage
157 templating Template Usage
158
158
159 Mercurial configuration:
159 Mercurial configuration:
160
160
161 config Configuration Files
161 config Configuration Files
162 environment Environment Variables
162 environment Environment Variables
163 extensions Using Additional Features
163 extensions Using Additional Features
164 flags Command-line flags
164 flags Command-line flags
165 hgweb Configuring hgweb
165 hgweb Configuring hgweb
166 merge-tools Merge Tools
166 merge-tools Merge Tools
167 pager Pager Support
167 pager Pager Support
168 rust Rust in Mercurial
168 rust Rust in Mercurial
169
169
170 Concepts:
170 Concepts:
171
171
172 bundlespec Bundle File Formats
172 bundlespec Bundle File Formats
173 evolution Safely rewriting history (EXPERIMENTAL)
173 evolution Safely rewriting history (EXPERIMENTAL)
174 glossary Glossary
174 glossary Glossary
175 phases Working with Phases
175 phases Working with Phases
176 subrepos Subrepositories
176 subrepos Subrepositories
177
177
178 Miscellaneous:
178 Miscellaneous:
179
179
180 deprecated Deprecated Features
180 deprecated Deprecated Features
181 internals Technical implementation topics
181 internals Technical implementation topics
182 scripting Using Mercurial from scripts and automation
182 scripting Using Mercurial from scripts and automation
183
183
184 (use 'hg help -v' to show built-in aliases and global options)
184 (use 'hg help -v' to show built-in aliases and global options)
185
185
186 $ hg -q help
186 $ hg -q help
187 Repository creation:
187 Repository creation:
188
188
189 clone make a copy of an existing repository
189 clone make a copy of an existing repository
190 init create a new repository in the given directory
190 init create a new repository in the given directory
191
191
192 Remote repository management:
192 Remote repository management:
193
193
194 incoming show new changesets found in source
194 incoming show new changesets found in source
195 outgoing show changesets not found in the destination
195 outgoing show changesets not found in the destination
196 paths show aliases for remote repositories
196 paths show aliases for remote repositories
197 pull pull changes from the specified source
197 pull pull changes from the specified source
198 push push changes to the specified destination
198 push push changes to the specified destination
199 serve start stand-alone webserver
199 serve start stand-alone webserver
200
200
201 Change creation:
201 Change creation:
202
202
203 commit commit the specified files or all outstanding changes
203 commit commit the specified files or all outstanding changes
204
204
205 Change manipulation:
205 Change manipulation:
206
206
207 backout reverse effect of earlier changeset
207 backout reverse effect of earlier changeset
208 graft copy changes from other branches onto the current branch
208 graft copy changes from other branches onto the current branch
209 merge merge another revision into working directory
209 merge merge another revision into working directory
210
210
211 Change organization:
211 Change organization:
212
212
213 bookmarks create a new bookmark or list existing bookmarks
213 bookmarks create a new bookmark or list existing bookmarks
214 branch set or show the current branch name
214 branch set or show the current branch name
215 branches list repository named branches
215 branches list repository named branches
216 phase set or show the current phase name
216 phase set or show the current phase name
217 tag add one or more tags for the current or given revision
217 tag add one or more tags for the current or given revision
218 tags list repository tags
218 tags list repository tags
219
219
220 File content management:
220 File content management:
221
221
222 annotate show changeset information by line for each file
222 annotate show changeset information by line for each file
223 cat output the current or given revision of files
223 cat output the current or given revision of files
224 copy mark files as copied for the next commit
224 copy mark files as copied for the next commit
225 diff diff repository (or selected files)
225 diff diff repository (or selected files)
226 grep search for a pattern in specified files
226 grep search for a pattern in specified files
227
227
228 Change navigation:
228 Change navigation:
229
229
230 bisect subdivision search of changesets
230 bisect subdivision search of changesets
231 heads show branch heads
231 heads show branch heads
232 identify identify the working directory or specified revision
232 identify identify the working directory or specified revision
233 log show revision history of entire repository or files
233 log show revision history of entire repository or files
234
234
235 Working directory management:
235 Working directory management:
236
236
237 add add the specified files on the next commit
237 add add the specified files on the next commit
238 addremove add all new files, delete all missing files
238 addremove add all new files, delete all missing files
239 files list tracked files
239 files list tracked files
240 forget forget the specified files on the next commit
240 forget forget the specified files on the next commit
241 purge removes files not tracked by Mercurial
241 purge removes files not tracked by Mercurial
242 remove remove the specified files on the next commit
242 remove remove the specified files on the next commit
243 rename rename files; equivalent of copy + remove
243 rename rename files; equivalent of copy + remove
244 resolve redo merges or set/view the merge status of files
244 resolve redo merges or set/view the merge status of files
245 revert restore files to their checkout state
245 revert restore files to their checkout state
246 root print the root (top) of the current working directory
246 root print the root (top) of the current working directory
247 shelve save and set aside changes from the working directory
247 shelve save and set aside changes from the working directory
248 status show changed files in the working directory
248 status show changed files in the working directory
249 summary summarize working directory state
249 summary summarize working directory state
250 unshelve restore a shelved change to the working directory
250 unshelve restore a shelved change to the working directory
251 update update working directory (or switch revisions)
251 update update working directory (or switch revisions)
252
252
253 Change import/export:
253 Change import/export:
254
254
255 archive create an unversioned archive of a repository revision
255 archive create an unversioned archive of a repository revision
256 bundle create a bundle file
256 bundle create a bundle file
257 export dump the header and diffs for one or more changesets
257 export dump the header and diffs for one or more changesets
258 import import an ordered set of patches
258 import import an ordered set of patches
259 unbundle apply one or more bundle files
259 unbundle apply one or more bundle files
260
260
261 Repository maintenance:
261 Repository maintenance:
262
262
263 manifest output the current or given revision of the project manifest
263 manifest output the current or given revision of the project manifest
264 recover roll back an interrupted transaction
264 recover roll back an interrupted transaction
265 verify verify the integrity of the repository
265 verify verify the integrity of the repository
266
266
267 Help:
267 Help:
268
268
269 config show combined config settings from all hgrc files
269 config show combined config settings from all hgrc files
270 help show help for a given topic or a help overview
270 help show help for a given topic or a help overview
271 version output version and copyright information
271 version output version and copyright information
272
272
273 additional help topics:
273 additional help topics:
274
274
275 Mercurial identifiers:
275 Mercurial identifiers:
276
276
277 filesets Specifying File Sets
277 filesets Specifying File Sets
278 hgignore Syntax for Mercurial Ignore Files
278 hgignore Syntax for Mercurial Ignore Files
279 patterns File Name Patterns
279 patterns File Name Patterns
280 revisions Specifying Revisions
280 revisions Specifying Revisions
281 urls URL Paths
281 urls URL Paths
282
282
283 Mercurial output:
283 Mercurial output:
284
284
285 color Colorizing Outputs
285 color Colorizing Outputs
286 dates Date Formats
286 dates Date Formats
287 diffs Diff Formats
287 diffs Diff Formats
288 templating Template Usage
288 templating Template Usage
289
289
290 Mercurial configuration:
290 Mercurial configuration:
291
291
292 config Configuration Files
292 config Configuration Files
293 environment Environment Variables
293 environment Environment Variables
294 extensions Using Additional Features
294 extensions Using Additional Features
295 flags Command-line flags
295 flags Command-line flags
296 hgweb Configuring hgweb
296 hgweb Configuring hgweb
297 merge-tools Merge Tools
297 merge-tools Merge Tools
298 pager Pager Support
298 pager Pager Support
299 rust Rust in Mercurial
299 rust Rust in Mercurial
300
300
301 Concepts:
301 Concepts:
302
302
303 bundlespec Bundle File Formats
303 bundlespec Bundle File Formats
304 evolution Safely rewriting history (EXPERIMENTAL)
304 evolution Safely rewriting history (EXPERIMENTAL)
305 glossary Glossary
305 glossary Glossary
306 phases Working with Phases
306 phases Working with Phases
307 subrepos Subrepositories
307 subrepos Subrepositories
308
308
309 Miscellaneous:
309 Miscellaneous:
310
310
311 deprecated Deprecated Features
311 deprecated Deprecated Features
312 internals Technical implementation topics
312 internals Technical implementation topics
313 scripting Using Mercurial from scripts and automation
313 scripting Using Mercurial from scripts and automation
314
314
315 Test extension help:
315 Test extension help:
316 $ hg help extensions --config extensions.rebase= --config extensions.children=
316 $ hg help extensions --config extensions.rebase= --config extensions.children=
317 Using Additional Features
317 Using Additional Features
318 """""""""""""""""""""""""
318 """""""""""""""""""""""""
319
319
320 Mercurial has the ability to add new features through the use of
320 Mercurial has the ability to add new features through the use of
321 extensions. Extensions may add new commands, add options to existing
321 extensions. Extensions may add new commands, add options to existing
322 commands, change the default behavior of commands, or implement hooks.
322 commands, change the default behavior of commands, or implement hooks.
323
323
324 To enable the "foo" extension, either shipped with Mercurial or in the
324 To enable the "foo" extension, either shipped with Mercurial or in the
325 Python search path, create an entry for it in your configuration file,
325 Python search path, create an entry for it in your configuration file,
326 like this:
326 like this:
327
327
328 [extensions]
328 [extensions]
329 foo =
329 foo =
330
330
331 You may also specify the full path to an extension:
331 You may also specify the full path to an extension:
332
332
333 [extensions]
333 [extensions]
334 myfeature = ~/.hgext/myfeature.py
334 myfeature = ~/.hgext/myfeature.py
335
335
336 See 'hg help config' for more information on configuration files.
336 See 'hg help config' for more information on configuration files.
337
337
338 Extensions are not loaded by default for a variety of reasons: they can
338 Extensions are not loaded by default for a variety of reasons: they can
339 increase startup overhead; they may be meant for advanced usage only; they
339 increase startup overhead; they may be meant for advanced usage only; they
340 may provide potentially dangerous abilities (such as letting you destroy
340 may provide potentially dangerous abilities (such as letting you destroy
341 or modify history); they might not be ready for prime time; or they may
341 or modify history); they might not be ready for prime time; or they may
342 alter some usual behaviors of stock Mercurial. It is thus up to the user
342 alter some usual behaviors of stock Mercurial. It is thus up to the user
343 to activate extensions as needed.
343 to activate extensions as needed.
344
344
345 To explicitly disable an extension enabled in a configuration file of
345 To explicitly disable an extension enabled in a configuration file of
346 broader scope, prepend its path with !:
346 broader scope, prepend its path with !:
347
347
348 [extensions]
348 [extensions]
349 # disabling extension bar residing in /path/to/extension/bar.py
349 # disabling extension bar residing in /path/to/extension/bar.py
350 bar = !/path/to/extension/bar.py
350 bar = !/path/to/extension/bar.py
351 # ditto, but no path was supplied for extension baz
351 # ditto, but no path was supplied for extension baz
352 baz = !
352 baz = !
353
353
354 enabled extensions:
354 enabled extensions:
355
355
356 children command to display child changesets (DEPRECATED)
356 children command to display child changesets (DEPRECATED)
357 rebase command to move sets of revisions to a different ancestor
357 rebase command to move sets of revisions to a different ancestor
358
358
359 disabled extensions:
359 disabled extensions:
360
360
361 acl hooks for controlling repository access
361 acl hooks for controlling repository access
362 blackbox log repository events to a blackbox for debugging
362 blackbox log repository events to a blackbox for debugging
363 bugzilla hooks for integrating with the Bugzilla bug tracker
363 bugzilla hooks for integrating with the Bugzilla bug tracker
364 censor erase file content at a given revision
364 censor erase file content at a given revision
365 churn command to display statistics about repository history
365 churn command to display statistics about repository history
366 clonebundles advertise pre-generated bundles to seed clones
366 clonebundles advertise pre-generated bundles to seed clones
367 closehead close arbitrary heads without checking them out first
367 closehead close arbitrary heads without checking them out first
368 convert import revisions from foreign VCS repositories into
368 convert import revisions from foreign VCS repositories into
369 Mercurial
369 Mercurial
370 eol automatically manage newlines in repository files
370 eol automatically manage newlines in repository files
371 extdiff command to allow external programs to compare revisions
371 extdiff command to allow external programs to compare revisions
372 factotum http authentication with factotum
372 factotum http authentication with factotum
373 fastexport export repositories as git fast-import stream
373 fastexport export repositories as git fast-import stream
374 githelp try mapping git commands to Mercurial commands
374 githelp try mapping git commands to Mercurial commands
375 gpg commands to sign and verify changesets
375 gpg commands to sign and verify changesets
376 hgk browse the repository in a graphical way
376 hgk browse the repository in a graphical way
377 highlight syntax highlighting for hgweb (requires Pygments)
377 highlight syntax highlighting for hgweb (requires Pygments)
378 histedit interactive history editing
378 histedit interactive history editing
379 keyword expand keywords in tracked files
379 keyword expand keywords in tracked files
380 largefiles track large binary files
380 largefiles track large binary files
381 mq manage a stack of patches
381 mq manage a stack of patches
382 notify hooks for sending email push notifications
382 notify hooks for sending email push notifications
383 patchbomb command to send changesets as (a series of) patch emails
383 patchbomb command to send changesets as (a series of) patch emails
384 relink recreates hardlinks between repository clones
384 relink recreates hardlinks between repository clones
385 schemes extend schemes with shortcuts to repository swarms
385 schemes extend schemes with shortcuts to repository swarms
386 share share a common history between several working directories
386 share share a common history between several working directories
387 transplant command to transplant changesets from another branch
387 transplant command to transplant changesets from another branch
388 win32mbcs allow the use of MBCS paths with problematic encodings
388 win32mbcs allow the use of MBCS paths with problematic encodings
389 zeroconf discover and advertise repositories on the local network
389 zeroconf discover and advertise repositories on the local network
390
390
391 #endif
391 #endif
392
392
393 Verify that deprecated extensions are included if --verbose:
393 Verify that deprecated extensions are included if --verbose:
394
394
395 $ hg -v help extensions | grep children
395 $ hg -v help extensions | grep children
396 children command to display child changesets (DEPRECATED)
396 children command to display child changesets (DEPRECATED)
397
397
398 Verify that extension keywords appear in help templates
398 Verify that extension keywords appear in help templates
399
399
400 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
400 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
401
401
402 Test short command list with verbose option
402 Test short command list with verbose option
403
403
404 $ hg -v help shortlist
404 $ hg -v help shortlist
405 Mercurial Distributed SCM
405 Mercurial Distributed SCM
406
406
407 basic commands:
407 basic commands:
408
408
409 abort abort an unfinished operation (EXPERIMENTAL)
409 abort abort an unfinished operation (EXPERIMENTAL)
410 add add the specified files on the next commit
410 add add the specified files on the next commit
411 annotate, blame
411 annotate, blame
412 show changeset information by line for each file
412 show changeset information by line for each file
413 clone make a copy of an existing repository
413 clone make a copy of an existing repository
414 commit, ci commit the specified files or all outstanding changes
414 commit, ci commit the specified files or all outstanding changes
415 continue resumes an interrupted operation (EXPERIMENTAL)
415 continue resumes an interrupted operation (EXPERIMENTAL)
416 diff diff repository (or selected files)
416 diff diff repository (or selected files)
417 export dump the header and diffs for one or more changesets
417 export dump the header and diffs for one or more changesets
418 forget forget the specified files on the next commit
418 forget forget the specified files on the next commit
419 init create a new repository in the given directory
419 init create a new repository in the given directory
420 log, history show revision history of entire repository or files
420 log, history show revision history of entire repository or files
421 merge merge another revision into working directory
421 merge merge another revision into working directory
422 pull pull changes from the specified source
422 pull pull changes from the specified source
423 push push changes to the specified destination
423 push push changes to the specified destination
424 remove, rm remove the specified files on the next commit
424 remove, rm remove the specified files on the next commit
425 serve start stand-alone webserver
425 serve start stand-alone webserver
426 status, st show changed files in the working directory
426 status, st show changed files in the working directory
427 summary, sum summarize working directory state
427 summary, sum summarize working directory state
428 update, up, checkout, co
428 update, up, checkout, co
429 update working directory (or switch revisions)
429 update working directory (or switch revisions)
430
430
431 global options ([+] can be repeated):
431 global options ([+] can be repeated):
432
432
433 -R --repository REPO repository root directory or name of overlay bundle
433 -R --repository REPO repository root directory or name of overlay bundle
434 file
434 file
435 --cwd DIR change working directory
435 --cwd DIR change working directory
436 -y --noninteractive do not prompt, automatically pick the first choice for
436 -y --noninteractive do not prompt, automatically pick the first choice for
437 all prompts
437 all prompts
438 -q --quiet suppress output
438 -q --quiet suppress output
439 -v --verbose enable additional output
439 -v --verbose enable additional output
440 --color TYPE when to colorize (boolean, always, auto, never, or
440 --color TYPE when to colorize (boolean, always, auto, never, or
441 debug)
441 debug)
442 --config CONFIG [+] set/override config option (use 'section.name=value')
442 --config CONFIG [+] set/override config option (use 'section.name=value')
443 --debug enable debugging output
443 --debug enable debugging output
444 --debugger start debugger
444 --debugger start debugger
445 --encoding ENCODE set the charset encoding (default: ascii)
445 --encoding ENCODE set the charset encoding (default: ascii)
446 --encodingmode MODE set the charset encoding mode (default: strict)
446 --encodingmode MODE set the charset encoding mode (default: strict)
447 --traceback always print a traceback on exception
447 --traceback always print a traceback on exception
448 --time time how long the command takes
448 --time time how long the command takes
449 --profile print command execution profile
449 --profile print command execution profile
450 --version output version information and exit
450 --version output version information and exit
451 -h --help display help and exit
451 -h --help display help and exit
452 --hidden consider hidden changesets
452 --hidden consider hidden changesets
453 --pager TYPE when to paginate (boolean, always, auto, or never)
453 --pager TYPE when to paginate (boolean, always, auto, or never)
454 (default: auto)
454 (default: auto)
455
455
456 (use 'hg help' for the full list of commands)
456 (use 'hg help' for the full list of commands)
457
457
458 $ hg add -h
458 $ hg add -h
459 hg add [OPTION]... [FILE]...
459 hg add [OPTION]... [FILE]...
460
460
461 add the specified files on the next commit
461 add the specified files on the next commit
462
462
463 Schedule files to be version controlled and added to the repository.
463 Schedule files to be version controlled and added to the repository.
464
464
465 The files will be added to the repository at the next commit. To undo an
465 The files will be added to the repository at the next commit. To undo an
466 add before that, see 'hg forget'.
466 add before that, see 'hg forget'.
467
467
468 If no names are given, add all files to the repository (except files
468 If no names are given, add all files to the repository (except files
469 matching ".hgignore").
469 matching ".hgignore").
470
470
471 Returns 0 if all files are successfully added.
471 Returns 0 if all files are successfully added.
472
472
473 options ([+] can be repeated):
473 options ([+] can be repeated):
474
474
475 -I --include PATTERN [+] include names matching the given patterns
475 -I --include PATTERN [+] include names matching the given patterns
476 -X --exclude PATTERN [+] exclude names matching the given patterns
476 -X --exclude PATTERN [+] exclude names matching the given patterns
477 -S --subrepos recurse into subrepositories
477 -S --subrepos recurse into subrepositories
478 -n --dry-run do not perform actions, just print output
478 -n --dry-run do not perform actions, just print output
479
479
480 (some details hidden, use --verbose to show complete help)
480 (some details hidden, use --verbose to show complete help)
481
481
482 Verbose help for add
482 Verbose help for add
483
483
484 $ hg add -hv
484 $ hg add -hv
485 hg add [OPTION]... [FILE]...
485 hg add [OPTION]... [FILE]...
486
486
487 add the specified files on the next commit
487 add the specified files on the next commit
488
488
489 Schedule files to be version controlled and added to the repository.
489 Schedule files to be version controlled and added to the repository.
490
490
491 The files will be added to the repository at the next commit. To undo an
491 The files will be added to the repository at the next commit. To undo an
492 add before that, see 'hg forget'.
492 add before that, see 'hg forget'.
493
493
494 If no names are given, add all files to the repository (except files
494 If no names are given, add all files to the repository (except files
495 matching ".hgignore").
495 matching ".hgignore").
496
496
497 Examples:
497 Examples:
498
498
499 - New (unknown) files are added automatically by 'hg add':
499 - New (unknown) files are added automatically by 'hg add':
500
500
501 $ ls
501 $ ls
502 foo.c
502 foo.c
503 $ hg status
503 $ hg status
504 ? foo.c
504 ? foo.c
505 $ hg add
505 $ hg add
506 adding foo.c
506 adding foo.c
507 $ hg status
507 $ hg status
508 A foo.c
508 A foo.c
509
509
510 - Specific files to be added can be specified:
510 - Specific files to be added can be specified:
511
511
512 $ ls
512 $ ls
513 bar.c foo.c
513 bar.c foo.c
514 $ hg status
514 $ hg status
515 ? bar.c
515 ? bar.c
516 ? foo.c
516 ? foo.c
517 $ hg add bar.c
517 $ hg add bar.c
518 $ hg status
518 $ hg status
519 A bar.c
519 A bar.c
520 ? foo.c
520 ? foo.c
521
521
522 Returns 0 if all files are successfully added.
522 Returns 0 if all files are successfully added.
523
523
524 options ([+] can be repeated):
524 options ([+] can be repeated):
525
525
526 -I --include PATTERN [+] include names matching the given patterns
526 -I --include PATTERN [+] include names matching the given patterns
527 -X --exclude PATTERN [+] exclude names matching the given patterns
527 -X --exclude PATTERN [+] exclude names matching the given patterns
528 -S --subrepos recurse into subrepositories
528 -S --subrepos recurse into subrepositories
529 -n --dry-run do not perform actions, just print output
529 -n --dry-run do not perform actions, just print output
530
530
531 global options ([+] can be repeated):
531 global options ([+] can be repeated):
532
532
533 -R --repository REPO repository root directory or name of overlay bundle
533 -R --repository REPO repository root directory or name of overlay bundle
534 file
534 file
535 --cwd DIR change working directory
535 --cwd DIR change working directory
536 -y --noninteractive do not prompt, automatically pick the first choice for
536 -y --noninteractive do not prompt, automatically pick the first choice for
537 all prompts
537 all prompts
538 -q --quiet suppress output
538 -q --quiet suppress output
539 -v --verbose enable additional output
539 -v --verbose enable additional output
540 --color TYPE when to colorize (boolean, always, auto, never, or
540 --color TYPE when to colorize (boolean, always, auto, never, or
541 debug)
541 debug)
542 --config CONFIG [+] set/override config option (use 'section.name=value')
542 --config CONFIG [+] set/override config option (use 'section.name=value')
543 --debug enable debugging output
543 --debug enable debugging output
544 --debugger start debugger
544 --debugger start debugger
545 --encoding ENCODE set the charset encoding (default: ascii)
545 --encoding ENCODE set the charset encoding (default: ascii)
546 --encodingmode MODE set the charset encoding mode (default: strict)
546 --encodingmode MODE set the charset encoding mode (default: strict)
547 --traceback always print a traceback on exception
547 --traceback always print a traceback on exception
548 --time time how long the command takes
548 --time time how long the command takes
549 --profile print command execution profile
549 --profile print command execution profile
550 --version output version information and exit
550 --version output version information and exit
551 -h --help display help and exit
551 -h --help display help and exit
552 --hidden consider hidden changesets
552 --hidden consider hidden changesets
553 --pager TYPE when to paginate (boolean, always, auto, or never)
553 --pager TYPE when to paginate (boolean, always, auto, or never)
554 (default: auto)
554 (default: auto)
555
555
556 Test the textwidth config option
556 Test the textwidth config option
557
557
558 $ hg root -h --config ui.textwidth=50
558 $ hg root -h --config ui.textwidth=50
559 hg root
559 hg root
560
560
561 print the root (top) of the current working
561 print the root (top) of the current working
562 directory
562 directory
563
563
564 Print the root directory of the current
564 Print the root directory of the current
565 repository.
565 repository.
566
566
567 Returns 0 on success.
567 Returns 0 on success.
568
568
569 options:
569 options:
570
570
571 -T --template TEMPLATE display with template
571 -T --template TEMPLATE display with template
572
572
573 (some details hidden, use --verbose to show
573 (some details hidden, use --verbose to show
574 complete help)
574 complete help)
575
575
576 Test help option with version option
576 Test help option with version option
577
577
578 $ hg add -h --version
578 $ hg add -h --version
579 Mercurial Distributed SCM (version *) (glob)
579 Mercurial Distributed SCM (version *) (glob)
580 (see https://mercurial-scm.org for more information)
580 (see https://mercurial-scm.org for more information)
581
581
582 Copyright (C) 2005-* Olivia Mackall and others (glob)
582 Copyright (C) 2005-* Olivia Mackall and others (glob)
583 This is free software; see the source for copying conditions. There is NO
583 This is free software; see the source for copying conditions. There is NO
584 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
584 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
585
585
586 $ hg add --skjdfks
586 $ hg add --skjdfks
587 hg add: option --skjdfks not recognized
587 hg add: option --skjdfks not recognized
588 hg add [OPTION]... [FILE]...
588 hg add [OPTION]... [FILE]...
589
589
590 add the specified files on the next commit
590 add the specified files on the next commit
591
591
592 options ([+] can be repeated):
592 options ([+] can be repeated):
593
593
594 -I --include PATTERN [+] include names matching the given patterns
594 -I --include PATTERN [+] include names matching the given patterns
595 -X --exclude PATTERN [+] exclude names matching the given patterns
595 -X --exclude PATTERN [+] exclude names matching the given patterns
596 -S --subrepos recurse into subrepositories
596 -S --subrepos recurse into subrepositories
597 -n --dry-run do not perform actions, just print output
597 -n --dry-run do not perform actions, just print output
598
598
599 (use 'hg add -h' to show more help)
599 (use 'hg add -h' to show more help)
600 [10]
600 [10]
601
601
602 Test ambiguous command help
602 Test ambiguous command help
603
603
604 $ hg help ad
604 $ hg help ad
605 list of commands:
605 list of commands:
606
606
607 add add the specified files on the next commit
607 add add the specified files on the next commit
608 addremove add all new files, delete all missing files
608 addremove add all new files, delete all missing files
609
609
610 (use 'hg help -v ad' to show built-in aliases and global options)
610 (use 'hg help -v ad' to show built-in aliases and global options)
611
611
612 Test command without options
612 Test command without options
613
613
614 $ hg help verify
614 $ hg help verify
615 hg verify
615 hg verify
616
616
617 verify the integrity of the repository
617 verify the integrity of the repository
618
618
619 Verify the integrity of the current repository.
619 Verify the integrity of the current repository.
620
620
621 This will perform an extensive check of the repository's integrity,
621 This will perform an extensive check of the repository's integrity,
622 validating the hashes and checksums of each entry in the changelog,
622 validating the hashes and checksums of each entry in the changelog,
623 manifest, and tracked files, as well as the integrity of their crosslinks
623 manifest, and tracked files, as well as the integrity of their crosslinks
624 and indices.
624 and indices.
625
625
626 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
626 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
627 information about recovery from corruption of the repository.
627 information about recovery from corruption of the repository.
628
628
629 Returns 0 on success, 1 if errors are encountered.
629 Returns 0 on success, 1 if errors are encountered.
630
630
631 options:
631 options:
632
632
633 (some details hidden, use --verbose to show complete help)
633 (some details hidden, use --verbose to show complete help)
634
634
635 $ hg help diff
635 $ hg help diff
636 hg diff [OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...
636 hg diff [OPTION]... ([-c REV] | [--from REV1] [--to REV2]) [FILE]...
637
637
638 diff repository (or selected files)
638 diff repository (or selected files)
639
639
640 Show differences between revisions for the specified files.
640 Show differences between revisions for the specified files.
641
641
642 Differences between files are shown using the unified diff format.
642 Differences between files are shown using the unified diff format.
643
643
644 Note:
644 Note:
645 'hg diff' may generate unexpected results for merges, as it will
645 'hg diff' may generate unexpected results for merges, as it will
646 default to comparing against the working directory's first parent
646 default to comparing against the working directory's first parent
647 changeset if no revisions are specified. To diff against the conflict
647 changeset if no revisions are specified. To diff against the conflict
648 regions, you can use '--config diff.merge=yes'.
648 regions, you can use '--config diff.merge=yes'.
649
649
650 By default, the working directory files are compared to its first parent.
650 By default, the working directory files are compared to its first parent.
651 To see the differences from another revision, use --from. To see the
651 To see the differences from another revision, use --from. To see the
652 difference to another revision, use --to. For example, 'hg diff --from .^'
652 difference to another revision, use --to. For example, 'hg diff --from .^'
653 will show the differences from the working copy's grandparent to the
653 will show the differences from the working copy's grandparent to the
654 working copy, 'hg diff --to .' will show the diff from the working copy to
654 working copy, 'hg diff --to .' will show the diff from the working copy to
655 its parent (i.e. the reverse of the default), and 'hg diff --from 1.0 --to
655 its parent (i.e. the reverse of the default), and 'hg diff --from 1.0 --to
656 1.2' will show the diff between those two revisions.
656 1.2' will show the diff between those two revisions.
657
657
658 Alternatively you can specify -c/--change with a revision to see the
658 Alternatively you can specify -c/--change with a revision to see the
659 changes in that changeset relative to its first parent (i.e. 'hg diff -c
659 changes in that changeset relative to its first parent (i.e. 'hg diff -c
660 42' is equivalent to 'hg diff --from 42^ --to 42')
660 42' is equivalent to 'hg diff --from 42^ --to 42')
661
661
662 Without the -a/--text option, diff will avoid generating diffs of files it
662 Without the -a/--text option, diff will avoid generating diffs of files it
663 detects as binary. With -a, diff will generate a diff anyway, probably
663 detects as binary. With -a, diff will generate a diff anyway, probably
664 with undesirable results.
664 with undesirable results.
665
665
666 Use the -g/--git option to generate diffs in the git extended diff format.
666 Use the -g/--git option to generate diffs in the git extended diff format.
667 For more information, read 'hg help diffs'.
667 For more information, read 'hg help diffs'.
668
668
669 Returns 0 on success.
669 Returns 0 on success.
670
670
671 options ([+] can be repeated):
671 options ([+] can be repeated):
672
672
673 --from REV1 revision to diff from
673 --from REV1 revision to diff from
674 --to REV2 revision to diff to
674 --to REV2 revision to diff to
675 -c --change REV change made by revision
675 -c --change REV change made by revision
676 -a --text treat all files as text
676 -a --text treat all files as text
677 -g --git use git extended diff format
677 -g --git use git extended diff format
678 --binary generate binary diffs in git mode (default)
678 --binary generate binary diffs in git mode (default)
679 --nodates omit dates from diff headers
679 --nodates omit dates from diff headers
680 --noprefix omit a/ and b/ prefixes from filenames
680 --noprefix omit a/ and b/ prefixes from filenames
681 -p --show-function show which function each change is in
681 -p --show-function show which function each change is in
682 --reverse produce a diff that undoes the changes
682 --reverse produce a diff that undoes the changes
683 -w --ignore-all-space ignore white space when comparing lines
683 -w --ignore-all-space ignore white space when comparing lines
684 -b --ignore-space-change ignore changes in the amount of white space
684 -b --ignore-space-change ignore changes in the amount of white space
685 -B --ignore-blank-lines ignore changes whose lines are all blank
685 -B --ignore-blank-lines ignore changes whose lines are all blank
686 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
686 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
687 -U --unified NUM number of lines of context to show
687 -U --unified NUM number of lines of context to show
688 --stat output diffstat-style summary of changes
688 --stat output diffstat-style summary of changes
689 --root DIR produce diffs relative to subdirectory
689 --root DIR produce diffs relative to subdirectory
690 -I --include PATTERN [+] include names matching the given patterns
690 -I --include PATTERN [+] include names matching the given patterns
691 -X --exclude PATTERN [+] exclude names matching the given patterns
691 -X --exclude PATTERN [+] exclude names matching the given patterns
692 -S --subrepos recurse into subrepositories
692 -S --subrepos recurse into subrepositories
693
693
694 (some details hidden, use --verbose to show complete help)
694 (some details hidden, use --verbose to show complete help)
695
695
696 $ hg help status
696 $ hg help status
697 hg status [OPTION]... [FILE]...
697 hg status [OPTION]... [FILE]...
698
698
699 aliases: st
699 aliases: st
700
700
701 show changed files in the working directory
701 show changed files in the working directory
702
702
703 Show status of files in the repository. If names are given, only files
703 Show status of files in the repository. If names are given, only files
704 that match are shown. Files that are clean or ignored or the source of a
704 that match are shown. Files that are clean or ignored or the source of a
705 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
705 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
706 -C/--copies or -A/--all are given. Unless options described with "show
706 -C/--copies or -A/--all are given. Unless options described with "show
707 only ..." are given, the options -mardu are used.
707 only ..." are given, the options -mardu are used.
708
708
709 Option -q/--quiet hides untracked (unknown and ignored) files unless
709 Option -q/--quiet hides untracked (unknown and ignored) files unless
710 explicitly requested with -u/--unknown or -i/--ignored.
710 explicitly requested with -u/--unknown or -i/--ignored.
711
711
712 Note:
712 Note:
713 'hg status' may appear to disagree with diff if permissions have
713 'hg status' may appear to disagree with diff if permissions have
714 changed or a merge has occurred. The standard diff format does not
714 changed or a merge has occurred. The standard diff format does not
715 report permission changes and diff only reports changes relative to one
715 report permission changes and diff only reports changes relative to one
716 merge parent.
716 merge parent.
717
717
718 If one revision is given, it is used as the base revision. If two
718 If one revision is given, it is used as the base revision. If two
719 revisions are given, the differences between them are shown. The --change
719 revisions are given, the differences between them are shown. The --change
720 option can also be used as a shortcut to list the changed files of a
720 option can also be used as a shortcut to list the changed files of a
721 revision from its first parent.
721 revision from its first parent.
722
722
723 The codes used to show the status of files are:
723 The codes used to show the status of files are:
724
724
725 M = modified
725 M = modified
726 A = added
726 A = added
727 R = removed
727 R = removed
728 C = clean
728 C = clean
729 ! = missing (deleted by non-hg command, but still tracked)
729 ! = missing (deleted by non-hg command, but still tracked)
730 ? = not tracked
730 ? = not tracked
731 I = ignored
731 I = ignored
732 = origin of the previous file (with --copies)
732 = origin of the previous file (with --copies)
733
733
734 Returns 0 on success.
734 Returns 0 on success.
735
735
736 options ([+] can be repeated):
736 options ([+] can be repeated):
737
737
738 -A --all show status of all files
738 -A --all show status of all files
739 -m --modified show only modified files
739 -m --modified show only modified files
740 -a --added show only added files
740 -a --added show only added files
741 -r --removed show only removed files
741 -r --removed show only removed files
742 -d --deleted show only missing files
742 -d --deleted show only missing files
743 -c --clean show only files without changes
743 -c --clean show only files without changes
744 -u --unknown show only unknown (not tracked) files
744 -u --unknown show only unknown (not tracked) files
745 -i --ignored show only ignored files
745 -i --ignored show only ignored files
746 -n --no-status hide status prefix
746 -n --no-status hide status prefix
747 -C --copies show source of copied files
747 -C --copies show source of copied files
748 -0 --print0 end filenames with NUL, for use with xargs
748 -0 --print0 end filenames with NUL, for use with xargs
749 --rev REV [+] show difference from revision
749 --rev REV [+] show difference from revision
750 --change REV list the changed files of a revision
750 --change REV list the changed files of a revision
751 -I --include PATTERN [+] include names matching the given patterns
751 -I --include PATTERN [+] include names matching the given patterns
752 -X --exclude PATTERN [+] exclude names matching the given patterns
752 -X --exclude PATTERN [+] exclude names matching the given patterns
753 -S --subrepos recurse into subrepositories
753 -S --subrepos recurse into subrepositories
754 -T --template TEMPLATE display with template
754 -T --template TEMPLATE display with template
755
755
756 (some details hidden, use --verbose to show complete help)
756 (some details hidden, use --verbose to show complete help)
757
757
758 $ hg -q help status
758 $ hg -q help status
759 hg status [OPTION]... [FILE]...
759 hg status [OPTION]... [FILE]...
760
760
761 show changed files in the working directory
761 show changed files in the working directory
762
762
763 $ hg help foo
763 $ hg help foo
764 abort: no such help topic: foo
764 abort: no such help topic: foo
765 (try 'hg help --keyword foo')
765 (try 'hg help --keyword foo')
766 [10]
766 [10]
767
767
768 $ hg skjdfks
768 $ hg skjdfks
769 hg: unknown command 'skjdfks'
769 hg: unknown command 'skjdfks'
770 (use 'hg help' for a list of commands)
770 (use 'hg help' for a list of commands)
771 [10]
771 [10]
772
772
773 Typoed command gives suggestion
773 Typoed command gives suggestion
774 $ hg puls
774 $ hg puls
775 hg: unknown command 'puls'
775 hg: unknown command 'puls'
776 (did you mean one of pull, push?)
776 (did you mean one of pull, push?)
777 [10]
777 [10]
778
778
779 Not enabled extension gets suggested
779 Not enabled extension gets suggested
780
780
781 $ hg rebase
781 $ hg rebase
782 hg: unknown command 'rebase'
782 hg: unknown command 'rebase'
783 'rebase' is provided by the following extension:
783 'rebase' is provided by the following extension:
784
784
785 rebase command to move sets of revisions to a different ancestor
785 rebase command to move sets of revisions to a different ancestor
786
786
787 (use 'hg help extensions' for information on enabling extensions)
787 (use 'hg help extensions' for information on enabling extensions)
788 [10]
788 [10]
789
789
790 Disabled extension gets suggested
790 Disabled extension gets suggested
791 $ hg --config extensions.rebase=! rebase
791 $ hg --config extensions.rebase=! rebase
792 hg: unknown command 'rebase'
792 hg: unknown command 'rebase'
793 'rebase' is provided by the following extension:
793 'rebase' is provided by the following extension:
794
794
795 rebase command to move sets of revisions to a different ancestor
795 rebase command to move sets of revisions to a different ancestor
796
796
797 (use 'hg help extensions' for information on enabling extensions)
797 (use 'hg help extensions' for information on enabling extensions)
798 [10]
798 [10]
799
799
800 Checking that help adapts based on the config:
800 Checking that help adapts based on the config:
801
801
802 $ hg help diff --config ui.tweakdefaults=true | egrep -e '^ *(-g|config)'
802 $ hg help diff --config ui.tweakdefaults=true | egrep -e '^ *(-g|config)'
803 -g --[no-]git use git extended diff format (default: on from
803 -g --[no-]git use git extended diff format (default: on from
804 config)
804 config)
805
805
806 Make sure that we don't run afoul of the help system thinking that
806 Make sure that we don't run afoul of the help system thinking that
807 this is a section and erroring out weirdly.
807 this is a section and erroring out weirdly.
808
808
809 $ hg .log
809 $ hg .log
810 hg: unknown command '.log'
810 hg: unknown command '.log'
811 (did you mean log?)
811 (did you mean log?)
812 [10]
812 [10]
813
813
814 $ hg log.
814 $ hg log.
815 hg: unknown command 'log.'
815 hg: unknown command 'log.'
816 (did you mean log?)
816 (did you mean log?)
817 [10]
817 [10]
818 $ hg pu.lh
818 $ hg pu.lh
819 hg: unknown command 'pu.lh'
819 hg: unknown command 'pu.lh'
820 (did you mean one of pull, push?)
820 (did you mean one of pull, push?)
821 [10]
821 [10]
822
822
823 $ cat > helpext.py <<EOF
823 $ cat > helpext.py <<EOF
824 > import os
824 > import os
825 > from mercurial import commands, fancyopts, registrar
825 > from mercurial import commands, fancyopts, registrar
826 >
826 >
827 > def func(arg):
827 > def func(arg):
828 > return '%sfoo' % arg
828 > return '%sfoo' % arg
829 > class customopt(fancyopts.customopt):
829 > class customopt(fancyopts.customopt):
830 > def newstate(self, oldstate, newparam, abort):
830 > def newstate(self, oldstate, newparam, abort):
831 > return '%sbar' % oldstate
831 > return '%sbar' % oldstate
832 > cmdtable = {}
832 > cmdtable = {}
833 > command = registrar.command(cmdtable)
833 > command = registrar.command(cmdtable)
834 >
834 >
835 > @command(b'nohelp',
835 > @command(b'nohelp',
836 > [(b'', b'longdesc', 3, b'x'*67),
836 > [(b'', b'longdesc', 3, b'x'*67),
837 > (b'n', b'', None, b'normal desc'),
837 > (b'n', b'', None, b'normal desc'),
838 > (b'', b'newline', b'', b'line1\nline2'),
838 > (b'', b'newline', b'', b'line1\nline2'),
839 > (b'', b'default-off', False, b'enable X'),
839 > (b'', b'default-off', False, b'enable X'),
840 > (b'', b'default-on', True, b'enable Y'),
840 > (b'', b'default-on', True, b'enable Y'),
841 > (b'', b'callableopt', func, b'adds foo'),
841 > (b'', b'callableopt', func, b'adds foo'),
842 > (b'', b'customopt', customopt(''), b'adds bar'),
842 > (b'', b'customopt', customopt(''), b'adds bar'),
843 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
843 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
844 > b'hg nohelp',
844 > b'hg nohelp',
845 > norepo=True)
845 > norepo=True)
846 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
846 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
847 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
847 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
848 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
848 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
849 > def nohelp(ui, *args, **kwargs):
849 > def nohelp(ui, *args, **kwargs):
850 > pass
850 > pass
851 >
851 >
852 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
852 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
853 > def hashelp(ui, *args, **kwargs):
853 > def hashelp(ui, *args, **kwargs):
854 > """Extension command's help"""
854 > """Extension command's help"""
855 >
855 >
856 > def uisetup(ui):
856 > def uisetup(ui):
857 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
857 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
858 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
858 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
859 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
859 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
860 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
860 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
861 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
861 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
862 >
862 >
863 > EOF
863 > EOF
864 $ echo '[extensions]' >> $HGRCPATH
864 $ echo '[extensions]' >> $HGRCPATH
865 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
865 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
866
866
867 Test for aliases
867 Test for aliases
868
868
869 $ hg help | grep hgalias
869 $ hg help | grep hgalias
870 hgalias My doc
870 hgalias My doc
871
871
872 $ hg help hgalias
872 $ hg help hgalias
873 hg hgalias [--remote]
873 hg hgalias [--remote]
874
874
875 alias for: hg summary
875 alias for: hg summary
876
876
877 My doc
877 My doc
878
878
879 defined by: helpext
879 defined by: helpext
880
880
881 options:
881 options:
882
882
883 --remote check for push and pull
883 --remote check for push and pull
884
884
885 (some details hidden, use --verbose to show complete help)
885 (some details hidden, use --verbose to show complete help)
886 $ hg help hgaliasnodoc
886 $ hg help hgaliasnodoc
887 hg hgaliasnodoc [--remote]
887 hg hgaliasnodoc [--remote]
888
888
889 alias for: hg summary
889 alias for: hg summary
890
890
891 summarize working directory state
891 summarize working directory state
892
892
893 This generates a brief summary of the working directory state, including
893 This generates a brief summary of the working directory state, including
894 parents, branch, commit status, phase and available updates.
894 parents, branch, commit status, phase and available updates.
895
895
896 With the --remote option, this will check the default paths for incoming
896 With the --remote option, this will check the default paths for incoming
897 and outgoing changes. This can be time-consuming.
897 and outgoing changes. This can be time-consuming.
898
898
899 Returns 0 on success.
899 Returns 0 on success.
900
900
901 defined by: helpext
901 defined by: helpext
902
902
903 options:
903 options:
904
904
905 --remote check for push and pull
905 --remote check for push and pull
906
906
907 (some details hidden, use --verbose to show complete help)
907 (some details hidden, use --verbose to show complete help)
908
908
909 $ hg help shellalias
909 $ hg help shellalias
910 hg shellalias
910 hg shellalias
911
911
912 shell alias for: echo hi
912 shell alias for: echo hi
913
913
914 (no help text available)
914 (no help text available)
915
915
916 defined by: helpext
916 defined by: helpext
917
917
918 (some details hidden, use --verbose to show complete help)
918 (some details hidden, use --verbose to show complete help)
919
919
920 Test command with no help text
920 Test command with no help text
921
921
922 $ hg help nohelp
922 $ hg help nohelp
923 hg nohelp
923 hg nohelp
924
924
925 (no help text available)
925 (no help text available)
926
926
927 options:
927 options:
928
928
929 --longdesc VALUE
929 --longdesc VALUE
930 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
930 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
931 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
931 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
932 -n -- normal desc
932 -n -- normal desc
933 --newline VALUE line1 line2
933 --newline VALUE line1 line2
934 --default-off enable X
934 --default-off enable X
935 --[no-]default-on enable Y (default: on)
935 --[no-]default-on enable Y (default: on)
936 --callableopt VALUE adds foo
936 --callableopt VALUE adds foo
937 --customopt VALUE adds bar
937 --customopt VALUE adds bar
938 --customopt-withdefault VALUE adds bar (default: foo)
938 --customopt-withdefault VALUE adds bar (default: foo)
939
939
940 (some details hidden, use --verbose to show complete help)
940 (some details hidden, use --verbose to show complete help)
941
941
942 Test that default list of commands includes extension commands that have help,
942 Test that default list of commands includes extension commands that have help,
943 but not those that don't, except in verbose mode, when a keyword is passed, or
943 but not those that don't, except in verbose mode, when a keyword is passed, or
944 when help about the extension is requested.
944 when help about the extension is requested.
945
945
946 #if no-extraextensions
946 #if no-extraextensions
947
947
948 $ hg help | grep hashelp
948 $ hg help | grep hashelp
949 hashelp Extension command's help
949 hashelp Extension command's help
950 $ hg help | grep nohelp
950 $ hg help | grep nohelp
951 [1]
951 [1]
952 $ hg help -v | grep nohelp
952 $ hg help -v | grep nohelp
953 nohelp (no help text available)
953 nohelp (no help text available)
954
954
955 $ hg help -k nohelp
955 $ hg help -k nohelp
956 Commands:
956 Commands:
957
957
958 nohelp hg nohelp
958 nohelp hg nohelp
959
959
960 Extension Commands:
960 Extension Commands:
961
961
962 nohelp (no help text available)
962 nohelp (no help text available)
963
963
964 $ hg help helpext
964 $ hg help helpext
965 helpext extension - no help text available
965 helpext extension - no help text available
966
966
967 list of commands:
967 list of commands:
968
968
969 hashelp Extension command's help
969 hashelp Extension command's help
970 nohelp (no help text available)
970 nohelp (no help text available)
971
971
972 (use 'hg help -v helpext' to show built-in aliases and global options)
972 (use 'hg help -v helpext' to show built-in aliases and global options)
973
973
974 #endif
974 #endif
975
975
976 Test list of internal help commands
976 Test list of internal help commands
977
977
978 $ hg help debug
978 $ hg help debug
979 debug commands (internal and unsupported):
979 debug commands (internal and unsupported):
980
980
981 debug-delta-find
981 debug-delta-find
982 display the computation to get to a valid delta for storing REV
982 display the computation to get to a valid delta for storing REV
983 debug-repair-issue6528
983 debug-repair-issue6528
984 find affected revisions and repair them. See issue6528 for more
984 find affected revisions and repair them. See issue6528 for more
985 details.
985 details.
986 debug-revlog-index
986 debug-revlog-index
987 dump index data for a revlog
987 dump index data for a revlog
988 debug-revlog-stats
989 display statistics about revlogs in the store
988 debugancestor
990 debugancestor
989 find the ancestor revision of two revisions in a given index
991 find the ancestor revision of two revisions in a given index
990 debugantivirusrunning
992 debugantivirusrunning
991 attempt to trigger an antivirus scanner to see if one is active
993 attempt to trigger an antivirus scanner to see if one is active
992 debugapplystreamclonebundle
994 debugapplystreamclonebundle
993 apply a stream clone bundle file
995 apply a stream clone bundle file
994 debugbackupbundle
996 debugbackupbundle
995 lists the changesets available in backup bundles
997 lists the changesets available in backup bundles
996 debugbuilddag
998 debugbuilddag
997 builds a repo with a given DAG from scratch in the current
999 builds a repo with a given DAG from scratch in the current
998 empty repo
1000 empty repo
999 debugbundle lists the contents of a bundle
1001 debugbundle lists the contents of a bundle
1000 debugcapabilities
1002 debugcapabilities
1001 lists the capabilities of a remote peer
1003 lists the capabilities of a remote peer
1002 debugchangedfiles
1004 debugchangedfiles
1003 list the stored files changes for a revision
1005 list the stored files changes for a revision
1004 debugcheckstate
1006 debugcheckstate
1005 validate the correctness of the current dirstate
1007 validate the correctness of the current dirstate
1006 debugcolor show available color, effects or style
1008 debugcolor show available color, effects or style
1007 debugcommands
1009 debugcommands
1008 list all available commands and options
1010 list all available commands and options
1009 debugcomplete
1011 debugcomplete
1010 returns the completion list associated with the given command
1012 returns the completion list associated with the given command
1011 debugcreatestreamclonebundle
1013 debugcreatestreamclonebundle
1012 create a stream clone bundle file
1014 create a stream clone bundle file
1013 debugdag format the changelog or an index DAG as a concise textual
1015 debugdag format the changelog or an index DAG as a concise textual
1014 description
1016 description
1015 debugdata dump the contents of a data file revision
1017 debugdata dump the contents of a data file revision
1016 debugdate parse and display a date
1018 debugdate parse and display a date
1017 debugdeltachain
1019 debugdeltachain
1018 dump information about delta chains in a revlog
1020 dump information about delta chains in a revlog
1019 debugdirstate
1021 debugdirstate
1020 show the contents of the current dirstate
1022 show the contents of the current dirstate
1021 debugdirstateignorepatternshash
1023 debugdirstateignorepatternshash
1022 show the hash of ignore patterns stored in dirstate if v2,
1024 show the hash of ignore patterns stored in dirstate if v2,
1023 debugdiscovery
1025 debugdiscovery
1024 runs the changeset discovery protocol in isolation
1026 runs the changeset discovery protocol in isolation
1025 debugdownload
1027 debugdownload
1026 download a resource using Mercurial logic and config
1028 download a resource using Mercurial logic and config
1027 debugextensions
1029 debugextensions
1028 show information about active extensions
1030 show information about active extensions
1029 debugfileset parse and apply a fileset specification
1031 debugfileset parse and apply a fileset specification
1030 debugformat display format information about the current repository
1032 debugformat display format information about the current repository
1031 debugfsinfo show information detected about current filesystem
1033 debugfsinfo show information detected about current filesystem
1032 debuggetbundle
1034 debuggetbundle
1033 retrieves a bundle from a repo
1035 retrieves a bundle from a repo
1034 debugignore display the combined ignore pattern and information about
1036 debugignore display the combined ignore pattern and information about
1035 ignored files
1037 ignored files
1036 debugindexdot
1038 debugindexdot
1037 dump an index DAG as a graphviz dot file
1039 dump an index DAG as a graphviz dot file
1038 debugindexstats
1040 debugindexstats
1039 show stats related to the changelog index
1041 show stats related to the changelog index
1040 debuginstall test Mercurial installation
1042 debuginstall test Mercurial installation
1041 debugknown test whether node ids are known to a repo
1043 debugknown test whether node ids are known to a repo
1042 debuglocks show or modify state of locks
1044 debuglocks show or modify state of locks
1043 debugmanifestfulltextcache
1045 debugmanifestfulltextcache
1044 show, clear or amend the contents of the manifest fulltext
1046 show, clear or amend the contents of the manifest fulltext
1045 cache
1047 cache
1046 debugmergestate
1048 debugmergestate
1047 print merge state
1049 print merge state
1048 debugnamecomplete
1050 debugnamecomplete
1049 complete "names" - tags, open branch names, bookmark names
1051 complete "names" - tags, open branch names, bookmark names
1050 debugnodemap write and inspect on disk nodemap
1052 debugnodemap write and inspect on disk nodemap
1051 debugobsolete
1053 debugobsolete
1052 create arbitrary obsolete marker
1054 create arbitrary obsolete marker
1053 debugoptADV (no help text available)
1055 debugoptADV (no help text available)
1054 debugoptDEP (no help text available)
1056 debugoptDEP (no help text available)
1055 debugoptEXP (no help text available)
1057 debugoptEXP (no help text available)
1056 debugp1copies
1058 debugp1copies
1057 dump copy information compared to p1
1059 dump copy information compared to p1
1058 debugp2copies
1060 debugp2copies
1059 dump copy information compared to p2
1061 dump copy information compared to p2
1060 debugpathcomplete
1062 debugpathcomplete
1061 complete part or all of a tracked path
1063 complete part or all of a tracked path
1062 debugpathcopies
1064 debugpathcopies
1063 show copies between two revisions
1065 show copies between two revisions
1064 debugpeer establish a connection to a peer repository
1066 debugpeer establish a connection to a peer repository
1065 debugpickmergetool
1067 debugpickmergetool
1066 examine which merge tool is chosen for specified file
1068 examine which merge tool is chosen for specified file
1067 debugpushkey access the pushkey key/value protocol
1069 debugpushkey access the pushkey key/value protocol
1068 debugpvec (no help text available)
1070 debugpvec (no help text available)
1069 debugrebuilddirstate
1071 debugrebuilddirstate
1070 rebuild the dirstate as it would look like for the given
1072 rebuild the dirstate as it would look like for the given
1071 revision
1073 revision
1072 debugrebuildfncache
1074 debugrebuildfncache
1073 rebuild the fncache file
1075 rebuild the fncache file
1074 debugrename dump rename information
1076 debugrename dump rename information
1075 debugrequires
1077 debugrequires
1076 print the current repo requirements
1078 print the current repo requirements
1077 debugrevlog show data and statistics about a revlog
1079 debugrevlog show data and statistics about a revlog
1078 debugrevlogindex
1080 debugrevlogindex
1079 dump the contents of a revlog index
1081 dump the contents of a revlog index
1080 debugrevspec parse and apply a revision specification
1082 debugrevspec parse and apply a revision specification
1081 debugserve run a server with advanced settings
1083 debugserve run a server with advanced settings
1082 debugsetparents
1084 debugsetparents
1083 manually set the parents of the current working directory
1085 manually set the parents of the current working directory
1084 (DANGEROUS)
1086 (DANGEROUS)
1085 debugshell run an interactive Python interpreter
1087 debugshell run an interactive Python interpreter
1086 debugsidedata
1088 debugsidedata
1087 dump the side data for a cl/manifest/file revision
1089 dump the side data for a cl/manifest/file revision
1088 debugssl test a secure connection to a server
1090 debugssl test a secure connection to a server
1089 debugstrip strip changesets and all their descendants from the repository
1091 debugstrip strip changesets and all their descendants from the repository
1090 debugsub (no help text available)
1092 debugsub (no help text available)
1091 debugsuccessorssets
1093 debugsuccessorssets
1092 show set of successors for revision
1094 show set of successors for revision
1093 debugtagscache
1095 debugtagscache
1094 display the contents of .hg/cache/hgtagsfnodes1
1096 display the contents of .hg/cache/hgtagsfnodes1
1095 debugtemplate
1097 debugtemplate
1096 parse and apply a template
1098 parse and apply a template
1097 debuguigetpass
1099 debuguigetpass
1098 show prompt to type password
1100 show prompt to type password
1099 debuguiprompt
1101 debuguiprompt
1100 show plain prompt
1102 show plain prompt
1101 debugupdatecaches
1103 debugupdatecaches
1102 warm all known caches in the repository
1104 warm all known caches in the repository
1103 debugupgraderepo
1105 debugupgraderepo
1104 upgrade a repository to use different features
1106 upgrade a repository to use different features
1105 debugwalk show how files match on given patterns
1107 debugwalk show how files match on given patterns
1106 debugwhyunstable
1108 debugwhyunstable
1107 explain instabilities of a changeset
1109 explain instabilities of a changeset
1108 debugwireargs
1110 debugwireargs
1109 (no help text available)
1111 (no help text available)
1110 debugwireproto
1112 debugwireproto
1111 send wire protocol commands to a server
1113 send wire protocol commands to a server
1112
1114
1113 (use 'hg help -v debug' to show built-in aliases and global options)
1115 (use 'hg help -v debug' to show built-in aliases and global options)
1114
1116
1115 internals topic renders index of available sub-topics
1117 internals topic renders index of available sub-topics
1116
1118
1117 $ hg help internals
1119 $ hg help internals
1118 Technical implementation topics
1120 Technical implementation topics
1119 """""""""""""""""""""""""""""""
1121 """""""""""""""""""""""""""""""
1120
1122
1121 To access a subtopic, use "hg help internals.{subtopic-name}"
1123 To access a subtopic, use "hg help internals.{subtopic-name}"
1122
1124
1123 bid-merge Bid Merge Algorithm
1125 bid-merge Bid Merge Algorithm
1124 bundle2 Bundle2
1126 bundle2 Bundle2
1125 bundles Bundles
1127 bundles Bundles
1126 cbor CBOR
1128 cbor CBOR
1127 censor Censor
1129 censor Censor
1128 changegroups Changegroups
1130 changegroups Changegroups
1129 config Config Registrar
1131 config Config Registrar
1130 dirstate-v2 dirstate-v2 file format
1132 dirstate-v2 dirstate-v2 file format
1131 extensions Extension API
1133 extensions Extension API
1132 mergestate Mergestate
1134 mergestate Mergestate
1133 requirements Repository Requirements
1135 requirements Repository Requirements
1134 revlogs Revision Logs
1136 revlogs Revision Logs
1135 wireprotocol Wire Protocol
1137 wireprotocol Wire Protocol
1136 wireprotocolrpc
1138 wireprotocolrpc
1137 Wire Protocol RPC
1139 Wire Protocol RPC
1138 wireprotocolv2
1140 wireprotocolv2
1139 Wire Protocol Version 2
1141 Wire Protocol Version 2
1140
1142
1141 sub-topics can be accessed
1143 sub-topics can be accessed
1142
1144
1143 $ hg help internals.changegroups
1145 $ hg help internals.changegroups
1144 Changegroups
1146 Changegroups
1145 """"""""""""
1147 """"""""""""
1146
1148
1147 Changegroups are representations of repository revlog data, specifically
1149 Changegroups are representations of repository revlog data, specifically
1148 the changelog data, root/flat manifest data, treemanifest data, and
1150 the changelog data, root/flat manifest data, treemanifest data, and
1149 filelogs.
1151 filelogs.
1150
1152
1151 There are 4 versions of changegroups: "1", "2", "3" and "4". From a high-
1153 There are 4 versions of changegroups: "1", "2", "3" and "4". From a high-
1152 level, versions "1" and "2" are almost exactly the same, with the only
1154 level, versions "1" and "2" are almost exactly the same, with the only
1153 difference being an additional item in the *delta header*. Version "3"
1155 difference being an additional item in the *delta header*. Version "3"
1154 adds support for storage flags in the *delta header* and optionally
1156 adds support for storage flags in the *delta header* and optionally
1155 exchanging treemanifests (enabled by setting an option on the
1157 exchanging treemanifests (enabled by setting an option on the
1156 "changegroup" part in the bundle2). Version "4" adds support for
1158 "changegroup" part in the bundle2). Version "4" adds support for
1157 exchanging sidedata (additional revision metadata not part of the digest).
1159 exchanging sidedata (additional revision metadata not part of the digest).
1158
1160
1159 Changegroups when not exchanging treemanifests consist of 3 logical
1161 Changegroups when not exchanging treemanifests consist of 3 logical
1160 segments:
1162 segments:
1161
1163
1162 +---------------------------------+
1164 +---------------------------------+
1163 | | | |
1165 | | | |
1164 | changeset | manifest | filelogs |
1166 | changeset | manifest | filelogs |
1165 | | | |
1167 | | | |
1166 | | | |
1168 | | | |
1167 +---------------------------------+
1169 +---------------------------------+
1168
1170
1169 When exchanging treemanifests, there are 4 logical segments:
1171 When exchanging treemanifests, there are 4 logical segments:
1170
1172
1171 +-------------------------------------------------+
1173 +-------------------------------------------------+
1172 | | | | |
1174 | | | | |
1173 | changeset | root | treemanifests | filelogs |
1175 | changeset | root | treemanifests | filelogs |
1174 | | manifest | | |
1176 | | manifest | | |
1175 | | | | |
1177 | | | | |
1176 +-------------------------------------------------+
1178 +-------------------------------------------------+
1177
1179
1178 The principle building block of each segment is a *chunk*. A *chunk* is a
1180 The principle building block of each segment is a *chunk*. A *chunk* is a
1179 framed piece of data:
1181 framed piece of data:
1180
1182
1181 +---------------------------------------+
1183 +---------------------------------------+
1182 | | |
1184 | | |
1183 | length | data |
1185 | length | data |
1184 | (4 bytes) | (<length - 4> bytes) |
1186 | (4 bytes) | (<length - 4> bytes) |
1185 | | |
1187 | | |
1186 +---------------------------------------+
1188 +---------------------------------------+
1187
1189
1188 All integers are big-endian signed integers. Each chunk starts with a
1190 All integers are big-endian signed integers. Each chunk starts with a
1189 32-bit integer indicating the length of the entire chunk (including the
1191 32-bit integer indicating the length of the entire chunk (including the
1190 length field itself).
1192 length field itself).
1191
1193
1192 There is a special case chunk that has a value of 0 for the length
1194 There is a special case chunk that has a value of 0 for the length
1193 ("0x00000000"). We call this an *empty chunk*.
1195 ("0x00000000"). We call this an *empty chunk*.
1194
1196
1195 Delta Groups
1197 Delta Groups
1196 ============
1198 ============
1197
1199
1198 A *delta group* expresses the content of a revlog as a series of deltas,
1200 A *delta group* expresses the content of a revlog as a series of deltas,
1199 or patches against previous revisions.
1201 or patches against previous revisions.
1200
1202
1201 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1203 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1202 to signal the end of the delta group:
1204 to signal the end of the delta group:
1203
1205
1204 +------------------------------------------------------------------------+
1206 +------------------------------------------------------------------------+
1205 | | | | | |
1207 | | | | | |
1206 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1208 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1207 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1209 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1208 | | | | | |
1210 | | | | | |
1209 +------------------------------------------------------------------------+
1211 +------------------------------------------------------------------------+
1210
1212
1211 Each *chunk*'s data consists of the following:
1213 Each *chunk*'s data consists of the following:
1212
1214
1213 +---------------------------------------+
1215 +---------------------------------------+
1214 | | |
1216 | | |
1215 | delta header | delta data |
1217 | delta header | delta data |
1216 | (various by version) | (various) |
1218 | (various by version) | (various) |
1217 | | |
1219 | | |
1218 +---------------------------------------+
1220 +---------------------------------------+
1219
1221
1220 The *delta data* is a series of *delta*s that describe a diff from an
1222 The *delta data* is a series of *delta*s that describe a diff from an
1221 existing entry (either that the recipient already has, or previously
1223 existing entry (either that the recipient already has, or previously
1222 specified in the bundle/changegroup).
1224 specified in the bundle/changegroup).
1223
1225
1224 The *delta header* is different between versions "1", "2", "3" and "4" of
1226 The *delta header* is different between versions "1", "2", "3" and "4" of
1225 the changegroup format.
1227 the changegroup format.
1226
1228
1227 Version 1 (headerlen=80):
1229 Version 1 (headerlen=80):
1228
1230
1229 +------------------------------------------------------+
1231 +------------------------------------------------------+
1230 | | | | |
1232 | | | | |
1231 | node | p1 node | p2 node | link node |
1233 | node | p1 node | p2 node | link node |
1232 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1234 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1233 | | | | |
1235 | | | | |
1234 +------------------------------------------------------+
1236 +------------------------------------------------------+
1235
1237
1236 Version 2 (headerlen=100):
1238 Version 2 (headerlen=100):
1237
1239
1238 +------------------------------------------------------------------+
1240 +------------------------------------------------------------------+
1239 | | | | | |
1241 | | | | | |
1240 | node | p1 node | p2 node | base node | link node |
1242 | node | p1 node | p2 node | base node | link node |
1241 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1243 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1242 | | | | | |
1244 | | | | | |
1243 +------------------------------------------------------------------+
1245 +------------------------------------------------------------------+
1244
1246
1245 Version 3 (headerlen=102):
1247 Version 3 (headerlen=102):
1246
1248
1247 +------------------------------------------------------------------------------+
1249 +------------------------------------------------------------------------------+
1248 | | | | | | |
1250 | | | | | | |
1249 | node | p1 node | p2 node | base node | link node | flags |
1251 | node | p1 node | p2 node | base node | link node | flags |
1250 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1252 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1251 | | | | | | |
1253 | | | | | | |
1252 +------------------------------------------------------------------------------+
1254 +------------------------------------------------------------------------------+
1253
1255
1254 Version 4 (headerlen=103):
1256 Version 4 (headerlen=103):
1255
1257
1256 +------------------------------------------------------------------------------+----------+
1258 +------------------------------------------------------------------------------+----------+
1257 | | | | | | | |
1259 | | | | | | | |
1258 | node | p1 node | p2 node | base node | link node | flags | pflags |
1260 | node | p1 node | p2 node | base node | link node | flags | pflags |
1259 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
1261 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
1260 | | | | | | | |
1262 | | | | | | | |
1261 +------------------------------------------------------------------------------+----------+
1263 +------------------------------------------------------------------------------+----------+
1262
1264
1263 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1265 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1264 contain a series of *delta*s, densely packed (no separators). These deltas
1266 contain a series of *delta*s, densely packed (no separators). These deltas
1265 describe a diff from an existing entry (either that the recipient already
1267 describe a diff from an existing entry (either that the recipient already
1266 has, or previously specified in the bundle/changegroup). The format is
1268 has, or previously specified in the bundle/changegroup). The format is
1267 described more fully in "hg help internals.bdiff", but briefly:
1269 described more fully in "hg help internals.bdiff", but briefly:
1268
1270
1269 +---------------------------------------------------------------+
1271 +---------------------------------------------------------------+
1270 | | | | |
1272 | | | | |
1271 | start offset | end offset | new length | content |
1273 | start offset | end offset | new length | content |
1272 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1274 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1273 | | | | |
1275 | | | | |
1274 +---------------------------------------------------------------+
1276 +---------------------------------------------------------------+
1275
1277
1276 Please note that the length field in the delta data does *not* include
1278 Please note that the length field in the delta data does *not* include
1277 itself.
1279 itself.
1278
1280
1279 In version 1, the delta is always applied against the previous node from
1281 In version 1, the delta is always applied against the previous node from
1280 the changegroup or the first parent if this is the first entry in the
1282 the changegroup or the first parent if this is the first entry in the
1281 changegroup.
1283 changegroup.
1282
1284
1283 In version 2 and up, the delta base node is encoded in the entry in the
1285 In version 2 and up, the delta base node is encoded in the entry in the
1284 changegroup. This allows the delta to be expressed against any parent,
1286 changegroup. This allows the delta to be expressed against any parent,
1285 which can result in smaller deltas and more efficient encoding of data.
1287 which can result in smaller deltas and more efficient encoding of data.
1286
1288
1287 The *flags* field holds bitwise flags affecting the processing of revision
1289 The *flags* field holds bitwise flags affecting the processing of revision
1288 data. The following flags are defined:
1290 data. The following flags are defined:
1289
1291
1290 32768
1292 32768
1291 Censored revision. The revision's fulltext has been replaced by censor
1293 Censored revision. The revision's fulltext has been replaced by censor
1292 metadata. May only occur on file revisions.
1294 metadata. May only occur on file revisions.
1293
1295
1294 16384
1296 16384
1295 Ellipsis revision. Revision hash does not match data (likely due to
1297 Ellipsis revision. Revision hash does not match data (likely due to
1296 rewritten parents).
1298 rewritten parents).
1297
1299
1298 8192
1300 8192
1299 Externally stored. The revision fulltext contains "key:value" "\n"
1301 Externally stored. The revision fulltext contains "key:value" "\n"
1300 delimited metadata defining an object stored elsewhere. Used by the LFS
1302 delimited metadata defining an object stored elsewhere. Used by the LFS
1301 extension.
1303 extension.
1302
1304
1303 4096
1305 4096
1304 Contains copy information. This revision changes files in a way that
1306 Contains copy information. This revision changes files in a way that
1305 could affect copy tracing. This does *not* affect changegroup handling,
1307 could affect copy tracing. This does *not* affect changegroup handling,
1306 but is relevant for other parts of Mercurial.
1308 but is relevant for other parts of Mercurial.
1307
1309
1308 For historical reasons, the integer values are identical to revlog version
1310 For historical reasons, the integer values are identical to revlog version
1309 1 per-revision storage flags and correspond to bits being set in this
1311 1 per-revision storage flags and correspond to bits being set in this
1310 2-byte field. Bits were allocated starting from the most-significant bit,
1312 2-byte field. Bits were allocated starting from the most-significant bit,
1311 hence the reverse ordering and allocation of these flags.
1313 hence the reverse ordering and allocation of these flags.
1312
1314
1313 The *pflags* (protocol flags) field holds bitwise flags affecting the
1315 The *pflags* (protocol flags) field holds bitwise flags affecting the
1314 protocol itself. They are first in the header since they may affect the
1316 protocol itself. They are first in the header since they may affect the
1315 handling of the rest of the fields in a future version. They are defined
1317 handling of the rest of the fields in a future version. They are defined
1316 as such:
1318 as such:
1317
1319
1318 1 indicates whether to read a chunk of sidedata (of variable length) right
1320 1 indicates whether to read a chunk of sidedata (of variable length) right
1319 after the revision flags.
1321 after the revision flags.
1320
1322
1321 Changeset Segment
1323 Changeset Segment
1322 =================
1324 =================
1323
1325
1324 The *changeset segment* consists of a single *delta group* holding
1326 The *changeset segment* consists of a single *delta group* holding
1325 changelog data. The *empty chunk* at the end of the *delta group* denotes
1327 changelog data. The *empty chunk* at the end of the *delta group* denotes
1326 the boundary to the *manifest segment*.
1328 the boundary to the *manifest segment*.
1327
1329
1328 Manifest Segment
1330 Manifest Segment
1329 ================
1331 ================
1330
1332
1331 The *manifest segment* consists of a single *delta group* holding manifest
1333 The *manifest segment* consists of a single *delta group* holding manifest
1332 data. If treemanifests are in use, it contains only the manifest for the
1334 data. If treemanifests are in use, it contains only the manifest for the
1333 root directory of the repository. Otherwise, it contains the entire
1335 root directory of the repository. Otherwise, it contains the entire
1334 manifest data. The *empty chunk* at the end of the *delta group* denotes
1336 manifest data. The *empty chunk* at the end of the *delta group* denotes
1335 the boundary to the next segment (either the *treemanifests segment* or
1337 the boundary to the next segment (either the *treemanifests segment* or
1336 the *filelogs segment*, depending on version and the request options).
1338 the *filelogs segment*, depending on version and the request options).
1337
1339
1338 Treemanifests Segment
1340 Treemanifests Segment
1339 ---------------------
1341 ---------------------
1340
1342
1341 The *treemanifests segment* only exists in changegroup version "3" and
1343 The *treemanifests segment* only exists in changegroup version "3" and
1342 "4", and only if the 'treemanifest' param is part of the bundle2
1344 "4", and only if the 'treemanifest' param is part of the bundle2
1343 changegroup part (it is not possible to use changegroup version 3 or 4
1345 changegroup part (it is not possible to use changegroup version 3 or 4
1344 outside of bundle2). Aside from the filenames in the *treemanifests
1346 outside of bundle2). Aside from the filenames in the *treemanifests
1345 segment* containing a trailing "/" character, it behaves identically to
1347 segment* containing a trailing "/" character, it behaves identically to
1346 the *filelogs segment* (see below). The final sub-segment is followed by
1348 the *filelogs segment* (see below). The final sub-segment is followed by
1347 an *empty chunk* (logically, a sub-segment with filename size 0). This
1349 an *empty chunk* (logically, a sub-segment with filename size 0). This
1348 denotes the boundary to the *filelogs segment*.
1350 denotes the boundary to the *filelogs segment*.
1349
1351
1350 Filelogs Segment
1352 Filelogs Segment
1351 ================
1353 ================
1352
1354
1353 The *filelogs segment* consists of multiple sub-segments, each
1355 The *filelogs segment* consists of multiple sub-segments, each
1354 corresponding to an individual file whose data is being described:
1356 corresponding to an individual file whose data is being described:
1355
1357
1356 +--------------------------------------------------+
1358 +--------------------------------------------------+
1357 | | | | | |
1359 | | | | | |
1358 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1360 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1359 | | | | | (4 bytes) |
1361 | | | | | (4 bytes) |
1360 | | | | | |
1362 | | | | | |
1361 +--------------------------------------------------+
1363 +--------------------------------------------------+
1362
1364
1363 The final filelog sub-segment is followed by an *empty chunk* (logically,
1365 The final filelog sub-segment is followed by an *empty chunk* (logically,
1364 a sub-segment with filename size 0). This denotes the end of the segment
1366 a sub-segment with filename size 0). This denotes the end of the segment
1365 and of the overall changegroup.
1367 and of the overall changegroup.
1366
1368
1367 Each filelog sub-segment consists of the following:
1369 Each filelog sub-segment consists of the following:
1368
1370
1369 +------------------------------------------------------+
1371 +------------------------------------------------------+
1370 | | | |
1372 | | | |
1371 | filename length | filename | delta group |
1373 | filename length | filename | delta group |
1372 | (4 bytes) | (<length - 4> bytes) | (various) |
1374 | (4 bytes) | (<length - 4> bytes) | (various) |
1373 | | | |
1375 | | | |
1374 +------------------------------------------------------+
1376 +------------------------------------------------------+
1375
1377
1376 That is, a *chunk* consisting of the filename (not terminated or padded)
1378 That is, a *chunk* consisting of the filename (not terminated or padded)
1377 followed by N chunks constituting the *delta group* for this file. The
1379 followed by N chunks constituting the *delta group* for this file. The
1378 *empty chunk* at the end of each *delta group* denotes the boundary to the
1380 *empty chunk* at the end of each *delta group* denotes the boundary to the
1379 next filelog sub-segment.
1381 next filelog sub-segment.
1380
1382
1381 non-existent subtopics print an error
1383 non-existent subtopics print an error
1382
1384
1383 $ hg help internals.foo
1385 $ hg help internals.foo
1384 abort: no such help topic: internals.foo
1386 abort: no such help topic: internals.foo
1385 (try 'hg help --keyword foo')
1387 (try 'hg help --keyword foo')
1386 [10]
1388 [10]
1387
1389
1388 test advanced, deprecated and experimental options are hidden in command help
1390 test advanced, deprecated and experimental options are hidden in command help
1389 $ hg help debugoptADV
1391 $ hg help debugoptADV
1390 hg debugoptADV
1392 hg debugoptADV
1391
1393
1392 (no help text available)
1394 (no help text available)
1393
1395
1394 options:
1396 options:
1395
1397
1396 (some details hidden, use --verbose to show complete help)
1398 (some details hidden, use --verbose to show complete help)
1397 $ hg help debugoptDEP
1399 $ hg help debugoptDEP
1398 hg debugoptDEP
1400 hg debugoptDEP
1399
1401
1400 (no help text available)
1402 (no help text available)
1401
1403
1402 options:
1404 options:
1403
1405
1404 (some details hidden, use --verbose to show complete help)
1406 (some details hidden, use --verbose to show complete help)
1405
1407
1406 $ hg help debugoptEXP
1408 $ hg help debugoptEXP
1407 hg debugoptEXP
1409 hg debugoptEXP
1408
1410
1409 (no help text available)
1411 (no help text available)
1410
1412
1411 options:
1413 options:
1412
1414
1413 (some details hidden, use --verbose to show complete help)
1415 (some details hidden, use --verbose to show complete help)
1414
1416
1415 test advanced, deprecated and experimental options are shown with -v
1417 test advanced, deprecated and experimental options are shown with -v
1416 $ hg help -v debugoptADV | grep aopt
1418 $ hg help -v debugoptADV | grep aopt
1417 --aopt option is (ADVANCED)
1419 --aopt option is (ADVANCED)
1418 $ hg help -v debugoptDEP | grep dopt
1420 $ hg help -v debugoptDEP | grep dopt
1419 --dopt option is (DEPRECATED)
1421 --dopt option is (DEPRECATED)
1420 $ hg help -v debugoptEXP | grep eopt
1422 $ hg help -v debugoptEXP | grep eopt
1421 --eopt option is (EXPERIMENTAL)
1423 --eopt option is (EXPERIMENTAL)
1422
1424
1423 #if gettext
1425 #if gettext
1424 test deprecated option is hidden with translation with untranslated description
1426 test deprecated option is hidden with translation with untranslated description
1425 (use many globy for not failing on changed transaction)
1427 (use many globy for not failing on changed transaction)
1426 $ LANGUAGE=sv hg help debugoptDEP
1428 $ LANGUAGE=sv hg help debugoptDEP
1427 hg debugoptDEP
1429 hg debugoptDEP
1428
1430
1429 (*) (glob)
1431 (*) (glob)
1430
1432
1431 options:
1433 options:
1432
1434
1433 (some details hidden, use --verbose to show complete help)
1435 (some details hidden, use --verbose to show complete help)
1434 #endif
1436 #endif
1435
1437
1436 Test commands that collide with topics (issue4240)
1438 Test commands that collide with topics (issue4240)
1437
1439
1438 $ hg config -hq
1440 $ hg config -hq
1439 hg config [-u] [NAME]...
1441 hg config [-u] [NAME]...
1440
1442
1441 show combined config settings from all hgrc files
1443 show combined config settings from all hgrc files
1442 $ hg showconfig -hq
1444 $ hg showconfig -hq
1443 hg config [-u] [NAME]...
1445 hg config [-u] [NAME]...
1444
1446
1445 show combined config settings from all hgrc files
1447 show combined config settings from all hgrc files
1446
1448
1447 Test a help topic
1449 Test a help topic
1448
1450
1449 $ hg help dates
1451 $ hg help dates
1450 Date Formats
1452 Date Formats
1451 """"""""""""
1453 """"""""""""
1452
1454
1453 Some commands allow the user to specify a date, e.g.:
1455 Some commands allow the user to specify a date, e.g.:
1454
1456
1455 - backout, commit, import, tag: Specify the commit date.
1457 - backout, commit, import, tag: Specify the commit date.
1456 - log, revert, update: Select revision(s) by date.
1458 - log, revert, update: Select revision(s) by date.
1457
1459
1458 Many date formats are valid. Here are some examples:
1460 Many date formats are valid. Here are some examples:
1459
1461
1460 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1462 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1461 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1463 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1462 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1464 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1463 - "Dec 6" (midnight)
1465 - "Dec 6" (midnight)
1464 - "13:18" (today assumed)
1466 - "13:18" (today assumed)
1465 - "3:39" (3:39AM assumed)
1467 - "3:39" (3:39AM assumed)
1466 - "3:39pm" (15:39)
1468 - "3:39pm" (15:39)
1467 - "2006-12-06 13:18:29" (ISO 8601 format)
1469 - "2006-12-06 13:18:29" (ISO 8601 format)
1468 - "2006-12-6 13:18"
1470 - "2006-12-6 13:18"
1469 - "2006-12-6"
1471 - "2006-12-6"
1470 - "12-6"
1472 - "12-6"
1471 - "12/6"
1473 - "12/6"
1472 - "12/6/6" (Dec 6 2006)
1474 - "12/6/6" (Dec 6 2006)
1473 - "today" (midnight)
1475 - "today" (midnight)
1474 - "yesterday" (midnight)
1476 - "yesterday" (midnight)
1475 - "now" - right now
1477 - "now" - right now
1476
1478
1477 Lastly, there is Mercurial's internal format:
1479 Lastly, there is Mercurial's internal format:
1478
1480
1479 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1481 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1480
1482
1481 This is the internal representation format for dates. The first number is
1483 This is the internal representation format for dates. The first number is
1482 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1484 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1483 is the offset of the local timezone, in seconds west of UTC (negative if
1485 is the offset of the local timezone, in seconds west of UTC (negative if
1484 the timezone is east of UTC).
1486 the timezone is east of UTC).
1485
1487
1486 The log command also accepts date ranges:
1488 The log command also accepts date ranges:
1487
1489
1488 - "<DATE" - at or before a given date/time
1490 - "<DATE" - at or before a given date/time
1489 - ">DATE" - on or after a given date/time
1491 - ">DATE" - on or after a given date/time
1490 - "DATE to DATE" - a date range, inclusive
1492 - "DATE to DATE" - a date range, inclusive
1491 - "-DAYS" - within a given number of days from today
1493 - "-DAYS" - within a given number of days from today
1492
1494
1493 Test repeated config section name
1495 Test repeated config section name
1494
1496
1495 $ hg help config.host
1497 $ hg help config.host
1496 "http_proxy.host"
1498 "http_proxy.host"
1497 Host name and (optional) port of the proxy server, for example
1499 Host name and (optional) port of the proxy server, for example
1498 "myproxy:8000".
1500 "myproxy:8000".
1499
1501
1500 "smtp.host"
1502 "smtp.host"
1501 Host name of mail server, e.g. "mail.example.com".
1503 Host name of mail server, e.g. "mail.example.com".
1502
1504
1503
1505
1504 Test section name with dot
1506 Test section name with dot
1505
1507
1506 $ hg help config.ui.username
1508 $ hg help config.ui.username
1507 "ui.username"
1509 "ui.username"
1508 The committer of a changeset created when running "commit". Typically
1510 The committer of a changeset created when running "commit". Typically
1509 a person's name and email address, e.g. "Fred Widget
1511 a person's name and email address, e.g. "Fred Widget
1510 <fred@example.com>". Environment variables in the username are
1512 <fred@example.com>". Environment variables in the username are
1511 expanded.
1513 expanded.
1512
1514
1513 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1515 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1514 empty, e.g. if the system admin set "username =" in the system hgrc,
1516 empty, e.g. if the system admin set "username =" in the system hgrc,
1515 it has to be specified manually or in a different hgrc file)
1517 it has to be specified manually or in a different hgrc file)
1516
1518
1517
1519
1518 $ hg help config.annotate.git
1520 $ hg help config.annotate.git
1519 abort: help section not found: config.annotate.git
1521 abort: help section not found: config.annotate.git
1520 [10]
1522 [10]
1521
1523
1522 $ hg help config.update.check
1524 $ hg help config.update.check
1523 "commands.update.check"
1525 "commands.update.check"
1524 Determines what level of checking 'hg update' will perform before
1526 Determines what level of checking 'hg update' will perform before
1525 moving to a destination revision. Valid values are "abort", "none",
1527 moving to a destination revision. Valid values are "abort", "none",
1526 "linear", and "noconflict".
1528 "linear", and "noconflict".
1527
1529
1528 - "abort" always fails if the working directory has uncommitted
1530 - "abort" always fails if the working directory has uncommitted
1529 changes.
1531 changes.
1530 - "none" performs no checking, and may result in a merge with
1532 - "none" performs no checking, and may result in a merge with
1531 uncommitted changes.
1533 uncommitted changes.
1532 - "linear" allows any update as long as it follows a straight line in
1534 - "linear" allows any update as long as it follows a straight line in
1533 the revision history, and may trigger a merge with uncommitted
1535 the revision history, and may trigger a merge with uncommitted
1534 changes.
1536 changes.
1535 - "noconflict" will allow any update which would not trigger a merge
1537 - "noconflict" will allow any update which would not trigger a merge
1536 with uncommitted changes, if any are present.
1538 with uncommitted changes, if any are present.
1537
1539
1538 (default: "linear")
1540 (default: "linear")
1539
1541
1540
1542
1541 $ hg help config.commands.update.check
1543 $ hg help config.commands.update.check
1542 "commands.update.check"
1544 "commands.update.check"
1543 Determines what level of checking 'hg update' will perform before
1545 Determines what level of checking 'hg update' will perform before
1544 moving to a destination revision. Valid values are "abort", "none",
1546 moving to a destination revision. Valid values are "abort", "none",
1545 "linear", and "noconflict".
1547 "linear", and "noconflict".
1546
1548
1547 - "abort" always fails if the working directory has uncommitted
1549 - "abort" always fails if the working directory has uncommitted
1548 changes.
1550 changes.
1549 - "none" performs no checking, and may result in a merge with
1551 - "none" performs no checking, and may result in a merge with
1550 uncommitted changes.
1552 uncommitted changes.
1551 - "linear" allows any update as long as it follows a straight line in
1553 - "linear" allows any update as long as it follows a straight line in
1552 the revision history, and may trigger a merge with uncommitted
1554 the revision history, and may trigger a merge with uncommitted
1553 changes.
1555 changes.
1554 - "noconflict" will allow any update which would not trigger a merge
1556 - "noconflict" will allow any update which would not trigger a merge
1555 with uncommitted changes, if any are present.
1557 with uncommitted changes, if any are present.
1556
1558
1557 (default: "linear")
1559 (default: "linear")
1558
1560
1559
1561
1560 $ hg help config.ommands.update.check
1562 $ hg help config.ommands.update.check
1561 abort: help section not found: config.ommands.update.check
1563 abort: help section not found: config.ommands.update.check
1562 [10]
1564 [10]
1563
1565
1564 Unrelated trailing paragraphs shouldn't be included
1566 Unrelated trailing paragraphs shouldn't be included
1565
1567
1566 $ hg help config.extramsg | grep '^$'
1568 $ hg help config.extramsg | grep '^$'
1567
1569
1568
1570
1569 Test capitalized section name
1571 Test capitalized section name
1570
1572
1571 $ hg help scripting.HGPLAIN > /dev/null
1573 $ hg help scripting.HGPLAIN > /dev/null
1572
1574
1573 Help subsection:
1575 Help subsection:
1574
1576
1575 $ hg help config.charsets |grep "Email example:" > /dev/null
1577 $ hg help config.charsets |grep "Email example:" > /dev/null
1576 [1]
1578 [1]
1577
1579
1578 Show nested definitions
1580 Show nested definitions
1579 ("profiling.type"[break]"ls"[break]"stat"[break])
1581 ("profiling.type"[break]"ls"[break]"stat"[break])
1580
1582
1581 $ hg help config.type | egrep '^$'|wc -l
1583 $ hg help config.type | egrep '^$'|wc -l
1582 \s*3 (re)
1584 \s*3 (re)
1583
1585
1584 $ hg help config.profiling.type.ls
1586 $ hg help config.profiling.type.ls
1585 "profiling.type.ls"
1587 "profiling.type.ls"
1586 Use Python's built-in instrumenting profiler. This profiler works on
1588 Use Python's built-in instrumenting profiler. This profiler works on
1587 all platforms, but each line number it reports is the first line of
1589 all platforms, but each line number it reports is the first line of
1588 a function. This restriction makes it difficult to identify the
1590 a function. This restriction makes it difficult to identify the
1589 expensive parts of a non-trivial function.
1591 expensive parts of a non-trivial function.
1590
1592
1591
1593
1592 Separate sections from subsections
1594 Separate sections from subsections
1593
1595
1594 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1596 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1595 "format"
1597 "format"
1596 --------
1598 --------
1597
1599
1598 "usegeneraldelta"
1600 "usegeneraldelta"
1599
1601
1600 "dotencode"
1602 "dotencode"
1601
1603
1602 "usefncache"
1604 "usefncache"
1603
1605
1604 "use-dirstate-v2"
1606 "use-dirstate-v2"
1605
1607
1606 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories"
1608 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories"
1607
1609
1608 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet"
1610 "use-dirstate-v2.automatic-upgrade-of-mismatching-repositories:quiet"
1609
1611
1610 "use-dirstate-tracked-hint"
1612 "use-dirstate-tracked-hint"
1611
1613
1612 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories"
1614 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories"
1613
1615
1614 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet"
1616 "use-dirstate-tracked-hint.automatic-upgrade-of-mismatching-repositories:quiet"
1615
1617
1616 "use-persistent-nodemap"
1618 "use-persistent-nodemap"
1617
1619
1618 "use-share-safe"
1620 "use-share-safe"
1619
1621
1620 "use-share-safe.automatic-upgrade-of-mismatching-repositories"
1622 "use-share-safe.automatic-upgrade-of-mismatching-repositories"
1621
1623
1622 "use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet"
1624 "use-share-safe.automatic-upgrade-of-mismatching-repositories:quiet"
1623
1625
1624 "usestore"
1626 "usestore"
1625
1627
1626 "sparse-revlog"
1628 "sparse-revlog"
1627
1629
1628 "revlog-compression"
1630 "revlog-compression"
1629
1631
1630 "bookmarks-in-store"
1632 "bookmarks-in-store"
1631
1633
1632 "profiling"
1634 "profiling"
1633 -----------
1635 -----------
1634
1636
1635 "format"
1637 "format"
1636
1638
1637 "progress"
1639 "progress"
1638 ----------
1640 ----------
1639
1641
1640 "format"
1642 "format"
1641
1643
1642
1644
1643 Last item in help config.*:
1645 Last item in help config.*:
1644
1646
1645 $ hg help config.`hg help config|grep '^ "'| \
1647 $ hg help config.`hg help config|grep '^ "'| \
1646 > tail -1|sed 's![ "]*!!g'`| \
1648 > tail -1|sed 's![ "]*!!g'`| \
1647 > grep 'hg help -c config' > /dev/null
1649 > grep 'hg help -c config' > /dev/null
1648 [1]
1650 [1]
1649
1651
1650 note to use help -c for general hg help config:
1652 note to use help -c for general hg help config:
1651
1653
1652 $ hg help config |grep 'hg help -c config' > /dev/null
1654 $ hg help config |grep 'hg help -c config' > /dev/null
1653
1655
1654 Test templating help
1656 Test templating help
1655
1657
1656 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1658 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1657 desc String. The text of the changeset description.
1659 desc String. The text of the changeset description.
1658 diffstat String. Statistics of changes with the following format:
1660 diffstat String. Statistics of changes with the following format:
1659 firstline Any text. Returns the first line of text.
1661 firstline Any text. Returns the first line of text.
1660 nonempty Any text. Returns '(none)' if the string is empty.
1662 nonempty Any text. Returns '(none)' if the string is empty.
1661
1663
1662 Test deprecated items
1664 Test deprecated items
1663
1665
1664 $ hg help -v templating | grep currentbookmark
1666 $ hg help -v templating | grep currentbookmark
1665 currentbookmark
1667 currentbookmark
1666 $ hg help templating | (grep currentbookmark || true)
1668 $ hg help templating | (grep currentbookmark || true)
1667
1669
1668 Test help hooks
1670 Test help hooks
1669
1671
1670 $ cat > helphook1.py <<EOF
1672 $ cat > helphook1.py <<EOF
1671 > from mercurial import help
1673 > from mercurial import help
1672 >
1674 >
1673 > def rewrite(ui, topic, doc):
1675 > def rewrite(ui, topic, doc):
1674 > return doc + b'\nhelphook1\n'
1676 > return doc + b'\nhelphook1\n'
1675 >
1677 >
1676 > def extsetup(ui):
1678 > def extsetup(ui):
1677 > help.addtopichook(b'revisions', rewrite)
1679 > help.addtopichook(b'revisions', rewrite)
1678 > EOF
1680 > EOF
1679 $ cat > helphook2.py <<EOF
1681 $ cat > helphook2.py <<EOF
1680 > from mercurial import help
1682 > from mercurial import help
1681 >
1683 >
1682 > def rewrite(ui, topic, doc):
1684 > def rewrite(ui, topic, doc):
1683 > return doc + b'\nhelphook2\n'
1685 > return doc + b'\nhelphook2\n'
1684 >
1686 >
1685 > def extsetup(ui):
1687 > def extsetup(ui):
1686 > help.addtopichook(b'revisions', rewrite)
1688 > help.addtopichook(b'revisions', rewrite)
1687 > EOF
1689 > EOF
1688 $ echo '[extensions]' >> $HGRCPATH
1690 $ echo '[extensions]' >> $HGRCPATH
1689 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1691 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1690 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1692 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1691 $ hg help revsets | grep helphook
1693 $ hg help revsets | grep helphook
1692 helphook1
1694 helphook1
1693 helphook2
1695 helphook2
1694
1696
1695 help -c should only show debug --debug
1697 help -c should only show debug --debug
1696
1698
1697 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1699 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1698 [1]
1700 [1]
1699
1701
1700 help -c should only show deprecated for -v
1702 help -c should only show deprecated for -v
1701
1703
1702 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1704 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1703 [1]
1705 [1]
1704
1706
1705 Test -s / --system
1707 Test -s / --system
1706
1708
1707 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1709 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1708 > wc -l | sed -e 's/ //g'
1710 > wc -l | sed -e 's/ //g'
1709 0
1711 0
1710 $ hg help config.files --system unix | grep 'USER' | \
1712 $ hg help config.files --system unix | grep 'USER' | \
1711 > wc -l | sed -e 's/ //g'
1713 > wc -l | sed -e 's/ //g'
1712 0
1714 0
1713
1715
1714 Test -e / -c / -k combinations
1716 Test -e / -c / -k combinations
1715
1717
1716 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1718 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1717 Commands:
1719 Commands:
1718 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1720 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1719 Extensions:
1721 Extensions:
1720 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1722 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1721 Topics:
1723 Topics:
1722 Commands:
1724 Commands:
1723 Extensions:
1725 Extensions:
1724 Extension Commands:
1726 Extension Commands:
1725 $ hg help -c schemes
1727 $ hg help -c schemes
1726 abort: no such help topic: schemes
1728 abort: no such help topic: schemes
1727 (try 'hg help --keyword schemes')
1729 (try 'hg help --keyword schemes')
1728 [10]
1730 [10]
1729 $ hg help -e schemes |head -1
1731 $ hg help -e schemes |head -1
1730 schemes extension - extend schemes with shortcuts to repository swarms
1732 schemes extension - extend schemes with shortcuts to repository swarms
1731 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1733 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1732 Commands:
1734 Commands:
1733 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1735 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1734 Extensions:
1736 Extensions:
1735 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1737 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1736 Extensions:
1738 Extensions:
1737 Commands:
1739 Commands:
1738 $ hg help -c commit > /dev/null
1740 $ hg help -c commit > /dev/null
1739 $ hg help -e -c commit > /dev/null
1741 $ hg help -e -c commit > /dev/null
1740 $ hg help -e commit
1742 $ hg help -e commit
1741 abort: no such help topic: commit
1743 abort: no such help topic: commit
1742 (try 'hg help --keyword commit')
1744 (try 'hg help --keyword commit')
1743 [10]
1745 [10]
1744
1746
1745 Test keyword search help
1747 Test keyword search help
1746
1748
1747 $ cat > prefixedname.py <<EOF
1749 $ cat > prefixedname.py <<EOF
1748 > '''matched against word "clone"
1750 > '''matched against word "clone"
1749 > '''
1751 > '''
1750 > EOF
1752 > EOF
1751 $ echo '[extensions]' >> $HGRCPATH
1753 $ echo '[extensions]' >> $HGRCPATH
1752 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1754 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1753 $ hg help -k clone
1755 $ hg help -k clone
1754 Topics:
1756 Topics:
1755
1757
1756 config Configuration Files
1758 config Configuration Files
1757 extensions Using Additional Features
1759 extensions Using Additional Features
1758 glossary Glossary
1760 glossary Glossary
1759 phases Working with Phases
1761 phases Working with Phases
1760 subrepos Subrepositories
1762 subrepos Subrepositories
1761 urls URL Paths
1763 urls URL Paths
1762
1764
1763 Commands:
1765 Commands:
1764
1766
1765 bookmarks create a new bookmark or list existing bookmarks
1767 bookmarks create a new bookmark or list existing bookmarks
1766 clone make a copy of an existing repository
1768 clone make a copy of an existing repository
1767 paths show aliases for remote repositories
1769 paths show aliases for remote repositories
1768 pull pull changes from the specified source
1770 pull pull changes from the specified source
1769 update update working directory (or switch revisions)
1771 update update working directory (or switch revisions)
1770
1772
1771 Extensions:
1773 Extensions:
1772
1774
1773 clonebundles advertise pre-generated bundles to seed clones
1775 clonebundles advertise pre-generated bundles to seed clones
1774 narrow create clones which fetch history data for subset of files
1776 narrow create clones which fetch history data for subset of files
1775 (EXPERIMENTAL)
1777 (EXPERIMENTAL)
1776 prefixedname matched against word "clone"
1778 prefixedname matched against word "clone"
1777 relink recreates hardlinks between repository clones
1779 relink recreates hardlinks between repository clones
1778
1780
1779 Extension Commands:
1781 Extension Commands:
1780
1782
1781 qclone clone main and patch repository at same time
1783 qclone clone main and patch repository at same time
1782
1784
1783 Test unfound topic
1785 Test unfound topic
1784
1786
1785 $ hg help nonexistingtopicthatwillneverexisteverever
1787 $ hg help nonexistingtopicthatwillneverexisteverever
1786 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1788 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1787 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1789 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1788 [10]
1790 [10]
1789
1791
1790 Test unfound keyword
1792 Test unfound keyword
1791
1793
1792 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1794 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1793 abort: no matches
1795 abort: no matches
1794 (try 'hg help' for a list of topics)
1796 (try 'hg help' for a list of topics)
1795 [10]
1797 [10]
1796
1798
1797 Test omit indicating for help
1799 Test omit indicating for help
1798
1800
1799 $ cat > addverboseitems.py <<EOF
1801 $ cat > addverboseitems.py <<EOF
1800 > r'''extension to test omit indicating.
1802 > r'''extension to test omit indicating.
1801 >
1803 >
1802 > This paragraph is never omitted (for extension)
1804 > This paragraph is never omitted (for extension)
1803 >
1805 >
1804 > .. container:: verbose
1806 > .. container:: verbose
1805 >
1807 >
1806 > This paragraph is omitted,
1808 > This paragraph is omitted,
1807 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1809 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1808 >
1810 >
1809 > This paragraph is never omitted, too (for extension)
1811 > This paragraph is never omitted, too (for extension)
1810 > '''
1812 > '''
1811 > from mercurial import commands, help
1813 > from mercurial import commands, help
1812 > testtopic = br"""This paragraph is never omitted (for topic).
1814 > testtopic = br"""This paragraph is never omitted (for topic).
1813 >
1815 >
1814 > .. container:: verbose
1816 > .. container:: verbose
1815 >
1817 >
1816 > This paragraph is omitted,
1818 > This paragraph is omitted,
1817 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1819 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1818 >
1820 >
1819 > This paragraph is never omitted, too (for topic)
1821 > This paragraph is never omitted, too (for topic)
1820 > """
1822 > """
1821 > def extsetup(ui):
1823 > def extsetup(ui):
1822 > help.helptable.append(([b"topic-containing-verbose"],
1824 > help.helptable.append(([b"topic-containing-verbose"],
1823 > b"This is the topic to test omit indicating.",
1825 > b"This is the topic to test omit indicating.",
1824 > lambda ui: testtopic))
1826 > lambda ui: testtopic))
1825 > EOF
1827 > EOF
1826 $ echo '[extensions]' >> $HGRCPATH
1828 $ echo '[extensions]' >> $HGRCPATH
1827 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1829 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1828 $ hg help addverboseitems
1830 $ hg help addverboseitems
1829 addverboseitems extension - extension to test omit indicating.
1831 addverboseitems extension - extension to test omit indicating.
1830
1832
1831 This paragraph is never omitted (for extension)
1833 This paragraph is never omitted (for extension)
1832
1834
1833 This paragraph is never omitted, too (for extension)
1835 This paragraph is never omitted, too (for extension)
1834
1836
1835 (some details hidden, use --verbose to show complete help)
1837 (some details hidden, use --verbose to show complete help)
1836
1838
1837 no commands defined
1839 no commands defined
1838 $ hg help -v addverboseitems
1840 $ hg help -v addverboseitems
1839 addverboseitems extension - extension to test omit indicating.
1841 addverboseitems extension - extension to test omit indicating.
1840
1842
1841 This paragraph is never omitted (for extension)
1843 This paragraph is never omitted (for extension)
1842
1844
1843 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1845 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1844 extension)
1846 extension)
1845
1847
1846 This paragraph is never omitted, too (for extension)
1848 This paragraph is never omitted, too (for extension)
1847
1849
1848 no commands defined
1850 no commands defined
1849 $ hg help topic-containing-verbose
1851 $ hg help topic-containing-verbose
1850 This is the topic to test omit indicating.
1852 This is the topic to test omit indicating.
1851 """"""""""""""""""""""""""""""""""""""""""
1853 """"""""""""""""""""""""""""""""""""""""""
1852
1854
1853 This paragraph is never omitted (for topic).
1855 This paragraph is never omitted (for topic).
1854
1856
1855 This paragraph is never omitted, too (for topic)
1857 This paragraph is never omitted, too (for topic)
1856
1858
1857 (some details hidden, use --verbose to show complete help)
1859 (some details hidden, use --verbose to show complete help)
1858 $ hg help -v topic-containing-verbose
1860 $ hg help -v topic-containing-verbose
1859 This is the topic to test omit indicating.
1861 This is the topic to test omit indicating.
1860 """"""""""""""""""""""""""""""""""""""""""
1862 """"""""""""""""""""""""""""""""""""""""""
1861
1863
1862 This paragraph is never omitted (for topic).
1864 This paragraph is never omitted (for topic).
1863
1865
1864 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1866 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1865 topic)
1867 topic)
1866
1868
1867 This paragraph is never omitted, too (for topic)
1869 This paragraph is never omitted, too (for topic)
1868
1870
1869 Test section lookup
1871 Test section lookup
1870
1872
1871 $ hg help revset.merge
1873 $ hg help revset.merge
1872 "merge()"
1874 "merge()"
1873 Changeset is a merge changeset.
1875 Changeset is a merge changeset.
1874
1876
1875 $ hg help glossary.dag
1877 $ hg help glossary.dag
1876 DAG
1878 DAG
1877 The repository of changesets of a distributed version control system
1879 The repository of changesets of a distributed version control system
1878 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1880 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1879 of nodes and edges, where nodes correspond to changesets and edges
1881 of nodes and edges, where nodes correspond to changesets and edges
1880 imply a parent -> child relation. This graph can be visualized by
1882 imply a parent -> child relation. This graph can be visualized by
1881 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1883 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1882 limited by the requirement for children to have at most two parents.
1884 limited by the requirement for children to have at most two parents.
1883
1885
1884
1886
1885 $ hg help hgrc.paths
1887 $ hg help hgrc.paths
1886 "paths"
1888 "paths"
1887 -------
1889 -------
1888
1890
1889 Assigns symbolic names and behavior to repositories.
1891 Assigns symbolic names and behavior to repositories.
1890
1892
1891 Options are symbolic names defining the URL or directory that is the
1893 Options are symbolic names defining the URL or directory that is the
1892 location of the repository. Example:
1894 location of the repository. Example:
1893
1895
1894 [paths]
1896 [paths]
1895 my_server = https://example.com/my_repo
1897 my_server = https://example.com/my_repo
1896 local_path = /home/me/repo
1898 local_path = /home/me/repo
1897
1899
1898 These symbolic names can be used from the command line. To pull from
1900 These symbolic names can be used from the command line. To pull from
1899 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1901 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1900 local_path'. You can check 'hg help urls' for details about valid URLs.
1902 local_path'. You can check 'hg help urls' for details about valid URLs.
1901
1903
1902 Options containing colons (":") denote sub-options that can influence
1904 Options containing colons (":") denote sub-options that can influence
1903 behavior for that specific path. Example:
1905 behavior for that specific path. Example:
1904
1906
1905 [paths]
1907 [paths]
1906 my_server = https://example.com/my_path
1908 my_server = https://example.com/my_path
1907 my_server:pushurl = ssh://example.com/my_path
1909 my_server:pushurl = ssh://example.com/my_path
1908
1910
1909 Paths using the 'path://otherpath' scheme will inherit the sub-options
1911 Paths using the 'path://otherpath' scheme will inherit the sub-options
1910 value from the path they point to.
1912 value from the path they point to.
1911
1913
1912 The following sub-options can be defined:
1914 The following sub-options can be defined:
1913
1915
1914 "multi-urls"
1916 "multi-urls"
1915 A boolean option. When enabled the value of the '[paths]' entry will be
1917 A boolean option. When enabled the value of the '[paths]' entry will be
1916 parsed as a list and the alias will resolve to multiple destination. If
1918 parsed as a list and the alias will resolve to multiple destination. If
1917 some of the list entry use the 'path://' syntax, the suboption will be
1919 some of the list entry use the 'path://' syntax, the suboption will be
1918 inherited individually.
1920 inherited individually.
1919
1921
1920 "pushurl"
1922 "pushurl"
1921 The URL to use for push operations. If not defined, the location
1923 The URL to use for push operations. If not defined, the location
1922 defined by the path's main entry is used.
1924 defined by the path's main entry is used.
1923
1925
1924 "pushrev"
1926 "pushrev"
1925 A revset defining which revisions to push by default.
1927 A revset defining which revisions to push by default.
1926
1928
1927 When 'hg push' is executed without a "-r" argument, the revset defined
1929 When 'hg push' is executed without a "-r" argument, the revset defined
1928 by this sub-option is evaluated to determine what to push.
1930 by this sub-option is evaluated to determine what to push.
1929
1931
1930 For example, a value of "." will push the working directory's revision
1932 For example, a value of "." will push the working directory's revision
1931 by default.
1933 by default.
1932
1934
1933 Revsets specifying bookmarks will not result in the bookmark being
1935 Revsets specifying bookmarks will not result in the bookmark being
1934 pushed.
1936 pushed.
1935
1937
1936 "bookmarks.mode"
1938 "bookmarks.mode"
1937 How bookmark will be dealt during the exchange. It support the following
1939 How bookmark will be dealt during the exchange. It support the following
1938 value
1940 value
1939
1941
1940 - "default": the default behavior, local and remote bookmarks are
1942 - "default": the default behavior, local and remote bookmarks are
1941 "merged" on push/pull.
1943 "merged" on push/pull.
1942 - "mirror": when pulling, replace local bookmarks by remote bookmarks.
1944 - "mirror": when pulling, replace local bookmarks by remote bookmarks.
1943 This is useful to replicate a repository, or as an optimization.
1945 This is useful to replicate a repository, or as an optimization.
1944 - "ignore": ignore bookmarks during exchange. (This currently only
1946 - "ignore": ignore bookmarks during exchange. (This currently only
1945 affect pulling)
1947 affect pulling)
1946
1948
1947 The following special named paths exist:
1949 The following special named paths exist:
1948
1950
1949 "default"
1951 "default"
1950 The URL or directory to use when no source or remote is specified.
1952 The URL or directory to use when no source or remote is specified.
1951
1953
1952 'hg clone' will automatically define this path to the location the
1954 'hg clone' will automatically define this path to the location the
1953 repository was cloned from.
1955 repository was cloned from.
1954
1956
1955 "default-push"
1957 "default-push"
1956 (deprecated) The URL or directory for the default 'hg push' location.
1958 (deprecated) The URL or directory for the default 'hg push' location.
1957 "default:pushurl" should be used instead.
1959 "default:pushurl" should be used instead.
1958
1960
1959 $ hg help glossary.mcguffin
1961 $ hg help glossary.mcguffin
1960 abort: help section not found: glossary.mcguffin
1962 abort: help section not found: glossary.mcguffin
1961 [10]
1963 [10]
1962
1964
1963 $ hg help glossary.mc.guffin
1965 $ hg help glossary.mc.guffin
1964 abort: help section not found: glossary.mc.guffin
1966 abort: help section not found: glossary.mc.guffin
1965 [10]
1967 [10]
1966
1968
1967 $ hg help template.files
1969 $ hg help template.files
1968 files List of strings. All files modified, added, or removed by
1970 files List of strings. All files modified, added, or removed by
1969 this changeset.
1971 this changeset.
1970 files(pattern)
1972 files(pattern)
1971 All files of the current changeset matching the pattern. See
1973 All files of the current changeset matching the pattern. See
1972 'hg help patterns'.
1974 'hg help patterns'.
1973
1975
1974 Test section lookup by translated message
1976 Test section lookup by translated message
1975
1977
1976 str.lower() instead of encoding.lower(str) on translated message might
1978 str.lower() instead of encoding.lower(str) on translated message might
1977 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1979 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1978 as the second or later byte of multi-byte character.
1980 as the second or later byte of multi-byte character.
1979
1981
1980 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1982 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1981 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1983 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1982 replacement makes message meaningless.
1984 replacement makes message meaningless.
1983
1985
1984 This tests that section lookup by translated string isn't broken by
1986 This tests that section lookup by translated string isn't broken by
1985 such str.lower().
1987 such str.lower().
1986
1988
1987 $ "$PYTHON" <<EOF
1989 $ "$PYTHON" <<EOF
1988 > def escape(s):
1990 > def escape(s):
1989 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1991 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1990 > # translation of "record" in ja_JP.cp932
1992 > # translation of "record" in ja_JP.cp932
1991 > upper = b"\x8bL\x98^"
1993 > upper = b"\x8bL\x98^"
1992 > # str.lower()-ed section name should be treated as different one
1994 > # str.lower()-ed section name should be treated as different one
1993 > lower = b"\x8bl\x98^"
1995 > lower = b"\x8bl\x98^"
1994 > with open('ambiguous.py', 'wb') as fp:
1996 > with open('ambiguous.py', 'wb') as fp:
1995 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1997 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1996 > u'''summary of extension
1998 > u'''summary of extension
1997 >
1999 >
1998 > %s
2000 > %s
1999 > ----
2001 > ----
2000 >
2002 >
2001 > Upper name should show only this message
2003 > Upper name should show only this message
2002 >
2004 >
2003 > %s
2005 > %s
2004 > ----
2006 > ----
2005 >
2007 >
2006 > Lower name should show only this message
2008 > Lower name should show only this message
2007 >
2009 >
2008 > subsequent section
2010 > subsequent section
2009 > ------------------
2011 > ------------------
2010 >
2012 >
2011 > This should be hidden at 'hg help ambiguous' with section name.
2013 > This should be hidden at 'hg help ambiguous' with section name.
2012 > '''
2014 > '''
2013 > """ % (escape(upper), escape(lower)))
2015 > """ % (escape(upper), escape(lower)))
2014 > EOF
2016 > EOF
2015
2017
2016 $ cat >> $HGRCPATH <<EOF
2018 $ cat >> $HGRCPATH <<EOF
2017 > [extensions]
2019 > [extensions]
2018 > ambiguous = ./ambiguous.py
2020 > ambiguous = ./ambiguous.py
2019 > EOF
2021 > EOF
2020
2022
2021 $ "$PYTHON" <<EOF | sh
2023 $ "$PYTHON" <<EOF | sh
2022 > from mercurial.utils import procutil
2024 > from mercurial.utils import procutil
2023 > upper = b"\x8bL\x98^"
2025 > upper = b"\x8bL\x98^"
2024 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
2026 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
2025 > EOF
2027 > EOF
2026 \x8bL\x98^ (esc)
2028 \x8bL\x98^ (esc)
2027 ----
2029 ----
2028
2030
2029 Upper name should show only this message
2031 Upper name should show only this message
2030
2032
2031
2033
2032 $ "$PYTHON" <<EOF | sh
2034 $ "$PYTHON" <<EOF | sh
2033 > from mercurial.utils import procutil
2035 > from mercurial.utils import procutil
2034 > lower = b"\x8bl\x98^"
2036 > lower = b"\x8bl\x98^"
2035 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
2037 > procutil.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
2036 > EOF
2038 > EOF
2037 \x8bl\x98^ (esc)
2039 \x8bl\x98^ (esc)
2038 ----
2040 ----
2039
2041
2040 Lower name should show only this message
2042 Lower name should show only this message
2041
2043
2042
2044
2043 $ cat >> $HGRCPATH <<EOF
2045 $ cat >> $HGRCPATH <<EOF
2044 > [extensions]
2046 > [extensions]
2045 > ambiguous = !
2047 > ambiguous = !
2046 > EOF
2048 > EOF
2047
2049
2048 Show help content of disabled extensions
2050 Show help content of disabled extensions
2049
2051
2050 $ cat >> $HGRCPATH <<EOF
2052 $ cat >> $HGRCPATH <<EOF
2051 > [extensions]
2053 > [extensions]
2052 > ambiguous = !./ambiguous.py
2054 > ambiguous = !./ambiguous.py
2053 > EOF
2055 > EOF
2054 $ hg help -e ambiguous
2056 $ hg help -e ambiguous
2055 ambiguous extension - (no help text available)
2057 ambiguous extension - (no help text available)
2056
2058
2057 (use 'hg help extensions' for information on enabling extensions)
2059 (use 'hg help extensions' for information on enabling extensions)
2058
2060
2059 Test dynamic list of merge tools only shows up once
2061 Test dynamic list of merge tools only shows up once
2060 $ hg help merge-tools
2062 $ hg help merge-tools
2061 Merge Tools
2063 Merge Tools
2062 """""""""""
2064 """""""""""
2063
2065
2064 To merge files Mercurial uses merge tools.
2066 To merge files Mercurial uses merge tools.
2065
2067
2066 A merge tool combines two different versions of a file into a merged file.
2068 A merge tool combines two different versions of a file into a merged file.
2067 Merge tools are given the two files and the greatest common ancestor of
2069 Merge tools are given the two files and the greatest common ancestor of
2068 the two file versions, so they can determine the changes made on both
2070 the two file versions, so they can determine the changes made on both
2069 branches.
2071 branches.
2070
2072
2071 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
2073 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
2072 backout' and in several extensions.
2074 backout' and in several extensions.
2073
2075
2074 Usually, the merge tool tries to automatically reconcile the files by
2076 Usually, the merge tool tries to automatically reconcile the files by
2075 combining all non-overlapping changes that occurred separately in the two
2077 combining all non-overlapping changes that occurred separately in the two
2076 different evolutions of the same initial base file. Furthermore, some
2078 different evolutions of the same initial base file. Furthermore, some
2077 interactive merge programs make it easier to manually resolve conflicting
2079 interactive merge programs make it easier to manually resolve conflicting
2078 merges, either in a graphical way, or by inserting some conflict markers.
2080 merges, either in a graphical way, or by inserting some conflict markers.
2079 Mercurial does not include any interactive merge programs but relies on
2081 Mercurial does not include any interactive merge programs but relies on
2080 external tools for that.
2082 external tools for that.
2081
2083
2082 Available merge tools
2084 Available merge tools
2083 =====================
2085 =====================
2084
2086
2085 External merge tools and their properties are configured in the merge-
2087 External merge tools and their properties are configured in the merge-
2086 tools configuration section - see hgrc(5) - but they can often just be
2088 tools configuration section - see hgrc(5) - but they can often just be
2087 named by their executable.
2089 named by their executable.
2088
2090
2089 A merge tool is generally usable if its executable can be found on the
2091 A merge tool is generally usable if its executable can be found on the
2090 system and if it can handle the merge. The executable is found if it is an
2092 system and if it can handle the merge. The executable is found if it is an
2091 absolute or relative executable path or the name of an application in the
2093 absolute or relative executable path or the name of an application in the
2092 executable search path. The tool is assumed to be able to handle the merge
2094 executable search path. The tool is assumed to be able to handle the merge
2093 if it can handle symlinks if the file is a symlink, if it can handle
2095 if it can handle symlinks if the file is a symlink, if it can handle
2094 binary files if the file is binary, and if a GUI is available if the tool
2096 binary files if the file is binary, and if a GUI is available if the tool
2095 requires a GUI.
2097 requires a GUI.
2096
2098
2097 There are some internal merge tools which can be used. The internal merge
2099 There are some internal merge tools which can be used. The internal merge
2098 tools are:
2100 tools are:
2099
2101
2100 ":dump"
2102 ":dump"
2101 Creates three versions of the files to merge, containing the contents of
2103 Creates three versions of the files to merge, containing the contents of
2102 local, other and base. These files can then be used to perform a merge
2104 local, other and base. These files can then be used to perform a merge
2103 manually. If the file to be merged is named "a.txt", these files will
2105 manually. If the file to be merged is named "a.txt", these files will
2104 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
2106 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
2105 they will be placed in the same directory as "a.txt".
2107 they will be placed in the same directory as "a.txt".
2106
2108
2107 This implies premerge. Therefore, files aren't dumped, if premerge runs
2109 This implies premerge. Therefore, files aren't dumped, if premerge runs
2108 successfully. Use :forcedump to forcibly write files out.
2110 successfully. Use :forcedump to forcibly write files out.
2109
2111
2110 (actual capabilities: binary, symlink)
2112 (actual capabilities: binary, symlink)
2111
2113
2112 ":fail"
2114 ":fail"
2113 Rather than attempting to merge files that were modified on both
2115 Rather than attempting to merge files that were modified on both
2114 branches, it marks them as unresolved. The resolve command must be used
2116 branches, it marks them as unresolved. The resolve command must be used
2115 to resolve these conflicts.
2117 to resolve these conflicts.
2116
2118
2117 (actual capabilities: binary, symlink)
2119 (actual capabilities: binary, symlink)
2118
2120
2119 ":forcedump"
2121 ":forcedump"
2120 Creates three versions of the files as same as :dump, but omits
2122 Creates three versions of the files as same as :dump, but omits
2121 premerge.
2123 premerge.
2122
2124
2123 (actual capabilities: binary, symlink)
2125 (actual capabilities: binary, symlink)
2124
2126
2125 ":local"
2127 ":local"
2126 Uses the local 'p1()' version of files as the merged version.
2128 Uses the local 'p1()' version of files as the merged version.
2127
2129
2128 (actual capabilities: binary, symlink)
2130 (actual capabilities: binary, symlink)
2129
2131
2130 ":merge"
2132 ":merge"
2131 Uses the internal non-interactive simple merge algorithm for merging
2133 Uses the internal non-interactive simple merge algorithm for merging
2132 files. It will fail if there are any conflicts and leave markers in the
2134 files. It will fail if there are any conflicts and leave markers in the
2133 partially merged file. Markers will have two sections, one for each side
2135 partially merged file. Markers will have two sections, one for each side
2134 of merge.
2136 of merge.
2135
2137
2136 ":merge-local"
2138 ":merge-local"
2137 Like :merge, but resolve all conflicts non-interactively in favor of the
2139 Like :merge, but resolve all conflicts non-interactively in favor of the
2138 local 'p1()' changes.
2140 local 'p1()' changes.
2139
2141
2140 ":merge-other"
2142 ":merge-other"
2141 Like :merge, but resolve all conflicts non-interactively in favor of the
2143 Like :merge, but resolve all conflicts non-interactively in favor of the
2142 other 'p2()' changes.
2144 other 'p2()' changes.
2143
2145
2144 ":merge3"
2146 ":merge3"
2145 Uses the internal non-interactive simple merge algorithm for merging
2147 Uses the internal non-interactive simple merge algorithm for merging
2146 files. It will fail if there are any conflicts and leave markers in the
2148 files. It will fail if there are any conflicts and leave markers in the
2147 partially merged file. Marker will have three sections, one from each
2149 partially merged file. Marker will have three sections, one from each
2148 side of the merge and one for the base content.
2150 side of the merge and one for the base content.
2149
2151
2150 ":mergediff"
2152 ":mergediff"
2151 Uses the internal non-interactive simple merge algorithm for merging
2153 Uses the internal non-interactive simple merge algorithm for merging
2152 files. It will fail if there are any conflicts and leave markers in the
2154 files. It will fail if there are any conflicts and leave markers in the
2153 partially merged file. The marker will have two sections, one with the
2155 partially merged file. The marker will have two sections, one with the
2154 content from one side of the merge, and one with a diff from the base
2156 content from one side of the merge, and one with a diff from the base
2155 content to the content on the other side. (experimental)
2157 content to the content on the other side. (experimental)
2156
2158
2157 ":other"
2159 ":other"
2158 Uses the other 'p2()' version of files as the merged version.
2160 Uses the other 'p2()' version of files as the merged version.
2159
2161
2160 (actual capabilities: binary, symlink)
2162 (actual capabilities: binary, symlink)
2161
2163
2162 ":prompt"
2164 ":prompt"
2163 Asks the user which of the local 'p1()' or the other 'p2()' version to
2165 Asks the user which of the local 'p1()' or the other 'p2()' version to
2164 keep as the merged version.
2166 keep as the merged version.
2165
2167
2166 (actual capabilities: binary, symlink)
2168 (actual capabilities: binary, symlink)
2167
2169
2168 ":tagmerge"
2170 ":tagmerge"
2169 Uses the internal tag merge algorithm (experimental).
2171 Uses the internal tag merge algorithm (experimental).
2170
2172
2171 ":union"
2173 ":union"
2172 Uses the internal non-interactive simple merge algorithm for merging
2174 Uses the internal non-interactive simple merge algorithm for merging
2173 files. It will use both left and right sides for conflict regions. No
2175 files. It will use both left and right sides for conflict regions. No
2174 markers are inserted.
2176 markers are inserted.
2175
2177
2176 Internal tools are always available and do not require a GUI but will by
2178 Internal tools are always available and do not require a GUI but will by
2177 default not handle symlinks or binary files. See next section for detail
2179 default not handle symlinks or binary files. See next section for detail
2178 about "actual capabilities" described above.
2180 about "actual capabilities" described above.
2179
2181
2180 Choosing a merge tool
2182 Choosing a merge tool
2181 =====================
2183 =====================
2182
2184
2183 Mercurial uses these rules when deciding which merge tool to use:
2185 Mercurial uses these rules when deciding which merge tool to use:
2184
2186
2185 1. If a tool has been specified with the --tool option to merge or
2187 1. If a tool has been specified with the --tool option to merge or
2186 resolve, it is used. If it is the name of a tool in the merge-tools
2188 resolve, it is used. If it is the name of a tool in the merge-tools
2187 configuration, its configuration is used. Otherwise the specified tool
2189 configuration, its configuration is used. Otherwise the specified tool
2188 must be executable by the shell.
2190 must be executable by the shell.
2189 2. If the "HGMERGE" environment variable is present, its value is used and
2191 2. If the "HGMERGE" environment variable is present, its value is used and
2190 must be executable by the shell.
2192 must be executable by the shell.
2191 3. If the filename of the file to be merged matches any of the patterns in
2193 3. If the filename of the file to be merged matches any of the patterns in
2192 the merge-patterns configuration section, the first usable merge tool
2194 the merge-patterns configuration section, the first usable merge tool
2193 corresponding to a matching pattern is used.
2195 corresponding to a matching pattern is used.
2194 4. If ui.merge is set it will be considered next. If the value is not the
2196 4. If ui.merge is set it will be considered next. If the value is not the
2195 name of a configured tool, the specified value is used and must be
2197 name of a configured tool, the specified value is used and must be
2196 executable by the shell. Otherwise the named tool is used if it is
2198 executable by the shell. Otherwise the named tool is used if it is
2197 usable.
2199 usable.
2198 5. If any usable merge tools are present in the merge-tools configuration
2200 5. If any usable merge tools are present in the merge-tools configuration
2199 section, the one with the highest priority is used.
2201 section, the one with the highest priority is used.
2200 6. If a program named "hgmerge" can be found on the system, it is used -
2202 6. If a program named "hgmerge" can be found on the system, it is used -
2201 but it will by default not be used for symlinks and binary files.
2203 but it will by default not be used for symlinks and binary files.
2202 7. If the file to be merged is not binary and is not a symlink, then
2204 7. If the file to be merged is not binary and is not a symlink, then
2203 internal ":merge" is used.
2205 internal ":merge" is used.
2204 8. Otherwise, ":prompt" is used.
2206 8. Otherwise, ":prompt" is used.
2205
2207
2206 For historical reason, Mercurial treats merge tools as below while
2208 For historical reason, Mercurial treats merge tools as below while
2207 examining rules above.
2209 examining rules above.
2208
2210
2209 step specified via binary symlink
2211 step specified via binary symlink
2210 ----------------------------------
2212 ----------------------------------
2211 1. --tool o/o o/o
2213 1. --tool o/o o/o
2212 2. HGMERGE o/o o/o
2214 2. HGMERGE o/o o/o
2213 3. merge-patterns o/o(*) x/?(*)
2215 3. merge-patterns o/o(*) x/?(*)
2214 4. ui.merge x/?(*) x/?(*)
2216 4. ui.merge x/?(*) x/?(*)
2215
2217
2216 Each capability column indicates Mercurial behavior for internal/external
2218 Each capability column indicates Mercurial behavior for internal/external
2217 merge tools at examining each rule.
2219 merge tools at examining each rule.
2218
2220
2219 - "o": "assume that a tool has capability"
2221 - "o": "assume that a tool has capability"
2220 - "x": "assume that a tool does not have capability"
2222 - "x": "assume that a tool does not have capability"
2221 - "?": "check actual capability of a tool"
2223 - "?": "check actual capability of a tool"
2222
2224
2223 If "merge.strict-capability-check" configuration is true, Mercurial checks
2225 If "merge.strict-capability-check" configuration is true, Mercurial checks
2224 capabilities of merge tools strictly in (*) cases above (= each capability
2226 capabilities of merge tools strictly in (*) cases above (= each capability
2225 column becomes "?/?"). It is false by default for backward compatibility.
2227 column becomes "?/?"). It is false by default for backward compatibility.
2226
2228
2227 Note:
2229 Note:
2228 After selecting a merge program, Mercurial will by default attempt to
2230 After selecting a merge program, Mercurial will by default attempt to
2229 merge the files using a simple merge algorithm first. Only if it
2231 merge the files using a simple merge algorithm first. Only if it
2230 doesn't succeed because of conflicting changes will Mercurial actually
2232 doesn't succeed because of conflicting changes will Mercurial actually
2231 execute the merge program. Whether to use the simple merge algorithm
2233 execute the merge program. Whether to use the simple merge algorithm
2232 first can be controlled by the premerge setting of the merge tool.
2234 first can be controlled by the premerge setting of the merge tool.
2233 Premerge is enabled by default unless the file is binary or a symlink.
2235 Premerge is enabled by default unless the file is binary or a symlink.
2234
2236
2235 See the merge-tools and ui sections of hgrc(5) for details on the
2237 See the merge-tools and ui sections of hgrc(5) for details on the
2236 configuration of merge tools.
2238 configuration of merge tools.
2237
2239
2238 Compression engines listed in `hg help bundlespec`
2240 Compression engines listed in `hg help bundlespec`
2239
2241
2240 $ hg help bundlespec | grep gzip
2242 $ hg help bundlespec | grep gzip
2241 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2243 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2242 An algorithm that produces smaller bundles than "gzip".
2244 An algorithm that produces smaller bundles than "gzip".
2243 This engine will likely produce smaller bundles than "gzip" but will be
2245 This engine will likely produce smaller bundles than "gzip" but will be
2244 "gzip"
2246 "gzip"
2245 better compression than "gzip". It also frequently yields better (?)
2247 better compression than "gzip". It also frequently yields better (?)
2246
2248
2247 Test usage of section marks in help documents
2249 Test usage of section marks in help documents
2248
2250
2249 $ cd "$TESTDIR"/../doc
2251 $ cd "$TESTDIR"/../doc
2250 $ "$PYTHON" check-seclevel.py
2252 $ "$PYTHON" check-seclevel.py
2251 $ cd $TESTTMP
2253 $ cd $TESTTMP
2252
2254
2253 #if serve
2255 #if serve
2254
2256
2255 Test the help pages in hgweb.
2257 Test the help pages in hgweb.
2256
2258
2257 Dish up an empty repo; serve it cold.
2259 Dish up an empty repo; serve it cold.
2258
2260
2259 $ hg init "$TESTTMP/test"
2261 $ hg init "$TESTTMP/test"
2260 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2262 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2261 $ cat hg.pid >> $DAEMON_PIDS
2263 $ cat hg.pid >> $DAEMON_PIDS
2262
2264
2263 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2265 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2264 200 Script output follows
2266 200 Script output follows
2265
2267
2266 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2268 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2267 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2269 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2268 <head>
2270 <head>
2269 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2271 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2270 <meta name="robots" content="index, nofollow" />
2272 <meta name="robots" content="index, nofollow" />
2271 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2273 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2272 <script type="text/javascript" src="/static/mercurial.js"></script>
2274 <script type="text/javascript" src="/static/mercurial.js"></script>
2273
2275
2274 <title>Help: Index</title>
2276 <title>Help: Index</title>
2275 </head>
2277 </head>
2276 <body>
2278 <body>
2277
2279
2278 <div class="container">
2280 <div class="container">
2279 <div class="menu">
2281 <div class="menu">
2280 <div class="logo">
2282 <div class="logo">
2281 <a href="https://mercurial-scm.org/">
2283 <a href="https://mercurial-scm.org/">
2282 <img src="/static/hglogo.png" alt="mercurial" /></a>
2284 <img src="/static/hglogo.png" alt="mercurial" /></a>
2283 </div>
2285 </div>
2284 <ul>
2286 <ul>
2285 <li><a href="/shortlog">log</a></li>
2287 <li><a href="/shortlog">log</a></li>
2286 <li><a href="/graph">graph</a></li>
2288 <li><a href="/graph">graph</a></li>
2287 <li><a href="/tags">tags</a></li>
2289 <li><a href="/tags">tags</a></li>
2288 <li><a href="/bookmarks">bookmarks</a></li>
2290 <li><a href="/bookmarks">bookmarks</a></li>
2289 <li><a href="/branches">branches</a></li>
2291 <li><a href="/branches">branches</a></li>
2290 </ul>
2292 </ul>
2291 <ul>
2293 <ul>
2292 <li class="active">help</li>
2294 <li class="active">help</li>
2293 </ul>
2295 </ul>
2294 </div>
2296 </div>
2295
2297
2296 <div class="main">
2298 <div class="main">
2297 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2299 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2298
2300
2299 <form class="search" action="/log">
2301 <form class="search" action="/log">
2300
2302
2301 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2303 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2302 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2304 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2303 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2305 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2304 </form>
2306 </form>
2305 <table class="bigtable">
2307 <table class="bigtable">
2306 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2308 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2307
2309
2308 <tr><td>
2310 <tr><td>
2309 <a href="/help/bundlespec">
2311 <a href="/help/bundlespec">
2310 bundlespec
2312 bundlespec
2311 </a>
2313 </a>
2312 </td><td>
2314 </td><td>
2313 Bundle File Formats
2315 Bundle File Formats
2314 </td></tr>
2316 </td></tr>
2315 <tr><td>
2317 <tr><td>
2316 <a href="/help/color">
2318 <a href="/help/color">
2317 color
2319 color
2318 </a>
2320 </a>
2319 </td><td>
2321 </td><td>
2320 Colorizing Outputs
2322 Colorizing Outputs
2321 </td></tr>
2323 </td></tr>
2322 <tr><td>
2324 <tr><td>
2323 <a href="/help/config">
2325 <a href="/help/config">
2324 config
2326 config
2325 </a>
2327 </a>
2326 </td><td>
2328 </td><td>
2327 Configuration Files
2329 Configuration Files
2328 </td></tr>
2330 </td></tr>
2329 <tr><td>
2331 <tr><td>
2330 <a href="/help/dates">
2332 <a href="/help/dates">
2331 dates
2333 dates
2332 </a>
2334 </a>
2333 </td><td>
2335 </td><td>
2334 Date Formats
2336 Date Formats
2335 </td></tr>
2337 </td></tr>
2336 <tr><td>
2338 <tr><td>
2337 <a href="/help/deprecated">
2339 <a href="/help/deprecated">
2338 deprecated
2340 deprecated
2339 </a>
2341 </a>
2340 </td><td>
2342 </td><td>
2341 Deprecated Features
2343 Deprecated Features
2342 </td></tr>
2344 </td></tr>
2343 <tr><td>
2345 <tr><td>
2344 <a href="/help/diffs">
2346 <a href="/help/diffs">
2345 diffs
2347 diffs
2346 </a>
2348 </a>
2347 </td><td>
2349 </td><td>
2348 Diff Formats
2350 Diff Formats
2349 </td></tr>
2351 </td></tr>
2350 <tr><td>
2352 <tr><td>
2351 <a href="/help/environment">
2353 <a href="/help/environment">
2352 environment
2354 environment
2353 </a>
2355 </a>
2354 </td><td>
2356 </td><td>
2355 Environment Variables
2357 Environment Variables
2356 </td></tr>
2358 </td></tr>
2357 <tr><td>
2359 <tr><td>
2358 <a href="/help/evolution">
2360 <a href="/help/evolution">
2359 evolution
2361 evolution
2360 </a>
2362 </a>
2361 </td><td>
2363 </td><td>
2362 Safely rewriting history (EXPERIMENTAL)
2364 Safely rewriting history (EXPERIMENTAL)
2363 </td></tr>
2365 </td></tr>
2364 <tr><td>
2366 <tr><td>
2365 <a href="/help/extensions">
2367 <a href="/help/extensions">
2366 extensions
2368 extensions
2367 </a>
2369 </a>
2368 </td><td>
2370 </td><td>
2369 Using Additional Features
2371 Using Additional Features
2370 </td></tr>
2372 </td></tr>
2371 <tr><td>
2373 <tr><td>
2372 <a href="/help/filesets">
2374 <a href="/help/filesets">
2373 filesets
2375 filesets
2374 </a>
2376 </a>
2375 </td><td>
2377 </td><td>
2376 Specifying File Sets
2378 Specifying File Sets
2377 </td></tr>
2379 </td></tr>
2378 <tr><td>
2380 <tr><td>
2379 <a href="/help/flags">
2381 <a href="/help/flags">
2380 flags
2382 flags
2381 </a>
2383 </a>
2382 </td><td>
2384 </td><td>
2383 Command-line flags
2385 Command-line flags
2384 </td></tr>
2386 </td></tr>
2385 <tr><td>
2387 <tr><td>
2386 <a href="/help/glossary">
2388 <a href="/help/glossary">
2387 glossary
2389 glossary
2388 </a>
2390 </a>
2389 </td><td>
2391 </td><td>
2390 Glossary
2392 Glossary
2391 </td></tr>
2393 </td></tr>
2392 <tr><td>
2394 <tr><td>
2393 <a href="/help/hgignore">
2395 <a href="/help/hgignore">
2394 hgignore
2396 hgignore
2395 </a>
2397 </a>
2396 </td><td>
2398 </td><td>
2397 Syntax for Mercurial Ignore Files
2399 Syntax for Mercurial Ignore Files
2398 </td></tr>
2400 </td></tr>
2399 <tr><td>
2401 <tr><td>
2400 <a href="/help/hgweb">
2402 <a href="/help/hgweb">
2401 hgweb
2403 hgweb
2402 </a>
2404 </a>
2403 </td><td>
2405 </td><td>
2404 Configuring hgweb
2406 Configuring hgweb
2405 </td></tr>
2407 </td></tr>
2406 <tr><td>
2408 <tr><td>
2407 <a href="/help/internals">
2409 <a href="/help/internals">
2408 internals
2410 internals
2409 </a>
2411 </a>
2410 </td><td>
2412 </td><td>
2411 Technical implementation topics
2413 Technical implementation topics
2412 </td></tr>
2414 </td></tr>
2413 <tr><td>
2415 <tr><td>
2414 <a href="/help/merge-tools">
2416 <a href="/help/merge-tools">
2415 merge-tools
2417 merge-tools
2416 </a>
2418 </a>
2417 </td><td>
2419 </td><td>
2418 Merge Tools
2420 Merge Tools
2419 </td></tr>
2421 </td></tr>
2420 <tr><td>
2422 <tr><td>
2421 <a href="/help/pager">
2423 <a href="/help/pager">
2422 pager
2424 pager
2423 </a>
2425 </a>
2424 </td><td>
2426 </td><td>
2425 Pager Support
2427 Pager Support
2426 </td></tr>
2428 </td></tr>
2427 <tr><td>
2429 <tr><td>
2428 <a href="/help/patterns">
2430 <a href="/help/patterns">
2429 patterns
2431 patterns
2430 </a>
2432 </a>
2431 </td><td>
2433 </td><td>
2432 File Name Patterns
2434 File Name Patterns
2433 </td></tr>
2435 </td></tr>
2434 <tr><td>
2436 <tr><td>
2435 <a href="/help/phases">
2437 <a href="/help/phases">
2436 phases
2438 phases
2437 </a>
2439 </a>
2438 </td><td>
2440 </td><td>
2439 Working with Phases
2441 Working with Phases
2440 </td></tr>
2442 </td></tr>
2441 <tr><td>
2443 <tr><td>
2442 <a href="/help/revisions">
2444 <a href="/help/revisions">
2443 revisions
2445 revisions
2444 </a>
2446 </a>
2445 </td><td>
2447 </td><td>
2446 Specifying Revisions
2448 Specifying Revisions
2447 </td></tr>
2449 </td></tr>
2448 <tr><td>
2450 <tr><td>
2449 <a href="/help/rust">
2451 <a href="/help/rust">
2450 rust
2452 rust
2451 </a>
2453 </a>
2452 </td><td>
2454 </td><td>
2453 Rust in Mercurial
2455 Rust in Mercurial
2454 </td></tr>
2456 </td></tr>
2455 <tr><td>
2457 <tr><td>
2456 <a href="/help/scripting">
2458 <a href="/help/scripting">
2457 scripting
2459 scripting
2458 </a>
2460 </a>
2459 </td><td>
2461 </td><td>
2460 Using Mercurial from scripts and automation
2462 Using Mercurial from scripts and automation
2461 </td></tr>
2463 </td></tr>
2462 <tr><td>
2464 <tr><td>
2463 <a href="/help/subrepos">
2465 <a href="/help/subrepos">
2464 subrepos
2466 subrepos
2465 </a>
2467 </a>
2466 </td><td>
2468 </td><td>
2467 Subrepositories
2469 Subrepositories
2468 </td></tr>
2470 </td></tr>
2469 <tr><td>
2471 <tr><td>
2470 <a href="/help/templating">
2472 <a href="/help/templating">
2471 templating
2473 templating
2472 </a>
2474 </a>
2473 </td><td>
2475 </td><td>
2474 Template Usage
2476 Template Usage
2475 </td></tr>
2477 </td></tr>
2476 <tr><td>
2478 <tr><td>
2477 <a href="/help/urls">
2479 <a href="/help/urls">
2478 urls
2480 urls
2479 </a>
2481 </a>
2480 </td><td>
2482 </td><td>
2481 URL Paths
2483 URL Paths
2482 </td></tr>
2484 </td></tr>
2483 <tr><td>
2485 <tr><td>
2484 <a href="/help/topic-containing-verbose">
2486 <a href="/help/topic-containing-verbose">
2485 topic-containing-verbose
2487 topic-containing-verbose
2486 </a>
2488 </a>
2487 </td><td>
2489 </td><td>
2488 This is the topic to test omit indicating.
2490 This is the topic to test omit indicating.
2489 </td></tr>
2491 </td></tr>
2490
2492
2491
2493
2492 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2494 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2493
2495
2494 <tr><td>
2496 <tr><td>
2495 <a href="/help/abort">
2497 <a href="/help/abort">
2496 abort
2498 abort
2497 </a>
2499 </a>
2498 </td><td>
2500 </td><td>
2499 abort an unfinished operation (EXPERIMENTAL)
2501 abort an unfinished operation (EXPERIMENTAL)
2500 </td></tr>
2502 </td></tr>
2501 <tr><td>
2503 <tr><td>
2502 <a href="/help/add">
2504 <a href="/help/add">
2503 add
2505 add
2504 </a>
2506 </a>
2505 </td><td>
2507 </td><td>
2506 add the specified files on the next commit
2508 add the specified files on the next commit
2507 </td></tr>
2509 </td></tr>
2508 <tr><td>
2510 <tr><td>
2509 <a href="/help/annotate">
2511 <a href="/help/annotate">
2510 annotate
2512 annotate
2511 </a>
2513 </a>
2512 </td><td>
2514 </td><td>
2513 show changeset information by line for each file
2515 show changeset information by line for each file
2514 </td></tr>
2516 </td></tr>
2515 <tr><td>
2517 <tr><td>
2516 <a href="/help/clone">
2518 <a href="/help/clone">
2517 clone
2519 clone
2518 </a>
2520 </a>
2519 </td><td>
2521 </td><td>
2520 make a copy of an existing repository
2522 make a copy of an existing repository
2521 </td></tr>
2523 </td></tr>
2522 <tr><td>
2524 <tr><td>
2523 <a href="/help/commit">
2525 <a href="/help/commit">
2524 commit
2526 commit
2525 </a>
2527 </a>
2526 </td><td>
2528 </td><td>
2527 commit the specified files or all outstanding changes
2529 commit the specified files or all outstanding changes
2528 </td></tr>
2530 </td></tr>
2529 <tr><td>
2531 <tr><td>
2530 <a href="/help/continue">
2532 <a href="/help/continue">
2531 continue
2533 continue
2532 </a>
2534 </a>
2533 </td><td>
2535 </td><td>
2534 resumes an interrupted operation (EXPERIMENTAL)
2536 resumes an interrupted operation (EXPERIMENTAL)
2535 </td></tr>
2537 </td></tr>
2536 <tr><td>
2538 <tr><td>
2537 <a href="/help/diff">
2539 <a href="/help/diff">
2538 diff
2540 diff
2539 </a>
2541 </a>
2540 </td><td>
2542 </td><td>
2541 diff repository (or selected files)
2543 diff repository (or selected files)
2542 </td></tr>
2544 </td></tr>
2543 <tr><td>
2545 <tr><td>
2544 <a href="/help/export">
2546 <a href="/help/export">
2545 export
2547 export
2546 </a>
2548 </a>
2547 </td><td>
2549 </td><td>
2548 dump the header and diffs for one or more changesets
2550 dump the header and diffs for one or more changesets
2549 </td></tr>
2551 </td></tr>
2550 <tr><td>
2552 <tr><td>
2551 <a href="/help/forget">
2553 <a href="/help/forget">
2552 forget
2554 forget
2553 </a>
2555 </a>
2554 </td><td>
2556 </td><td>
2555 forget the specified files on the next commit
2557 forget the specified files on the next commit
2556 </td></tr>
2558 </td></tr>
2557 <tr><td>
2559 <tr><td>
2558 <a href="/help/init">
2560 <a href="/help/init">
2559 init
2561 init
2560 </a>
2562 </a>
2561 </td><td>
2563 </td><td>
2562 create a new repository in the given directory
2564 create a new repository in the given directory
2563 </td></tr>
2565 </td></tr>
2564 <tr><td>
2566 <tr><td>
2565 <a href="/help/log">
2567 <a href="/help/log">
2566 log
2568 log
2567 </a>
2569 </a>
2568 </td><td>
2570 </td><td>
2569 show revision history of entire repository or files
2571 show revision history of entire repository or files
2570 </td></tr>
2572 </td></tr>
2571 <tr><td>
2573 <tr><td>
2572 <a href="/help/merge">
2574 <a href="/help/merge">
2573 merge
2575 merge
2574 </a>
2576 </a>
2575 </td><td>
2577 </td><td>
2576 merge another revision into working directory
2578 merge another revision into working directory
2577 </td></tr>
2579 </td></tr>
2578 <tr><td>
2580 <tr><td>
2579 <a href="/help/pull">
2581 <a href="/help/pull">
2580 pull
2582 pull
2581 </a>
2583 </a>
2582 </td><td>
2584 </td><td>
2583 pull changes from the specified source
2585 pull changes from the specified source
2584 </td></tr>
2586 </td></tr>
2585 <tr><td>
2587 <tr><td>
2586 <a href="/help/push">
2588 <a href="/help/push">
2587 push
2589 push
2588 </a>
2590 </a>
2589 </td><td>
2591 </td><td>
2590 push changes to the specified destination
2592 push changes to the specified destination
2591 </td></tr>
2593 </td></tr>
2592 <tr><td>
2594 <tr><td>
2593 <a href="/help/remove">
2595 <a href="/help/remove">
2594 remove
2596 remove
2595 </a>
2597 </a>
2596 </td><td>
2598 </td><td>
2597 remove the specified files on the next commit
2599 remove the specified files on the next commit
2598 </td></tr>
2600 </td></tr>
2599 <tr><td>
2601 <tr><td>
2600 <a href="/help/serve">
2602 <a href="/help/serve">
2601 serve
2603 serve
2602 </a>
2604 </a>
2603 </td><td>
2605 </td><td>
2604 start stand-alone webserver
2606 start stand-alone webserver
2605 </td></tr>
2607 </td></tr>
2606 <tr><td>
2608 <tr><td>
2607 <a href="/help/status">
2609 <a href="/help/status">
2608 status
2610 status
2609 </a>
2611 </a>
2610 </td><td>
2612 </td><td>
2611 show changed files in the working directory
2613 show changed files in the working directory
2612 </td></tr>
2614 </td></tr>
2613 <tr><td>
2615 <tr><td>
2614 <a href="/help/summary">
2616 <a href="/help/summary">
2615 summary
2617 summary
2616 </a>
2618 </a>
2617 </td><td>
2619 </td><td>
2618 summarize working directory state
2620 summarize working directory state
2619 </td></tr>
2621 </td></tr>
2620 <tr><td>
2622 <tr><td>
2621 <a href="/help/update">
2623 <a href="/help/update">
2622 update
2624 update
2623 </a>
2625 </a>
2624 </td><td>
2626 </td><td>
2625 update working directory (or switch revisions)
2627 update working directory (or switch revisions)
2626 </td></tr>
2628 </td></tr>
2627
2629
2628
2630
2629
2631
2630 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2632 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2631
2633
2632 <tr><td>
2634 <tr><td>
2633 <a href="/help/addremove">
2635 <a href="/help/addremove">
2634 addremove
2636 addremove
2635 </a>
2637 </a>
2636 </td><td>
2638 </td><td>
2637 add all new files, delete all missing files
2639 add all new files, delete all missing files
2638 </td></tr>
2640 </td></tr>
2639 <tr><td>
2641 <tr><td>
2640 <a href="/help/archive">
2642 <a href="/help/archive">
2641 archive
2643 archive
2642 </a>
2644 </a>
2643 </td><td>
2645 </td><td>
2644 create an unversioned archive of a repository revision
2646 create an unversioned archive of a repository revision
2645 </td></tr>
2647 </td></tr>
2646 <tr><td>
2648 <tr><td>
2647 <a href="/help/backout">
2649 <a href="/help/backout">
2648 backout
2650 backout
2649 </a>
2651 </a>
2650 </td><td>
2652 </td><td>
2651 reverse effect of earlier changeset
2653 reverse effect of earlier changeset
2652 </td></tr>
2654 </td></tr>
2653 <tr><td>
2655 <tr><td>
2654 <a href="/help/bisect">
2656 <a href="/help/bisect">
2655 bisect
2657 bisect
2656 </a>
2658 </a>
2657 </td><td>
2659 </td><td>
2658 subdivision search of changesets
2660 subdivision search of changesets
2659 </td></tr>
2661 </td></tr>
2660 <tr><td>
2662 <tr><td>
2661 <a href="/help/bookmarks">
2663 <a href="/help/bookmarks">
2662 bookmarks
2664 bookmarks
2663 </a>
2665 </a>
2664 </td><td>
2666 </td><td>
2665 create a new bookmark or list existing bookmarks
2667 create a new bookmark or list existing bookmarks
2666 </td></tr>
2668 </td></tr>
2667 <tr><td>
2669 <tr><td>
2668 <a href="/help/branch">
2670 <a href="/help/branch">
2669 branch
2671 branch
2670 </a>
2672 </a>
2671 </td><td>
2673 </td><td>
2672 set or show the current branch name
2674 set or show the current branch name
2673 </td></tr>
2675 </td></tr>
2674 <tr><td>
2676 <tr><td>
2675 <a href="/help/branches">
2677 <a href="/help/branches">
2676 branches
2678 branches
2677 </a>
2679 </a>
2678 </td><td>
2680 </td><td>
2679 list repository named branches
2681 list repository named branches
2680 </td></tr>
2682 </td></tr>
2681 <tr><td>
2683 <tr><td>
2682 <a href="/help/bundle">
2684 <a href="/help/bundle">
2683 bundle
2685 bundle
2684 </a>
2686 </a>
2685 </td><td>
2687 </td><td>
2686 create a bundle file
2688 create a bundle file
2687 </td></tr>
2689 </td></tr>
2688 <tr><td>
2690 <tr><td>
2689 <a href="/help/cat">
2691 <a href="/help/cat">
2690 cat
2692 cat
2691 </a>
2693 </a>
2692 </td><td>
2694 </td><td>
2693 output the current or given revision of files
2695 output the current or given revision of files
2694 </td></tr>
2696 </td></tr>
2695 <tr><td>
2697 <tr><td>
2696 <a href="/help/config">
2698 <a href="/help/config">
2697 config
2699 config
2698 </a>
2700 </a>
2699 </td><td>
2701 </td><td>
2700 show combined config settings from all hgrc files
2702 show combined config settings from all hgrc files
2701 </td></tr>
2703 </td></tr>
2702 <tr><td>
2704 <tr><td>
2703 <a href="/help/copy">
2705 <a href="/help/copy">
2704 copy
2706 copy
2705 </a>
2707 </a>
2706 </td><td>
2708 </td><td>
2707 mark files as copied for the next commit
2709 mark files as copied for the next commit
2708 </td></tr>
2710 </td></tr>
2709 <tr><td>
2711 <tr><td>
2710 <a href="/help/files">
2712 <a href="/help/files">
2711 files
2713 files
2712 </a>
2714 </a>
2713 </td><td>
2715 </td><td>
2714 list tracked files
2716 list tracked files
2715 </td></tr>
2717 </td></tr>
2716 <tr><td>
2718 <tr><td>
2717 <a href="/help/graft">
2719 <a href="/help/graft">
2718 graft
2720 graft
2719 </a>
2721 </a>
2720 </td><td>
2722 </td><td>
2721 copy changes from other branches onto the current branch
2723 copy changes from other branches onto the current branch
2722 </td></tr>
2724 </td></tr>
2723 <tr><td>
2725 <tr><td>
2724 <a href="/help/grep">
2726 <a href="/help/grep">
2725 grep
2727 grep
2726 </a>
2728 </a>
2727 </td><td>
2729 </td><td>
2728 search for a pattern in specified files
2730 search for a pattern in specified files
2729 </td></tr>
2731 </td></tr>
2730 <tr><td>
2732 <tr><td>
2731 <a href="/help/hashelp">
2733 <a href="/help/hashelp">
2732 hashelp
2734 hashelp
2733 </a>
2735 </a>
2734 </td><td>
2736 </td><td>
2735 Extension command's help
2737 Extension command's help
2736 </td></tr>
2738 </td></tr>
2737 <tr><td>
2739 <tr><td>
2738 <a href="/help/heads">
2740 <a href="/help/heads">
2739 heads
2741 heads
2740 </a>
2742 </a>
2741 </td><td>
2743 </td><td>
2742 show branch heads
2744 show branch heads
2743 </td></tr>
2745 </td></tr>
2744 <tr><td>
2746 <tr><td>
2745 <a href="/help/help">
2747 <a href="/help/help">
2746 help
2748 help
2747 </a>
2749 </a>
2748 </td><td>
2750 </td><td>
2749 show help for a given topic or a help overview
2751 show help for a given topic or a help overview
2750 </td></tr>
2752 </td></tr>
2751 <tr><td>
2753 <tr><td>
2752 <a href="/help/hgalias">
2754 <a href="/help/hgalias">
2753 hgalias
2755 hgalias
2754 </a>
2756 </a>
2755 </td><td>
2757 </td><td>
2756 My doc
2758 My doc
2757 </td></tr>
2759 </td></tr>
2758 <tr><td>
2760 <tr><td>
2759 <a href="/help/hgaliasnodoc">
2761 <a href="/help/hgaliasnodoc">
2760 hgaliasnodoc
2762 hgaliasnodoc
2761 </a>
2763 </a>
2762 </td><td>
2764 </td><td>
2763 summarize working directory state
2765 summarize working directory state
2764 </td></tr>
2766 </td></tr>
2765 <tr><td>
2767 <tr><td>
2766 <a href="/help/identify">
2768 <a href="/help/identify">
2767 identify
2769 identify
2768 </a>
2770 </a>
2769 </td><td>
2771 </td><td>
2770 identify the working directory or specified revision
2772 identify the working directory or specified revision
2771 </td></tr>
2773 </td></tr>
2772 <tr><td>
2774 <tr><td>
2773 <a href="/help/import">
2775 <a href="/help/import">
2774 import
2776 import
2775 </a>
2777 </a>
2776 </td><td>
2778 </td><td>
2777 import an ordered set of patches
2779 import an ordered set of patches
2778 </td></tr>
2780 </td></tr>
2779 <tr><td>
2781 <tr><td>
2780 <a href="/help/incoming">
2782 <a href="/help/incoming">
2781 incoming
2783 incoming
2782 </a>
2784 </a>
2783 </td><td>
2785 </td><td>
2784 show new changesets found in source
2786 show new changesets found in source
2785 </td></tr>
2787 </td></tr>
2786 <tr><td>
2788 <tr><td>
2787 <a href="/help/manifest">
2789 <a href="/help/manifest">
2788 manifest
2790 manifest
2789 </a>
2791 </a>
2790 </td><td>
2792 </td><td>
2791 output the current or given revision of the project manifest
2793 output the current or given revision of the project manifest
2792 </td></tr>
2794 </td></tr>
2793 <tr><td>
2795 <tr><td>
2794 <a href="/help/nohelp">
2796 <a href="/help/nohelp">
2795 nohelp
2797 nohelp
2796 </a>
2798 </a>
2797 </td><td>
2799 </td><td>
2798 (no help text available)
2800 (no help text available)
2799 </td></tr>
2801 </td></tr>
2800 <tr><td>
2802 <tr><td>
2801 <a href="/help/outgoing">
2803 <a href="/help/outgoing">
2802 outgoing
2804 outgoing
2803 </a>
2805 </a>
2804 </td><td>
2806 </td><td>
2805 show changesets not found in the destination
2807 show changesets not found in the destination
2806 </td></tr>
2808 </td></tr>
2807 <tr><td>
2809 <tr><td>
2808 <a href="/help/paths">
2810 <a href="/help/paths">
2809 paths
2811 paths
2810 </a>
2812 </a>
2811 </td><td>
2813 </td><td>
2812 show aliases for remote repositories
2814 show aliases for remote repositories
2813 </td></tr>
2815 </td></tr>
2814 <tr><td>
2816 <tr><td>
2815 <a href="/help/phase">
2817 <a href="/help/phase">
2816 phase
2818 phase
2817 </a>
2819 </a>
2818 </td><td>
2820 </td><td>
2819 set or show the current phase name
2821 set or show the current phase name
2820 </td></tr>
2822 </td></tr>
2821 <tr><td>
2823 <tr><td>
2822 <a href="/help/purge">
2824 <a href="/help/purge">
2823 purge
2825 purge
2824 </a>
2826 </a>
2825 </td><td>
2827 </td><td>
2826 removes files not tracked by Mercurial
2828 removes files not tracked by Mercurial
2827 </td></tr>
2829 </td></tr>
2828 <tr><td>
2830 <tr><td>
2829 <a href="/help/recover">
2831 <a href="/help/recover">
2830 recover
2832 recover
2831 </a>
2833 </a>
2832 </td><td>
2834 </td><td>
2833 roll back an interrupted transaction
2835 roll back an interrupted transaction
2834 </td></tr>
2836 </td></tr>
2835 <tr><td>
2837 <tr><td>
2836 <a href="/help/rename">
2838 <a href="/help/rename">
2837 rename
2839 rename
2838 </a>
2840 </a>
2839 </td><td>
2841 </td><td>
2840 rename files; equivalent of copy + remove
2842 rename files; equivalent of copy + remove
2841 </td></tr>
2843 </td></tr>
2842 <tr><td>
2844 <tr><td>
2843 <a href="/help/resolve">
2845 <a href="/help/resolve">
2844 resolve
2846 resolve
2845 </a>
2847 </a>
2846 </td><td>
2848 </td><td>
2847 redo merges or set/view the merge status of files
2849 redo merges or set/view the merge status of files
2848 </td></tr>
2850 </td></tr>
2849 <tr><td>
2851 <tr><td>
2850 <a href="/help/revert">
2852 <a href="/help/revert">
2851 revert
2853 revert
2852 </a>
2854 </a>
2853 </td><td>
2855 </td><td>
2854 restore files to their checkout state
2856 restore files to their checkout state
2855 </td></tr>
2857 </td></tr>
2856 <tr><td>
2858 <tr><td>
2857 <a href="/help/root">
2859 <a href="/help/root">
2858 root
2860 root
2859 </a>
2861 </a>
2860 </td><td>
2862 </td><td>
2861 print the root (top) of the current working directory
2863 print the root (top) of the current working directory
2862 </td></tr>
2864 </td></tr>
2863 <tr><td>
2865 <tr><td>
2864 <a href="/help/shellalias">
2866 <a href="/help/shellalias">
2865 shellalias
2867 shellalias
2866 </a>
2868 </a>
2867 </td><td>
2869 </td><td>
2868 (no help text available)
2870 (no help text available)
2869 </td></tr>
2871 </td></tr>
2870 <tr><td>
2872 <tr><td>
2871 <a href="/help/shelve">
2873 <a href="/help/shelve">
2872 shelve
2874 shelve
2873 </a>
2875 </a>
2874 </td><td>
2876 </td><td>
2875 save and set aside changes from the working directory
2877 save and set aside changes from the working directory
2876 </td></tr>
2878 </td></tr>
2877 <tr><td>
2879 <tr><td>
2878 <a href="/help/tag">
2880 <a href="/help/tag">
2879 tag
2881 tag
2880 </a>
2882 </a>
2881 </td><td>
2883 </td><td>
2882 add one or more tags for the current or given revision
2884 add one or more tags for the current or given revision
2883 </td></tr>
2885 </td></tr>
2884 <tr><td>
2886 <tr><td>
2885 <a href="/help/tags">
2887 <a href="/help/tags">
2886 tags
2888 tags
2887 </a>
2889 </a>
2888 </td><td>
2890 </td><td>
2889 list repository tags
2891 list repository tags
2890 </td></tr>
2892 </td></tr>
2891 <tr><td>
2893 <tr><td>
2892 <a href="/help/unbundle">
2894 <a href="/help/unbundle">
2893 unbundle
2895 unbundle
2894 </a>
2896 </a>
2895 </td><td>
2897 </td><td>
2896 apply one or more bundle files
2898 apply one or more bundle files
2897 </td></tr>
2899 </td></tr>
2898 <tr><td>
2900 <tr><td>
2899 <a href="/help/unshelve">
2901 <a href="/help/unshelve">
2900 unshelve
2902 unshelve
2901 </a>
2903 </a>
2902 </td><td>
2904 </td><td>
2903 restore a shelved change to the working directory
2905 restore a shelved change to the working directory
2904 </td></tr>
2906 </td></tr>
2905 <tr><td>
2907 <tr><td>
2906 <a href="/help/verify">
2908 <a href="/help/verify">
2907 verify
2909 verify
2908 </a>
2910 </a>
2909 </td><td>
2911 </td><td>
2910 verify the integrity of the repository
2912 verify the integrity of the repository
2911 </td></tr>
2913 </td></tr>
2912 <tr><td>
2914 <tr><td>
2913 <a href="/help/version">
2915 <a href="/help/version">
2914 version
2916 version
2915 </a>
2917 </a>
2916 </td><td>
2918 </td><td>
2917 output version and copyright information
2919 output version and copyright information
2918 </td></tr>
2920 </td></tr>
2919
2921
2920
2922
2921 </table>
2923 </table>
2922 </div>
2924 </div>
2923 </div>
2925 </div>
2924
2926
2925
2927
2926
2928
2927 </body>
2929 </body>
2928 </html>
2930 </html>
2929
2931
2930
2932
2931 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2933 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2932 200 Script output follows
2934 200 Script output follows
2933
2935
2934 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2936 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2935 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2937 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2936 <head>
2938 <head>
2937 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2939 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2938 <meta name="robots" content="index, nofollow" />
2940 <meta name="robots" content="index, nofollow" />
2939 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2941 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2940 <script type="text/javascript" src="/static/mercurial.js"></script>
2942 <script type="text/javascript" src="/static/mercurial.js"></script>
2941
2943
2942 <title>Help: add</title>
2944 <title>Help: add</title>
2943 </head>
2945 </head>
2944 <body>
2946 <body>
2945
2947
2946 <div class="container">
2948 <div class="container">
2947 <div class="menu">
2949 <div class="menu">
2948 <div class="logo">
2950 <div class="logo">
2949 <a href="https://mercurial-scm.org/">
2951 <a href="https://mercurial-scm.org/">
2950 <img src="/static/hglogo.png" alt="mercurial" /></a>
2952 <img src="/static/hglogo.png" alt="mercurial" /></a>
2951 </div>
2953 </div>
2952 <ul>
2954 <ul>
2953 <li><a href="/shortlog">log</a></li>
2955 <li><a href="/shortlog">log</a></li>
2954 <li><a href="/graph">graph</a></li>
2956 <li><a href="/graph">graph</a></li>
2955 <li><a href="/tags">tags</a></li>
2957 <li><a href="/tags">tags</a></li>
2956 <li><a href="/bookmarks">bookmarks</a></li>
2958 <li><a href="/bookmarks">bookmarks</a></li>
2957 <li><a href="/branches">branches</a></li>
2959 <li><a href="/branches">branches</a></li>
2958 </ul>
2960 </ul>
2959 <ul>
2961 <ul>
2960 <li class="active"><a href="/help">help</a></li>
2962 <li class="active"><a href="/help">help</a></li>
2961 </ul>
2963 </ul>
2962 </div>
2964 </div>
2963
2965
2964 <div class="main">
2966 <div class="main">
2965 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2967 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2966 <h3>Help: add</h3>
2968 <h3>Help: add</h3>
2967
2969
2968 <form class="search" action="/log">
2970 <form class="search" action="/log">
2969
2971
2970 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2972 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2971 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2973 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2972 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2974 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2973 </form>
2975 </form>
2974 <div id="doc">
2976 <div id="doc">
2975 <p>
2977 <p>
2976 hg add [OPTION]... [FILE]...
2978 hg add [OPTION]... [FILE]...
2977 </p>
2979 </p>
2978 <p>
2980 <p>
2979 add the specified files on the next commit
2981 add the specified files on the next commit
2980 </p>
2982 </p>
2981 <p>
2983 <p>
2982 Schedule files to be version controlled and added to the
2984 Schedule files to be version controlled and added to the
2983 repository.
2985 repository.
2984 </p>
2986 </p>
2985 <p>
2987 <p>
2986 The files will be added to the repository at the next commit. To
2988 The files will be added to the repository at the next commit. To
2987 undo an add before that, see 'hg forget'.
2989 undo an add before that, see 'hg forget'.
2988 </p>
2990 </p>
2989 <p>
2991 <p>
2990 If no names are given, add all files to the repository (except
2992 If no names are given, add all files to the repository (except
2991 files matching &quot;.hgignore&quot;).
2993 files matching &quot;.hgignore&quot;).
2992 </p>
2994 </p>
2993 <p>
2995 <p>
2994 Examples:
2996 Examples:
2995 </p>
2997 </p>
2996 <ul>
2998 <ul>
2997 <li> New (unknown) files are added automatically by 'hg add':
2999 <li> New (unknown) files are added automatically by 'hg add':
2998 <pre>
3000 <pre>
2999 \$ ls (re)
3001 \$ ls (re)
3000 foo.c
3002 foo.c
3001 \$ hg status (re)
3003 \$ hg status (re)
3002 ? foo.c
3004 ? foo.c
3003 \$ hg add (re)
3005 \$ hg add (re)
3004 adding foo.c
3006 adding foo.c
3005 \$ hg status (re)
3007 \$ hg status (re)
3006 A foo.c
3008 A foo.c
3007 </pre>
3009 </pre>
3008 <li> Specific files to be added can be specified:
3010 <li> Specific files to be added can be specified:
3009 <pre>
3011 <pre>
3010 \$ ls (re)
3012 \$ ls (re)
3011 bar.c foo.c
3013 bar.c foo.c
3012 \$ hg status (re)
3014 \$ hg status (re)
3013 ? bar.c
3015 ? bar.c
3014 ? foo.c
3016 ? foo.c
3015 \$ hg add bar.c (re)
3017 \$ hg add bar.c (re)
3016 \$ hg status (re)
3018 \$ hg status (re)
3017 A bar.c
3019 A bar.c
3018 ? foo.c
3020 ? foo.c
3019 </pre>
3021 </pre>
3020 </ul>
3022 </ul>
3021 <p>
3023 <p>
3022 Returns 0 if all files are successfully added.
3024 Returns 0 if all files are successfully added.
3023 </p>
3025 </p>
3024 <p>
3026 <p>
3025 options ([+] can be repeated):
3027 options ([+] can be repeated):
3026 </p>
3028 </p>
3027 <table>
3029 <table>
3028 <tr><td>-I</td>
3030 <tr><td>-I</td>
3029 <td>--include PATTERN [+]</td>
3031 <td>--include PATTERN [+]</td>
3030 <td>include names matching the given patterns</td></tr>
3032 <td>include names matching the given patterns</td></tr>
3031 <tr><td>-X</td>
3033 <tr><td>-X</td>
3032 <td>--exclude PATTERN [+]</td>
3034 <td>--exclude PATTERN [+]</td>
3033 <td>exclude names matching the given patterns</td></tr>
3035 <td>exclude names matching the given patterns</td></tr>
3034 <tr><td>-S</td>
3036 <tr><td>-S</td>
3035 <td>--subrepos</td>
3037 <td>--subrepos</td>
3036 <td>recurse into subrepositories</td></tr>
3038 <td>recurse into subrepositories</td></tr>
3037 <tr><td>-n</td>
3039 <tr><td>-n</td>
3038 <td>--dry-run</td>
3040 <td>--dry-run</td>
3039 <td>do not perform actions, just print output</td></tr>
3041 <td>do not perform actions, just print output</td></tr>
3040 </table>
3042 </table>
3041 <p>
3043 <p>
3042 global options ([+] can be repeated):
3044 global options ([+] can be repeated):
3043 </p>
3045 </p>
3044 <table>
3046 <table>
3045 <tr><td>-R</td>
3047 <tr><td>-R</td>
3046 <td>--repository REPO</td>
3048 <td>--repository REPO</td>
3047 <td>repository root directory or name of overlay bundle file</td></tr>
3049 <td>repository root directory or name of overlay bundle file</td></tr>
3048 <tr><td></td>
3050 <tr><td></td>
3049 <td>--cwd DIR</td>
3051 <td>--cwd DIR</td>
3050 <td>change working directory</td></tr>
3052 <td>change working directory</td></tr>
3051 <tr><td>-y</td>
3053 <tr><td>-y</td>
3052 <td>--noninteractive</td>
3054 <td>--noninteractive</td>
3053 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3055 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3054 <tr><td>-q</td>
3056 <tr><td>-q</td>
3055 <td>--quiet</td>
3057 <td>--quiet</td>
3056 <td>suppress output</td></tr>
3058 <td>suppress output</td></tr>
3057 <tr><td>-v</td>
3059 <tr><td>-v</td>
3058 <td>--verbose</td>
3060 <td>--verbose</td>
3059 <td>enable additional output</td></tr>
3061 <td>enable additional output</td></tr>
3060 <tr><td></td>
3062 <tr><td></td>
3061 <td>--color TYPE</td>
3063 <td>--color TYPE</td>
3062 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3064 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3063 <tr><td></td>
3065 <tr><td></td>
3064 <td>--config CONFIG [+]</td>
3066 <td>--config CONFIG [+]</td>
3065 <td>set/override config option (use 'section.name=value')</td></tr>
3067 <td>set/override config option (use 'section.name=value')</td></tr>
3066 <tr><td></td>
3068 <tr><td></td>
3067 <td>--debug</td>
3069 <td>--debug</td>
3068 <td>enable debugging output</td></tr>
3070 <td>enable debugging output</td></tr>
3069 <tr><td></td>
3071 <tr><td></td>
3070 <td>--debugger</td>
3072 <td>--debugger</td>
3071 <td>start debugger</td></tr>
3073 <td>start debugger</td></tr>
3072 <tr><td></td>
3074 <tr><td></td>
3073 <td>--encoding ENCODE</td>
3075 <td>--encoding ENCODE</td>
3074 <td>set the charset encoding (default: ascii)</td></tr>
3076 <td>set the charset encoding (default: ascii)</td></tr>
3075 <tr><td></td>
3077 <tr><td></td>
3076 <td>--encodingmode MODE</td>
3078 <td>--encodingmode MODE</td>
3077 <td>set the charset encoding mode (default: strict)</td></tr>
3079 <td>set the charset encoding mode (default: strict)</td></tr>
3078 <tr><td></td>
3080 <tr><td></td>
3079 <td>--traceback</td>
3081 <td>--traceback</td>
3080 <td>always print a traceback on exception</td></tr>
3082 <td>always print a traceback on exception</td></tr>
3081 <tr><td></td>
3083 <tr><td></td>
3082 <td>--time</td>
3084 <td>--time</td>
3083 <td>time how long the command takes</td></tr>
3085 <td>time how long the command takes</td></tr>
3084 <tr><td></td>
3086 <tr><td></td>
3085 <td>--profile</td>
3087 <td>--profile</td>
3086 <td>print command execution profile</td></tr>
3088 <td>print command execution profile</td></tr>
3087 <tr><td></td>
3089 <tr><td></td>
3088 <td>--version</td>
3090 <td>--version</td>
3089 <td>output version information and exit</td></tr>
3091 <td>output version information and exit</td></tr>
3090 <tr><td>-h</td>
3092 <tr><td>-h</td>
3091 <td>--help</td>
3093 <td>--help</td>
3092 <td>display help and exit</td></tr>
3094 <td>display help and exit</td></tr>
3093 <tr><td></td>
3095 <tr><td></td>
3094 <td>--hidden</td>
3096 <td>--hidden</td>
3095 <td>consider hidden changesets</td></tr>
3097 <td>consider hidden changesets</td></tr>
3096 <tr><td></td>
3098 <tr><td></td>
3097 <td>--pager TYPE</td>
3099 <td>--pager TYPE</td>
3098 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3100 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3099 </table>
3101 </table>
3100
3102
3101 </div>
3103 </div>
3102 </div>
3104 </div>
3103 </div>
3105 </div>
3104
3106
3105
3107
3106
3108
3107 </body>
3109 </body>
3108 </html>
3110 </html>
3109
3111
3110
3112
3111 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
3113 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
3112 200 Script output follows
3114 200 Script output follows
3113
3115
3114 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3116 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3115 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3117 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3116 <head>
3118 <head>
3117 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3119 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3118 <meta name="robots" content="index, nofollow" />
3120 <meta name="robots" content="index, nofollow" />
3119 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3121 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3120 <script type="text/javascript" src="/static/mercurial.js"></script>
3122 <script type="text/javascript" src="/static/mercurial.js"></script>
3121
3123
3122 <title>Help: remove</title>
3124 <title>Help: remove</title>
3123 </head>
3125 </head>
3124 <body>
3126 <body>
3125
3127
3126 <div class="container">
3128 <div class="container">
3127 <div class="menu">
3129 <div class="menu">
3128 <div class="logo">
3130 <div class="logo">
3129 <a href="https://mercurial-scm.org/">
3131 <a href="https://mercurial-scm.org/">
3130 <img src="/static/hglogo.png" alt="mercurial" /></a>
3132 <img src="/static/hglogo.png" alt="mercurial" /></a>
3131 </div>
3133 </div>
3132 <ul>
3134 <ul>
3133 <li><a href="/shortlog">log</a></li>
3135 <li><a href="/shortlog">log</a></li>
3134 <li><a href="/graph">graph</a></li>
3136 <li><a href="/graph">graph</a></li>
3135 <li><a href="/tags">tags</a></li>
3137 <li><a href="/tags">tags</a></li>
3136 <li><a href="/bookmarks">bookmarks</a></li>
3138 <li><a href="/bookmarks">bookmarks</a></li>
3137 <li><a href="/branches">branches</a></li>
3139 <li><a href="/branches">branches</a></li>
3138 </ul>
3140 </ul>
3139 <ul>
3141 <ul>
3140 <li class="active"><a href="/help">help</a></li>
3142 <li class="active"><a href="/help">help</a></li>
3141 </ul>
3143 </ul>
3142 </div>
3144 </div>
3143
3145
3144 <div class="main">
3146 <div class="main">
3145 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3147 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3146 <h3>Help: remove</h3>
3148 <h3>Help: remove</h3>
3147
3149
3148 <form class="search" action="/log">
3150 <form class="search" action="/log">
3149
3151
3150 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3152 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3151 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3153 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3152 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3154 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3153 </form>
3155 </form>
3154 <div id="doc">
3156 <div id="doc">
3155 <p>
3157 <p>
3156 hg remove [OPTION]... FILE...
3158 hg remove [OPTION]... FILE...
3157 </p>
3159 </p>
3158 <p>
3160 <p>
3159 aliases: rm
3161 aliases: rm
3160 </p>
3162 </p>
3161 <p>
3163 <p>
3162 remove the specified files on the next commit
3164 remove the specified files on the next commit
3163 </p>
3165 </p>
3164 <p>
3166 <p>
3165 Schedule the indicated files for removal from the current branch.
3167 Schedule the indicated files for removal from the current branch.
3166 </p>
3168 </p>
3167 <p>
3169 <p>
3168 This command schedules the files to be removed at the next commit.
3170 This command schedules the files to be removed at the next commit.
3169 To undo a remove before that, see 'hg revert'. To undo added
3171 To undo a remove before that, see 'hg revert'. To undo added
3170 files, see 'hg forget'.
3172 files, see 'hg forget'.
3171 </p>
3173 </p>
3172 <p>
3174 <p>
3173 -A/--after can be used to remove only files that have already
3175 -A/--after can be used to remove only files that have already
3174 been deleted, -f/--force can be used to force deletion, and -Af
3176 been deleted, -f/--force can be used to force deletion, and -Af
3175 can be used to remove files from the next revision without
3177 can be used to remove files from the next revision without
3176 deleting them from the working directory.
3178 deleting them from the working directory.
3177 </p>
3179 </p>
3178 <p>
3180 <p>
3179 The following table details the behavior of remove for different
3181 The following table details the behavior of remove for different
3180 file states (columns) and option combinations (rows). The file
3182 file states (columns) and option combinations (rows). The file
3181 states are Added [A], Clean [C], Modified [M] and Missing [!]
3183 states are Added [A], Clean [C], Modified [M] and Missing [!]
3182 (as reported by 'hg status'). The actions are Warn, Remove
3184 (as reported by 'hg status'). The actions are Warn, Remove
3183 (from branch) and Delete (from disk):
3185 (from branch) and Delete (from disk):
3184 </p>
3186 </p>
3185 <table>
3187 <table>
3186 <tr><td>opt/state</td>
3188 <tr><td>opt/state</td>
3187 <td>A</td>
3189 <td>A</td>
3188 <td>C</td>
3190 <td>C</td>
3189 <td>M</td>
3191 <td>M</td>
3190 <td>!</td></tr>
3192 <td>!</td></tr>
3191 <tr><td>none</td>
3193 <tr><td>none</td>
3192 <td>W</td>
3194 <td>W</td>
3193 <td>RD</td>
3195 <td>RD</td>
3194 <td>W</td>
3196 <td>W</td>
3195 <td>R</td></tr>
3197 <td>R</td></tr>
3196 <tr><td>-f</td>
3198 <tr><td>-f</td>
3197 <td>R</td>
3199 <td>R</td>
3198 <td>RD</td>
3200 <td>RD</td>
3199 <td>RD</td>
3201 <td>RD</td>
3200 <td>R</td></tr>
3202 <td>R</td></tr>
3201 <tr><td>-A</td>
3203 <tr><td>-A</td>
3202 <td>W</td>
3204 <td>W</td>
3203 <td>W</td>
3205 <td>W</td>
3204 <td>W</td>
3206 <td>W</td>
3205 <td>R</td></tr>
3207 <td>R</td></tr>
3206 <tr><td>-Af</td>
3208 <tr><td>-Af</td>
3207 <td>R</td>
3209 <td>R</td>
3208 <td>R</td>
3210 <td>R</td>
3209 <td>R</td>
3211 <td>R</td>
3210 <td>R</td></tr>
3212 <td>R</td></tr>
3211 </table>
3213 </table>
3212 <p>
3214 <p>
3213 <b>Note:</b>
3215 <b>Note:</b>
3214 </p>
3216 </p>
3215 <p>
3217 <p>
3216 'hg remove' never deletes files in Added [A] state from the
3218 'hg remove' never deletes files in Added [A] state from the
3217 working directory, not even if &quot;--force&quot; is specified.
3219 working directory, not even if &quot;--force&quot; is specified.
3218 </p>
3220 </p>
3219 <p>
3221 <p>
3220 Returns 0 on success, 1 if any warnings encountered.
3222 Returns 0 on success, 1 if any warnings encountered.
3221 </p>
3223 </p>
3222 <p>
3224 <p>
3223 options ([+] can be repeated):
3225 options ([+] can be repeated):
3224 </p>
3226 </p>
3225 <table>
3227 <table>
3226 <tr><td>-A</td>
3228 <tr><td>-A</td>
3227 <td>--after</td>
3229 <td>--after</td>
3228 <td>record delete for missing files</td></tr>
3230 <td>record delete for missing files</td></tr>
3229 <tr><td>-f</td>
3231 <tr><td>-f</td>
3230 <td>--force</td>
3232 <td>--force</td>
3231 <td>forget added files, delete modified files</td></tr>
3233 <td>forget added files, delete modified files</td></tr>
3232 <tr><td>-S</td>
3234 <tr><td>-S</td>
3233 <td>--subrepos</td>
3235 <td>--subrepos</td>
3234 <td>recurse into subrepositories</td></tr>
3236 <td>recurse into subrepositories</td></tr>
3235 <tr><td>-I</td>
3237 <tr><td>-I</td>
3236 <td>--include PATTERN [+]</td>
3238 <td>--include PATTERN [+]</td>
3237 <td>include names matching the given patterns</td></tr>
3239 <td>include names matching the given patterns</td></tr>
3238 <tr><td>-X</td>
3240 <tr><td>-X</td>
3239 <td>--exclude PATTERN [+]</td>
3241 <td>--exclude PATTERN [+]</td>
3240 <td>exclude names matching the given patterns</td></tr>
3242 <td>exclude names matching the given patterns</td></tr>
3241 <tr><td>-n</td>
3243 <tr><td>-n</td>
3242 <td>--dry-run</td>
3244 <td>--dry-run</td>
3243 <td>do not perform actions, just print output</td></tr>
3245 <td>do not perform actions, just print output</td></tr>
3244 </table>
3246 </table>
3245 <p>
3247 <p>
3246 global options ([+] can be repeated):
3248 global options ([+] can be repeated):
3247 </p>
3249 </p>
3248 <table>
3250 <table>
3249 <tr><td>-R</td>
3251 <tr><td>-R</td>
3250 <td>--repository REPO</td>
3252 <td>--repository REPO</td>
3251 <td>repository root directory or name of overlay bundle file</td></tr>
3253 <td>repository root directory or name of overlay bundle file</td></tr>
3252 <tr><td></td>
3254 <tr><td></td>
3253 <td>--cwd DIR</td>
3255 <td>--cwd DIR</td>
3254 <td>change working directory</td></tr>
3256 <td>change working directory</td></tr>
3255 <tr><td>-y</td>
3257 <tr><td>-y</td>
3256 <td>--noninteractive</td>
3258 <td>--noninteractive</td>
3257 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3259 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3258 <tr><td>-q</td>
3260 <tr><td>-q</td>
3259 <td>--quiet</td>
3261 <td>--quiet</td>
3260 <td>suppress output</td></tr>
3262 <td>suppress output</td></tr>
3261 <tr><td>-v</td>
3263 <tr><td>-v</td>
3262 <td>--verbose</td>
3264 <td>--verbose</td>
3263 <td>enable additional output</td></tr>
3265 <td>enable additional output</td></tr>
3264 <tr><td></td>
3266 <tr><td></td>
3265 <td>--color TYPE</td>
3267 <td>--color TYPE</td>
3266 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3268 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3267 <tr><td></td>
3269 <tr><td></td>
3268 <td>--config CONFIG [+]</td>
3270 <td>--config CONFIG [+]</td>
3269 <td>set/override config option (use 'section.name=value')</td></tr>
3271 <td>set/override config option (use 'section.name=value')</td></tr>
3270 <tr><td></td>
3272 <tr><td></td>
3271 <td>--debug</td>
3273 <td>--debug</td>
3272 <td>enable debugging output</td></tr>
3274 <td>enable debugging output</td></tr>
3273 <tr><td></td>
3275 <tr><td></td>
3274 <td>--debugger</td>
3276 <td>--debugger</td>
3275 <td>start debugger</td></tr>
3277 <td>start debugger</td></tr>
3276 <tr><td></td>
3278 <tr><td></td>
3277 <td>--encoding ENCODE</td>
3279 <td>--encoding ENCODE</td>
3278 <td>set the charset encoding (default: ascii)</td></tr>
3280 <td>set the charset encoding (default: ascii)</td></tr>
3279 <tr><td></td>
3281 <tr><td></td>
3280 <td>--encodingmode MODE</td>
3282 <td>--encodingmode MODE</td>
3281 <td>set the charset encoding mode (default: strict)</td></tr>
3283 <td>set the charset encoding mode (default: strict)</td></tr>
3282 <tr><td></td>
3284 <tr><td></td>
3283 <td>--traceback</td>
3285 <td>--traceback</td>
3284 <td>always print a traceback on exception</td></tr>
3286 <td>always print a traceback on exception</td></tr>
3285 <tr><td></td>
3287 <tr><td></td>
3286 <td>--time</td>
3288 <td>--time</td>
3287 <td>time how long the command takes</td></tr>
3289 <td>time how long the command takes</td></tr>
3288 <tr><td></td>
3290 <tr><td></td>
3289 <td>--profile</td>
3291 <td>--profile</td>
3290 <td>print command execution profile</td></tr>
3292 <td>print command execution profile</td></tr>
3291 <tr><td></td>
3293 <tr><td></td>
3292 <td>--version</td>
3294 <td>--version</td>
3293 <td>output version information and exit</td></tr>
3295 <td>output version information and exit</td></tr>
3294 <tr><td>-h</td>
3296 <tr><td>-h</td>
3295 <td>--help</td>
3297 <td>--help</td>
3296 <td>display help and exit</td></tr>
3298 <td>display help and exit</td></tr>
3297 <tr><td></td>
3299 <tr><td></td>
3298 <td>--hidden</td>
3300 <td>--hidden</td>
3299 <td>consider hidden changesets</td></tr>
3301 <td>consider hidden changesets</td></tr>
3300 <tr><td></td>
3302 <tr><td></td>
3301 <td>--pager TYPE</td>
3303 <td>--pager TYPE</td>
3302 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3304 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3303 </table>
3305 </table>
3304
3306
3305 </div>
3307 </div>
3306 </div>
3308 </div>
3307 </div>
3309 </div>
3308
3310
3309
3311
3310
3312
3311 </body>
3313 </body>
3312 </html>
3314 </html>
3313
3315
3314
3316
3315 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3317 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3316 200 Script output follows
3318 200 Script output follows
3317
3319
3318 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3320 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3319 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3321 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3320 <head>
3322 <head>
3321 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3323 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3322 <meta name="robots" content="index, nofollow" />
3324 <meta name="robots" content="index, nofollow" />
3323 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3325 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3324 <script type="text/javascript" src="/static/mercurial.js"></script>
3326 <script type="text/javascript" src="/static/mercurial.js"></script>
3325
3327
3326 <title>Help: dates</title>
3328 <title>Help: dates</title>
3327 </head>
3329 </head>
3328 <body>
3330 <body>
3329
3331
3330 <div class="container">
3332 <div class="container">
3331 <div class="menu">
3333 <div class="menu">
3332 <div class="logo">
3334 <div class="logo">
3333 <a href="https://mercurial-scm.org/">
3335 <a href="https://mercurial-scm.org/">
3334 <img src="/static/hglogo.png" alt="mercurial" /></a>
3336 <img src="/static/hglogo.png" alt="mercurial" /></a>
3335 </div>
3337 </div>
3336 <ul>
3338 <ul>
3337 <li><a href="/shortlog">log</a></li>
3339 <li><a href="/shortlog">log</a></li>
3338 <li><a href="/graph">graph</a></li>
3340 <li><a href="/graph">graph</a></li>
3339 <li><a href="/tags">tags</a></li>
3341 <li><a href="/tags">tags</a></li>
3340 <li><a href="/bookmarks">bookmarks</a></li>
3342 <li><a href="/bookmarks">bookmarks</a></li>
3341 <li><a href="/branches">branches</a></li>
3343 <li><a href="/branches">branches</a></li>
3342 </ul>
3344 </ul>
3343 <ul>
3345 <ul>
3344 <li class="active"><a href="/help">help</a></li>
3346 <li class="active"><a href="/help">help</a></li>
3345 </ul>
3347 </ul>
3346 </div>
3348 </div>
3347
3349
3348 <div class="main">
3350 <div class="main">
3349 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3351 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3350 <h3>Help: dates</h3>
3352 <h3>Help: dates</h3>
3351
3353
3352 <form class="search" action="/log">
3354 <form class="search" action="/log">
3353
3355
3354 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3356 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3355 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3357 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3356 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3358 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3357 </form>
3359 </form>
3358 <div id="doc">
3360 <div id="doc">
3359 <h1>Date Formats</h1>
3361 <h1>Date Formats</h1>
3360 <p>
3362 <p>
3361 Some commands allow the user to specify a date, e.g.:
3363 Some commands allow the user to specify a date, e.g.:
3362 </p>
3364 </p>
3363 <ul>
3365 <ul>
3364 <li> backout, commit, import, tag: Specify the commit date.
3366 <li> backout, commit, import, tag: Specify the commit date.
3365 <li> log, revert, update: Select revision(s) by date.
3367 <li> log, revert, update: Select revision(s) by date.
3366 </ul>
3368 </ul>
3367 <p>
3369 <p>
3368 Many date formats are valid. Here are some examples:
3370 Many date formats are valid. Here are some examples:
3369 </p>
3371 </p>
3370 <ul>
3372 <ul>
3371 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3373 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3372 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3374 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3373 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3375 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3374 <li> &quot;Dec 6&quot; (midnight)
3376 <li> &quot;Dec 6&quot; (midnight)
3375 <li> &quot;13:18&quot; (today assumed)
3377 <li> &quot;13:18&quot; (today assumed)
3376 <li> &quot;3:39&quot; (3:39AM assumed)
3378 <li> &quot;3:39&quot; (3:39AM assumed)
3377 <li> &quot;3:39pm&quot; (15:39)
3379 <li> &quot;3:39pm&quot; (15:39)
3378 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3380 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3379 <li> &quot;2006-12-6 13:18&quot;
3381 <li> &quot;2006-12-6 13:18&quot;
3380 <li> &quot;2006-12-6&quot;
3382 <li> &quot;2006-12-6&quot;
3381 <li> &quot;12-6&quot;
3383 <li> &quot;12-6&quot;
3382 <li> &quot;12/6&quot;
3384 <li> &quot;12/6&quot;
3383 <li> &quot;12/6/6&quot; (Dec 6 2006)
3385 <li> &quot;12/6/6&quot; (Dec 6 2006)
3384 <li> &quot;today&quot; (midnight)
3386 <li> &quot;today&quot; (midnight)
3385 <li> &quot;yesterday&quot; (midnight)
3387 <li> &quot;yesterday&quot; (midnight)
3386 <li> &quot;now&quot; - right now
3388 <li> &quot;now&quot; - right now
3387 </ul>
3389 </ul>
3388 <p>
3390 <p>
3389 Lastly, there is Mercurial's internal format:
3391 Lastly, there is Mercurial's internal format:
3390 </p>
3392 </p>
3391 <ul>
3393 <ul>
3392 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3394 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3393 </ul>
3395 </ul>
3394 <p>
3396 <p>
3395 This is the internal representation format for dates. The first number
3397 This is the internal representation format for dates. The first number
3396 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3398 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3397 second is the offset of the local timezone, in seconds west of UTC
3399 second is the offset of the local timezone, in seconds west of UTC
3398 (negative if the timezone is east of UTC).
3400 (negative if the timezone is east of UTC).
3399 </p>
3401 </p>
3400 <p>
3402 <p>
3401 The log command also accepts date ranges:
3403 The log command also accepts date ranges:
3402 </p>
3404 </p>
3403 <ul>
3405 <ul>
3404 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3406 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3405 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3407 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3406 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3408 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3407 <li> &quot;-DAYS&quot; - within a given number of days from today
3409 <li> &quot;-DAYS&quot; - within a given number of days from today
3408 </ul>
3410 </ul>
3409
3411
3410 </div>
3412 </div>
3411 </div>
3413 </div>
3412 </div>
3414 </div>
3413
3415
3414
3416
3415
3417
3416 </body>
3418 </body>
3417 </html>
3419 </html>
3418
3420
3419
3421
3420 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3422 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3421 200 Script output follows
3423 200 Script output follows
3422
3424
3423 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3425 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3424 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3426 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3425 <head>
3427 <head>
3426 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3428 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3427 <meta name="robots" content="index, nofollow" />
3429 <meta name="robots" content="index, nofollow" />
3428 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3430 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3429 <script type="text/javascript" src="/static/mercurial.js"></script>
3431 <script type="text/javascript" src="/static/mercurial.js"></script>
3430
3432
3431 <title>Help: pager</title>
3433 <title>Help: pager</title>
3432 </head>
3434 </head>
3433 <body>
3435 <body>
3434
3436
3435 <div class="container">
3437 <div class="container">
3436 <div class="menu">
3438 <div class="menu">
3437 <div class="logo">
3439 <div class="logo">
3438 <a href="https://mercurial-scm.org/">
3440 <a href="https://mercurial-scm.org/">
3439 <img src="/static/hglogo.png" alt="mercurial" /></a>
3441 <img src="/static/hglogo.png" alt="mercurial" /></a>
3440 </div>
3442 </div>
3441 <ul>
3443 <ul>
3442 <li><a href="/shortlog">log</a></li>
3444 <li><a href="/shortlog">log</a></li>
3443 <li><a href="/graph">graph</a></li>
3445 <li><a href="/graph">graph</a></li>
3444 <li><a href="/tags">tags</a></li>
3446 <li><a href="/tags">tags</a></li>
3445 <li><a href="/bookmarks">bookmarks</a></li>
3447 <li><a href="/bookmarks">bookmarks</a></li>
3446 <li><a href="/branches">branches</a></li>
3448 <li><a href="/branches">branches</a></li>
3447 </ul>
3449 </ul>
3448 <ul>
3450 <ul>
3449 <li class="active"><a href="/help">help</a></li>
3451 <li class="active"><a href="/help">help</a></li>
3450 </ul>
3452 </ul>
3451 </div>
3453 </div>
3452
3454
3453 <div class="main">
3455 <div class="main">
3454 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3456 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3455 <h3>Help: pager</h3>
3457 <h3>Help: pager</h3>
3456
3458
3457 <form class="search" action="/log">
3459 <form class="search" action="/log">
3458
3460
3459 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3461 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3460 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3462 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3461 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3463 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3462 </form>
3464 </form>
3463 <div id="doc">
3465 <div id="doc">
3464 <h1>Pager Support</h1>
3466 <h1>Pager Support</h1>
3465 <p>
3467 <p>
3466 Some Mercurial commands can produce a lot of output, and Mercurial will
3468 Some Mercurial commands can produce a lot of output, and Mercurial will
3467 attempt to use a pager to make those commands more pleasant.
3469 attempt to use a pager to make those commands more pleasant.
3468 </p>
3470 </p>
3469 <p>
3471 <p>
3470 To set the pager that should be used, set the application variable:
3472 To set the pager that should be used, set the application variable:
3471 </p>
3473 </p>
3472 <pre>
3474 <pre>
3473 [pager]
3475 [pager]
3474 pager = less -FRX
3476 pager = less -FRX
3475 </pre>
3477 </pre>
3476 <p>
3478 <p>
3477 If no pager is set in the user or repository configuration, Mercurial uses the
3479 If no pager is set in the user or repository configuration, Mercurial uses the
3478 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3480 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3479 or system configuration is used. If none of these are set, a default pager will
3481 or system configuration is used. If none of these are set, a default pager will
3480 be used, typically 'less' on Unix and 'more' on Windows.
3482 be used, typically 'less' on Unix and 'more' on Windows.
3481 </p>
3483 </p>
3482 <p>
3484 <p>
3483 You can disable the pager for certain commands by adding them to the
3485 You can disable the pager for certain commands by adding them to the
3484 pager.ignore list:
3486 pager.ignore list:
3485 </p>
3487 </p>
3486 <pre>
3488 <pre>
3487 [pager]
3489 [pager]
3488 ignore = version, help, update
3490 ignore = version, help, update
3489 </pre>
3491 </pre>
3490 <p>
3492 <p>
3491 To ignore global commands like 'hg version' or 'hg help', you have
3493 To ignore global commands like 'hg version' or 'hg help', you have
3492 to specify them in your user configuration file.
3494 to specify them in your user configuration file.
3493 </p>
3495 </p>
3494 <p>
3496 <p>
3495 To control whether the pager is used at all for an individual command,
3497 To control whether the pager is used at all for an individual command,
3496 you can use --pager=&lt;value&gt;:
3498 you can use --pager=&lt;value&gt;:
3497 </p>
3499 </p>
3498 <ul>
3500 <ul>
3499 <li> use as needed: 'auto'.
3501 <li> use as needed: 'auto'.
3500 <li> require the pager: 'yes' or 'on'.
3502 <li> require the pager: 'yes' or 'on'.
3501 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3503 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3502 </ul>
3504 </ul>
3503 <p>
3505 <p>
3504 To globally turn off all attempts to use a pager, set:
3506 To globally turn off all attempts to use a pager, set:
3505 </p>
3507 </p>
3506 <pre>
3508 <pre>
3507 [ui]
3509 [ui]
3508 paginate = never
3510 paginate = never
3509 </pre>
3511 </pre>
3510 <p>
3512 <p>
3511 which will prevent the pager from running.
3513 which will prevent the pager from running.
3512 </p>
3514 </p>
3513
3515
3514 </div>
3516 </div>
3515 </div>
3517 </div>
3516 </div>
3518 </div>
3517
3519
3518
3520
3519
3521
3520 </body>
3522 </body>
3521 </html>
3523 </html>
3522
3524
3523
3525
3524 Sub-topic indexes rendered properly
3526 Sub-topic indexes rendered properly
3525
3527
3526 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3528 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3527 200 Script output follows
3529 200 Script output follows
3528
3530
3529 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3531 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3530 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3532 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3531 <head>
3533 <head>
3532 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3534 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3533 <meta name="robots" content="index, nofollow" />
3535 <meta name="robots" content="index, nofollow" />
3534 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3536 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3535 <script type="text/javascript" src="/static/mercurial.js"></script>
3537 <script type="text/javascript" src="/static/mercurial.js"></script>
3536
3538
3537 <title>Help: internals</title>
3539 <title>Help: internals</title>
3538 </head>
3540 </head>
3539 <body>
3541 <body>
3540
3542
3541 <div class="container">
3543 <div class="container">
3542 <div class="menu">
3544 <div class="menu">
3543 <div class="logo">
3545 <div class="logo">
3544 <a href="https://mercurial-scm.org/">
3546 <a href="https://mercurial-scm.org/">
3545 <img src="/static/hglogo.png" alt="mercurial" /></a>
3547 <img src="/static/hglogo.png" alt="mercurial" /></a>
3546 </div>
3548 </div>
3547 <ul>
3549 <ul>
3548 <li><a href="/shortlog">log</a></li>
3550 <li><a href="/shortlog">log</a></li>
3549 <li><a href="/graph">graph</a></li>
3551 <li><a href="/graph">graph</a></li>
3550 <li><a href="/tags">tags</a></li>
3552 <li><a href="/tags">tags</a></li>
3551 <li><a href="/bookmarks">bookmarks</a></li>
3553 <li><a href="/bookmarks">bookmarks</a></li>
3552 <li><a href="/branches">branches</a></li>
3554 <li><a href="/branches">branches</a></li>
3553 </ul>
3555 </ul>
3554 <ul>
3556 <ul>
3555 <li><a href="/help">help</a></li>
3557 <li><a href="/help">help</a></li>
3556 </ul>
3558 </ul>
3557 </div>
3559 </div>
3558
3560
3559 <div class="main">
3561 <div class="main">
3560 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3562 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3561
3563
3562 <form class="search" action="/log">
3564 <form class="search" action="/log">
3563
3565
3564 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3566 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3565 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3567 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3566 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3568 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3567 </form>
3569 </form>
3568 <table class="bigtable">
3570 <table class="bigtable">
3569 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3571 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3570
3572
3571 <tr><td>
3573 <tr><td>
3572 <a href="/help/internals.bid-merge">
3574 <a href="/help/internals.bid-merge">
3573 bid-merge
3575 bid-merge
3574 </a>
3576 </a>
3575 </td><td>
3577 </td><td>
3576 Bid Merge Algorithm
3578 Bid Merge Algorithm
3577 </td></tr>
3579 </td></tr>
3578 <tr><td>
3580 <tr><td>
3579 <a href="/help/internals.bundle2">
3581 <a href="/help/internals.bundle2">
3580 bundle2
3582 bundle2
3581 </a>
3583 </a>
3582 </td><td>
3584 </td><td>
3583 Bundle2
3585 Bundle2
3584 </td></tr>
3586 </td></tr>
3585 <tr><td>
3587 <tr><td>
3586 <a href="/help/internals.bundles">
3588 <a href="/help/internals.bundles">
3587 bundles
3589 bundles
3588 </a>
3590 </a>
3589 </td><td>
3591 </td><td>
3590 Bundles
3592 Bundles
3591 </td></tr>
3593 </td></tr>
3592 <tr><td>
3594 <tr><td>
3593 <a href="/help/internals.cbor">
3595 <a href="/help/internals.cbor">
3594 cbor
3596 cbor
3595 </a>
3597 </a>
3596 </td><td>
3598 </td><td>
3597 CBOR
3599 CBOR
3598 </td></tr>
3600 </td></tr>
3599 <tr><td>
3601 <tr><td>
3600 <a href="/help/internals.censor">
3602 <a href="/help/internals.censor">
3601 censor
3603 censor
3602 </a>
3604 </a>
3603 </td><td>
3605 </td><td>
3604 Censor
3606 Censor
3605 </td></tr>
3607 </td></tr>
3606 <tr><td>
3608 <tr><td>
3607 <a href="/help/internals.changegroups">
3609 <a href="/help/internals.changegroups">
3608 changegroups
3610 changegroups
3609 </a>
3611 </a>
3610 </td><td>
3612 </td><td>
3611 Changegroups
3613 Changegroups
3612 </td></tr>
3614 </td></tr>
3613 <tr><td>
3615 <tr><td>
3614 <a href="/help/internals.config">
3616 <a href="/help/internals.config">
3615 config
3617 config
3616 </a>
3618 </a>
3617 </td><td>
3619 </td><td>
3618 Config Registrar
3620 Config Registrar
3619 </td></tr>
3621 </td></tr>
3620 <tr><td>
3622 <tr><td>
3621 <a href="/help/internals.dirstate-v2">
3623 <a href="/help/internals.dirstate-v2">
3622 dirstate-v2
3624 dirstate-v2
3623 </a>
3625 </a>
3624 </td><td>
3626 </td><td>
3625 dirstate-v2 file format
3627 dirstate-v2 file format
3626 </td></tr>
3628 </td></tr>
3627 <tr><td>
3629 <tr><td>
3628 <a href="/help/internals.extensions">
3630 <a href="/help/internals.extensions">
3629 extensions
3631 extensions
3630 </a>
3632 </a>
3631 </td><td>
3633 </td><td>
3632 Extension API
3634 Extension API
3633 </td></tr>
3635 </td></tr>
3634 <tr><td>
3636 <tr><td>
3635 <a href="/help/internals.mergestate">
3637 <a href="/help/internals.mergestate">
3636 mergestate
3638 mergestate
3637 </a>
3639 </a>
3638 </td><td>
3640 </td><td>
3639 Mergestate
3641 Mergestate
3640 </td></tr>
3642 </td></tr>
3641 <tr><td>
3643 <tr><td>
3642 <a href="/help/internals.requirements">
3644 <a href="/help/internals.requirements">
3643 requirements
3645 requirements
3644 </a>
3646 </a>
3645 </td><td>
3647 </td><td>
3646 Repository Requirements
3648 Repository Requirements
3647 </td></tr>
3649 </td></tr>
3648 <tr><td>
3650 <tr><td>
3649 <a href="/help/internals.revlogs">
3651 <a href="/help/internals.revlogs">
3650 revlogs
3652 revlogs
3651 </a>
3653 </a>
3652 </td><td>
3654 </td><td>
3653 Revision Logs
3655 Revision Logs
3654 </td></tr>
3656 </td></tr>
3655 <tr><td>
3657 <tr><td>
3656 <a href="/help/internals.wireprotocol">
3658 <a href="/help/internals.wireprotocol">
3657 wireprotocol
3659 wireprotocol
3658 </a>
3660 </a>
3659 </td><td>
3661 </td><td>
3660 Wire Protocol
3662 Wire Protocol
3661 </td></tr>
3663 </td></tr>
3662 <tr><td>
3664 <tr><td>
3663 <a href="/help/internals.wireprotocolrpc">
3665 <a href="/help/internals.wireprotocolrpc">
3664 wireprotocolrpc
3666 wireprotocolrpc
3665 </a>
3667 </a>
3666 </td><td>
3668 </td><td>
3667 Wire Protocol RPC
3669 Wire Protocol RPC
3668 </td></tr>
3670 </td></tr>
3669 <tr><td>
3671 <tr><td>
3670 <a href="/help/internals.wireprotocolv2">
3672 <a href="/help/internals.wireprotocolv2">
3671 wireprotocolv2
3673 wireprotocolv2
3672 </a>
3674 </a>
3673 </td><td>
3675 </td><td>
3674 Wire Protocol Version 2
3676 Wire Protocol Version 2
3675 </td></tr>
3677 </td></tr>
3676
3678
3677
3679
3678
3680
3679
3681
3680
3682
3681 </table>
3683 </table>
3682 </div>
3684 </div>
3683 </div>
3685 </div>
3684
3686
3685
3687
3686
3688
3687 </body>
3689 </body>
3688 </html>
3690 </html>
3689
3691
3690
3692
3691 Sub-topic topics rendered properly
3693 Sub-topic topics rendered properly
3692
3694
3693 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3695 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3694 200 Script output follows
3696 200 Script output follows
3695
3697
3696 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3698 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3697 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3699 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3698 <head>
3700 <head>
3699 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3701 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3700 <meta name="robots" content="index, nofollow" />
3702 <meta name="robots" content="index, nofollow" />
3701 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3703 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3702 <script type="text/javascript" src="/static/mercurial.js"></script>
3704 <script type="text/javascript" src="/static/mercurial.js"></script>
3703
3705
3704 <title>Help: internals.changegroups</title>
3706 <title>Help: internals.changegroups</title>
3705 </head>
3707 </head>
3706 <body>
3708 <body>
3707
3709
3708 <div class="container">
3710 <div class="container">
3709 <div class="menu">
3711 <div class="menu">
3710 <div class="logo">
3712 <div class="logo">
3711 <a href="https://mercurial-scm.org/">
3713 <a href="https://mercurial-scm.org/">
3712 <img src="/static/hglogo.png" alt="mercurial" /></a>
3714 <img src="/static/hglogo.png" alt="mercurial" /></a>
3713 </div>
3715 </div>
3714 <ul>
3716 <ul>
3715 <li><a href="/shortlog">log</a></li>
3717 <li><a href="/shortlog">log</a></li>
3716 <li><a href="/graph">graph</a></li>
3718 <li><a href="/graph">graph</a></li>
3717 <li><a href="/tags">tags</a></li>
3719 <li><a href="/tags">tags</a></li>
3718 <li><a href="/bookmarks">bookmarks</a></li>
3720 <li><a href="/bookmarks">bookmarks</a></li>
3719 <li><a href="/branches">branches</a></li>
3721 <li><a href="/branches">branches</a></li>
3720 </ul>
3722 </ul>
3721 <ul>
3723 <ul>
3722 <li class="active"><a href="/help">help</a></li>
3724 <li class="active"><a href="/help">help</a></li>
3723 </ul>
3725 </ul>
3724 </div>
3726 </div>
3725
3727
3726 <div class="main">
3728 <div class="main">
3727 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3729 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3728 <h3>Help: internals.changegroups</h3>
3730 <h3>Help: internals.changegroups</h3>
3729
3731
3730 <form class="search" action="/log">
3732 <form class="search" action="/log">
3731
3733
3732 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3734 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3733 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3735 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3734 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3736 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3735 </form>
3737 </form>
3736 <div id="doc">
3738 <div id="doc">
3737 <h1>Changegroups</h1>
3739 <h1>Changegroups</h1>
3738 <p>
3740 <p>
3739 Changegroups are representations of repository revlog data, specifically
3741 Changegroups are representations of repository revlog data, specifically
3740 the changelog data, root/flat manifest data, treemanifest data, and
3742 the changelog data, root/flat manifest data, treemanifest data, and
3741 filelogs.
3743 filelogs.
3742 </p>
3744 </p>
3743 <p>
3745 <p>
3744 There are 4 versions of changegroups: &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;. From a
3746 There are 4 versions of changegroups: &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;. From a
3745 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3747 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3746 only difference being an additional item in the *delta header*. Version
3748 only difference being an additional item in the *delta header*. Version
3747 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3749 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3748 exchanging treemanifests (enabled by setting an option on the
3750 exchanging treemanifests (enabled by setting an option on the
3749 &quot;changegroup&quot; part in the bundle2). Version &quot;4&quot; adds support for exchanging
3751 &quot;changegroup&quot; part in the bundle2). Version &quot;4&quot; adds support for exchanging
3750 sidedata (additional revision metadata not part of the digest).
3752 sidedata (additional revision metadata not part of the digest).
3751 </p>
3753 </p>
3752 <p>
3754 <p>
3753 Changegroups when not exchanging treemanifests consist of 3 logical
3755 Changegroups when not exchanging treemanifests consist of 3 logical
3754 segments:
3756 segments:
3755 </p>
3757 </p>
3756 <pre>
3758 <pre>
3757 +---------------------------------+
3759 +---------------------------------+
3758 | | | |
3760 | | | |
3759 | changeset | manifest | filelogs |
3761 | changeset | manifest | filelogs |
3760 | | | |
3762 | | | |
3761 | | | |
3763 | | | |
3762 +---------------------------------+
3764 +---------------------------------+
3763 </pre>
3765 </pre>
3764 <p>
3766 <p>
3765 When exchanging treemanifests, there are 4 logical segments:
3767 When exchanging treemanifests, there are 4 logical segments:
3766 </p>
3768 </p>
3767 <pre>
3769 <pre>
3768 +-------------------------------------------------+
3770 +-------------------------------------------------+
3769 | | | | |
3771 | | | | |
3770 | changeset | root | treemanifests | filelogs |
3772 | changeset | root | treemanifests | filelogs |
3771 | | manifest | | |
3773 | | manifest | | |
3772 | | | | |
3774 | | | | |
3773 +-------------------------------------------------+
3775 +-------------------------------------------------+
3774 </pre>
3776 </pre>
3775 <p>
3777 <p>
3776 The principle building block of each segment is a *chunk*. A *chunk*
3778 The principle building block of each segment is a *chunk*. A *chunk*
3777 is a framed piece of data:
3779 is a framed piece of data:
3778 </p>
3780 </p>
3779 <pre>
3781 <pre>
3780 +---------------------------------------+
3782 +---------------------------------------+
3781 | | |
3783 | | |
3782 | length | data |
3784 | length | data |
3783 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3785 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3784 | | |
3786 | | |
3785 +---------------------------------------+
3787 +---------------------------------------+
3786 </pre>
3788 </pre>
3787 <p>
3789 <p>
3788 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3790 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3789 integer indicating the length of the entire chunk (including the length field
3791 integer indicating the length of the entire chunk (including the length field
3790 itself).
3792 itself).
3791 </p>
3793 </p>
3792 <p>
3794 <p>
3793 There is a special case chunk that has a value of 0 for the length
3795 There is a special case chunk that has a value of 0 for the length
3794 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3796 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3795 </p>
3797 </p>
3796 <h2>Delta Groups</h2>
3798 <h2>Delta Groups</h2>
3797 <p>
3799 <p>
3798 A *delta group* expresses the content of a revlog as a series of deltas,
3800 A *delta group* expresses the content of a revlog as a series of deltas,
3799 or patches against previous revisions.
3801 or patches against previous revisions.
3800 </p>
3802 </p>
3801 <p>
3803 <p>
3802 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3804 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3803 to signal the end of the delta group:
3805 to signal the end of the delta group:
3804 </p>
3806 </p>
3805 <pre>
3807 <pre>
3806 +------------------------------------------------------------------------+
3808 +------------------------------------------------------------------------+
3807 | | | | | |
3809 | | | | | |
3808 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3810 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3809 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3811 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3810 | | | | | |
3812 | | | | | |
3811 +------------------------------------------------------------------------+
3813 +------------------------------------------------------------------------+
3812 </pre>
3814 </pre>
3813 <p>
3815 <p>
3814 Each *chunk*'s data consists of the following:
3816 Each *chunk*'s data consists of the following:
3815 </p>
3817 </p>
3816 <pre>
3818 <pre>
3817 +---------------------------------------+
3819 +---------------------------------------+
3818 | | |
3820 | | |
3819 | delta header | delta data |
3821 | delta header | delta data |
3820 | (various by version) | (various) |
3822 | (various by version) | (various) |
3821 | | |
3823 | | |
3822 +---------------------------------------+
3824 +---------------------------------------+
3823 </pre>
3825 </pre>
3824 <p>
3826 <p>
3825 The *delta data* is a series of *delta*s that describe a diff from an existing
3827 The *delta data* is a series of *delta*s that describe a diff from an existing
3826 entry (either that the recipient already has, or previously specified in the
3828 entry (either that the recipient already has, or previously specified in the
3827 bundle/changegroup).
3829 bundle/changegroup).
3828 </p>
3830 </p>
3829 <p>
3831 <p>
3830 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;
3832 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, &quot;3&quot; and &quot;4&quot;
3831 of the changegroup format.
3833 of the changegroup format.
3832 </p>
3834 </p>
3833 <p>
3835 <p>
3834 Version 1 (headerlen=80):
3836 Version 1 (headerlen=80):
3835 </p>
3837 </p>
3836 <pre>
3838 <pre>
3837 +------------------------------------------------------+
3839 +------------------------------------------------------+
3838 | | | | |
3840 | | | | |
3839 | node | p1 node | p2 node | link node |
3841 | node | p1 node | p2 node | link node |
3840 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3842 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3841 | | | | |
3843 | | | | |
3842 +------------------------------------------------------+
3844 +------------------------------------------------------+
3843 </pre>
3845 </pre>
3844 <p>
3846 <p>
3845 Version 2 (headerlen=100):
3847 Version 2 (headerlen=100):
3846 </p>
3848 </p>
3847 <pre>
3849 <pre>
3848 +------------------------------------------------------------------+
3850 +------------------------------------------------------------------+
3849 | | | | | |
3851 | | | | | |
3850 | node | p1 node | p2 node | base node | link node |
3852 | node | p1 node | p2 node | base node | link node |
3851 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3853 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3852 | | | | | |
3854 | | | | | |
3853 +------------------------------------------------------------------+
3855 +------------------------------------------------------------------+
3854 </pre>
3856 </pre>
3855 <p>
3857 <p>
3856 Version 3 (headerlen=102):
3858 Version 3 (headerlen=102):
3857 </p>
3859 </p>
3858 <pre>
3860 <pre>
3859 +------------------------------------------------------------------------------+
3861 +------------------------------------------------------------------------------+
3860 | | | | | | |
3862 | | | | | | |
3861 | node | p1 node | p2 node | base node | link node | flags |
3863 | node | p1 node | p2 node | base node | link node | flags |
3862 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3864 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3863 | | | | | | |
3865 | | | | | | |
3864 +------------------------------------------------------------------------------+
3866 +------------------------------------------------------------------------------+
3865 </pre>
3867 </pre>
3866 <p>
3868 <p>
3867 Version 4 (headerlen=103):
3869 Version 4 (headerlen=103):
3868 </p>
3870 </p>
3869 <pre>
3871 <pre>
3870 +------------------------------------------------------------------------------+----------+
3872 +------------------------------------------------------------------------------+----------+
3871 | | | | | | | |
3873 | | | | | | | |
3872 | node | p1 node | p2 node | base node | link node | flags | pflags |
3874 | node | p1 node | p2 node | base node | link node | flags | pflags |
3873 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
3875 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) | (1 byte) |
3874 | | | | | | | |
3876 | | | | | | | |
3875 +------------------------------------------------------------------------------+----------+
3877 +------------------------------------------------------------------------------+----------+
3876 </pre>
3878 </pre>
3877 <p>
3879 <p>
3878 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3880 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3879 series of *delta*s, densely packed (no separators). These deltas describe a diff
3881 series of *delta*s, densely packed (no separators). These deltas describe a diff
3880 from an existing entry (either that the recipient already has, or previously
3882 from an existing entry (either that the recipient already has, or previously
3881 specified in the bundle/changegroup). The format is described more fully in
3883 specified in the bundle/changegroup). The format is described more fully in
3882 &quot;hg help internals.bdiff&quot;, but briefly:
3884 &quot;hg help internals.bdiff&quot;, but briefly:
3883 </p>
3885 </p>
3884 <pre>
3886 <pre>
3885 +---------------------------------------------------------------+
3887 +---------------------------------------------------------------+
3886 | | | | |
3888 | | | | |
3887 | start offset | end offset | new length | content |
3889 | start offset | end offset | new length | content |
3888 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3890 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3889 | | | | |
3891 | | | | |
3890 +---------------------------------------------------------------+
3892 +---------------------------------------------------------------+
3891 </pre>
3893 </pre>
3892 <p>
3894 <p>
3893 Please note that the length field in the delta data does *not* include itself.
3895 Please note that the length field in the delta data does *not* include itself.
3894 </p>
3896 </p>
3895 <p>
3897 <p>
3896 In version 1, the delta is always applied against the previous node from
3898 In version 1, the delta is always applied against the previous node from
3897 the changegroup or the first parent if this is the first entry in the
3899 the changegroup or the first parent if this is the first entry in the
3898 changegroup.
3900 changegroup.
3899 </p>
3901 </p>
3900 <p>
3902 <p>
3901 In version 2 and up, the delta base node is encoded in the entry in the
3903 In version 2 and up, the delta base node is encoded in the entry in the
3902 changegroup. This allows the delta to be expressed against any parent,
3904 changegroup. This allows the delta to be expressed against any parent,
3903 which can result in smaller deltas and more efficient encoding of data.
3905 which can result in smaller deltas and more efficient encoding of data.
3904 </p>
3906 </p>
3905 <p>
3907 <p>
3906 The *flags* field holds bitwise flags affecting the processing of revision
3908 The *flags* field holds bitwise flags affecting the processing of revision
3907 data. The following flags are defined:
3909 data. The following flags are defined:
3908 </p>
3910 </p>
3909 <dl>
3911 <dl>
3910 <dt>32768
3912 <dt>32768
3911 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3913 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3912 <dt>16384
3914 <dt>16384
3913 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3915 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3914 <dt>8192
3916 <dt>8192
3915 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3917 <dd>Externally stored. The revision fulltext contains &quot;key:value&quot; &quot;\n&quot; delimited metadata defining an object stored elsewhere. Used by the LFS extension.
3916 <dt>4096
3918 <dt>4096
3917 <dd>Contains copy information. This revision changes files in a way that could affect copy tracing. This does *not* affect changegroup handling, but is relevant for other parts of Mercurial.
3919 <dd>Contains copy information. This revision changes files in a way that could affect copy tracing. This does *not* affect changegroup handling, but is relevant for other parts of Mercurial.
3918 </dl>
3920 </dl>
3919 <p>
3921 <p>
3920 For historical reasons, the integer values are identical to revlog version 1
3922 For historical reasons, the integer values are identical to revlog version 1
3921 per-revision storage flags and correspond to bits being set in this 2-byte
3923 per-revision storage flags and correspond to bits being set in this 2-byte
3922 field. Bits were allocated starting from the most-significant bit, hence the
3924 field. Bits were allocated starting from the most-significant bit, hence the
3923 reverse ordering and allocation of these flags.
3925 reverse ordering and allocation of these flags.
3924 </p>
3926 </p>
3925 <p>
3927 <p>
3926 The *pflags* (protocol flags) field holds bitwise flags affecting the protocol
3928 The *pflags* (protocol flags) field holds bitwise flags affecting the protocol
3927 itself. They are first in the header since they may affect the handling of the
3929 itself. They are first in the header since they may affect the handling of the
3928 rest of the fields in a future version. They are defined as such:
3930 rest of the fields in a future version. They are defined as such:
3929 </p>
3931 </p>
3930 <dl>
3932 <dl>
3931 <dt>1 indicates whether to read a chunk of sidedata (of variable length) right
3933 <dt>1 indicates whether to read a chunk of sidedata (of variable length) right
3932 <dd>after the revision flags.
3934 <dd>after the revision flags.
3933 </dl>
3935 </dl>
3934 <h2>Changeset Segment</h2>
3936 <h2>Changeset Segment</h2>
3935 <p>
3937 <p>
3936 The *changeset segment* consists of a single *delta group* holding
3938 The *changeset segment* consists of a single *delta group* holding
3937 changelog data. The *empty chunk* at the end of the *delta group* denotes
3939 changelog data. The *empty chunk* at the end of the *delta group* denotes
3938 the boundary to the *manifest segment*.
3940 the boundary to the *manifest segment*.
3939 </p>
3941 </p>
3940 <h2>Manifest Segment</h2>
3942 <h2>Manifest Segment</h2>
3941 <p>
3943 <p>
3942 The *manifest segment* consists of a single *delta group* holding manifest
3944 The *manifest segment* consists of a single *delta group* holding manifest
3943 data. If treemanifests are in use, it contains only the manifest for the
3945 data. If treemanifests are in use, it contains only the manifest for the
3944 root directory of the repository. Otherwise, it contains the entire
3946 root directory of the repository. Otherwise, it contains the entire
3945 manifest data. The *empty chunk* at the end of the *delta group* denotes
3947 manifest data. The *empty chunk* at the end of the *delta group* denotes
3946 the boundary to the next segment (either the *treemanifests segment* or the
3948 the boundary to the next segment (either the *treemanifests segment* or the
3947 *filelogs segment*, depending on version and the request options).
3949 *filelogs segment*, depending on version and the request options).
3948 </p>
3950 </p>
3949 <h3>Treemanifests Segment</h3>
3951 <h3>Treemanifests Segment</h3>
3950 <p>
3952 <p>
3951 The *treemanifests segment* only exists in changegroup version &quot;3&quot; and &quot;4&quot;,
3953 The *treemanifests segment* only exists in changegroup version &quot;3&quot; and &quot;4&quot;,
3952 and only if the 'treemanifest' param is part of the bundle2 changegroup part
3954 and only if the 'treemanifest' param is part of the bundle2 changegroup part
3953 (it is not possible to use changegroup version 3 or 4 outside of bundle2).
3955 (it is not possible to use changegroup version 3 or 4 outside of bundle2).
3954 Aside from the filenames in the *treemanifests segment* containing a
3956 Aside from the filenames in the *treemanifests segment* containing a
3955 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3957 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3956 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3958 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3957 a sub-segment with filename size 0). This denotes the boundary to the
3959 a sub-segment with filename size 0). This denotes the boundary to the
3958 *filelogs segment*.
3960 *filelogs segment*.
3959 </p>
3961 </p>
3960 <h2>Filelogs Segment</h2>
3962 <h2>Filelogs Segment</h2>
3961 <p>
3963 <p>
3962 The *filelogs segment* consists of multiple sub-segments, each
3964 The *filelogs segment* consists of multiple sub-segments, each
3963 corresponding to an individual file whose data is being described:
3965 corresponding to an individual file whose data is being described:
3964 </p>
3966 </p>
3965 <pre>
3967 <pre>
3966 +--------------------------------------------------+
3968 +--------------------------------------------------+
3967 | | | | | |
3969 | | | | | |
3968 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3970 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3969 | | | | | (4 bytes) |
3971 | | | | | (4 bytes) |
3970 | | | | | |
3972 | | | | | |
3971 +--------------------------------------------------+
3973 +--------------------------------------------------+
3972 </pre>
3974 </pre>
3973 <p>
3975 <p>
3974 The final filelog sub-segment is followed by an *empty chunk* (logically,
3976 The final filelog sub-segment is followed by an *empty chunk* (logically,
3975 a sub-segment with filename size 0). This denotes the end of the segment
3977 a sub-segment with filename size 0). This denotes the end of the segment
3976 and of the overall changegroup.
3978 and of the overall changegroup.
3977 </p>
3979 </p>
3978 <p>
3980 <p>
3979 Each filelog sub-segment consists of the following:
3981 Each filelog sub-segment consists of the following:
3980 </p>
3982 </p>
3981 <pre>
3983 <pre>
3982 +------------------------------------------------------+
3984 +------------------------------------------------------+
3983 | | | |
3985 | | | |
3984 | filename length | filename | delta group |
3986 | filename length | filename | delta group |
3985 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3987 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3986 | | | |
3988 | | | |
3987 +------------------------------------------------------+
3989 +------------------------------------------------------+
3988 </pre>
3990 </pre>
3989 <p>
3991 <p>
3990 That is, a *chunk* consisting of the filename (not terminated or padded)
3992 That is, a *chunk* consisting of the filename (not terminated or padded)
3991 followed by N chunks constituting the *delta group* for this file. The
3993 followed by N chunks constituting the *delta group* for this file. The
3992 *empty chunk* at the end of each *delta group* denotes the boundary to the
3994 *empty chunk* at the end of each *delta group* denotes the boundary to the
3993 next filelog sub-segment.
3995 next filelog sub-segment.
3994 </p>
3996 </p>
3995
3997
3996 </div>
3998 </div>
3997 </div>
3999 </div>
3998 </div>
4000 </div>
3999
4001
4000
4002
4001
4003
4002 </body>
4004 </body>
4003 </html>
4005 </html>
4004
4006
4005
4007
4006 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
4008 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
4007 404 Not Found
4009 404 Not Found
4008
4010
4009 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4011 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4010 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
4012 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
4011 <head>
4013 <head>
4012 <link rel="icon" href="/static/hgicon.png" type="image/png" />
4014 <link rel="icon" href="/static/hgicon.png" type="image/png" />
4013 <meta name="robots" content="index, nofollow" />
4015 <meta name="robots" content="index, nofollow" />
4014 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
4016 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
4015 <script type="text/javascript" src="/static/mercurial.js"></script>
4017 <script type="text/javascript" src="/static/mercurial.js"></script>
4016
4018
4017 <title>test: error</title>
4019 <title>test: error</title>
4018 </head>
4020 </head>
4019 <body>
4021 <body>
4020
4022
4021 <div class="container">
4023 <div class="container">
4022 <div class="menu">
4024 <div class="menu">
4023 <div class="logo">
4025 <div class="logo">
4024 <a href="https://mercurial-scm.org/">
4026 <a href="https://mercurial-scm.org/">
4025 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
4027 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
4026 </div>
4028 </div>
4027 <ul>
4029 <ul>
4028 <li><a href="/shortlog">log</a></li>
4030 <li><a href="/shortlog">log</a></li>
4029 <li><a href="/graph">graph</a></li>
4031 <li><a href="/graph">graph</a></li>
4030 <li><a href="/tags">tags</a></li>
4032 <li><a href="/tags">tags</a></li>
4031 <li><a href="/bookmarks">bookmarks</a></li>
4033 <li><a href="/bookmarks">bookmarks</a></li>
4032 <li><a href="/branches">branches</a></li>
4034 <li><a href="/branches">branches</a></li>
4033 </ul>
4035 </ul>
4034 <ul>
4036 <ul>
4035 <li><a href="/help">help</a></li>
4037 <li><a href="/help">help</a></li>
4036 </ul>
4038 </ul>
4037 </div>
4039 </div>
4038
4040
4039 <div class="main">
4041 <div class="main">
4040
4042
4041 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
4043 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
4042 <h3>error</h3>
4044 <h3>error</h3>
4043
4045
4044
4046
4045 <form class="search" action="/log">
4047 <form class="search" action="/log">
4046
4048
4047 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
4049 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
4048 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
4050 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
4049 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
4051 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
4050 </form>
4052 </form>
4051
4053
4052 <div class="description">
4054 <div class="description">
4053 <p>
4055 <p>
4054 An error occurred while processing your request:
4056 An error occurred while processing your request:
4055 </p>
4057 </p>
4056 <p>
4058 <p>
4057 Not Found
4059 Not Found
4058 </p>
4060 </p>
4059 </div>
4061 </div>
4060 </div>
4062 </div>
4061 </div>
4063 </div>
4062
4064
4063
4065
4064
4066
4065 </body>
4067 </body>
4066 </html>
4068 </html>
4067
4069
4068 [1]
4070 [1]
4069
4071
4070 $ killdaemons.py
4072 $ killdaemons.py
4071
4073
4072 #endif
4074 #endif
General Comments 0
You need to be logged in to leave comments. Login now