##// END OF EJS Templates
context: introduce p[12]copies() methods and debugp[12]copies commands...
Martin von Zweigbergk -
r41905:456ad0fd default draft
parent child Browse files
Show More
@@ -1,2485 +1,2551 b''
1 # context.py - changeset and file context objects for mercurial
1 # context.py - changeset and file context objects for mercurial
2 #
2 #
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import filecmp
11 import filecmp
12 import os
12 import os
13 import stat
13 import stat
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 addednodeid,
17 addednodeid,
18 hex,
18 hex,
19 modifiednodeid,
19 modifiednodeid,
20 nullid,
20 nullid,
21 nullrev,
21 nullrev,
22 short,
22 short,
23 wdirfilenodeids,
23 wdirfilenodeids,
24 wdirid,
24 wdirid,
25 )
25 )
26 from . import (
26 from . import (
27 dagop,
27 dagop,
28 encoding,
28 encoding,
29 error,
29 error,
30 fileset,
30 fileset,
31 match as matchmod,
31 match as matchmod,
32 obsolete as obsmod,
32 obsolete as obsmod,
33 patch,
33 patch,
34 pathutil,
34 pathutil,
35 phases,
35 phases,
36 pycompat,
36 pycompat,
37 repoview,
37 repoview,
38 scmutil,
38 scmutil,
39 sparse,
39 sparse,
40 subrepo,
40 subrepo,
41 subrepoutil,
41 subrepoutil,
42 util,
42 util,
43 )
43 )
44 from .utils import (
44 from .utils import (
45 dateutil,
45 dateutil,
46 stringutil,
46 stringutil,
47 )
47 )
48
48
49 propertycache = util.propertycache
49 propertycache = util.propertycache
50
50
51 class basectx(object):
51 class basectx(object):
52 """A basectx object represents the common logic for its children:
52 """A basectx object represents the common logic for its children:
53 changectx: read-only context that is already present in the repo,
53 changectx: read-only context that is already present in the repo,
54 workingctx: a context that represents the working directory and can
54 workingctx: a context that represents the working directory and can
55 be committed,
55 be committed,
56 memctx: a context that represents changes in-memory and can also
56 memctx: a context that represents changes in-memory and can also
57 be committed."""
57 be committed."""
58
58
59 def __init__(self, repo):
59 def __init__(self, repo):
60 self._repo = repo
60 self._repo = repo
61
61
62 def __bytes__(self):
62 def __bytes__(self):
63 return short(self.node())
63 return short(self.node())
64
64
65 __str__ = encoding.strmethod(__bytes__)
65 __str__ = encoding.strmethod(__bytes__)
66
66
67 def __repr__(self):
67 def __repr__(self):
68 return r"<%s %s>" % (type(self).__name__, str(self))
68 return r"<%s %s>" % (type(self).__name__, str(self))
69
69
70 def __eq__(self, other):
70 def __eq__(self, other):
71 try:
71 try:
72 return type(self) == type(other) and self._rev == other._rev
72 return type(self) == type(other) and self._rev == other._rev
73 except AttributeError:
73 except AttributeError:
74 return False
74 return False
75
75
76 def __ne__(self, other):
76 def __ne__(self, other):
77 return not (self == other)
77 return not (self == other)
78
78
79 def __contains__(self, key):
79 def __contains__(self, key):
80 return key in self._manifest
80 return key in self._manifest
81
81
82 def __getitem__(self, key):
82 def __getitem__(self, key):
83 return self.filectx(key)
83 return self.filectx(key)
84
84
85 def __iter__(self):
85 def __iter__(self):
86 return iter(self._manifest)
86 return iter(self._manifest)
87
87
88 def _buildstatusmanifest(self, status):
88 def _buildstatusmanifest(self, status):
89 """Builds a manifest that includes the given status results, if this is
89 """Builds a manifest that includes the given status results, if this is
90 a working copy context. For non-working copy contexts, it just returns
90 a working copy context. For non-working copy contexts, it just returns
91 the normal manifest."""
91 the normal manifest."""
92 return self.manifest()
92 return self.manifest()
93
93
94 def _matchstatus(self, other, match):
94 def _matchstatus(self, other, match):
95 """This internal method provides a way for child objects to override the
95 """This internal method provides a way for child objects to override the
96 match operator.
96 match operator.
97 """
97 """
98 return match
98 return match
99
99
100 def _buildstatus(self, other, s, match, listignored, listclean,
100 def _buildstatus(self, other, s, match, listignored, listclean,
101 listunknown):
101 listunknown):
102 """build a status with respect to another context"""
102 """build a status with respect to another context"""
103 # Load earliest manifest first for caching reasons. More specifically,
103 # Load earliest manifest first for caching reasons. More specifically,
104 # if you have revisions 1000 and 1001, 1001 is probably stored as a
104 # if you have revisions 1000 and 1001, 1001 is probably stored as a
105 # delta against 1000. Thus, if you read 1000 first, we'll reconstruct
105 # delta against 1000. Thus, if you read 1000 first, we'll reconstruct
106 # 1000 and cache it so that when you read 1001, we just need to apply a
106 # 1000 and cache it so that when you read 1001, we just need to apply a
107 # delta to what's in the cache. So that's one full reconstruction + one
107 # delta to what's in the cache. So that's one full reconstruction + one
108 # delta application.
108 # delta application.
109 mf2 = None
109 mf2 = None
110 if self.rev() is not None and self.rev() < other.rev():
110 if self.rev() is not None and self.rev() < other.rev():
111 mf2 = self._buildstatusmanifest(s)
111 mf2 = self._buildstatusmanifest(s)
112 mf1 = other._buildstatusmanifest(s)
112 mf1 = other._buildstatusmanifest(s)
113 if mf2 is None:
113 if mf2 is None:
114 mf2 = self._buildstatusmanifest(s)
114 mf2 = self._buildstatusmanifest(s)
115
115
116 modified, added = [], []
116 modified, added = [], []
117 removed = []
117 removed = []
118 clean = []
118 clean = []
119 deleted, unknown, ignored = s.deleted, s.unknown, s.ignored
119 deleted, unknown, ignored = s.deleted, s.unknown, s.ignored
120 deletedset = set(deleted)
120 deletedset = set(deleted)
121 d = mf1.diff(mf2, match=match, clean=listclean)
121 d = mf1.diff(mf2, match=match, clean=listclean)
122 for fn, value in d.iteritems():
122 for fn, value in d.iteritems():
123 if fn in deletedset:
123 if fn in deletedset:
124 continue
124 continue
125 if value is None:
125 if value is None:
126 clean.append(fn)
126 clean.append(fn)
127 continue
127 continue
128 (node1, flag1), (node2, flag2) = value
128 (node1, flag1), (node2, flag2) = value
129 if node1 is None:
129 if node1 is None:
130 added.append(fn)
130 added.append(fn)
131 elif node2 is None:
131 elif node2 is None:
132 removed.append(fn)
132 removed.append(fn)
133 elif flag1 != flag2:
133 elif flag1 != flag2:
134 modified.append(fn)
134 modified.append(fn)
135 elif node2 not in wdirfilenodeids:
135 elif node2 not in wdirfilenodeids:
136 # When comparing files between two commits, we save time by
136 # When comparing files between two commits, we save time by
137 # not comparing the file contents when the nodeids differ.
137 # not comparing the file contents when the nodeids differ.
138 # Note that this means we incorrectly report a reverted change
138 # Note that this means we incorrectly report a reverted change
139 # to a file as a modification.
139 # to a file as a modification.
140 modified.append(fn)
140 modified.append(fn)
141 elif self[fn].cmp(other[fn]):
141 elif self[fn].cmp(other[fn]):
142 modified.append(fn)
142 modified.append(fn)
143 else:
143 else:
144 clean.append(fn)
144 clean.append(fn)
145
145
146 if removed:
146 if removed:
147 # need to filter files if they are already reported as removed
147 # need to filter files if they are already reported as removed
148 unknown = [fn for fn in unknown if fn not in mf1 and
148 unknown = [fn for fn in unknown if fn not in mf1 and
149 (not match or match(fn))]
149 (not match or match(fn))]
150 ignored = [fn for fn in ignored if fn not in mf1 and
150 ignored = [fn for fn in ignored if fn not in mf1 and
151 (not match or match(fn))]
151 (not match or match(fn))]
152 # if they're deleted, don't report them as removed
152 # if they're deleted, don't report them as removed
153 removed = [fn for fn in removed if fn not in deletedset]
153 removed = [fn for fn in removed if fn not in deletedset]
154
154
155 return scmutil.status(modified, added, removed, deleted, unknown,
155 return scmutil.status(modified, added, removed, deleted, unknown,
156 ignored, clean)
156 ignored, clean)
157
157
158 @propertycache
158 @propertycache
159 def substate(self):
159 def substate(self):
160 return subrepoutil.state(self, self._repo.ui)
160 return subrepoutil.state(self, self._repo.ui)
161
161
162 def subrev(self, subpath):
162 def subrev(self, subpath):
163 return self.substate[subpath][1]
163 return self.substate[subpath][1]
164
164
165 def rev(self):
165 def rev(self):
166 return self._rev
166 return self._rev
167 def node(self):
167 def node(self):
168 return self._node
168 return self._node
169 def hex(self):
169 def hex(self):
170 return hex(self.node())
170 return hex(self.node())
171 def manifest(self):
171 def manifest(self):
172 return self._manifest
172 return self._manifest
173 def manifestctx(self):
173 def manifestctx(self):
174 return self._manifestctx
174 return self._manifestctx
175 def repo(self):
175 def repo(self):
176 return self._repo
176 return self._repo
177 def phasestr(self):
177 def phasestr(self):
178 return phases.phasenames[self.phase()]
178 return phases.phasenames[self.phase()]
179 def mutable(self):
179 def mutable(self):
180 return self.phase() > phases.public
180 return self.phase() > phases.public
181
181
182 def matchfileset(self, expr, badfn=None):
182 def matchfileset(self, expr, badfn=None):
183 return fileset.match(self, expr, badfn=badfn)
183 return fileset.match(self, expr, badfn=badfn)
184
184
185 def obsolete(self):
185 def obsolete(self):
186 """True if the changeset is obsolete"""
186 """True if the changeset is obsolete"""
187 return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
187 return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
188
188
189 def extinct(self):
189 def extinct(self):
190 """True if the changeset is extinct"""
190 """True if the changeset is extinct"""
191 return self.rev() in obsmod.getrevs(self._repo, 'extinct')
191 return self.rev() in obsmod.getrevs(self._repo, 'extinct')
192
192
193 def orphan(self):
193 def orphan(self):
194 """True if the changeset is not obsolete, but its ancestor is"""
194 """True if the changeset is not obsolete, but its ancestor is"""
195 return self.rev() in obsmod.getrevs(self._repo, 'orphan')
195 return self.rev() in obsmod.getrevs(self._repo, 'orphan')
196
196
197 def phasedivergent(self):
197 def phasedivergent(self):
198 """True if the changeset tries to be a successor of a public changeset
198 """True if the changeset tries to be a successor of a public changeset
199
199
200 Only non-public and non-obsolete changesets may be phase-divergent.
200 Only non-public and non-obsolete changesets may be phase-divergent.
201 """
201 """
202 return self.rev() in obsmod.getrevs(self._repo, 'phasedivergent')
202 return self.rev() in obsmod.getrevs(self._repo, 'phasedivergent')
203
203
204 def contentdivergent(self):
204 def contentdivergent(self):
205 """Is a successor of a changeset with multiple possible successor sets
205 """Is a successor of a changeset with multiple possible successor sets
206
206
207 Only non-public and non-obsolete changesets may be content-divergent.
207 Only non-public and non-obsolete changesets may be content-divergent.
208 """
208 """
209 return self.rev() in obsmod.getrevs(self._repo, 'contentdivergent')
209 return self.rev() in obsmod.getrevs(self._repo, 'contentdivergent')
210
210
211 def isunstable(self):
211 def isunstable(self):
212 """True if the changeset is either orphan, phase-divergent or
212 """True if the changeset is either orphan, phase-divergent or
213 content-divergent"""
213 content-divergent"""
214 return self.orphan() or self.phasedivergent() or self.contentdivergent()
214 return self.orphan() or self.phasedivergent() or self.contentdivergent()
215
215
216 def instabilities(self):
216 def instabilities(self):
217 """return the list of instabilities affecting this changeset.
217 """return the list of instabilities affecting this changeset.
218
218
219 Instabilities are returned as strings. possible values are:
219 Instabilities are returned as strings. possible values are:
220 - orphan,
220 - orphan,
221 - phase-divergent,
221 - phase-divergent,
222 - content-divergent.
222 - content-divergent.
223 """
223 """
224 instabilities = []
224 instabilities = []
225 if self.orphan():
225 if self.orphan():
226 instabilities.append('orphan')
226 instabilities.append('orphan')
227 if self.phasedivergent():
227 if self.phasedivergent():
228 instabilities.append('phase-divergent')
228 instabilities.append('phase-divergent')
229 if self.contentdivergent():
229 if self.contentdivergent():
230 instabilities.append('content-divergent')
230 instabilities.append('content-divergent')
231 return instabilities
231 return instabilities
232
232
233 def parents(self):
233 def parents(self):
234 """return contexts for each parent changeset"""
234 """return contexts for each parent changeset"""
235 return self._parents
235 return self._parents
236
236
237 def p1(self):
237 def p1(self):
238 return self._parents[0]
238 return self._parents[0]
239
239
240 def p2(self):
240 def p2(self):
241 parents = self._parents
241 parents = self._parents
242 if len(parents) == 2:
242 if len(parents) == 2:
243 return parents[1]
243 return parents[1]
244 return self._repo[nullrev]
244 return self._repo[nullrev]
245
245
246 def _fileinfo(self, path):
246 def _fileinfo(self, path):
247 if r'_manifest' in self.__dict__:
247 if r'_manifest' in self.__dict__:
248 try:
248 try:
249 return self._manifest[path], self._manifest.flags(path)
249 return self._manifest[path], self._manifest.flags(path)
250 except KeyError:
250 except KeyError:
251 raise error.ManifestLookupError(self._node, path,
251 raise error.ManifestLookupError(self._node, path,
252 _('not found in manifest'))
252 _('not found in manifest'))
253 if r'_manifestdelta' in self.__dict__ or path in self.files():
253 if r'_manifestdelta' in self.__dict__ or path in self.files():
254 if path in self._manifestdelta:
254 if path in self._manifestdelta:
255 return (self._manifestdelta[path],
255 return (self._manifestdelta[path],
256 self._manifestdelta.flags(path))
256 self._manifestdelta.flags(path))
257 mfl = self._repo.manifestlog
257 mfl = self._repo.manifestlog
258 try:
258 try:
259 node, flag = mfl[self._changeset.manifest].find(path)
259 node, flag = mfl[self._changeset.manifest].find(path)
260 except KeyError:
260 except KeyError:
261 raise error.ManifestLookupError(self._node, path,
261 raise error.ManifestLookupError(self._node, path,
262 _('not found in manifest'))
262 _('not found in manifest'))
263
263
264 return node, flag
264 return node, flag
265
265
266 def filenode(self, path):
266 def filenode(self, path):
267 return self._fileinfo(path)[0]
267 return self._fileinfo(path)[0]
268
268
269 def flags(self, path):
269 def flags(self, path):
270 try:
270 try:
271 return self._fileinfo(path)[1]
271 return self._fileinfo(path)[1]
272 except error.LookupError:
272 except error.LookupError:
273 return ''
273 return ''
274
274
275 def sub(self, path, allowcreate=True):
275 def sub(self, path, allowcreate=True):
276 '''return a subrepo for the stored revision of path, never wdir()'''
276 '''return a subrepo for the stored revision of path, never wdir()'''
277 return subrepo.subrepo(self, path, allowcreate=allowcreate)
277 return subrepo.subrepo(self, path, allowcreate=allowcreate)
278
278
279 def nullsub(self, path, pctx):
279 def nullsub(self, path, pctx):
280 return subrepo.nullsubrepo(self, path, pctx)
280 return subrepo.nullsubrepo(self, path, pctx)
281
281
282 def workingsub(self, path):
282 def workingsub(self, path):
283 '''return a subrepo for the stored revision, or wdir if this is a wdir
283 '''return a subrepo for the stored revision, or wdir if this is a wdir
284 context.
284 context.
285 '''
285 '''
286 return subrepo.subrepo(self, path, allowwdir=True)
286 return subrepo.subrepo(self, path, allowwdir=True)
287
287
288 def match(self, pats=None, include=None, exclude=None, default='glob',
288 def match(self, pats=None, include=None, exclude=None, default='glob',
289 listsubrepos=False, badfn=None):
289 listsubrepos=False, badfn=None):
290 r = self._repo
290 r = self._repo
291 return matchmod.match(r.root, r.getcwd(), pats,
291 return matchmod.match(r.root, r.getcwd(), pats,
292 include, exclude, default,
292 include, exclude, default,
293 auditor=r.nofsauditor, ctx=self,
293 auditor=r.nofsauditor, ctx=self,
294 listsubrepos=listsubrepos, badfn=badfn)
294 listsubrepos=listsubrepos, badfn=badfn)
295
295
296 def diff(self, ctx2=None, match=None, changes=None, opts=None,
296 def diff(self, ctx2=None, match=None, changes=None, opts=None,
297 losedatafn=None, pathfn=None, copy=None,
297 losedatafn=None, pathfn=None, copy=None,
298 copysourcematch=None, hunksfilterfn=None):
298 copysourcematch=None, hunksfilterfn=None):
299 """Returns a diff generator for the given contexts and matcher"""
299 """Returns a diff generator for the given contexts and matcher"""
300 if ctx2 is None:
300 if ctx2 is None:
301 ctx2 = self.p1()
301 ctx2 = self.p1()
302 if ctx2 is not None:
302 if ctx2 is not None:
303 ctx2 = self._repo[ctx2]
303 ctx2 = self._repo[ctx2]
304 return patch.diff(self._repo, ctx2, self, match=match, changes=changes,
304 return patch.diff(self._repo, ctx2, self, match=match, changes=changes,
305 opts=opts, losedatafn=losedatafn, pathfn=pathfn,
305 opts=opts, losedatafn=losedatafn, pathfn=pathfn,
306 copy=copy, copysourcematch=copysourcematch,
306 copy=copy, copysourcematch=copysourcematch,
307 hunksfilterfn=hunksfilterfn)
307 hunksfilterfn=hunksfilterfn)
308
308
309 def dirs(self):
309 def dirs(self):
310 return self._manifest.dirs()
310 return self._manifest.dirs()
311
311
312 def hasdir(self, dir):
312 def hasdir(self, dir):
313 return self._manifest.hasdir(dir)
313 return self._manifest.hasdir(dir)
314
314
315 def status(self, other=None, match=None, listignored=False,
315 def status(self, other=None, match=None, listignored=False,
316 listclean=False, listunknown=False, listsubrepos=False):
316 listclean=False, listunknown=False, listsubrepos=False):
317 """return status of files between two nodes or node and working
317 """return status of files between two nodes or node and working
318 directory.
318 directory.
319
319
320 If other is None, compare this node with working directory.
320 If other is None, compare this node with working directory.
321
321
322 returns (modified, added, removed, deleted, unknown, ignored, clean)
322 returns (modified, added, removed, deleted, unknown, ignored, clean)
323 """
323 """
324
324
325 ctx1 = self
325 ctx1 = self
326 ctx2 = self._repo[other]
326 ctx2 = self._repo[other]
327
327
328 # This next code block is, admittedly, fragile logic that tests for
328 # This next code block is, admittedly, fragile logic that tests for
329 # reversing the contexts and wouldn't need to exist if it weren't for
329 # reversing the contexts and wouldn't need to exist if it weren't for
330 # the fast (and common) code path of comparing the working directory
330 # the fast (and common) code path of comparing the working directory
331 # with its first parent.
331 # with its first parent.
332 #
332 #
333 # What we're aiming for here is the ability to call:
333 # What we're aiming for here is the ability to call:
334 #
334 #
335 # workingctx.status(parentctx)
335 # workingctx.status(parentctx)
336 #
336 #
337 # If we always built the manifest for each context and compared those,
337 # If we always built the manifest for each context and compared those,
338 # then we'd be done. But the special case of the above call means we
338 # then we'd be done. But the special case of the above call means we
339 # just copy the manifest of the parent.
339 # just copy the manifest of the parent.
340 reversed = False
340 reversed = False
341 if (not isinstance(ctx1, changectx)
341 if (not isinstance(ctx1, changectx)
342 and isinstance(ctx2, changectx)):
342 and isinstance(ctx2, changectx)):
343 reversed = True
343 reversed = True
344 ctx1, ctx2 = ctx2, ctx1
344 ctx1, ctx2 = ctx2, ctx1
345
345
346 match = self._repo.narrowmatch(match)
346 match = self._repo.narrowmatch(match)
347 match = ctx2._matchstatus(ctx1, match)
347 match = ctx2._matchstatus(ctx1, match)
348 r = scmutil.status([], [], [], [], [], [], [])
348 r = scmutil.status([], [], [], [], [], [], [])
349 r = ctx2._buildstatus(ctx1, r, match, listignored, listclean,
349 r = ctx2._buildstatus(ctx1, r, match, listignored, listclean,
350 listunknown)
350 listunknown)
351
351
352 if reversed:
352 if reversed:
353 # Reverse added and removed. Clear deleted, unknown and ignored as
353 # Reverse added and removed. Clear deleted, unknown and ignored as
354 # these make no sense to reverse.
354 # these make no sense to reverse.
355 r = scmutil.status(r.modified, r.removed, r.added, [], [], [],
355 r = scmutil.status(r.modified, r.removed, r.added, [], [], [],
356 r.clean)
356 r.clean)
357
357
358 if listsubrepos:
358 if listsubrepos:
359 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
359 for subpath, sub in scmutil.itersubrepos(ctx1, ctx2):
360 try:
360 try:
361 rev2 = ctx2.subrev(subpath)
361 rev2 = ctx2.subrev(subpath)
362 except KeyError:
362 except KeyError:
363 # A subrepo that existed in node1 was deleted between
363 # A subrepo that existed in node1 was deleted between
364 # node1 and node2 (inclusive). Thus, ctx2's substate
364 # node1 and node2 (inclusive). Thus, ctx2's substate
365 # won't contain that subpath. The best we can do ignore it.
365 # won't contain that subpath. The best we can do ignore it.
366 rev2 = None
366 rev2 = None
367 submatch = matchmod.subdirmatcher(subpath, match)
367 submatch = matchmod.subdirmatcher(subpath, match)
368 s = sub.status(rev2, match=submatch, ignored=listignored,
368 s = sub.status(rev2, match=submatch, ignored=listignored,
369 clean=listclean, unknown=listunknown,
369 clean=listclean, unknown=listunknown,
370 listsubrepos=True)
370 listsubrepos=True)
371 for rfiles, sfiles in zip(r, s):
371 for rfiles, sfiles in zip(r, s):
372 rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
372 rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
373
373
374 for l in r:
374 for l in r:
375 l.sort()
375 l.sort()
376
376
377 return r
377 return r
378
378
379 class changectx(basectx):
379 class changectx(basectx):
380 """A changecontext object makes access to data related to a particular
380 """A changecontext object makes access to data related to a particular
381 changeset convenient. It represents a read-only context already present in
381 changeset convenient. It represents a read-only context already present in
382 the repo."""
382 the repo."""
383 def __init__(self, repo, rev, node):
383 def __init__(self, repo, rev, node):
384 super(changectx, self).__init__(repo)
384 super(changectx, self).__init__(repo)
385 self._rev = rev
385 self._rev = rev
386 self._node = node
386 self._node = node
387
387
388 def __hash__(self):
388 def __hash__(self):
389 try:
389 try:
390 return hash(self._rev)
390 return hash(self._rev)
391 except AttributeError:
391 except AttributeError:
392 return id(self)
392 return id(self)
393
393
394 def __nonzero__(self):
394 def __nonzero__(self):
395 return self._rev != nullrev
395 return self._rev != nullrev
396
396
397 __bool__ = __nonzero__
397 __bool__ = __nonzero__
398
398
399 @propertycache
399 @propertycache
400 def _changeset(self):
400 def _changeset(self):
401 return self._repo.changelog.changelogrevision(self.rev())
401 return self._repo.changelog.changelogrevision(self.rev())
402
402
403 @propertycache
403 @propertycache
404 def _manifest(self):
404 def _manifest(self):
405 return self._manifestctx.read()
405 return self._manifestctx.read()
406
406
407 @property
407 @property
408 def _manifestctx(self):
408 def _manifestctx(self):
409 return self._repo.manifestlog[self._changeset.manifest]
409 return self._repo.manifestlog[self._changeset.manifest]
410
410
411 @propertycache
411 @propertycache
412 def _manifestdelta(self):
412 def _manifestdelta(self):
413 return self._manifestctx.readdelta()
413 return self._manifestctx.readdelta()
414
414
415 @propertycache
415 @propertycache
416 def _parents(self):
416 def _parents(self):
417 repo = self._repo
417 repo = self._repo
418 p1, p2 = repo.changelog.parentrevs(self._rev)
418 p1, p2 = repo.changelog.parentrevs(self._rev)
419 if p2 == nullrev:
419 if p2 == nullrev:
420 return [repo[p1]]
420 return [repo[p1]]
421 return [repo[p1], repo[p2]]
421 return [repo[p1], repo[p2]]
422
422
423 def changeset(self):
423 def changeset(self):
424 c = self._changeset
424 c = self._changeset
425 return (
425 return (
426 c.manifest,
426 c.manifest,
427 c.user,
427 c.user,
428 c.date,
428 c.date,
429 c.files,
429 c.files,
430 c.description,
430 c.description,
431 c.extra,
431 c.extra,
432 )
432 )
433 def manifestnode(self):
433 def manifestnode(self):
434 return self._changeset.manifest
434 return self._changeset.manifest
435
435
436 def user(self):
436 def user(self):
437 return self._changeset.user
437 return self._changeset.user
438 def date(self):
438 def date(self):
439 return self._changeset.date
439 return self._changeset.date
440 def files(self):
440 def files(self):
441 return self._changeset.files
441 return self._changeset.files
442 @propertycache
443 def _copies(self):
444 p1copies = {}
445 p2copies = {}
446 p1 = self.p1()
447 p2 = self.p2()
448 narrowmatch = self._repo.narrowmatch()
449 for dst in self.files():
450 if not narrowmatch(dst) or dst not in self:
451 continue
452 copied = self[dst].renamed()
453 if not copied:
454 continue
455 src, srcnode = copied
456 if src in p1 and p1[src].filenode() == srcnode:
457 p1copies[dst] = src
458 elif src in p2 and p2[src].filenode() == srcnode:
459 p2copies[dst] = src
460 return p1copies, p2copies
461 def p1copies(self):
462 return self._copies[0]
463 def p2copies(self):
464 return self._copies[1]
442 def description(self):
465 def description(self):
443 return self._changeset.description
466 return self._changeset.description
444 def branch(self):
467 def branch(self):
445 return encoding.tolocal(self._changeset.extra.get("branch"))
468 return encoding.tolocal(self._changeset.extra.get("branch"))
446 def closesbranch(self):
469 def closesbranch(self):
447 return 'close' in self._changeset.extra
470 return 'close' in self._changeset.extra
448 def extra(self):
471 def extra(self):
449 """Return a dict of extra information."""
472 """Return a dict of extra information."""
450 return self._changeset.extra
473 return self._changeset.extra
451 def tags(self):
474 def tags(self):
452 """Return a list of byte tag names"""
475 """Return a list of byte tag names"""
453 return self._repo.nodetags(self._node)
476 return self._repo.nodetags(self._node)
454 def bookmarks(self):
477 def bookmarks(self):
455 """Return a list of byte bookmark names."""
478 """Return a list of byte bookmark names."""
456 return self._repo.nodebookmarks(self._node)
479 return self._repo.nodebookmarks(self._node)
457 def phase(self):
480 def phase(self):
458 return self._repo._phasecache.phase(self._repo, self._rev)
481 return self._repo._phasecache.phase(self._repo, self._rev)
459 def hidden(self):
482 def hidden(self):
460 return self._rev in repoview.filterrevs(self._repo, 'visible')
483 return self._rev in repoview.filterrevs(self._repo, 'visible')
461
484
462 def isinmemory(self):
485 def isinmemory(self):
463 return False
486 return False
464
487
465 def children(self):
488 def children(self):
466 """return list of changectx contexts for each child changeset.
489 """return list of changectx contexts for each child changeset.
467
490
468 This returns only the immediate child changesets. Use descendants() to
491 This returns only the immediate child changesets. Use descendants() to
469 recursively walk children.
492 recursively walk children.
470 """
493 """
471 c = self._repo.changelog.children(self._node)
494 c = self._repo.changelog.children(self._node)
472 return [self._repo[x] for x in c]
495 return [self._repo[x] for x in c]
473
496
474 def ancestors(self):
497 def ancestors(self):
475 for a in self._repo.changelog.ancestors([self._rev]):
498 for a in self._repo.changelog.ancestors([self._rev]):
476 yield self._repo[a]
499 yield self._repo[a]
477
500
478 def descendants(self):
501 def descendants(self):
479 """Recursively yield all children of the changeset.
502 """Recursively yield all children of the changeset.
480
503
481 For just the immediate children, use children()
504 For just the immediate children, use children()
482 """
505 """
483 for d in self._repo.changelog.descendants([self._rev]):
506 for d in self._repo.changelog.descendants([self._rev]):
484 yield self._repo[d]
507 yield self._repo[d]
485
508
486 def filectx(self, path, fileid=None, filelog=None):
509 def filectx(self, path, fileid=None, filelog=None):
487 """get a file context from this changeset"""
510 """get a file context from this changeset"""
488 if fileid is None:
511 if fileid is None:
489 fileid = self.filenode(path)
512 fileid = self.filenode(path)
490 return filectx(self._repo, path, fileid=fileid,
513 return filectx(self._repo, path, fileid=fileid,
491 changectx=self, filelog=filelog)
514 changectx=self, filelog=filelog)
492
515
493 def ancestor(self, c2, warn=False):
516 def ancestor(self, c2, warn=False):
494 """return the "best" ancestor context of self and c2
517 """return the "best" ancestor context of self and c2
495
518
496 If there are multiple candidates, it will show a message and check
519 If there are multiple candidates, it will show a message and check
497 merge.preferancestor configuration before falling back to the
520 merge.preferancestor configuration before falling back to the
498 revlog ancestor."""
521 revlog ancestor."""
499 # deal with workingctxs
522 # deal with workingctxs
500 n2 = c2._node
523 n2 = c2._node
501 if n2 is None:
524 if n2 is None:
502 n2 = c2._parents[0]._node
525 n2 = c2._parents[0]._node
503 cahs = self._repo.changelog.commonancestorsheads(self._node, n2)
526 cahs = self._repo.changelog.commonancestorsheads(self._node, n2)
504 if not cahs:
527 if not cahs:
505 anc = nullid
528 anc = nullid
506 elif len(cahs) == 1:
529 elif len(cahs) == 1:
507 anc = cahs[0]
530 anc = cahs[0]
508 else:
531 else:
509 # experimental config: merge.preferancestor
532 # experimental config: merge.preferancestor
510 for r in self._repo.ui.configlist('merge', 'preferancestor'):
533 for r in self._repo.ui.configlist('merge', 'preferancestor'):
511 try:
534 try:
512 ctx = scmutil.revsymbol(self._repo, r)
535 ctx = scmutil.revsymbol(self._repo, r)
513 except error.RepoLookupError:
536 except error.RepoLookupError:
514 continue
537 continue
515 anc = ctx.node()
538 anc = ctx.node()
516 if anc in cahs:
539 if anc in cahs:
517 break
540 break
518 else:
541 else:
519 anc = self._repo.changelog.ancestor(self._node, n2)
542 anc = self._repo.changelog.ancestor(self._node, n2)
520 if warn:
543 if warn:
521 self._repo.ui.status(
544 self._repo.ui.status(
522 (_("note: using %s as ancestor of %s and %s\n") %
545 (_("note: using %s as ancestor of %s and %s\n") %
523 (short(anc), short(self._node), short(n2))) +
546 (short(anc), short(self._node), short(n2))) +
524 ''.join(_(" alternatively, use --config "
547 ''.join(_(" alternatively, use --config "
525 "merge.preferancestor=%s\n") %
548 "merge.preferancestor=%s\n") %
526 short(n) for n in sorted(cahs) if n != anc))
549 short(n) for n in sorted(cahs) if n != anc))
527 return self._repo[anc]
550 return self._repo[anc]
528
551
529 def isancestorof(self, other):
552 def isancestorof(self, other):
530 """True if this changeset is an ancestor of other"""
553 """True if this changeset is an ancestor of other"""
531 return self._repo.changelog.isancestorrev(self._rev, other._rev)
554 return self._repo.changelog.isancestorrev(self._rev, other._rev)
532
555
533 def walk(self, match):
556 def walk(self, match):
534 '''Generates matching file names.'''
557 '''Generates matching file names.'''
535
558
536 # Wrap match.bad method to have message with nodeid
559 # Wrap match.bad method to have message with nodeid
537 def bad(fn, msg):
560 def bad(fn, msg):
538 # The manifest doesn't know about subrepos, so don't complain about
561 # The manifest doesn't know about subrepos, so don't complain about
539 # paths into valid subrepos.
562 # paths into valid subrepos.
540 if any(fn == s or fn.startswith(s + '/')
563 if any(fn == s or fn.startswith(s + '/')
541 for s in self.substate):
564 for s in self.substate):
542 return
565 return
543 match.bad(fn, _('no such file in rev %s') % self)
566 match.bad(fn, _('no such file in rev %s') % self)
544
567
545 m = matchmod.badmatch(self._repo.narrowmatch(match), bad)
568 m = matchmod.badmatch(self._repo.narrowmatch(match), bad)
546 return self._manifest.walk(m)
569 return self._manifest.walk(m)
547
570
548 def matches(self, match):
571 def matches(self, match):
549 return self.walk(match)
572 return self.walk(match)
550
573
551 class basefilectx(object):
574 class basefilectx(object):
552 """A filecontext object represents the common logic for its children:
575 """A filecontext object represents the common logic for its children:
553 filectx: read-only access to a filerevision that is already present
576 filectx: read-only access to a filerevision that is already present
554 in the repo,
577 in the repo,
555 workingfilectx: a filecontext that represents files from the working
578 workingfilectx: a filecontext that represents files from the working
556 directory,
579 directory,
557 memfilectx: a filecontext that represents files in-memory,
580 memfilectx: a filecontext that represents files in-memory,
558 """
581 """
559 @propertycache
582 @propertycache
560 def _filelog(self):
583 def _filelog(self):
561 return self._repo.file(self._path)
584 return self._repo.file(self._path)
562
585
563 @propertycache
586 @propertycache
564 def _changeid(self):
587 def _changeid(self):
565 if r'_changectx' in self.__dict__:
588 if r'_changectx' in self.__dict__:
566 return self._changectx.rev()
589 return self._changectx.rev()
567 elif r'_descendantrev' in self.__dict__:
590 elif r'_descendantrev' in self.__dict__:
568 # this file context was created from a revision with a known
591 # this file context was created from a revision with a known
569 # descendant, we can (lazily) correct for linkrev aliases
592 # descendant, we can (lazily) correct for linkrev aliases
570 return self._adjustlinkrev(self._descendantrev)
593 return self._adjustlinkrev(self._descendantrev)
571 else:
594 else:
572 return self._filelog.linkrev(self._filerev)
595 return self._filelog.linkrev(self._filerev)
573
596
574 @propertycache
597 @propertycache
575 def _filenode(self):
598 def _filenode(self):
576 if r'_fileid' in self.__dict__:
599 if r'_fileid' in self.__dict__:
577 return self._filelog.lookup(self._fileid)
600 return self._filelog.lookup(self._fileid)
578 else:
601 else:
579 return self._changectx.filenode(self._path)
602 return self._changectx.filenode(self._path)
580
603
581 @propertycache
604 @propertycache
582 def _filerev(self):
605 def _filerev(self):
583 return self._filelog.rev(self._filenode)
606 return self._filelog.rev(self._filenode)
584
607
585 @propertycache
608 @propertycache
586 def _repopath(self):
609 def _repopath(self):
587 return self._path
610 return self._path
588
611
589 def __nonzero__(self):
612 def __nonzero__(self):
590 try:
613 try:
591 self._filenode
614 self._filenode
592 return True
615 return True
593 except error.LookupError:
616 except error.LookupError:
594 # file is missing
617 # file is missing
595 return False
618 return False
596
619
597 __bool__ = __nonzero__
620 __bool__ = __nonzero__
598
621
599 def __bytes__(self):
622 def __bytes__(self):
600 try:
623 try:
601 return "%s@%s" % (self.path(), self._changectx)
624 return "%s@%s" % (self.path(), self._changectx)
602 except error.LookupError:
625 except error.LookupError:
603 return "%s@???" % self.path()
626 return "%s@???" % self.path()
604
627
605 __str__ = encoding.strmethod(__bytes__)
628 __str__ = encoding.strmethod(__bytes__)
606
629
607 def __repr__(self):
630 def __repr__(self):
608 return r"<%s %s>" % (type(self).__name__, str(self))
631 return r"<%s %s>" % (type(self).__name__, str(self))
609
632
610 def __hash__(self):
633 def __hash__(self):
611 try:
634 try:
612 return hash((self._path, self._filenode))
635 return hash((self._path, self._filenode))
613 except AttributeError:
636 except AttributeError:
614 return id(self)
637 return id(self)
615
638
616 def __eq__(self, other):
639 def __eq__(self, other):
617 try:
640 try:
618 return (type(self) == type(other) and self._path == other._path
641 return (type(self) == type(other) and self._path == other._path
619 and self._filenode == other._filenode)
642 and self._filenode == other._filenode)
620 except AttributeError:
643 except AttributeError:
621 return False
644 return False
622
645
623 def __ne__(self, other):
646 def __ne__(self, other):
624 return not (self == other)
647 return not (self == other)
625
648
626 def filerev(self):
649 def filerev(self):
627 return self._filerev
650 return self._filerev
628 def filenode(self):
651 def filenode(self):
629 return self._filenode
652 return self._filenode
630 @propertycache
653 @propertycache
631 def _flags(self):
654 def _flags(self):
632 return self._changectx.flags(self._path)
655 return self._changectx.flags(self._path)
633 def flags(self):
656 def flags(self):
634 return self._flags
657 return self._flags
635 def filelog(self):
658 def filelog(self):
636 return self._filelog
659 return self._filelog
637 def rev(self):
660 def rev(self):
638 return self._changeid
661 return self._changeid
639 def linkrev(self):
662 def linkrev(self):
640 return self._filelog.linkrev(self._filerev)
663 return self._filelog.linkrev(self._filerev)
641 def node(self):
664 def node(self):
642 return self._changectx.node()
665 return self._changectx.node()
643 def hex(self):
666 def hex(self):
644 return self._changectx.hex()
667 return self._changectx.hex()
645 def user(self):
668 def user(self):
646 return self._changectx.user()
669 return self._changectx.user()
647 def date(self):
670 def date(self):
648 return self._changectx.date()
671 return self._changectx.date()
649 def files(self):
672 def files(self):
650 return self._changectx.files()
673 return self._changectx.files()
651 def description(self):
674 def description(self):
652 return self._changectx.description()
675 return self._changectx.description()
653 def branch(self):
676 def branch(self):
654 return self._changectx.branch()
677 return self._changectx.branch()
655 def extra(self):
678 def extra(self):
656 return self._changectx.extra()
679 return self._changectx.extra()
657 def phase(self):
680 def phase(self):
658 return self._changectx.phase()
681 return self._changectx.phase()
659 def phasestr(self):
682 def phasestr(self):
660 return self._changectx.phasestr()
683 return self._changectx.phasestr()
661 def obsolete(self):
684 def obsolete(self):
662 return self._changectx.obsolete()
685 return self._changectx.obsolete()
663 def instabilities(self):
686 def instabilities(self):
664 return self._changectx.instabilities()
687 return self._changectx.instabilities()
665 def manifest(self):
688 def manifest(self):
666 return self._changectx.manifest()
689 return self._changectx.manifest()
667 def changectx(self):
690 def changectx(self):
668 return self._changectx
691 return self._changectx
669 def renamed(self):
692 def renamed(self):
670 return self._copied
693 return self._copied
671 def repo(self):
694 def repo(self):
672 return self._repo
695 return self._repo
673 def size(self):
696 def size(self):
674 return len(self.data())
697 return len(self.data())
675
698
676 def path(self):
699 def path(self):
677 return self._path
700 return self._path
678
701
679 def isbinary(self):
702 def isbinary(self):
680 try:
703 try:
681 return stringutil.binary(self.data())
704 return stringutil.binary(self.data())
682 except IOError:
705 except IOError:
683 return False
706 return False
684 def isexec(self):
707 def isexec(self):
685 return 'x' in self.flags()
708 return 'x' in self.flags()
686 def islink(self):
709 def islink(self):
687 return 'l' in self.flags()
710 return 'l' in self.flags()
688
711
689 def isabsent(self):
712 def isabsent(self):
690 """whether this filectx represents a file not in self._changectx
713 """whether this filectx represents a file not in self._changectx
691
714
692 This is mainly for merge code to detect change/delete conflicts. This is
715 This is mainly for merge code to detect change/delete conflicts. This is
693 expected to be True for all subclasses of basectx."""
716 expected to be True for all subclasses of basectx."""
694 return False
717 return False
695
718
696 _customcmp = False
719 _customcmp = False
697 def cmp(self, fctx):
720 def cmp(self, fctx):
698 """compare with other file context
721 """compare with other file context
699
722
700 returns True if different than fctx.
723 returns True if different than fctx.
701 """
724 """
702 if fctx._customcmp:
725 if fctx._customcmp:
703 return fctx.cmp(self)
726 return fctx.cmp(self)
704
727
705 if self._filenode is None:
728 if self._filenode is None:
706 raise error.ProgrammingError(
729 raise error.ProgrammingError(
707 'filectx.cmp() must be reimplemented if not backed by revlog')
730 'filectx.cmp() must be reimplemented if not backed by revlog')
708
731
709 if fctx._filenode is None:
732 if fctx._filenode is None:
710 if self._repo._encodefilterpats:
733 if self._repo._encodefilterpats:
711 # can't rely on size() because wdir content may be decoded
734 # can't rely on size() because wdir content may be decoded
712 return self._filelog.cmp(self._filenode, fctx.data())
735 return self._filelog.cmp(self._filenode, fctx.data())
713 if self.size() - 4 == fctx.size():
736 if self.size() - 4 == fctx.size():
714 # size() can match:
737 # size() can match:
715 # if file data starts with '\1\n', empty metadata block is
738 # if file data starts with '\1\n', empty metadata block is
716 # prepended, which adds 4 bytes to filelog.size().
739 # prepended, which adds 4 bytes to filelog.size().
717 return self._filelog.cmp(self._filenode, fctx.data())
740 return self._filelog.cmp(self._filenode, fctx.data())
718 if self.size() == fctx.size():
741 if self.size() == fctx.size():
719 # size() matches: need to compare content
742 # size() matches: need to compare content
720 return self._filelog.cmp(self._filenode, fctx.data())
743 return self._filelog.cmp(self._filenode, fctx.data())
721
744
722 # size() differs
745 # size() differs
723 return True
746 return True
724
747
725 def _adjustlinkrev(self, srcrev, inclusive=False, stoprev=None):
748 def _adjustlinkrev(self, srcrev, inclusive=False, stoprev=None):
726 """return the first ancestor of <srcrev> introducing <fnode>
749 """return the first ancestor of <srcrev> introducing <fnode>
727
750
728 If the linkrev of the file revision does not point to an ancestor of
751 If the linkrev of the file revision does not point to an ancestor of
729 srcrev, we'll walk down the ancestors until we find one introducing
752 srcrev, we'll walk down the ancestors until we find one introducing
730 this file revision.
753 this file revision.
731
754
732 :srcrev: the changeset revision we search ancestors from
755 :srcrev: the changeset revision we search ancestors from
733 :inclusive: if true, the src revision will also be checked
756 :inclusive: if true, the src revision will also be checked
734 :stoprev: an optional revision to stop the walk at. If no introduction
757 :stoprev: an optional revision to stop the walk at. If no introduction
735 of this file content could be found before this floor
758 of this file content could be found before this floor
736 revision, the function will returns "None" and stops its
759 revision, the function will returns "None" and stops its
737 iteration.
760 iteration.
738 """
761 """
739 repo = self._repo
762 repo = self._repo
740 cl = repo.unfiltered().changelog
763 cl = repo.unfiltered().changelog
741 mfl = repo.manifestlog
764 mfl = repo.manifestlog
742 # fetch the linkrev
765 # fetch the linkrev
743 lkr = self.linkrev()
766 lkr = self.linkrev()
744 if srcrev == lkr:
767 if srcrev == lkr:
745 return lkr
768 return lkr
746 # hack to reuse ancestor computation when searching for renames
769 # hack to reuse ancestor computation when searching for renames
747 memberanc = getattr(self, '_ancestrycontext', None)
770 memberanc = getattr(self, '_ancestrycontext', None)
748 iteranc = None
771 iteranc = None
749 if srcrev is None:
772 if srcrev is None:
750 # wctx case, used by workingfilectx during mergecopy
773 # wctx case, used by workingfilectx during mergecopy
751 revs = [p.rev() for p in self._repo[None].parents()]
774 revs = [p.rev() for p in self._repo[None].parents()]
752 inclusive = True # we skipped the real (revless) source
775 inclusive = True # we skipped the real (revless) source
753 else:
776 else:
754 revs = [srcrev]
777 revs = [srcrev]
755 if memberanc is None:
778 if memberanc is None:
756 memberanc = iteranc = cl.ancestors(revs, lkr,
779 memberanc = iteranc = cl.ancestors(revs, lkr,
757 inclusive=inclusive)
780 inclusive=inclusive)
758 # check if this linkrev is an ancestor of srcrev
781 # check if this linkrev is an ancestor of srcrev
759 if lkr not in memberanc:
782 if lkr not in memberanc:
760 if iteranc is None:
783 if iteranc is None:
761 iteranc = cl.ancestors(revs, lkr, inclusive=inclusive)
784 iteranc = cl.ancestors(revs, lkr, inclusive=inclusive)
762 fnode = self._filenode
785 fnode = self._filenode
763 path = self._path
786 path = self._path
764 for a in iteranc:
787 for a in iteranc:
765 if stoprev is not None and a < stoprev:
788 if stoprev is not None and a < stoprev:
766 return None
789 return None
767 ac = cl.read(a) # get changeset data (we avoid object creation)
790 ac = cl.read(a) # get changeset data (we avoid object creation)
768 if path in ac[3]: # checking the 'files' field.
791 if path in ac[3]: # checking the 'files' field.
769 # The file has been touched, check if the content is
792 # The file has been touched, check if the content is
770 # similar to the one we search for.
793 # similar to the one we search for.
771 if fnode == mfl[ac[0]].readfast().get(path):
794 if fnode == mfl[ac[0]].readfast().get(path):
772 return a
795 return a
773 # In theory, we should never get out of that loop without a result.
796 # In theory, we should never get out of that loop without a result.
774 # But if manifest uses a buggy file revision (not children of the
797 # But if manifest uses a buggy file revision (not children of the
775 # one it replaces) we could. Such a buggy situation will likely
798 # one it replaces) we could. Such a buggy situation will likely
776 # result is crash somewhere else at to some point.
799 # result is crash somewhere else at to some point.
777 return lkr
800 return lkr
778
801
779 def isintroducedafter(self, changelogrev):
802 def isintroducedafter(self, changelogrev):
780 """True if a filectx has been introduced after a given floor revision
803 """True if a filectx has been introduced after a given floor revision
781 """
804 """
782 if self.linkrev() >= changelogrev:
805 if self.linkrev() >= changelogrev:
783 return True
806 return True
784 introrev = self._introrev(stoprev=changelogrev)
807 introrev = self._introrev(stoprev=changelogrev)
785 if introrev is None:
808 if introrev is None:
786 return False
809 return False
787 return introrev >= changelogrev
810 return introrev >= changelogrev
788
811
789 def introrev(self):
812 def introrev(self):
790 """return the rev of the changeset which introduced this file revision
813 """return the rev of the changeset which introduced this file revision
791
814
792 This method is different from linkrev because it take into account the
815 This method is different from linkrev because it take into account the
793 changeset the filectx was created from. It ensures the returned
816 changeset the filectx was created from. It ensures the returned
794 revision is one of its ancestors. This prevents bugs from
817 revision is one of its ancestors. This prevents bugs from
795 'linkrev-shadowing' when a file revision is used by multiple
818 'linkrev-shadowing' when a file revision is used by multiple
796 changesets.
819 changesets.
797 """
820 """
798 return self._introrev()
821 return self._introrev()
799
822
800 def _introrev(self, stoprev=None):
823 def _introrev(self, stoprev=None):
801 """
824 """
802 Same as `introrev` but, with an extra argument to limit changelog
825 Same as `introrev` but, with an extra argument to limit changelog
803 iteration range in some internal usecase.
826 iteration range in some internal usecase.
804
827
805 If `stoprev` is set, the `introrev` will not be searched past that
828 If `stoprev` is set, the `introrev` will not be searched past that
806 `stoprev` revision and "None" might be returned. This is useful to
829 `stoprev` revision and "None" might be returned. This is useful to
807 limit the iteration range.
830 limit the iteration range.
808 """
831 """
809 toprev = None
832 toprev = None
810 attrs = vars(self)
833 attrs = vars(self)
811 if r'_changeid' in attrs:
834 if r'_changeid' in attrs:
812 # We have a cached value already
835 # We have a cached value already
813 toprev = self._changeid
836 toprev = self._changeid
814 elif r'_changectx' in attrs:
837 elif r'_changectx' in attrs:
815 # We know which changelog entry we are coming from
838 # We know which changelog entry we are coming from
816 toprev = self._changectx.rev()
839 toprev = self._changectx.rev()
817
840
818 if toprev is not None:
841 if toprev is not None:
819 return self._adjustlinkrev(toprev, inclusive=True, stoprev=stoprev)
842 return self._adjustlinkrev(toprev, inclusive=True, stoprev=stoprev)
820 elif r'_descendantrev' in attrs:
843 elif r'_descendantrev' in attrs:
821 introrev = self._adjustlinkrev(self._descendantrev, stoprev=stoprev)
844 introrev = self._adjustlinkrev(self._descendantrev, stoprev=stoprev)
822 # be nice and cache the result of the computation
845 # be nice and cache the result of the computation
823 if introrev is not None:
846 if introrev is not None:
824 self._changeid = introrev
847 self._changeid = introrev
825 return introrev
848 return introrev
826 else:
849 else:
827 return self.linkrev()
850 return self.linkrev()
828
851
829 def introfilectx(self):
852 def introfilectx(self):
830 """Return filectx having identical contents, but pointing to the
853 """Return filectx having identical contents, but pointing to the
831 changeset revision where this filectx was introduced"""
854 changeset revision where this filectx was introduced"""
832 introrev = self.introrev()
855 introrev = self.introrev()
833 if self.rev() == introrev:
856 if self.rev() == introrev:
834 return self
857 return self
835 return self.filectx(self.filenode(), changeid=introrev)
858 return self.filectx(self.filenode(), changeid=introrev)
836
859
837 def _parentfilectx(self, path, fileid, filelog):
860 def _parentfilectx(self, path, fileid, filelog):
838 """create parent filectx keeping ancestry info for _adjustlinkrev()"""
861 """create parent filectx keeping ancestry info for _adjustlinkrev()"""
839 fctx = filectx(self._repo, path, fileid=fileid, filelog=filelog)
862 fctx = filectx(self._repo, path, fileid=fileid, filelog=filelog)
840 if r'_changeid' in vars(self) or r'_changectx' in vars(self):
863 if r'_changeid' in vars(self) or r'_changectx' in vars(self):
841 # If self is associated with a changeset (probably explicitly
864 # If self is associated with a changeset (probably explicitly
842 # fed), ensure the created filectx is associated with a
865 # fed), ensure the created filectx is associated with a
843 # changeset that is an ancestor of self.changectx.
866 # changeset that is an ancestor of self.changectx.
844 # This lets us later use _adjustlinkrev to get a correct link.
867 # This lets us later use _adjustlinkrev to get a correct link.
845 fctx._descendantrev = self.rev()
868 fctx._descendantrev = self.rev()
846 fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
869 fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
847 elif r'_descendantrev' in vars(self):
870 elif r'_descendantrev' in vars(self):
848 # Otherwise propagate _descendantrev if we have one associated.
871 # Otherwise propagate _descendantrev if we have one associated.
849 fctx._descendantrev = self._descendantrev
872 fctx._descendantrev = self._descendantrev
850 fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
873 fctx._ancestrycontext = getattr(self, '_ancestrycontext', None)
851 return fctx
874 return fctx
852
875
853 def parents(self):
876 def parents(self):
854 _path = self._path
877 _path = self._path
855 fl = self._filelog
878 fl = self._filelog
856 parents = self._filelog.parents(self._filenode)
879 parents = self._filelog.parents(self._filenode)
857 pl = [(_path, node, fl) for node in parents if node != nullid]
880 pl = [(_path, node, fl) for node in parents if node != nullid]
858
881
859 r = fl.renamed(self._filenode)
882 r = fl.renamed(self._filenode)
860 if r:
883 if r:
861 # - In the simple rename case, both parent are nullid, pl is empty.
884 # - In the simple rename case, both parent are nullid, pl is empty.
862 # - In case of merge, only one of the parent is null id and should
885 # - In case of merge, only one of the parent is null id and should
863 # be replaced with the rename information. This parent is -always-
886 # be replaced with the rename information. This parent is -always-
864 # the first one.
887 # the first one.
865 #
888 #
866 # As null id have always been filtered out in the previous list
889 # As null id have always been filtered out in the previous list
867 # comprehension, inserting to 0 will always result in "replacing
890 # comprehension, inserting to 0 will always result in "replacing
868 # first nullid parent with rename information.
891 # first nullid parent with rename information.
869 pl.insert(0, (r[0], r[1], self._repo.file(r[0])))
892 pl.insert(0, (r[0], r[1], self._repo.file(r[0])))
870
893
871 return [self._parentfilectx(path, fnode, l) for path, fnode, l in pl]
894 return [self._parentfilectx(path, fnode, l) for path, fnode, l in pl]
872
895
873 def p1(self):
896 def p1(self):
874 return self.parents()[0]
897 return self.parents()[0]
875
898
876 def p2(self):
899 def p2(self):
877 p = self.parents()
900 p = self.parents()
878 if len(p) == 2:
901 if len(p) == 2:
879 return p[1]
902 return p[1]
880 return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
903 return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
881
904
882 def annotate(self, follow=False, skiprevs=None, diffopts=None):
905 def annotate(self, follow=False, skiprevs=None, diffopts=None):
883 """Returns a list of annotateline objects for each line in the file
906 """Returns a list of annotateline objects for each line in the file
884
907
885 - line.fctx is the filectx of the node where that line was last changed
908 - line.fctx is the filectx of the node where that line was last changed
886 - line.lineno is the line number at the first appearance in the managed
909 - line.lineno is the line number at the first appearance in the managed
887 file
910 file
888 - line.text is the data on that line (including newline character)
911 - line.text is the data on that line (including newline character)
889 """
912 """
890 getlog = util.lrucachefunc(lambda x: self._repo.file(x))
913 getlog = util.lrucachefunc(lambda x: self._repo.file(x))
891
914
892 def parents(f):
915 def parents(f):
893 # Cut _descendantrev here to mitigate the penalty of lazy linkrev
916 # Cut _descendantrev here to mitigate the penalty of lazy linkrev
894 # adjustment. Otherwise, p._adjustlinkrev() would walk changelog
917 # adjustment. Otherwise, p._adjustlinkrev() would walk changelog
895 # from the topmost introrev (= srcrev) down to p.linkrev() if it
918 # from the topmost introrev (= srcrev) down to p.linkrev() if it
896 # isn't an ancestor of the srcrev.
919 # isn't an ancestor of the srcrev.
897 f._changeid
920 f._changeid
898 pl = f.parents()
921 pl = f.parents()
899
922
900 # Don't return renamed parents if we aren't following.
923 # Don't return renamed parents if we aren't following.
901 if not follow:
924 if not follow:
902 pl = [p for p in pl if p.path() == f.path()]
925 pl = [p for p in pl if p.path() == f.path()]
903
926
904 # renamed filectx won't have a filelog yet, so set it
927 # renamed filectx won't have a filelog yet, so set it
905 # from the cache to save time
928 # from the cache to save time
906 for p in pl:
929 for p in pl:
907 if not r'_filelog' in p.__dict__:
930 if not r'_filelog' in p.__dict__:
908 p._filelog = getlog(p.path())
931 p._filelog = getlog(p.path())
909
932
910 return pl
933 return pl
911
934
912 # use linkrev to find the first changeset where self appeared
935 # use linkrev to find the first changeset where self appeared
913 base = self.introfilectx()
936 base = self.introfilectx()
914 if getattr(base, '_ancestrycontext', None) is None:
937 if getattr(base, '_ancestrycontext', None) is None:
915 cl = self._repo.changelog
938 cl = self._repo.changelog
916 if base.rev() is None:
939 if base.rev() is None:
917 # wctx is not inclusive, but works because _ancestrycontext
940 # wctx is not inclusive, but works because _ancestrycontext
918 # is used to test filelog revisions
941 # is used to test filelog revisions
919 ac = cl.ancestors([p.rev() for p in base.parents()],
942 ac = cl.ancestors([p.rev() for p in base.parents()],
920 inclusive=True)
943 inclusive=True)
921 else:
944 else:
922 ac = cl.ancestors([base.rev()], inclusive=True)
945 ac = cl.ancestors([base.rev()], inclusive=True)
923 base._ancestrycontext = ac
946 base._ancestrycontext = ac
924
947
925 return dagop.annotate(base, parents, skiprevs=skiprevs,
948 return dagop.annotate(base, parents, skiprevs=skiprevs,
926 diffopts=diffopts)
949 diffopts=diffopts)
927
950
928 def ancestors(self, followfirst=False):
951 def ancestors(self, followfirst=False):
929 visit = {}
952 visit = {}
930 c = self
953 c = self
931 if followfirst:
954 if followfirst:
932 cut = 1
955 cut = 1
933 else:
956 else:
934 cut = None
957 cut = None
935
958
936 while True:
959 while True:
937 for parent in c.parents()[:cut]:
960 for parent in c.parents()[:cut]:
938 visit[(parent.linkrev(), parent.filenode())] = parent
961 visit[(parent.linkrev(), parent.filenode())] = parent
939 if not visit:
962 if not visit:
940 break
963 break
941 c = visit.pop(max(visit))
964 c = visit.pop(max(visit))
942 yield c
965 yield c
943
966
944 def decodeddata(self):
967 def decodeddata(self):
945 """Returns `data()` after running repository decoding filters.
968 """Returns `data()` after running repository decoding filters.
946
969
947 This is often equivalent to how the data would be expressed on disk.
970 This is often equivalent to how the data would be expressed on disk.
948 """
971 """
949 return self._repo.wwritedata(self.path(), self.data())
972 return self._repo.wwritedata(self.path(), self.data())
950
973
951 class filectx(basefilectx):
974 class filectx(basefilectx):
952 """A filecontext object makes access to data related to a particular
975 """A filecontext object makes access to data related to a particular
953 filerevision convenient."""
976 filerevision convenient."""
954 def __init__(self, repo, path, changeid=None, fileid=None,
977 def __init__(self, repo, path, changeid=None, fileid=None,
955 filelog=None, changectx=None):
978 filelog=None, changectx=None):
956 """changeid must be a revision number, if specified.
979 """changeid must be a revision number, if specified.
957 fileid can be a file revision or node."""
980 fileid can be a file revision or node."""
958 self._repo = repo
981 self._repo = repo
959 self._path = path
982 self._path = path
960
983
961 assert (changeid is not None
984 assert (changeid is not None
962 or fileid is not None
985 or fileid is not None
963 or changectx is not None), \
986 or changectx is not None), \
964 ("bad args: changeid=%r, fileid=%r, changectx=%r"
987 ("bad args: changeid=%r, fileid=%r, changectx=%r"
965 % (changeid, fileid, changectx))
988 % (changeid, fileid, changectx))
966
989
967 if filelog is not None:
990 if filelog is not None:
968 self._filelog = filelog
991 self._filelog = filelog
969
992
970 if changeid is not None:
993 if changeid is not None:
971 self._changeid = changeid
994 self._changeid = changeid
972 if changectx is not None:
995 if changectx is not None:
973 self._changectx = changectx
996 self._changectx = changectx
974 if fileid is not None:
997 if fileid is not None:
975 self._fileid = fileid
998 self._fileid = fileid
976
999
977 @propertycache
1000 @propertycache
978 def _changectx(self):
1001 def _changectx(self):
979 try:
1002 try:
980 return self._repo[self._changeid]
1003 return self._repo[self._changeid]
981 except error.FilteredRepoLookupError:
1004 except error.FilteredRepoLookupError:
982 # Linkrev may point to any revision in the repository. When the
1005 # Linkrev may point to any revision in the repository. When the
983 # repository is filtered this may lead to `filectx` trying to build
1006 # repository is filtered this may lead to `filectx` trying to build
984 # `changectx` for filtered revision. In such case we fallback to
1007 # `changectx` for filtered revision. In such case we fallback to
985 # creating `changectx` on the unfiltered version of the reposition.
1008 # creating `changectx` on the unfiltered version of the reposition.
986 # This fallback should not be an issue because `changectx` from
1009 # This fallback should not be an issue because `changectx` from
987 # `filectx` are not used in complex operations that care about
1010 # `filectx` are not used in complex operations that care about
988 # filtering.
1011 # filtering.
989 #
1012 #
990 # This fallback is a cheap and dirty fix that prevent several
1013 # This fallback is a cheap and dirty fix that prevent several
991 # crashes. It does not ensure the behavior is correct. However the
1014 # crashes. It does not ensure the behavior is correct. However the
992 # behavior was not correct before filtering either and "incorrect
1015 # behavior was not correct before filtering either and "incorrect
993 # behavior" is seen as better as "crash"
1016 # behavior" is seen as better as "crash"
994 #
1017 #
995 # Linkrevs have several serious troubles with filtering that are
1018 # Linkrevs have several serious troubles with filtering that are
996 # complicated to solve. Proper handling of the issue here should be
1019 # complicated to solve. Proper handling of the issue here should be
997 # considered when solving linkrev issue are on the table.
1020 # considered when solving linkrev issue are on the table.
998 return self._repo.unfiltered()[self._changeid]
1021 return self._repo.unfiltered()[self._changeid]
999
1022
1000 def filectx(self, fileid, changeid=None):
1023 def filectx(self, fileid, changeid=None):
1001 '''opens an arbitrary revision of the file without
1024 '''opens an arbitrary revision of the file without
1002 opening a new filelog'''
1025 opening a new filelog'''
1003 return filectx(self._repo, self._path, fileid=fileid,
1026 return filectx(self._repo, self._path, fileid=fileid,
1004 filelog=self._filelog, changeid=changeid)
1027 filelog=self._filelog, changeid=changeid)
1005
1028
1006 def rawdata(self):
1029 def rawdata(self):
1007 return self._filelog.revision(self._filenode, raw=True)
1030 return self._filelog.revision(self._filenode, raw=True)
1008
1031
1009 def rawflags(self):
1032 def rawflags(self):
1010 """low-level revlog flags"""
1033 """low-level revlog flags"""
1011 return self._filelog.flags(self._filerev)
1034 return self._filelog.flags(self._filerev)
1012
1035
1013 def data(self):
1036 def data(self):
1014 try:
1037 try:
1015 return self._filelog.read(self._filenode)
1038 return self._filelog.read(self._filenode)
1016 except error.CensoredNodeError:
1039 except error.CensoredNodeError:
1017 if self._repo.ui.config("censor", "policy") == "ignore":
1040 if self._repo.ui.config("censor", "policy") == "ignore":
1018 return ""
1041 return ""
1019 raise error.Abort(_("censored node: %s") % short(self._filenode),
1042 raise error.Abort(_("censored node: %s") % short(self._filenode),
1020 hint=_("set censor.policy to ignore errors"))
1043 hint=_("set censor.policy to ignore errors"))
1021
1044
1022 def size(self):
1045 def size(self):
1023 return self._filelog.size(self._filerev)
1046 return self._filelog.size(self._filerev)
1024
1047
1025 @propertycache
1048 @propertycache
1026 def _copied(self):
1049 def _copied(self):
1027 """check if file was actually renamed in this changeset revision
1050 """check if file was actually renamed in this changeset revision
1028
1051
1029 If rename logged in file revision, we report copy for changeset only
1052 If rename logged in file revision, we report copy for changeset only
1030 if file revisions linkrev points back to the changeset in question
1053 if file revisions linkrev points back to the changeset in question
1031 or both changeset parents contain different file revisions.
1054 or both changeset parents contain different file revisions.
1032 """
1055 """
1033
1056
1034 renamed = self._filelog.renamed(self._filenode)
1057 renamed = self._filelog.renamed(self._filenode)
1035 if not renamed:
1058 if not renamed:
1036 return None
1059 return None
1037
1060
1038 if self.rev() == self.linkrev():
1061 if self.rev() == self.linkrev():
1039 return renamed
1062 return renamed
1040
1063
1041 name = self.path()
1064 name = self.path()
1042 fnode = self._filenode
1065 fnode = self._filenode
1043 for p in self._changectx.parents():
1066 for p in self._changectx.parents():
1044 try:
1067 try:
1045 if fnode == p.filenode(name):
1068 if fnode == p.filenode(name):
1046 return None
1069 return None
1047 except error.LookupError:
1070 except error.LookupError:
1048 pass
1071 pass
1049 return renamed
1072 return renamed
1050
1073
1051 def children(self):
1074 def children(self):
1052 # hard for renames
1075 # hard for renames
1053 c = self._filelog.children(self._filenode)
1076 c = self._filelog.children(self._filenode)
1054 return [filectx(self._repo, self._path, fileid=x,
1077 return [filectx(self._repo, self._path, fileid=x,
1055 filelog=self._filelog) for x in c]
1078 filelog=self._filelog) for x in c]
1056
1079
1057 class committablectx(basectx):
1080 class committablectx(basectx):
1058 """A committablectx object provides common functionality for a context that
1081 """A committablectx object provides common functionality for a context that
1059 wants the ability to commit, e.g. workingctx or memctx."""
1082 wants the ability to commit, e.g. workingctx or memctx."""
1060 def __init__(self, repo, text="", user=None, date=None, extra=None,
1083 def __init__(self, repo, text="", user=None, date=None, extra=None,
1061 changes=None):
1084 changes=None):
1062 super(committablectx, self).__init__(repo)
1085 super(committablectx, self).__init__(repo)
1063 self._rev = None
1086 self._rev = None
1064 self._node = None
1087 self._node = None
1065 self._text = text
1088 self._text = text
1066 if date:
1089 if date:
1067 self._date = dateutil.parsedate(date)
1090 self._date = dateutil.parsedate(date)
1068 if user:
1091 if user:
1069 self._user = user
1092 self._user = user
1070 if changes:
1093 if changes:
1071 self._status = changes
1094 self._status = changes
1072
1095
1073 self._extra = {}
1096 self._extra = {}
1074 if extra:
1097 if extra:
1075 self._extra = extra.copy()
1098 self._extra = extra.copy()
1076 if 'branch' not in self._extra:
1099 if 'branch' not in self._extra:
1077 try:
1100 try:
1078 branch = encoding.fromlocal(self._repo.dirstate.branch())
1101 branch = encoding.fromlocal(self._repo.dirstate.branch())
1079 except UnicodeDecodeError:
1102 except UnicodeDecodeError:
1080 raise error.Abort(_('branch name not in UTF-8!'))
1103 raise error.Abort(_('branch name not in UTF-8!'))
1081 self._extra['branch'] = branch
1104 self._extra['branch'] = branch
1082 if self._extra['branch'] == '':
1105 if self._extra['branch'] == '':
1083 self._extra['branch'] = 'default'
1106 self._extra['branch'] = 'default'
1084
1107
1085 def __bytes__(self):
1108 def __bytes__(self):
1086 return bytes(self._parents[0]) + "+"
1109 return bytes(self._parents[0]) + "+"
1087
1110
1088 __str__ = encoding.strmethod(__bytes__)
1111 __str__ = encoding.strmethod(__bytes__)
1089
1112
1090 def __nonzero__(self):
1113 def __nonzero__(self):
1091 return True
1114 return True
1092
1115
1093 __bool__ = __nonzero__
1116 __bool__ = __nonzero__
1094
1117
1095 def _buildflagfunc(self):
1118 def _buildflagfunc(self):
1096 # Create a fallback function for getting file flags when the
1119 # Create a fallback function for getting file flags when the
1097 # filesystem doesn't support them
1120 # filesystem doesn't support them
1098
1121
1099 copiesget = self._repo.dirstate.copies().get
1122 copiesget = self._repo.dirstate.copies().get
1100 parents = self.parents()
1123 parents = self.parents()
1101 if len(parents) < 2:
1124 if len(parents) < 2:
1102 # when we have one parent, it's easy: copy from parent
1125 # when we have one parent, it's easy: copy from parent
1103 man = parents[0].manifest()
1126 man = parents[0].manifest()
1104 def func(f):
1127 def func(f):
1105 f = copiesget(f, f)
1128 f = copiesget(f, f)
1106 return man.flags(f)
1129 return man.flags(f)
1107 else:
1130 else:
1108 # merges are tricky: we try to reconstruct the unstored
1131 # merges are tricky: we try to reconstruct the unstored
1109 # result from the merge (issue1802)
1132 # result from the merge (issue1802)
1110 p1, p2 = parents
1133 p1, p2 = parents
1111 pa = p1.ancestor(p2)
1134 pa = p1.ancestor(p2)
1112 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
1135 m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
1113
1136
1114 def func(f):
1137 def func(f):
1115 f = copiesget(f, f) # may be wrong for merges with copies
1138 f = copiesget(f, f) # may be wrong for merges with copies
1116 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
1139 fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
1117 if fl1 == fl2:
1140 if fl1 == fl2:
1118 return fl1
1141 return fl1
1119 if fl1 == fla:
1142 if fl1 == fla:
1120 return fl2
1143 return fl2
1121 if fl2 == fla:
1144 if fl2 == fla:
1122 return fl1
1145 return fl1
1123 return '' # punt for conflicts
1146 return '' # punt for conflicts
1124
1147
1125 return func
1148 return func
1126
1149
1127 @propertycache
1150 @propertycache
1128 def _flagfunc(self):
1151 def _flagfunc(self):
1129 return self._repo.dirstate.flagfunc(self._buildflagfunc)
1152 return self._repo.dirstate.flagfunc(self._buildflagfunc)
1130
1153
1131 @propertycache
1154 @propertycache
1132 def _status(self):
1155 def _status(self):
1133 return self._repo.status()
1156 return self._repo.status()
1134
1157
1135 @propertycache
1158 @propertycache
1136 def _user(self):
1159 def _user(self):
1137 return self._repo.ui.username()
1160 return self._repo.ui.username()
1138
1161
1139 @propertycache
1162 @propertycache
1140 def _date(self):
1163 def _date(self):
1141 ui = self._repo.ui
1164 ui = self._repo.ui
1142 date = ui.configdate('devel', 'default-date')
1165 date = ui.configdate('devel', 'default-date')
1143 if date is None:
1166 if date is None:
1144 date = dateutil.makedate()
1167 date = dateutil.makedate()
1145 return date
1168 return date
1146
1169
1147 def subrev(self, subpath):
1170 def subrev(self, subpath):
1148 return None
1171 return None
1149
1172
1150 def manifestnode(self):
1173 def manifestnode(self):
1151 return None
1174 return None
1152 def user(self):
1175 def user(self):
1153 return self._user or self._repo.ui.username()
1176 return self._user or self._repo.ui.username()
1154 def date(self):
1177 def date(self):
1155 return self._date
1178 return self._date
1156 def description(self):
1179 def description(self):
1157 return self._text
1180 return self._text
1158 def files(self):
1181 def files(self):
1159 return sorted(self._status.modified + self._status.added +
1182 return sorted(self._status.modified + self._status.added +
1160 self._status.removed)
1183 self._status.removed)
1161
1184 @propertycache
1185 def _copies(self):
1186 p1copies = {}
1187 p2copies = {}
1188 parents = self._repo.dirstate.parents()
1189 p1manifest = self._repo[parents[0]].manifest()
1190 p2manifest = self._repo[parents[1]].manifest()
1191 narrowmatch = self._repo.narrowmatch()
1192 for dst, src in self._repo.dirstate.copies().items():
1193 if not narrowmatch(dst):
1194 continue
1195 if src in p1manifest:
1196 p1copies[dst] = src
1197 elif src in p2manifest:
1198 p2copies[dst] = src
1199 return p1copies, p2copies
1200 def p1copies(self):
1201 return self._copies[0]
1202 def p2copies(self):
1203 return self._copies[1]
1162 def modified(self):
1204 def modified(self):
1163 return self._status.modified
1205 return self._status.modified
1164 def added(self):
1206 def added(self):
1165 return self._status.added
1207 return self._status.added
1166 def removed(self):
1208 def removed(self):
1167 return self._status.removed
1209 return self._status.removed
1168 def deleted(self):
1210 def deleted(self):
1169 return self._status.deleted
1211 return self._status.deleted
1170 def branch(self):
1212 def branch(self):
1171 return encoding.tolocal(self._extra['branch'])
1213 return encoding.tolocal(self._extra['branch'])
1172 def closesbranch(self):
1214 def closesbranch(self):
1173 return 'close' in self._extra
1215 return 'close' in self._extra
1174 def extra(self):
1216 def extra(self):
1175 return self._extra
1217 return self._extra
1176
1218
1177 def isinmemory(self):
1219 def isinmemory(self):
1178 return False
1220 return False
1179
1221
1180 def tags(self):
1222 def tags(self):
1181 return []
1223 return []
1182
1224
1183 def bookmarks(self):
1225 def bookmarks(self):
1184 b = []
1226 b = []
1185 for p in self.parents():
1227 for p in self.parents():
1186 b.extend(p.bookmarks())
1228 b.extend(p.bookmarks())
1187 return b
1229 return b
1188
1230
1189 def phase(self):
1231 def phase(self):
1190 phase = phases.draft # default phase to draft
1232 phase = phases.draft # default phase to draft
1191 for p in self.parents():
1233 for p in self.parents():
1192 phase = max(phase, p.phase())
1234 phase = max(phase, p.phase())
1193 return phase
1235 return phase
1194
1236
1195 def hidden(self):
1237 def hidden(self):
1196 return False
1238 return False
1197
1239
1198 def children(self):
1240 def children(self):
1199 return []
1241 return []
1200
1242
1201 def flags(self, path):
1243 def flags(self, path):
1202 if r'_manifest' in self.__dict__:
1244 if r'_manifest' in self.__dict__:
1203 try:
1245 try:
1204 return self._manifest.flags(path)
1246 return self._manifest.flags(path)
1205 except KeyError:
1247 except KeyError:
1206 return ''
1248 return ''
1207
1249
1208 try:
1250 try:
1209 return self._flagfunc(path)
1251 return self._flagfunc(path)
1210 except OSError:
1252 except OSError:
1211 return ''
1253 return ''
1212
1254
1213 def ancestor(self, c2):
1255 def ancestor(self, c2):
1214 """return the "best" ancestor context of self and c2"""
1256 """return the "best" ancestor context of self and c2"""
1215 return self._parents[0].ancestor(c2) # punt on two parents for now
1257 return self._parents[0].ancestor(c2) # punt on two parents for now
1216
1258
1217 def walk(self, match):
1259 def walk(self, match):
1218 '''Generates matching file names.'''
1260 '''Generates matching file names.'''
1219 return sorted(self._repo.dirstate.walk(self._repo.narrowmatch(match),
1261 return sorted(self._repo.dirstate.walk(self._repo.narrowmatch(match),
1220 subrepos=sorted(self.substate),
1262 subrepos=sorted(self.substate),
1221 unknown=True, ignored=False))
1263 unknown=True, ignored=False))
1222
1264
1223 def matches(self, match):
1265 def matches(self, match):
1224 match = self._repo.narrowmatch(match)
1266 match = self._repo.narrowmatch(match)
1225 ds = self._repo.dirstate
1267 ds = self._repo.dirstate
1226 return sorted(f for f in ds.matches(match) if ds[f] != 'r')
1268 return sorted(f for f in ds.matches(match) if ds[f] != 'r')
1227
1269
1228 def ancestors(self):
1270 def ancestors(self):
1229 for p in self._parents:
1271 for p in self._parents:
1230 yield p
1272 yield p
1231 for a in self._repo.changelog.ancestors(
1273 for a in self._repo.changelog.ancestors(
1232 [p.rev() for p in self._parents]):
1274 [p.rev() for p in self._parents]):
1233 yield self._repo[a]
1275 yield self._repo[a]
1234
1276
1235 def markcommitted(self, node):
1277 def markcommitted(self, node):
1236 """Perform post-commit cleanup necessary after committing this ctx
1278 """Perform post-commit cleanup necessary after committing this ctx
1237
1279
1238 Specifically, this updates backing stores this working context
1280 Specifically, this updates backing stores this working context
1239 wraps to reflect the fact that the changes reflected by this
1281 wraps to reflect the fact that the changes reflected by this
1240 workingctx have been committed. For example, it marks
1282 workingctx have been committed. For example, it marks
1241 modified and added files as normal in the dirstate.
1283 modified and added files as normal in the dirstate.
1242
1284
1243 """
1285 """
1244
1286
1245 with self._repo.dirstate.parentchange():
1287 with self._repo.dirstate.parentchange():
1246 for f in self.modified() + self.added():
1288 for f in self.modified() + self.added():
1247 self._repo.dirstate.normal(f)
1289 self._repo.dirstate.normal(f)
1248 for f in self.removed():
1290 for f in self.removed():
1249 self._repo.dirstate.drop(f)
1291 self._repo.dirstate.drop(f)
1250 self._repo.dirstate.setparents(node)
1292 self._repo.dirstate.setparents(node)
1251
1293
1252 # write changes out explicitly, because nesting wlock at
1294 # write changes out explicitly, because nesting wlock at
1253 # runtime may prevent 'wlock.release()' in 'repo.commit()'
1295 # runtime may prevent 'wlock.release()' in 'repo.commit()'
1254 # from immediately doing so for subsequent changing files
1296 # from immediately doing so for subsequent changing files
1255 self._repo.dirstate.write(self._repo.currenttransaction())
1297 self._repo.dirstate.write(self._repo.currenttransaction())
1256
1298
1257 def dirty(self, missing=False, merge=True, branch=True):
1299 def dirty(self, missing=False, merge=True, branch=True):
1258 return False
1300 return False
1259
1301
1260 class workingctx(committablectx):
1302 class workingctx(committablectx):
1261 """A workingctx object makes access to data related to
1303 """A workingctx object makes access to data related to
1262 the current working directory convenient.
1304 the current working directory convenient.
1263 date - any valid date string or (unixtime, offset), or None.
1305 date - any valid date string or (unixtime, offset), or None.
1264 user - username string, or None.
1306 user - username string, or None.
1265 extra - a dictionary of extra values, or None.
1307 extra - a dictionary of extra values, or None.
1266 changes - a list of file lists as returned by localrepo.status()
1308 changes - a list of file lists as returned by localrepo.status()
1267 or None to use the repository status.
1309 or None to use the repository status.
1268 """
1310 """
1269 def __init__(self, repo, text="", user=None, date=None, extra=None,
1311 def __init__(self, repo, text="", user=None, date=None, extra=None,
1270 changes=None):
1312 changes=None):
1271 super(workingctx, self).__init__(repo, text, user, date, extra, changes)
1313 super(workingctx, self).__init__(repo, text, user, date, extra, changes)
1272
1314
1273 def __iter__(self):
1315 def __iter__(self):
1274 d = self._repo.dirstate
1316 d = self._repo.dirstate
1275 for f in d:
1317 for f in d:
1276 if d[f] != 'r':
1318 if d[f] != 'r':
1277 yield f
1319 yield f
1278
1320
1279 def __contains__(self, key):
1321 def __contains__(self, key):
1280 return self._repo.dirstate[key] not in "?r"
1322 return self._repo.dirstate[key] not in "?r"
1281
1323
1282 def hex(self):
1324 def hex(self):
1283 return hex(wdirid)
1325 return hex(wdirid)
1284
1326
1285 @propertycache
1327 @propertycache
1286 def _parents(self):
1328 def _parents(self):
1287 p = self._repo.dirstate.parents()
1329 p = self._repo.dirstate.parents()
1288 if p[1] == nullid:
1330 if p[1] == nullid:
1289 p = p[:-1]
1331 p = p[:-1]
1290 # use unfiltered repo to delay/avoid loading obsmarkers
1332 # use unfiltered repo to delay/avoid loading obsmarkers
1291 unfi = self._repo.unfiltered()
1333 unfi = self._repo.unfiltered()
1292 return [changectx(self._repo, unfi.changelog.rev(n), n) for n in p]
1334 return [changectx(self._repo, unfi.changelog.rev(n), n) for n in p]
1293
1335
1294 def _fileinfo(self, path):
1336 def _fileinfo(self, path):
1295 # populate __dict__['_manifest'] as workingctx has no _manifestdelta
1337 # populate __dict__['_manifest'] as workingctx has no _manifestdelta
1296 self._manifest
1338 self._manifest
1297 return super(workingctx, self)._fileinfo(path)
1339 return super(workingctx, self)._fileinfo(path)
1298
1340
1299 def filectx(self, path, filelog=None):
1341 def filectx(self, path, filelog=None):
1300 """get a file context from the working directory"""
1342 """get a file context from the working directory"""
1301 return workingfilectx(self._repo, path, workingctx=self,
1343 return workingfilectx(self._repo, path, workingctx=self,
1302 filelog=filelog)
1344 filelog=filelog)
1303
1345
1304 def dirty(self, missing=False, merge=True, branch=True):
1346 def dirty(self, missing=False, merge=True, branch=True):
1305 "check whether a working directory is modified"
1347 "check whether a working directory is modified"
1306 # check subrepos first
1348 # check subrepos first
1307 for s in sorted(self.substate):
1349 for s in sorted(self.substate):
1308 if self.sub(s).dirty(missing=missing):
1350 if self.sub(s).dirty(missing=missing):
1309 return True
1351 return True
1310 # check current working dir
1352 # check current working dir
1311 return ((merge and self.p2()) or
1353 return ((merge and self.p2()) or
1312 (branch and self.branch() != self.p1().branch()) or
1354 (branch and self.branch() != self.p1().branch()) or
1313 self.modified() or self.added() or self.removed() or
1355 self.modified() or self.added() or self.removed() or
1314 (missing and self.deleted()))
1356 (missing and self.deleted()))
1315
1357
1316 def add(self, list, prefix=""):
1358 def add(self, list, prefix=""):
1317 with self._repo.wlock():
1359 with self._repo.wlock():
1318 ui, ds = self._repo.ui, self._repo.dirstate
1360 ui, ds = self._repo.ui, self._repo.dirstate
1319 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
1361 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
1320 rejected = []
1362 rejected = []
1321 lstat = self._repo.wvfs.lstat
1363 lstat = self._repo.wvfs.lstat
1322 for f in list:
1364 for f in list:
1323 # ds.pathto() returns an absolute file when this is invoked from
1365 # ds.pathto() returns an absolute file when this is invoked from
1324 # the keyword extension. That gets flagged as non-portable on
1366 # the keyword extension. That gets flagged as non-portable on
1325 # Windows, since it contains the drive letter and colon.
1367 # Windows, since it contains the drive letter and colon.
1326 scmutil.checkportable(ui, os.path.join(prefix, f))
1368 scmutil.checkportable(ui, os.path.join(prefix, f))
1327 try:
1369 try:
1328 st = lstat(f)
1370 st = lstat(f)
1329 except OSError:
1371 except OSError:
1330 ui.warn(_("%s does not exist!\n") % uipath(f))
1372 ui.warn(_("%s does not exist!\n") % uipath(f))
1331 rejected.append(f)
1373 rejected.append(f)
1332 continue
1374 continue
1333 limit = ui.configbytes('ui', 'large-file-limit')
1375 limit = ui.configbytes('ui', 'large-file-limit')
1334 if limit != 0 and st.st_size > limit:
1376 if limit != 0 and st.st_size > limit:
1335 ui.warn(_("%s: up to %d MB of RAM may be required "
1377 ui.warn(_("%s: up to %d MB of RAM may be required "
1336 "to manage this file\n"
1378 "to manage this file\n"
1337 "(use 'hg revert %s' to cancel the "
1379 "(use 'hg revert %s' to cancel the "
1338 "pending addition)\n")
1380 "pending addition)\n")
1339 % (f, 3 * st.st_size // 1000000, uipath(f)))
1381 % (f, 3 * st.st_size // 1000000, uipath(f)))
1340 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
1382 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
1341 ui.warn(_("%s not added: only files and symlinks "
1383 ui.warn(_("%s not added: only files and symlinks "
1342 "supported currently\n") % uipath(f))
1384 "supported currently\n") % uipath(f))
1343 rejected.append(f)
1385 rejected.append(f)
1344 elif ds[f] in 'amn':
1386 elif ds[f] in 'amn':
1345 ui.warn(_("%s already tracked!\n") % uipath(f))
1387 ui.warn(_("%s already tracked!\n") % uipath(f))
1346 elif ds[f] == 'r':
1388 elif ds[f] == 'r':
1347 ds.normallookup(f)
1389 ds.normallookup(f)
1348 else:
1390 else:
1349 ds.add(f)
1391 ds.add(f)
1350 return rejected
1392 return rejected
1351
1393
1352 def forget(self, files, prefix=""):
1394 def forget(self, files, prefix=""):
1353 with self._repo.wlock():
1395 with self._repo.wlock():
1354 ds = self._repo.dirstate
1396 ds = self._repo.dirstate
1355 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
1397 uipath = lambda f: ds.pathto(pathutil.join(prefix, f))
1356 rejected = []
1398 rejected = []
1357 for f in files:
1399 for f in files:
1358 if f not in ds:
1400 if f not in ds:
1359 self._repo.ui.warn(_("%s not tracked!\n") % uipath(f))
1401 self._repo.ui.warn(_("%s not tracked!\n") % uipath(f))
1360 rejected.append(f)
1402 rejected.append(f)
1361 elif ds[f] != 'a':
1403 elif ds[f] != 'a':
1362 ds.remove(f)
1404 ds.remove(f)
1363 else:
1405 else:
1364 ds.drop(f)
1406 ds.drop(f)
1365 return rejected
1407 return rejected
1366
1408
1367 def copy(self, source, dest):
1409 def copy(self, source, dest):
1368 try:
1410 try:
1369 st = self._repo.wvfs.lstat(dest)
1411 st = self._repo.wvfs.lstat(dest)
1370 except OSError as err:
1412 except OSError as err:
1371 if err.errno != errno.ENOENT:
1413 if err.errno != errno.ENOENT:
1372 raise
1414 raise
1373 self._repo.ui.warn(_("%s does not exist!\n")
1415 self._repo.ui.warn(_("%s does not exist!\n")
1374 % self._repo.dirstate.pathto(dest))
1416 % self._repo.dirstate.pathto(dest))
1375 return
1417 return
1376 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
1418 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
1377 self._repo.ui.warn(_("copy failed: %s is not a file or a "
1419 self._repo.ui.warn(_("copy failed: %s is not a file or a "
1378 "symbolic link\n")
1420 "symbolic link\n")
1379 % self._repo.dirstate.pathto(dest))
1421 % self._repo.dirstate.pathto(dest))
1380 else:
1422 else:
1381 with self._repo.wlock():
1423 with self._repo.wlock():
1382 ds = self._repo.dirstate
1424 ds = self._repo.dirstate
1383 if ds[dest] in '?':
1425 if ds[dest] in '?':
1384 ds.add(dest)
1426 ds.add(dest)
1385 elif ds[dest] in 'r':
1427 elif ds[dest] in 'r':
1386 ds.normallookup(dest)
1428 ds.normallookup(dest)
1387 ds.copy(source, dest)
1429 ds.copy(source, dest)
1388
1430
1389 def match(self, pats=None, include=None, exclude=None, default='glob',
1431 def match(self, pats=None, include=None, exclude=None, default='glob',
1390 listsubrepos=False, badfn=None):
1432 listsubrepos=False, badfn=None):
1391 r = self._repo
1433 r = self._repo
1392
1434
1393 # Only a case insensitive filesystem needs magic to translate user input
1435 # Only a case insensitive filesystem needs magic to translate user input
1394 # to actual case in the filesystem.
1436 # to actual case in the filesystem.
1395 icasefs = not util.fscasesensitive(r.root)
1437 icasefs = not util.fscasesensitive(r.root)
1396 return matchmod.match(r.root, r.getcwd(), pats, include, exclude,
1438 return matchmod.match(r.root, r.getcwd(), pats, include, exclude,
1397 default, auditor=r.auditor, ctx=self,
1439 default, auditor=r.auditor, ctx=self,
1398 listsubrepos=listsubrepos, badfn=badfn,
1440 listsubrepos=listsubrepos, badfn=badfn,
1399 icasefs=icasefs)
1441 icasefs=icasefs)
1400
1442
1401 def _filtersuspectsymlink(self, files):
1443 def _filtersuspectsymlink(self, files):
1402 if not files or self._repo.dirstate._checklink:
1444 if not files or self._repo.dirstate._checklink:
1403 return files
1445 return files
1404
1446
1405 # Symlink placeholders may get non-symlink-like contents
1447 # Symlink placeholders may get non-symlink-like contents
1406 # via user error or dereferencing by NFS or Samba servers,
1448 # via user error or dereferencing by NFS or Samba servers,
1407 # so we filter out any placeholders that don't look like a
1449 # so we filter out any placeholders that don't look like a
1408 # symlink
1450 # symlink
1409 sane = []
1451 sane = []
1410 for f in files:
1452 for f in files:
1411 if self.flags(f) == 'l':
1453 if self.flags(f) == 'l':
1412 d = self[f].data()
1454 d = self[f].data()
1413 if (d == '' or len(d) >= 1024 or '\n' in d
1455 if (d == '' or len(d) >= 1024 or '\n' in d
1414 or stringutil.binary(d)):
1456 or stringutil.binary(d)):
1415 self._repo.ui.debug('ignoring suspect symlink placeholder'
1457 self._repo.ui.debug('ignoring suspect symlink placeholder'
1416 ' "%s"\n' % f)
1458 ' "%s"\n' % f)
1417 continue
1459 continue
1418 sane.append(f)
1460 sane.append(f)
1419 return sane
1461 return sane
1420
1462
1421 def _checklookup(self, files):
1463 def _checklookup(self, files):
1422 # check for any possibly clean files
1464 # check for any possibly clean files
1423 if not files:
1465 if not files:
1424 return [], [], []
1466 return [], [], []
1425
1467
1426 modified = []
1468 modified = []
1427 deleted = []
1469 deleted = []
1428 fixup = []
1470 fixup = []
1429 pctx = self._parents[0]
1471 pctx = self._parents[0]
1430 # do a full compare of any files that might have changed
1472 # do a full compare of any files that might have changed
1431 for f in sorted(files):
1473 for f in sorted(files):
1432 try:
1474 try:
1433 # This will return True for a file that got replaced by a
1475 # This will return True for a file that got replaced by a
1434 # directory in the interim, but fixing that is pretty hard.
1476 # directory in the interim, but fixing that is pretty hard.
1435 if (f not in pctx or self.flags(f) != pctx.flags(f)
1477 if (f not in pctx or self.flags(f) != pctx.flags(f)
1436 or pctx[f].cmp(self[f])):
1478 or pctx[f].cmp(self[f])):
1437 modified.append(f)
1479 modified.append(f)
1438 else:
1480 else:
1439 fixup.append(f)
1481 fixup.append(f)
1440 except (IOError, OSError):
1482 except (IOError, OSError):
1441 # A file become inaccessible in between? Mark it as deleted,
1483 # A file become inaccessible in between? Mark it as deleted,
1442 # matching dirstate behavior (issue5584).
1484 # matching dirstate behavior (issue5584).
1443 # The dirstate has more complex behavior around whether a
1485 # The dirstate has more complex behavior around whether a
1444 # missing file matches a directory, etc, but we don't need to
1486 # missing file matches a directory, etc, but we don't need to
1445 # bother with that: if f has made it to this point, we're sure
1487 # bother with that: if f has made it to this point, we're sure
1446 # it's in the dirstate.
1488 # it's in the dirstate.
1447 deleted.append(f)
1489 deleted.append(f)
1448
1490
1449 return modified, deleted, fixup
1491 return modified, deleted, fixup
1450
1492
1451 def _poststatusfixup(self, status, fixup):
1493 def _poststatusfixup(self, status, fixup):
1452 """update dirstate for files that are actually clean"""
1494 """update dirstate for files that are actually clean"""
1453 poststatus = self._repo.postdsstatus()
1495 poststatus = self._repo.postdsstatus()
1454 if fixup or poststatus:
1496 if fixup or poststatus:
1455 try:
1497 try:
1456 oldid = self._repo.dirstate.identity()
1498 oldid = self._repo.dirstate.identity()
1457
1499
1458 # updating the dirstate is optional
1500 # updating the dirstate is optional
1459 # so we don't wait on the lock
1501 # so we don't wait on the lock
1460 # wlock can invalidate the dirstate, so cache normal _after_
1502 # wlock can invalidate the dirstate, so cache normal _after_
1461 # taking the lock
1503 # taking the lock
1462 with self._repo.wlock(False):
1504 with self._repo.wlock(False):
1463 if self._repo.dirstate.identity() == oldid:
1505 if self._repo.dirstate.identity() == oldid:
1464 if fixup:
1506 if fixup:
1465 normal = self._repo.dirstate.normal
1507 normal = self._repo.dirstate.normal
1466 for f in fixup:
1508 for f in fixup:
1467 normal(f)
1509 normal(f)
1468 # write changes out explicitly, because nesting
1510 # write changes out explicitly, because nesting
1469 # wlock at runtime may prevent 'wlock.release()'
1511 # wlock at runtime may prevent 'wlock.release()'
1470 # after this block from doing so for subsequent
1512 # after this block from doing so for subsequent
1471 # changing files
1513 # changing files
1472 tr = self._repo.currenttransaction()
1514 tr = self._repo.currenttransaction()
1473 self._repo.dirstate.write(tr)
1515 self._repo.dirstate.write(tr)
1474
1516
1475 if poststatus:
1517 if poststatus:
1476 for ps in poststatus:
1518 for ps in poststatus:
1477 ps(self, status)
1519 ps(self, status)
1478 else:
1520 else:
1479 # in this case, writing changes out breaks
1521 # in this case, writing changes out breaks
1480 # consistency, because .hg/dirstate was
1522 # consistency, because .hg/dirstate was
1481 # already changed simultaneously after last
1523 # already changed simultaneously after last
1482 # caching (see also issue5584 for detail)
1524 # caching (see also issue5584 for detail)
1483 self._repo.ui.debug('skip updating dirstate: '
1525 self._repo.ui.debug('skip updating dirstate: '
1484 'identity mismatch\n')
1526 'identity mismatch\n')
1485 except error.LockError:
1527 except error.LockError:
1486 pass
1528 pass
1487 finally:
1529 finally:
1488 # Even if the wlock couldn't be grabbed, clear out the list.
1530 # Even if the wlock couldn't be grabbed, clear out the list.
1489 self._repo.clearpostdsstatus()
1531 self._repo.clearpostdsstatus()
1490
1532
1491 def _dirstatestatus(self, match, ignored=False, clean=False, unknown=False):
1533 def _dirstatestatus(self, match, ignored=False, clean=False, unknown=False):
1492 '''Gets the status from the dirstate -- internal use only.'''
1534 '''Gets the status from the dirstate -- internal use only.'''
1493 subrepos = []
1535 subrepos = []
1494 if '.hgsub' in self:
1536 if '.hgsub' in self:
1495 subrepos = sorted(self.substate)
1537 subrepos = sorted(self.substate)
1496 cmp, s = self._repo.dirstate.status(match, subrepos, ignored=ignored,
1538 cmp, s = self._repo.dirstate.status(match, subrepos, ignored=ignored,
1497 clean=clean, unknown=unknown)
1539 clean=clean, unknown=unknown)
1498
1540
1499 # check for any possibly clean files
1541 # check for any possibly clean files
1500 fixup = []
1542 fixup = []
1501 if cmp:
1543 if cmp:
1502 modified2, deleted2, fixup = self._checklookup(cmp)
1544 modified2, deleted2, fixup = self._checklookup(cmp)
1503 s.modified.extend(modified2)
1545 s.modified.extend(modified2)
1504 s.deleted.extend(deleted2)
1546 s.deleted.extend(deleted2)
1505
1547
1506 if fixup and clean:
1548 if fixup and clean:
1507 s.clean.extend(fixup)
1549 s.clean.extend(fixup)
1508
1550
1509 self._poststatusfixup(s, fixup)
1551 self._poststatusfixup(s, fixup)
1510
1552
1511 if match.always():
1553 if match.always():
1512 # cache for performance
1554 # cache for performance
1513 if s.unknown or s.ignored or s.clean:
1555 if s.unknown or s.ignored or s.clean:
1514 # "_status" is cached with list*=False in the normal route
1556 # "_status" is cached with list*=False in the normal route
1515 self._status = scmutil.status(s.modified, s.added, s.removed,
1557 self._status = scmutil.status(s.modified, s.added, s.removed,
1516 s.deleted, [], [], [])
1558 s.deleted, [], [], [])
1517 else:
1559 else:
1518 self._status = s
1560 self._status = s
1519
1561
1520 return s
1562 return s
1521
1563
1522 @propertycache
1564 @propertycache
1523 def _manifest(self):
1565 def _manifest(self):
1524 """generate a manifest corresponding to the values in self._status
1566 """generate a manifest corresponding to the values in self._status
1525
1567
1526 This reuse the file nodeid from parent, but we use special node
1568 This reuse the file nodeid from parent, but we use special node
1527 identifiers for added and modified files. This is used by manifests
1569 identifiers for added and modified files. This is used by manifests
1528 merge to see that files are different and by update logic to avoid
1570 merge to see that files are different and by update logic to avoid
1529 deleting newly added files.
1571 deleting newly added files.
1530 """
1572 """
1531 return self._buildstatusmanifest(self._status)
1573 return self._buildstatusmanifest(self._status)
1532
1574
1533 def _buildstatusmanifest(self, status):
1575 def _buildstatusmanifest(self, status):
1534 """Builds a manifest that includes the given status results."""
1576 """Builds a manifest that includes the given status results."""
1535 parents = self.parents()
1577 parents = self.parents()
1536
1578
1537 man = parents[0].manifest().copy()
1579 man = parents[0].manifest().copy()
1538
1580
1539 ff = self._flagfunc
1581 ff = self._flagfunc
1540 for i, l in ((addednodeid, status.added),
1582 for i, l in ((addednodeid, status.added),
1541 (modifiednodeid, status.modified)):
1583 (modifiednodeid, status.modified)):
1542 for f in l:
1584 for f in l:
1543 man[f] = i
1585 man[f] = i
1544 try:
1586 try:
1545 man.setflag(f, ff(f))
1587 man.setflag(f, ff(f))
1546 except OSError:
1588 except OSError:
1547 pass
1589 pass
1548
1590
1549 for f in status.deleted + status.removed:
1591 for f in status.deleted + status.removed:
1550 if f in man:
1592 if f in man:
1551 del man[f]
1593 del man[f]
1552
1594
1553 return man
1595 return man
1554
1596
1555 def _buildstatus(self, other, s, match, listignored, listclean,
1597 def _buildstatus(self, other, s, match, listignored, listclean,
1556 listunknown):
1598 listunknown):
1557 """build a status with respect to another context
1599 """build a status with respect to another context
1558
1600
1559 This includes logic for maintaining the fast path of status when
1601 This includes logic for maintaining the fast path of status when
1560 comparing the working directory against its parent, which is to skip
1602 comparing the working directory against its parent, which is to skip
1561 building a new manifest if self (working directory) is not comparing
1603 building a new manifest if self (working directory) is not comparing
1562 against its parent (repo['.']).
1604 against its parent (repo['.']).
1563 """
1605 """
1564 s = self._dirstatestatus(match, listignored, listclean, listunknown)
1606 s = self._dirstatestatus(match, listignored, listclean, listunknown)
1565 # Filter out symlinks that, in the case of FAT32 and NTFS filesystems,
1607 # Filter out symlinks that, in the case of FAT32 and NTFS filesystems,
1566 # might have accidentally ended up with the entire contents of the file
1608 # might have accidentally ended up with the entire contents of the file
1567 # they are supposed to be linking to.
1609 # they are supposed to be linking to.
1568 s.modified[:] = self._filtersuspectsymlink(s.modified)
1610 s.modified[:] = self._filtersuspectsymlink(s.modified)
1569 if other != self._repo['.']:
1611 if other != self._repo['.']:
1570 s = super(workingctx, self)._buildstatus(other, s, match,
1612 s = super(workingctx, self)._buildstatus(other, s, match,
1571 listignored, listclean,
1613 listignored, listclean,
1572 listunknown)
1614 listunknown)
1573 return s
1615 return s
1574
1616
1575 def _matchstatus(self, other, match):
1617 def _matchstatus(self, other, match):
1576 """override the match method with a filter for directory patterns
1618 """override the match method with a filter for directory patterns
1577
1619
1578 We use inheritance to customize the match.bad method only in cases of
1620 We use inheritance to customize the match.bad method only in cases of
1579 workingctx since it belongs only to the working directory when
1621 workingctx since it belongs only to the working directory when
1580 comparing against the parent changeset.
1622 comparing against the parent changeset.
1581
1623
1582 If we aren't comparing against the working directory's parent, then we
1624 If we aren't comparing against the working directory's parent, then we
1583 just use the default match object sent to us.
1625 just use the default match object sent to us.
1584 """
1626 """
1585 if other != self._repo['.']:
1627 if other != self._repo['.']:
1586 def bad(f, msg):
1628 def bad(f, msg):
1587 # 'f' may be a directory pattern from 'match.files()',
1629 # 'f' may be a directory pattern from 'match.files()',
1588 # so 'f not in ctx1' is not enough
1630 # so 'f not in ctx1' is not enough
1589 if f not in other and not other.hasdir(f):
1631 if f not in other and not other.hasdir(f):
1590 self._repo.ui.warn('%s: %s\n' %
1632 self._repo.ui.warn('%s: %s\n' %
1591 (self._repo.dirstate.pathto(f), msg))
1633 (self._repo.dirstate.pathto(f), msg))
1592 match.bad = bad
1634 match.bad = bad
1593 return match
1635 return match
1594
1636
1595 def markcommitted(self, node):
1637 def markcommitted(self, node):
1596 super(workingctx, self).markcommitted(node)
1638 super(workingctx, self).markcommitted(node)
1597
1639
1598 sparse.aftercommit(self._repo, node)
1640 sparse.aftercommit(self._repo, node)
1599
1641
1600 class committablefilectx(basefilectx):
1642 class committablefilectx(basefilectx):
1601 """A committablefilectx provides common functionality for a file context
1643 """A committablefilectx provides common functionality for a file context
1602 that wants the ability to commit, e.g. workingfilectx or memfilectx."""
1644 that wants the ability to commit, e.g. workingfilectx or memfilectx."""
1603 def __init__(self, repo, path, filelog=None, ctx=None):
1645 def __init__(self, repo, path, filelog=None, ctx=None):
1604 self._repo = repo
1646 self._repo = repo
1605 self._path = path
1647 self._path = path
1606 self._changeid = None
1648 self._changeid = None
1607 self._filerev = self._filenode = None
1649 self._filerev = self._filenode = None
1608
1650
1609 if filelog is not None:
1651 if filelog is not None:
1610 self._filelog = filelog
1652 self._filelog = filelog
1611 if ctx:
1653 if ctx:
1612 self._changectx = ctx
1654 self._changectx = ctx
1613
1655
1614 def __nonzero__(self):
1656 def __nonzero__(self):
1615 return True
1657 return True
1616
1658
1617 __bool__ = __nonzero__
1659 __bool__ = __nonzero__
1618
1660
1619 def linkrev(self):
1661 def linkrev(self):
1620 # linked to self._changectx no matter if file is modified or not
1662 # linked to self._changectx no matter if file is modified or not
1621 return self.rev()
1663 return self.rev()
1622
1664
1623 def parents(self):
1665 def parents(self):
1624 '''return parent filectxs, following copies if necessary'''
1666 '''return parent filectxs, following copies if necessary'''
1625 def filenode(ctx, path):
1667 def filenode(ctx, path):
1626 return ctx._manifest.get(path, nullid)
1668 return ctx._manifest.get(path, nullid)
1627
1669
1628 path = self._path
1670 path = self._path
1629 fl = self._filelog
1671 fl = self._filelog
1630 pcl = self._changectx._parents
1672 pcl = self._changectx._parents
1631 renamed = self.renamed()
1673 renamed = self.renamed()
1632
1674
1633 if renamed:
1675 if renamed:
1634 pl = [renamed + (None,)]
1676 pl = [renamed + (None,)]
1635 else:
1677 else:
1636 pl = [(path, filenode(pcl[0], path), fl)]
1678 pl = [(path, filenode(pcl[0], path), fl)]
1637
1679
1638 for pc in pcl[1:]:
1680 for pc in pcl[1:]:
1639 pl.append((path, filenode(pc, path), fl))
1681 pl.append((path, filenode(pc, path), fl))
1640
1682
1641 return [self._parentfilectx(p, fileid=n, filelog=l)
1683 return [self._parentfilectx(p, fileid=n, filelog=l)
1642 for p, n, l in pl if n != nullid]
1684 for p, n, l in pl if n != nullid]
1643
1685
1644 def children(self):
1686 def children(self):
1645 return []
1687 return []
1646
1688
1647 class workingfilectx(committablefilectx):
1689 class workingfilectx(committablefilectx):
1648 """A workingfilectx object makes access to data related to a particular
1690 """A workingfilectx object makes access to data related to a particular
1649 file in the working directory convenient."""
1691 file in the working directory convenient."""
1650 def __init__(self, repo, path, filelog=None, workingctx=None):
1692 def __init__(self, repo, path, filelog=None, workingctx=None):
1651 super(workingfilectx, self).__init__(repo, path, filelog, workingctx)
1693 super(workingfilectx, self).__init__(repo, path, filelog, workingctx)
1652
1694
1653 @propertycache
1695 @propertycache
1654 def _changectx(self):
1696 def _changectx(self):
1655 return workingctx(self._repo)
1697 return workingctx(self._repo)
1656
1698
1657 def data(self):
1699 def data(self):
1658 return self._repo.wread(self._path)
1700 return self._repo.wread(self._path)
1659 def renamed(self):
1701 def renamed(self):
1660 rp = self._repo.dirstate.copied(self._path)
1702 rp = self._repo.dirstate.copied(self._path)
1661 if not rp:
1703 if not rp:
1662 return None
1704 return None
1663 return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
1705 return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
1664
1706
1665 def size(self):
1707 def size(self):
1666 return self._repo.wvfs.lstat(self._path).st_size
1708 return self._repo.wvfs.lstat(self._path).st_size
1667 def date(self):
1709 def date(self):
1668 t, tz = self._changectx.date()
1710 t, tz = self._changectx.date()
1669 try:
1711 try:
1670 return (self._repo.wvfs.lstat(self._path)[stat.ST_MTIME], tz)
1712 return (self._repo.wvfs.lstat(self._path)[stat.ST_MTIME], tz)
1671 except OSError as err:
1713 except OSError as err:
1672 if err.errno != errno.ENOENT:
1714 if err.errno != errno.ENOENT:
1673 raise
1715 raise
1674 return (t, tz)
1716 return (t, tz)
1675
1717
1676 def exists(self):
1718 def exists(self):
1677 return self._repo.wvfs.exists(self._path)
1719 return self._repo.wvfs.exists(self._path)
1678
1720
1679 def lexists(self):
1721 def lexists(self):
1680 return self._repo.wvfs.lexists(self._path)
1722 return self._repo.wvfs.lexists(self._path)
1681
1723
1682 def audit(self):
1724 def audit(self):
1683 return self._repo.wvfs.audit(self._path)
1725 return self._repo.wvfs.audit(self._path)
1684
1726
1685 def cmp(self, fctx):
1727 def cmp(self, fctx):
1686 """compare with other file context
1728 """compare with other file context
1687
1729
1688 returns True if different than fctx.
1730 returns True if different than fctx.
1689 """
1731 """
1690 # fctx should be a filectx (not a workingfilectx)
1732 # fctx should be a filectx (not a workingfilectx)
1691 # invert comparison to reuse the same code path
1733 # invert comparison to reuse the same code path
1692 return fctx.cmp(self)
1734 return fctx.cmp(self)
1693
1735
1694 def remove(self, ignoremissing=False):
1736 def remove(self, ignoremissing=False):
1695 """wraps unlink for a repo's working directory"""
1737 """wraps unlink for a repo's working directory"""
1696 rmdir = self._repo.ui.configbool('experimental', 'removeemptydirs')
1738 rmdir = self._repo.ui.configbool('experimental', 'removeemptydirs')
1697 self._repo.wvfs.unlinkpath(self._path, ignoremissing=ignoremissing,
1739 self._repo.wvfs.unlinkpath(self._path, ignoremissing=ignoremissing,
1698 rmdir=rmdir)
1740 rmdir=rmdir)
1699
1741
1700 def write(self, data, flags, backgroundclose=False, **kwargs):
1742 def write(self, data, flags, backgroundclose=False, **kwargs):
1701 """wraps repo.wwrite"""
1743 """wraps repo.wwrite"""
1702 self._repo.wwrite(self._path, data, flags,
1744 self._repo.wwrite(self._path, data, flags,
1703 backgroundclose=backgroundclose,
1745 backgroundclose=backgroundclose,
1704 **kwargs)
1746 **kwargs)
1705
1747
1706 def markcopied(self, src):
1748 def markcopied(self, src):
1707 """marks this file a copy of `src`"""
1749 """marks this file a copy of `src`"""
1708 if self._repo.dirstate[self._path] in "nma":
1750 if self._repo.dirstate[self._path] in "nma":
1709 self._repo.dirstate.copy(src, self._path)
1751 self._repo.dirstate.copy(src, self._path)
1710
1752
1711 def clearunknown(self):
1753 def clearunknown(self):
1712 """Removes conflicting items in the working directory so that
1754 """Removes conflicting items in the working directory so that
1713 ``write()`` can be called successfully.
1755 ``write()`` can be called successfully.
1714 """
1756 """
1715 wvfs = self._repo.wvfs
1757 wvfs = self._repo.wvfs
1716 f = self._path
1758 f = self._path
1717 wvfs.audit(f)
1759 wvfs.audit(f)
1718 if self._repo.ui.configbool('experimental', 'merge.checkpathconflicts'):
1760 if self._repo.ui.configbool('experimental', 'merge.checkpathconflicts'):
1719 # remove files under the directory as they should already be
1761 # remove files under the directory as they should already be
1720 # warned and backed up
1762 # warned and backed up
1721 if wvfs.isdir(f) and not wvfs.islink(f):
1763 if wvfs.isdir(f) and not wvfs.islink(f):
1722 wvfs.rmtree(f, forcibly=True)
1764 wvfs.rmtree(f, forcibly=True)
1723 for p in reversed(list(util.finddirs(f))):
1765 for p in reversed(list(util.finddirs(f))):
1724 if wvfs.isfileorlink(p):
1766 if wvfs.isfileorlink(p):
1725 wvfs.unlink(p)
1767 wvfs.unlink(p)
1726 break
1768 break
1727 else:
1769 else:
1728 # don't remove files if path conflicts are not processed
1770 # don't remove files if path conflicts are not processed
1729 if wvfs.isdir(f) and not wvfs.islink(f):
1771 if wvfs.isdir(f) and not wvfs.islink(f):
1730 wvfs.removedirs(f)
1772 wvfs.removedirs(f)
1731
1773
1732 def setflags(self, l, x):
1774 def setflags(self, l, x):
1733 self._repo.wvfs.setflags(self._path, l, x)
1775 self._repo.wvfs.setflags(self._path, l, x)
1734
1776
1735 class overlayworkingctx(committablectx):
1777 class overlayworkingctx(committablectx):
1736 """Wraps another mutable context with a write-back cache that can be
1778 """Wraps another mutable context with a write-back cache that can be
1737 converted into a commit context.
1779 converted into a commit context.
1738
1780
1739 self._cache[path] maps to a dict with keys: {
1781 self._cache[path] maps to a dict with keys: {
1740 'exists': bool?
1782 'exists': bool?
1741 'date': date?
1783 'date': date?
1742 'data': str?
1784 'data': str?
1743 'flags': str?
1785 'flags': str?
1744 'copied': str? (path or None)
1786 'copied': str? (path or None)
1745 }
1787 }
1746 If `exists` is True, `flags` must be non-None and 'date' is non-None. If it
1788 If `exists` is True, `flags` must be non-None and 'date' is non-None. If it
1747 is `False`, the file was deleted.
1789 is `False`, the file was deleted.
1748 """
1790 """
1749
1791
1750 def __init__(self, repo):
1792 def __init__(self, repo):
1751 super(overlayworkingctx, self).__init__(repo)
1793 super(overlayworkingctx, self).__init__(repo)
1752 self.clean()
1794 self.clean()
1753
1795
1754 def setbase(self, wrappedctx):
1796 def setbase(self, wrappedctx):
1755 self._wrappedctx = wrappedctx
1797 self._wrappedctx = wrappedctx
1756 self._parents = [wrappedctx]
1798 self._parents = [wrappedctx]
1757 # Drop old manifest cache as it is now out of date.
1799 # Drop old manifest cache as it is now out of date.
1758 # This is necessary when, e.g., rebasing several nodes with one
1800 # This is necessary when, e.g., rebasing several nodes with one
1759 # ``overlayworkingctx`` (e.g. with --collapse).
1801 # ``overlayworkingctx`` (e.g. with --collapse).
1760 util.clearcachedproperty(self, '_manifest')
1802 util.clearcachedproperty(self, '_manifest')
1761
1803
1762 def data(self, path):
1804 def data(self, path):
1763 if self.isdirty(path):
1805 if self.isdirty(path):
1764 if self._cache[path]['exists']:
1806 if self._cache[path]['exists']:
1765 if self._cache[path]['data']:
1807 if self._cache[path]['data']:
1766 return self._cache[path]['data']
1808 return self._cache[path]['data']
1767 else:
1809 else:
1768 # Must fallback here, too, because we only set flags.
1810 # Must fallback here, too, because we only set flags.
1769 return self._wrappedctx[path].data()
1811 return self._wrappedctx[path].data()
1770 else:
1812 else:
1771 raise error.ProgrammingError("No such file or directory: %s" %
1813 raise error.ProgrammingError("No such file or directory: %s" %
1772 path)
1814 path)
1773 else:
1815 else:
1774 return self._wrappedctx[path].data()
1816 return self._wrappedctx[path].data()
1775
1817
1776 @propertycache
1818 @propertycache
1777 def _manifest(self):
1819 def _manifest(self):
1778 parents = self.parents()
1820 parents = self.parents()
1779 man = parents[0].manifest().copy()
1821 man = parents[0].manifest().copy()
1780
1822
1781 flag = self._flagfunc
1823 flag = self._flagfunc
1782 for path in self.added():
1824 for path in self.added():
1783 man[path] = addednodeid
1825 man[path] = addednodeid
1784 man.setflag(path, flag(path))
1826 man.setflag(path, flag(path))
1785 for path in self.modified():
1827 for path in self.modified():
1786 man[path] = modifiednodeid
1828 man[path] = modifiednodeid
1787 man.setflag(path, flag(path))
1829 man.setflag(path, flag(path))
1788 for path in self.removed():
1830 for path in self.removed():
1789 del man[path]
1831 del man[path]
1790 return man
1832 return man
1791
1833
1792 @propertycache
1834 @propertycache
1793 def _flagfunc(self):
1835 def _flagfunc(self):
1794 def f(path):
1836 def f(path):
1795 return self._cache[path]['flags']
1837 return self._cache[path]['flags']
1796 return f
1838 return f
1797
1839
1798 def files(self):
1840 def files(self):
1799 return sorted(self.added() + self.modified() + self.removed())
1841 return sorted(self.added() + self.modified() + self.removed())
1800
1842
1801 def modified(self):
1843 def modified(self):
1802 return [f for f in self._cache.keys() if self._cache[f]['exists'] and
1844 return [f for f in self._cache.keys() if self._cache[f]['exists'] and
1803 self._existsinparent(f)]
1845 self._existsinparent(f)]
1804
1846
1805 def added(self):
1847 def added(self):
1806 return [f for f in self._cache.keys() if self._cache[f]['exists'] and
1848 return [f for f in self._cache.keys() if self._cache[f]['exists'] and
1807 not self._existsinparent(f)]
1849 not self._existsinparent(f)]
1808
1850
1809 def removed(self):
1851 def removed(self):
1810 return [f for f in self._cache.keys() if
1852 return [f for f in self._cache.keys() if
1811 not self._cache[f]['exists'] and self._existsinparent(f)]
1853 not self._cache[f]['exists'] and self._existsinparent(f)]
1812
1854
1855 def p1copies(self):
1856 copies = self._repo._wrappedctx.p1copies().copy()
1857 narrowmatch = self._repo.narrowmatch()
1858 for f in self._cache.keys():
1859 if not narrowmatch(f):
1860 continue
1861 copies.pop(f, None) # delete if it exists
1862 source = self._cache[f]['copied']
1863 if source:
1864 copies[f] = source
1865 return copies
1866
1867 def p2copies(self):
1868 copies = self._repo._wrappedctx.p2copies().copy()
1869 narrowmatch = self._repo.narrowmatch()
1870 for f in self._cache.keys():
1871 if not narrowmatch(f):
1872 continue
1873 copies.pop(f, None) # delete if it exists
1874 source = self._cache[f]['copied']
1875 if source:
1876 copies[f] = source
1877 return copies
1878
1813 def isinmemory(self):
1879 def isinmemory(self):
1814 return True
1880 return True
1815
1881
1816 def filedate(self, path):
1882 def filedate(self, path):
1817 if self.isdirty(path):
1883 if self.isdirty(path):
1818 return self._cache[path]['date']
1884 return self._cache[path]['date']
1819 else:
1885 else:
1820 return self._wrappedctx[path].date()
1886 return self._wrappedctx[path].date()
1821
1887
1822 def markcopied(self, path, origin):
1888 def markcopied(self, path, origin):
1823 if self.isdirty(path):
1889 if self.isdirty(path):
1824 self._cache[path]['copied'] = origin
1890 self._cache[path]['copied'] = origin
1825 else:
1891 else:
1826 raise error.ProgrammingError('markcopied() called on clean context')
1892 raise error.ProgrammingError('markcopied() called on clean context')
1827
1893
1828 def copydata(self, path):
1894 def copydata(self, path):
1829 if self.isdirty(path):
1895 if self.isdirty(path):
1830 return self._cache[path]['copied']
1896 return self._cache[path]['copied']
1831 else:
1897 else:
1832 raise error.ProgrammingError('copydata() called on clean context')
1898 raise error.ProgrammingError('copydata() called on clean context')
1833
1899
1834 def flags(self, path):
1900 def flags(self, path):
1835 if self.isdirty(path):
1901 if self.isdirty(path):
1836 if self._cache[path]['exists']:
1902 if self._cache[path]['exists']:
1837 return self._cache[path]['flags']
1903 return self._cache[path]['flags']
1838 else:
1904 else:
1839 raise error.ProgrammingError("No such file or directory: %s" %
1905 raise error.ProgrammingError("No such file or directory: %s" %
1840 self._path)
1906 self._path)
1841 else:
1907 else:
1842 return self._wrappedctx[path].flags()
1908 return self._wrappedctx[path].flags()
1843
1909
1844 def __contains__(self, key):
1910 def __contains__(self, key):
1845 if key in self._cache:
1911 if key in self._cache:
1846 return self._cache[key]['exists']
1912 return self._cache[key]['exists']
1847 return key in self.p1()
1913 return key in self.p1()
1848
1914
1849 def _existsinparent(self, path):
1915 def _existsinparent(self, path):
1850 try:
1916 try:
1851 # ``commitctx` raises a ``ManifestLookupError`` if a path does not
1917 # ``commitctx` raises a ``ManifestLookupError`` if a path does not
1852 # exist, unlike ``workingctx``, which returns a ``workingfilectx``
1918 # exist, unlike ``workingctx``, which returns a ``workingfilectx``
1853 # with an ``exists()`` function.
1919 # with an ``exists()`` function.
1854 self._wrappedctx[path]
1920 self._wrappedctx[path]
1855 return True
1921 return True
1856 except error.ManifestLookupError:
1922 except error.ManifestLookupError:
1857 return False
1923 return False
1858
1924
1859 def _auditconflicts(self, path):
1925 def _auditconflicts(self, path):
1860 """Replicates conflict checks done by wvfs.write().
1926 """Replicates conflict checks done by wvfs.write().
1861
1927
1862 Since we never write to the filesystem and never call `applyupdates` in
1928 Since we never write to the filesystem and never call `applyupdates` in
1863 IMM, we'll never check that a path is actually writable -- e.g., because
1929 IMM, we'll never check that a path is actually writable -- e.g., because
1864 it adds `a/foo`, but `a` is actually a file in the other commit.
1930 it adds `a/foo`, but `a` is actually a file in the other commit.
1865 """
1931 """
1866 def fail(path, component):
1932 def fail(path, component):
1867 # p1() is the base and we're receiving "writes" for p2()'s
1933 # p1() is the base and we're receiving "writes" for p2()'s
1868 # files.
1934 # files.
1869 if 'l' in self.p1()[component].flags():
1935 if 'l' in self.p1()[component].flags():
1870 raise error.Abort("error: %s conflicts with symlink %s "
1936 raise error.Abort("error: %s conflicts with symlink %s "
1871 "in %d." % (path, component,
1937 "in %d." % (path, component,
1872 self.p1().rev()))
1938 self.p1().rev()))
1873 else:
1939 else:
1874 raise error.Abort("error: '%s' conflicts with file '%s' in "
1940 raise error.Abort("error: '%s' conflicts with file '%s' in "
1875 "%d." % (path, component,
1941 "%d." % (path, component,
1876 self.p1().rev()))
1942 self.p1().rev()))
1877
1943
1878 # Test that each new directory to be created to write this path from p2
1944 # Test that each new directory to be created to write this path from p2
1879 # is not a file in p1.
1945 # is not a file in p1.
1880 components = path.split('/')
1946 components = path.split('/')
1881 for i in pycompat.xrange(len(components)):
1947 for i in pycompat.xrange(len(components)):
1882 component = "/".join(components[0:i])
1948 component = "/".join(components[0:i])
1883 if component in self:
1949 if component in self:
1884 fail(path, component)
1950 fail(path, component)
1885
1951
1886 # Test the other direction -- that this path from p2 isn't a directory
1952 # Test the other direction -- that this path from p2 isn't a directory
1887 # in p1 (test that p1 doesn't have any paths matching `path/*`).
1953 # in p1 (test that p1 doesn't have any paths matching `path/*`).
1888 match = self.match(pats=[path + '/'], default=b'path')
1954 match = self.match(pats=[path + '/'], default=b'path')
1889 matches = self.p1().manifest().matches(match)
1955 matches = self.p1().manifest().matches(match)
1890 mfiles = matches.keys()
1956 mfiles = matches.keys()
1891 if len(mfiles) > 0:
1957 if len(mfiles) > 0:
1892 if len(mfiles) == 1 and mfiles[0] == path:
1958 if len(mfiles) == 1 and mfiles[0] == path:
1893 return
1959 return
1894 # omit the files which are deleted in current IMM wctx
1960 # omit the files which are deleted in current IMM wctx
1895 mfiles = [m for m in mfiles if m in self]
1961 mfiles = [m for m in mfiles if m in self]
1896 if not mfiles:
1962 if not mfiles:
1897 return
1963 return
1898 raise error.Abort("error: file '%s' cannot be written because "
1964 raise error.Abort("error: file '%s' cannot be written because "
1899 " '%s/' is a folder in %s (containing %d "
1965 " '%s/' is a folder in %s (containing %d "
1900 "entries: %s)"
1966 "entries: %s)"
1901 % (path, path, self.p1(), len(mfiles),
1967 % (path, path, self.p1(), len(mfiles),
1902 ', '.join(mfiles)))
1968 ', '.join(mfiles)))
1903
1969
1904 def write(self, path, data, flags='', **kwargs):
1970 def write(self, path, data, flags='', **kwargs):
1905 if data is None:
1971 if data is None:
1906 raise error.ProgrammingError("data must be non-None")
1972 raise error.ProgrammingError("data must be non-None")
1907 self._auditconflicts(path)
1973 self._auditconflicts(path)
1908 self._markdirty(path, exists=True, data=data, date=dateutil.makedate(),
1974 self._markdirty(path, exists=True, data=data, date=dateutil.makedate(),
1909 flags=flags)
1975 flags=flags)
1910
1976
1911 def setflags(self, path, l, x):
1977 def setflags(self, path, l, x):
1912 flag = ''
1978 flag = ''
1913 if l:
1979 if l:
1914 flag = 'l'
1980 flag = 'l'
1915 elif x:
1981 elif x:
1916 flag = 'x'
1982 flag = 'x'
1917 self._markdirty(path, exists=True, date=dateutil.makedate(),
1983 self._markdirty(path, exists=True, date=dateutil.makedate(),
1918 flags=flag)
1984 flags=flag)
1919
1985
1920 def remove(self, path):
1986 def remove(self, path):
1921 self._markdirty(path, exists=False)
1987 self._markdirty(path, exists=False)
1922
1988
1923 def exists(self, path):
1989 def exists(self, path):
1924 """exists behaves like `lexists`, but needs to follow symlinks and
1990 """exists behaves like `lexists`, but needs to follow symlinks and
1925 return False if they are broken.
1991 return False if they are broken.
1926 """
1992 """
1927 if self.isdirty(path):
1993 if self.isdirty(path):
1928 # If this path exists and is a symlink, "follow" it by calling
1994 # If this path exists and is a symlink, "follow" it by calling
1929 # exists on the destination path.
1995 # exists on the destination path.
1930 if (self._cache[path]['exists'] and
1996 if (self._cache[path]['exists'] and
1931 'l' in self._cache[path]['flags']):
1997 'l' in self._cache[path]['flags']):
1932 return self.exists(self._cache[path]['data'].strip())
1998 return self.exists(self._cache[path]['data'].strip())
1933 else:
1999 else:
1934 return self._cache[path]['exists']
2000 return self._cache[path]['exists']
1935
2001
1936 return self._existsinparent(path)
2002 return self._existsinparent(path)
1937
2003
1938 def lexists(self, path):
2004 def lexists(self, path):
1939 """lexists returns True if the path exists"""
2005 """lexists returns True if the path exists"""
1940 if self.isdirty(path):
2006 if self.isdirty(path):
1941 return self._cache[path]['exists']
2007 return self._cache[path]['exists']
1942
2008
1943 return self._existsinparent(path)
2009 return self._existsinparent(path)
1944
2010
1945 def size(self, path):
2011 def size(self, path):
1946 if self.isdirty(path):
2012 if self.isdirty(path):
1947 if self._cache[path]['exists']:
2013 if self._cache[path]['exists']:
1948 return len(self._cache[path]['data'])
2014 return len(self._cache[path]['data'])
1949 else:
2015 else:
1950 raise error.ProgrammingError("No such file or directory: %s" %
2016 raise error.ProgrammingError("No such file or directory: %s" %
1951 self._path)
2017 self._path)
1952 return self._wrappedctx[path].size()
2018 return self._wrappedctx[path].size()
1953
2019
1954 def tomemctx(self, text, branch=None, extra=None, date=None, parents=None,
2020 def tomemctx(self, text, branch=None, extra=None, date=None, parents=None,
1955 user=None, editor=None):
2021 user=None, editor=None):
1956 """Converts this ``overlayworkingctx`` into a ``memctx`` ready to be
2022 """Converts this ``overlayworkingctx`` into a ``memctx`` ready to be
1957 committed.
2023 committed.
1958
2024
1959 ``text`` is the commit message.
2025 ``text`` is the commit message.
1960 ``parents`` (optional) are rev numbers.
2026 ``parents`` (optional) are rev numbers.
1961 """
2027 """
1962 # Default parents to the wrapped contexts' if not passed.
2028 # Default parents to the wrapped contexts' if not passed.
1963 if parents is None:
2029 if parents is None:
1964 parents = self._wrappedctx.parents()
2030 parents = self._wrappedctx.parents()
1965 if len(parents) == 1:
2031 if len(parents) == 1:
1966 parents = (parents[0], None)
2032 parents = (parents[0], None)
1967
2033
1968 # ``parents`` is passed as rev numbers; convert to ``commitctxs``.
2034 # ``parents`` is passed as rev numbers; convert to ``commitctxs``.
1969 if parents[1] is None:
2035 if parents[1] is None:
1970 parents = (self._repo[parents[0]], None)
2036 parents = (self._repo[parents[0]], None)
1971 else:
2037 else:
1972 parents = (self._repo[parents[0]], self._repo[parents[1]])
2038 parents = (self._repo[parents[0]], self._repo[parents[1]])
1973
2039
1974 files = self._cache.keys()
2040 files = self._cache.keys()
1975 def getfile(repo, memctx, path):
2041 def getfile(repo, memctx, path):
1976 if self._cache[path]['exists']:
2042 if self._cache[path]['exists']:
1977 return memfilectx(repo, memctx, path,
2043 return memfilectx(repo, memctx, path,
1978 self._cache[path]['data'],
2044 self._cache[path]['data'],
1979 'l' in self._cache[path]['flags'],
2045 'l' in self._cache[path]['flags'],
1980 'x' in self._cache[path]['flags'],
2046 'x' in self._cache[path]['flags'],
1981 self._cache[path]['copied'])
2047 self._cache[path]['copied'])
1982 else:
2048 else:
1983 # Returning None, but including the path in `files`, is
2049 # Returning None, but including the path in `files`, is
1984 # necessary for memctx to register a deletion.
2050 # necessary for memctx to register a deletion.
1985 return None
2051 return None
1986 return memctx(self._repo, parents, text, files, getfile, date=date,
2052 return memctx(self._repo, parents, text, files, getfile, date=date,
1987 extra=extra, user=user, branch=branch, editor=editor)
2053 extra=extra, user=user, branch=branch, editor=editor)
1988
2054
1989 def isdirty(self, path):
2055 def isdirty(self, path):
1990 return path in self._cache
2056 return path in self._cache
1991
2057
1992 def isempty(self):
2058 def isempty(self):
1993 # We need to discard any keys that are actually clean before the empty
2059 # We need to discard any keys that are actually clean before the empty
1994 # commit check.
2060 # commit check.
1995 self._compact()
2061 self._compact()
1996 return len(self._cache) == 0
2062 return len(self._cache) == 0
1997
2063
1998 def clean(self):
2064 def clean(self):
1999 self._cache = {}
2065 self._cache = {}
2000
2066
2001 def _compact(self):
2067 def _compact(self):
2002 """Removes keys from the cache that are actually clean, by comparing
2068 """Removes keys from the cache that are actually clean, by comparing
2003 them with the underlying context.
2069 them with the underlying context.
2004
2070
2005 This can occur during the merge process, e.g. by passing --tool :local
2071 This can occur during the merge process, e.g. by passing --tool :local
2006 to resolve a conflict.
2072 to resolve a conflict.
2007 """
2073 """
2008 keys = []
2074 keys = []
2009 # This won't be perfect, but can help performance significantly when
2075 # This won't be perfect, but can help performance significantly when
2010 # using things like remotefilelog.
2076 # using things like remotefilelog.
2011 scmutil.prefetchfiles(
2077 scmutil.prefetchfiles(
2012 self.repo(), [self.p1().rev()],
2078 self.repo(), [self.p1().rev()],
2013 scmutil.matchfiles(self.repo(), self._cache.keys()))
2079 scmutil.matchfiles(self.repo(), self._cache.keys()))
2014
2080
2015 for path in self._cache.keys():
2081 for path in self._cache.keys():
2016 cache = self._cache[path]
2082 cache = self._cache[path]
2017 try:
2083 try:
2018 underlying = self._wrappedctx[path]
2084 underlying = self._wrappedctx[path]
2019 if (underlying.data() == cache['data'] and
2085 if (underlying.data() == cache['data'] and
2020 underlying.flags() == cache['flags']):
2086 underlying.flags() == cache['flags']):
2021 keys.append(path)
2087 keys.append(path)
2022 except error.ManifestLookupError:
2088 except error.ManifestLookupError:
2023 # Path not in the underlying manifest (created).
2089 # Path not in the underlying manifest (created).
2024 continue
2090 continue
2025
2091
2026 for path in keys:
2092 for path in keys:
2027 del self._cache[path]
2093 del self._cache[path]
2028 return keys
2094 return keys
2029
2095
2030 def _markdirty(self, path, exists, data=None, date=None, flags=''):
2096 def _markdirty(self, path, exists, data=None, date=None, flags=''):
2031 # data not provided, let's see if we already have some; if not, let's
2097 # data not provided, let's see if we already have some; if not, let's
2032 # grab it from our underlying context, so that we always have data if
2098 # grab it from our underlying context, so that we always have data if
2033 # the file is marked as existing.
2099 # the file is marked as existing.
2034 if exists and data is None:
2100 if exists and data is None:
2035 oldentry = self._cache.get(path) or {}
2101 oldentry = self._cache.get(path) or {}
2036 data = oldentry.get('data') or self._wrappedctx[path].data()
2102 data = oldentry.get('data') or self._wrappedctx[path].data()
2037
2103
2038 self._cache[path] = {
2104 self._cache[path] = {
2039 'exists': exists,
2105 'exists': exists,
2040 'data': data,
2106 'data': data,
2041 'date': date,
2107 'date': date,
2042 'flags': flags,
2108 'flags': flags,
2043 'copied': None,
2109 'copied': None,
2044 }
2110 }
2045
2111
2046 def filectx(self, path, filelog=None):
2112 def filectx(self, path, filelog=None):
2047 return overlayworkingfilectx(self._repo, path, parent=self,
2113 return overlayworkingfilectx(self._repo, path, parent=self,
2048 filelog=filelog)
2114 filelog=filelog)
2049
2115
2050 class overlayworkingfilectx(committablefilectx):
2116 class overlayworkingfilectx(committablefilectx):
2051 """Wrap a ``workingfilectx`` but intercepts all writes into an in-memory
2117 """Wrap a ``workingfilectx`` but intercepts all writes into an in-memory
2052 cache, which can be flushed through later by calling ``flush()``."""
2118 cache, which can be flushed through later by calling ``flush()``."""
2053
2119
2054 def __init__(self, repo, path, filelog=None, parent=None):
2120 def __init__(self, repo, path, filelog=None, parent=None):
2055 super(overlayworkingfilectx, self).__init__(repo, path, filelog,
2121 super(overlayworkingfilectx, self).__init__(repo, path, filelog,
2056 parent)
2122 parent)
2057 self._repo = repo
2123 self._repo = repo
2058 self._parent = parent
2124 self._parent = parent
2059 self._path = path
2125 self._path = path
2060
2126
2061 def cmp(self, fctx):
2127 def cmp(self, fctx):
2062 return self.data() != fctx.data()
2128 return self.data() != fctx.data()
2063
2129
2064 def changectx(self):
2130 def changectx(self):
2065 return self._parent
2131 return self._parent
2066
2132
2067 def data(self):
2133 def data(self):
2068 return self._parent.data(self._path)
2134 return self._parent.data(self._path)
2069
2135
2070 def date(self):
2136 def date(self):
2071 return self._parent.filedate(self._path)
2137 return self._parent.filedate(self._path)
2072
2138
2073 def exists(self):
2139 def exists(self):
2074 return self.lexists()
2140 return self.lexists()
2075
2141
2076 def lexists(self):
2142 def lexists(self):
2077 return self._parent.exists(self._path)
2143 return self._parent.exists(self._path)
2078
2144
2079 def renamed(self):
2145 def renamed(self):
2080 path = self._parent.copydata(self._path)
2146 path = self._parent.copydata(self._path)
2081 if not path:
2147 if not path:
2082 return None
2148 return None
2083 return path, self._changectx._parents[0]._manifest.get(path, nullid)
2149 return path, self._changectx._parents[0]._manifest.get(path, nullid)
2084
2150
2085 def size(self):
2151 def size(self):
2086 return self._parent.size(self._path)
2152 return self._parent.size(self._path)
2087
2153
2088 def markcopied(self, origin):
2154 def markcopied(self, origin):
2089 self._parent.markcopied(self._path, origin)
2155 self._parent.markcopied(self._path, origin)
2090
2156
2091 def audit(self):
2157 def audit(self):
2092 pass
2158 pass
2093
2159
2094 def flags(self):
2160 def flags(self):
2095 return self._parent.flags(self._path)
2161 return self._parent.flags(self._path)
2096
2162
2097 def setflags(self, islink, isexec):
2163 def setflags(self, islink, isexec):
2098 return self._parent.setflags(self._path, islink, isexec)
2164 return self._parent.setflags(self._path, islink, isexec)
2099
2165
2100 def write(self, data, flags, backgroundclose=False, **kwargs):
2166 def write(self, data, flags, backgroundclose=False, **kwargs):
2101 return self._parent.write(self._path, data, flags, **kwargs)
2167 return self._parent.write(self._path, data, flags, **kwargs)
2102
2168
2103 def remove(self, ignoremissing=False):
2169 def remove(self, ignoremissing=False):
2104 return self._parent.remove(self._path)
2170 return self._parent.remove(self._path)
2105
2171
2106 def clearunknown(self):
2172 def clearunknown(self):
2107 pass
2173 pass
2108
2174
2109 class workingcommitctx(workingctx):
2175 class workingcommitctx(workingctx):
2110 """A workingcommitctx object makes access to data related to
2176 """A workingcommitctx object makes access to data related to
2111 the revision being committed convenient.
2177 the revision being committed convenient.
2112
2178
2113 This hides changes in the working directory, if they aren't
2179 This hides changes in the working directory, if they aren't
2114 committed in this context.
2180 committed in this context.
2115 """
2181 """
2116 def __init__(self, repo, changes,
2182 def __init__(self, repo, changes,
2117 text="", user=None, date=None, extra=None):
2183 text="", user=None, date=None, extra=None):
2118 super(workingcommitctx, self).__init__(repo, text, user, date, extra,
2184 super(workingcommitctx, self).__init__(repo, text, user, date, extra,
2119 changes)
2185 changes)
2120
2186
2121 def _dirstatestatus(self, match, ignored=False, clean=False, unknown=False):
2187 def _dirstatestatus(self, match, ignored=False, clean=False, unknown=False):
2122 """Return matched files only in ``self._status``
2188 """Return matched files only in ``self._status``
2123
2189
2124 Uncommitted files appear "clean" via this context, even if
2190 Uncommitted files appear "clean" via this context, even if
2125 they aren't actually so in the working directory.
2191 they aren't actually so in the working directory.
2126 """
2192 """
2127 if clean:
2193 if clean:
2128 clean = [f for f in self._manifest if f not in self._changedset]
2194 clean = [f for f in self._manifest if f not in self._changedset]
2129 else:
2195 else:
2130 clean = []
2196 clean = []
2131 return scmutil.status([f for f in self._status.modified if match(f)],
2197 return scmutil.status([f for f in self._status.modified if match(f)],
2132 [f for f in self._status.added if match(f)],
2198 [f for f in self._status.added if match(f)],
2133 [f for f in self._status.removed if match(f)],
2199 [f for f in self._status.removed if match(f)],
2134 [], [], [], clean)
2200 [], [], [], clean)
2135
2201
2136 @propertycache
2202 @propertycache
2137 def _changedset(self):
2203 def _changedset(self):
2138 """Return the set of files changed in this context
2204 """Return the set of files changed in this context
2139 """
2205 """
2140 changed = set(self._status.modified)
2206 changed = set(self._status.modified)
2141 changed.update(self._status.added)
2207 changed.update(self._status.added)
2142 changed.update(self._status.removed)
2208 changed.update(self._status.removed)
2143 return changed
2209 return changed
2144
2210
2145 def makecachingfilectxfn(func):
2211 def makecachingfilectxfn(func):
2146 """Create a filectxfn that caches based on the path.
2212 """Create a filectxfn that caches based on the path.
2147
2213
2148 We can't use util.cachefunc because it uses all arguments as the cache
2214 We can't use util.cachefunc because it uses all arguments as the cache
2149 key and this creates a cycle since the arguments include the repo and
2215 key and this creates a cycle since the arguments include the repo and
2150 memctx.
2216 memctx.
2151 """
2217 """
2152 cache = {}
2218 cache = {}
2153
2219
2154 def getfilectx(repo, memctx, path):
2220 def getfilectx(repo, memctx, path):
2155 if path not in cache:
2221 if path not in cache:
2156 cache[path] = func(repo, memctx, path)
2222 cache[path] = func(repo, memctx, path)
2157 return cache[path]
2223 return cache[path]
2158
2224
2159 return getfilectx
2225 return getfilectx
2160
2226
2161 def memfilefromctx(ctx):
2227 def memfilefromctx(ctx):
2162 """Given a context return a memfilectx for ctx[path]
2228 """Given a context return a memfilectx for ctx[path]
2163
2229
2164 This is a convenience method for building a memctx based on another
2230 This is a convenience method for building a memctx based on another
2165 context.
2231 context.
2166 """
2232 """
2167 def getfilectx(repo, memctx, path):
2233 def getfilectx(repo, memctx, path):
2168 fctx = ctx[path]
2234 fctx = ctx[path]
2169 copied = fctx.renamed()
2235 copied = fctx.renamed()
2170 if copied:
2236 if copied:
2171 copied = copied[0]
2237 copied = copied[0]
2172 return memfilectx(repo, memctx, path, fctx.data(),
2238 return memfilectx(repo, memctx, path, fctx.data(),
2173 islink=fctx.islink(), isexec=fctx.isexec(),
2239 islink=fctx.islink(), isexec=fctx.isexec(),
2174 copied=copied)
2240 copied=copied)
2175
2241
2176 return getfilectx
2242 return getfilectx
2177
2243
2178 def memfilefrompatch(patchstore):
2244 def memfilefrompatch(patchstore):
2179 """Given a patch (e.g. patchstore object) return a memfilectx
2245 """Given a patch (e.g. patchstore object) return a memfilectx
2180
2246
2181 This is a convenience method for building a memctx based on a patchstore.
2247 This is a convenience method for building a memctx based on a patchstore.
2182 """
2248 """
2183 def getfilectx(repo, memctx, path):
2249 def getfilectx(repo, memctx, path):
2184 data, mode, copied = patchstore.getfile(path)
2250 data, mode, copied = patchstore.getfile(path)
2185 if data is None:
2251 if data is None:
2186 return None
2252 return None
2187 islink, isexec = mode
2253 islink, isexec = mode
2188 return memfilectx(repo, memctx, path, data, islink=islink,
2254 return memfilectx(repo, memctx, path, data, islink=islink,
2189 isexec=isexec, copied=copied)
2255 isexec=isexec, copied=copied)
2190
2256
2191 return getfilectx
2257 return getfilectx
2192
2258
2193 class memctx(committablectx):
2259 class memctx(committablectx):
2194 """Use memctx to perform in-memory commits via localrepo.commitctx().
2260 """Use memctx to perform in-memory commits via localrepo.commitctx().
2195
2261
2196 Revision information is supplied at initialization time while
2262 Revision information is supplied at initialization time while
2197 related files data and is made available through a callback
2263 related files data and is made available through a callback
2198 mechanism. 'repo' is the current localrepo, 'parents' is a
2264 mechanism. 'repo' is the current localrepo, 'parents' is a
2199 sequence of two parent revisions identifiers (pass None for every
2265 sequence of two parent revisions identifiers (pass None for every
2200 missing parent), 'text' is the commit message and 'files' lists
2266 missing parent), 'text' is the commit message and 'files' lists
2201 names of files touched by the revision (normalized and relative to
2267 names of files touched by the revision (normalized and relative to
2202 repository root).
2268 repository root).
2203
2269
2204 filectxfn(repo, memctx, path) is a callable receiving the
2270 filectxfn(repo, memctx, path) is a callable receiving the
2205 repository, the current memctx object and the normalized path of
2271 repository, the current memctx object and the normalized path of
2206 requested file, relative to repository root. It is fired by the
2272 requested file, relative to repository root. It is fired by the
2207 commit function for every file in 'files', but calls order is
2273 commit function for every file in 'files', but calls order is
2208 undefined. If the file is available in the revision being
2274 undefined. If the file is available in the revision being
2209 committed (updated or added), filectxfn returns a memfilectx
2275 committed (updated or added), filectxfn returns a memfilectx
2210 object. If the file was removed, filectxfn return None for recent
2276 object. If the file was removed, filectxfn return None for recent
2211 Mercurial. Moved files are represented by marking the source file
2277 Mercurial. Moved files are represented by marking the source file
2212 removed and the new file added with copy information (see
2278 removed and the new file added with copy information (see
2213 memfilectx).
2279 memfilectx).
2214
2280
2215 user receives the committer name and defaults to current
2281 user receives the committer name and defaults to current
2216 repository username, date is the commit date in any format
2282 repository username, date is the commit date in any format
2217 supported by dateutil.parsedate() and defaults to current date, extra
2283 supported by dateutil.parsedate() and defaults to current date, extra
2218 is a dictionary of metadata or is left empty.
2284 is a dictionary of metadata or is left empty.
2219 """
2285 """
2220
2286
2221 # Mercurial <= 3.1 expects the filectxfn to raise IOError for missing files.
2287 # Mercurial <= 3.1 expects the filectxfn to raise IOError for missing files.
2222 # Extensions that need to retain compatibility across Mercurial 3.1 can use
2288 # Extensions that need to retain compatibility across Mercurial 3.1 can use
2223 # this field to determine what to do in filectxfn.
2289 # this field to determine what to do in filectxfn.
2224 _returnnoneformissingfiles = True
2290 _returnnoneformissingfiles = True
2225
2291
2226 def __init__(self, repo, parents, text, files, filectxfn, user=None,
2292 def __init__(self, repo, parents, text, files, filectxfn, user=None,
2227 date=None, extra=None, branch=None, editor=False):
2293 date=None, extra=None, branch=None, editor=False):
2228 super(memctx, self).__init__(repo, text, user, date, extra)
2294 super(memctx, self).__init__(repo, text, user, date, extra)
2229 self._rev = None
2295 self._rev = None
2230 self._node = None
2296 self._node = None
2231 parents = [(p or nullid) for p in parents]
2297 parents = [(p or nullid) for p in parents]
2232 p1, p2 = parents
2298 p1, p2 = parents
2233 self._parents = [self._repo[p] for p in (p1, p2)]
2299 self._parents = [self._repo[p] for p in (p1, p2)]
2234 files = sorted(set(files))
2300 files = sorted(set(files))
2235 self._files = files
2301 self._files = files
2236 if branch is not None:
2302 if branch is not None:
2237 self._extra['branch'] = encoding.fromlocal(branch)
2303 self._extra['branch'] = encoding.fromlocal(branch)
2238 self.substate = {}
2304 self.substate = {}
2239
2305
2240 if isinstance(filectxfn, patch.filestore):
2306 if isinstance(filectxfn, patch.filestore):
2241 filectxfn = memfilefrompatch(filectxfn)
2307 filectxfn = memfilefrompatch(filectxfn)
2242 elif not callable(filectxfn):
2308 elif not callable(filectxfn):
2243 # if store is not callable, wrap it in a function
2309 # if store is not callable, wrap it in a function
2244 filectxfn = memfilefromctx(filectxfn)
2310 filectxfn = memfilefromctx(filectxfn)
2245
2311
2246 # memoizing increases performance for e.g. vcs convert scenarios.
2312 # memoizing increases performance for e.g. vcs convert scenarios.
2247 self._filectxfn = makecachingfilectxfn(filectxfn)
2313 self._filectxfn = makecachingfilectxfn(filectxfn)
2248
2314
2249 if editor:
2315 if editor:
2250 self._text = editor(self._repo, self, [])
2316 self._text = editor(self._repo, self, [])
2251 self._repo.savecommitmessage(self._text)
2317 self._repo.savecommitmessage(self._text)
2252
2318
2253 def filectx(self, path, filelog=None):
2319 def filectx(self, path, filelog=None):
2254 """get a file context from the working directory
2320 """get a file context from the working directory
2255
2321
2256 Returns None if file doesn't exist and should be removed."""
2322 Returns None if file doesn't exist and should be removed."""
2257 return self._filectxfn(self._repo, self, path)
2323 return self._filectxfn(self._repo, self, path)
2258
2324
2259 def commit(self):
2325 def commit(self):
2260 """commit context to the repo"""
2326 """commit context to the repo"""
2261 return self._repo.commitctx(self)
2327 return self._repo.commitctx(self)
2262
2328
2263 @propertycache
2329 @propertycache
2264 def _manifest(self):
2330 def _manifest(self):
2265 """generate a manifest based on the return values of filectxfn"""
2331 """generate a manifest based on the return values of filectxfn"""
2266
2332
2267 # keep this simple for now; just worry about p1
2333 # keep this simple for now; just worry about p1
2268 pctx = self._parents[0]
2334 pctx = self._parents[0]
2269 man = pctx.manifest().copy()
2335 man = pctx.manifest().copy()
2270
2336
2271 for f in self._status.modified:
2337 for f in self._status.modified:
2272 man[f] = modifiednodeid
2338 man[f] = modifiednodeid
2273
2339
2274 for f in self._status.added:
2340 for f in self._status.added:
2275 man[f] = addednodeid
2341 man[f] = addednodeid
2276
2342
2277 for f in self._status.removed:
2343 for f in self._status.removed:
2278 if f in man:
2344 if f in man:
2279 del man[f]
2345 del man[f]
2280
2346
2281 return man
2347 return man
2282
2348
2283 @propertycache
2349 @propertycache
2284 def _status(self):
2350 def _status(self):
2285 """Calculate exact status from ``files`` specified at construction
2351 """Calculate exact status from ``files`` specified at construction
2286 """
2352 """
2287 man1 = self.p1().manifest()
2353 man1 = self.p1().manifest()
2288 p2 = self._parents[1]
2354 p2 = self._parents[1]
2289 # "1 < len(self._parents)" can't be used for checking
2355 # "1 < len(self._parents)" can't be used for checking
2290 # existence of the 2nd parent, because "memctx._parents" is
2356 # existence of the 2nd parent, because "memctx._parents" is
2291 # explicitly initialized by the list, of which length is 2.
2357 # explicitly initialized by the list, of which length is 2.
2292 if p2.node() != nullid:
2358 if p2.node() != nullid:
2293 man2 = p2.manifest()
2359 man2 = p2.manifest()
2294 managing = lambda f: f in man1 or f in man2
2360 managing = lambda f: f in man1 or f in man2
2295 else:
2361 else:
2296 managing = lambda f: f in man1
2362 managing = lambda f: f in man1
2297
2363
2298 modified, added, removed = [], [], []
2364 modified, added, removed = [], [], []
2299 for f in self._files:
2365 for f in self._files:
2300 if not managing(f):
2366 if not managing(f):
2301 added.append(f)
2367 added.append(f)
2302 elif self[f]:
2368 elif self[f]:
2303 modified.append(f)
2369 modified.append(f)
2304 else:
2370 else:
2305 removed.append(f)
2371 removed.append(f)
2306
2372
2307 return scmutil.status(modified, added, removed, [], [], [], [])
2373 return scmutil.status(modified, added, removed, [], [], [], [])
2308
2374
2309 class memfilectx(committablefilectx):
2375 class memfilectx(committablefilectx):
2310 """memfilectx represents an in-memory file to commit.
2376 """memfilectx represents an in-memory file to commit.
2311
2377
2312 See memctx and committablefilectx for more details.
2378 See memctx and committablefilectx for more details.
2313 """
2379 """
2314 def __init__(self, repo, changectx, path, data, islink=False,
2380 def __init__(self, repo, changectx, path, data, islink=False,
2315 isexec=False, copied=None):
2381 isexec=False, copied=None):
2316 """
2382 """
2317 path is the normalized file path relative to repository root.
2383 path is the normalized file path relative to repository root.
2318 data is the file content as a string.
2384 data is the file content as a string.
2319 islink is True if the file is a symbolic link.
2385 islink is True if the file is a symbolic link.
2320 isexec is True if the file is executable.
2386 isexec is True if the file is executable.
2321 copied is the source file path if current file was copied in the
2387 copied is the source file path if current file was copied in the
2322 revision being committed, or None."""
2388 revision being committed, or None."""
2323 super(memfilectx, self).__init__(repo, path, None, changectx)
2389 super(memfilectx, self).__init__(repo, path, None, changectx)
2324 self._data = data
2390 self._data = data
2325 if islink:
2391 if islink:
2326 self._flags = 'l'
2392 self._flags = 'l'
2327 elif isexec:
2393 elif isexec:
2328 self._flags = 'x'
2394 self._flags = 'x'
2329 else:
2395 else:
2330 self._flags = ''
2396 self._flags = ''
2331 self._copied = None
2397 self._copied = None
2332 if copied:
2398 if copied:
2333 self._copied = (copied, nullid)
2399 self._copied = (copied, nullid)
2334
2400
2335 def cmp(self, fctx):
2401 def cmp(self, fctx):
2336 return self.data() != fctx.data()
2402 return self.data() != fctx.data()
2337
2403
2338 def data(self):
2404 def data(self):
2339 return self._data
2405 return self._data
2340
2406
2341 def remove(self, ignoremissing=False):
2407 def remove(self, ignoremissing=False):
2342 """wraps unlink for a repo's working directory"""
2408 """wraps unlink for a repo's working directory"""
2343 # need to figure out what to do here
2409 # need to figure out what to do here
2344 del self._changectx[self._path]
2410 del self._changectx[self._path]
2345
2411
2346 def write(self, data, flags, **kwargs):
2412 def write(self, data, flags, **kwargs):
2347 """wraps repo.wwrite"""
2413 """wraps repo.wwrite"""
2348 self._data = data
2414 self._data = data
2349
2415
2350
2416
2351 class metadataonlyctx(committablectx):
2417 class metadataonlyctx(committablectx):
2352 """Like memctx but it's reusing the manifest of different commit.
2418 """Like memctx but it's reusing the manifest of different commit.
2353 Intended to be used by lightweight operations that are creating
2419 Intended to be used by lightweight operations that are creating
2354 metadata-only changes.
2420 metadata-only changes.
2355
2421
2356 Revision information is supplied at initialization time. 'repo' is the
2422 Revision information is supplied at initialization time. 'repo' is the
2357 current localrepo, 'ctx' is original revision which manifest we're reuisng
2423 current localrepo, 'ctx' is original revision which manifest we're reuisng
2358 'parents' is a sequence of two parent revisions identifiers (pass None for
2424 'parents' is a sequence of two parent revisions identifiers (pass None for
2359 every missing parent), 'text' is the commit.
2425 every missing parent), 'text' is the commit.
2360
2426
2361 user receives the committer name and defaults to current repository
2427 user receives the committer name and defaults to current repository
2362 username, date is the commit date in any format supported by
2428 username, date is the commit date in any format supported by
2363 dateutil.parsedate() and defaults to current date, extra is a dictionary of
2429 dateutil.parsedate() and defaults to current date, extra is a dictionary of
2364 metadata or is left empty.
2430 metadata or is left empty.
2365 """
2431 """
2366 def __init__(self, repo, originalctx, parents=None, text=None, user=None,
2432 def __init__(self, repo, originalctx, parents=None, text=None, user=None,
2367 date=None, extra=None, editor=False):
2433 date=None, extra=None, editor=False):
2368 if text is None:
2434 if text is None:
2369 text = originalctx.description()
2435 text = originalctx.description()
2370 super(metadataonlyctx, self).__init__(repo, text, user, date, extra)
2436 super(metadataonlyctx, self).__init__(repo, text, user, date, extra)
2371 self._rev = None
2437 self._rev = None
2372 self._node = None
2438 self._node = None
2373 self._originalctx = originalctx
2439 self._originalctx = originalctx
2374 self._manifestnode = originalctx.manifestnode()
2440 self._manifestnode = originalctx.manifestnode()
2375 if parents is None:
2441 if parents is None:
2376 parents = originalctx.parents()
2442 parents = originalctx.parents()
2377 else:
2443 else:
2378 parents = [repo[p] for p in parents if p is not None]
2444 parents = [repo[p] for p in parents if p is not None]
2379 parents = parents[:]
2445 parents = parents[:]
2380 while len(parents) < 2:
2446 while len(parents) < 2:
2381 parents.append(repo[nullid])
2447 parents.append(repo[nullid])
2382 p1, p2 = self._parents = parents
2448 p1, p2 = self._parents = parents
2383
2449
2384 # sanity check to ensure that the reused manifest parents are
2450 # sanity check to ensure that the reused manifest parents are
2385 # manifests of our commit parents
2451 # manifests of our commit parents
2386 mp1, mp2 = self.manifestctx().parents
2452 mp1, mp2 = self.manifestctx().parents
2387 if p1 != nullid and p1.manifestnode() != mp1:
2453 if p1 != nullid and p1.manifestnode() != mp1:
2388 raise RuntimeError(r"can't reuse the manifest: its p1 "
2454 raise RuntimeError(r"can't reuse the manifest: its p1 "
2389 r"doesn't match the new ctx p1")
2455 r"doesn't match the new ctx p1")
2390 if p2 != nullid and p2.manifestnode() != mp2:
2456 if p2 != nullid and p2.manifestnode() != mp2:
2391 raise RuntimeError(r"can't reuse the manifest: "
2457 raise RuntimeError(r"can't reuse the manifest: "
2392 r"its p2 doesn't match the new ctx p2")
2458 r"its p2 doesn't match the new ctx p2")
2393
2459
2394 self._files = originalctx.files()
2460 self._files = originalctx.files()
2395 self.substate = {}
2461 self.substate = {}
2396
2462
2397 if editor:
2463 if editor:
2398 self._text = editor(self._repo, self, [])
2464 self._text = editor(self._repo, self, [])
2399 self._repo.savecommitmessage(self._text)
2465 self._repo.savecommitmessage(self._text)
2400
2466
2401 def manifestnode(self):
2467 def manifestnode(self):
2402 return self._manifestnode
2468 return self._manifestnode
2403
2469
2404 @property
2470 @property
2405 def _manifestctx(self):
2471 def _manifestctx(self):
2406 return self._repo.manifestlog[self._manifestnode]
2472 return self._repo.manifestlog[self._manifestnode]
2407
2473
2408 def filectx(self, path, filelog=None):
2474 def filectx(self, path, filelog=None):
2409 return self._originalctx.filectx(path, filelog=filelog)
2475 return self._originalctx.filectx(path, filelog=filelog)
2410
2476
2411 def commit(self):
2477 def commit(self):
2412 """commit context to the repo"""
2478 """commit context to the repo"""
2413 return self._repo.commitctx(self)
2479 return self._repo.commitctx(self)
2414
2480
2415 @property
2481 @property
2416 def _manifest(self):
2482 def _manifest(self):
2417 return self._originalctx.manifest()
2483 return self._originalctx.manifest()
2418
2484
2419 @propertycache
2485 @propertycache
2420 def _status(self):
2486 def _status(self):
2421 """Calculate exact status from ``files`` specified in the ``origctx``
2487 """Calculate exact status from ``files`` specified in the ``origctx``
2422 and parents manifests.
2488 and parents manifests.
2423 """
2489 """
2424 man1 = self.p1().manifest()
2490 man1 = self.p1().manifest()
2425 p2 = self._parents[1]
2491 p2 = self._parents[1]
2426 # "1 < len(self._parents)" can't be used for checking
2492 # "1 < len(self._parents)" can't be used for checking
2427 # existence of the 2nd parent, because "metadataonlyctx._parents" is
2493 # existence of the 2nd parent, because "metadataonlyctx._parents" is
2428 # explicitly initialized by the list, of which length is 2.
2494 # explicitly initialized by the list, of which length is 2.
2429 if p2.node() != nullid:
2495 if p2.node() != nullid:
2430 man2 = p2.manifest()
2496 man2 = p2.manifest()
2431 managing = lambda f: f in man1 or f in man2
2497 managing = lambda f: f in man1 or f in man2
2432 else:
2498 else:
2433 managing = lambda f: f in man1
2499 managing = lambda f: f in man1
2434
2500
2435 modified, added, removed = [], [], []
2501 modified, added, removed = [], [], []
2436 for f in self._files:
2502 for f in self._files:
2437 if not managing(f):
2503 if not managing(f):
2438 added.append(f)
2504 added.append(f)
2439 elif f in self:
2505 elif f in self:
2440 modified.append(f)
2506 modified.append(f)
2441 else:
2507 else:
2442 removed.append(f)
2508 removed.append(f)
2443
2509
2444 return scmutil.status(modified, added, removed, [], [], [], [])
2510 return scmutil.status(modified, added, removed, [], [], [], [])
2445
2511
2446 class arbitraryfilectx(object):
2512 class arbitraryfilectx(object):
2447 """Allows you to use filectx-like functions on a file in an arbitrary
2513 """Allows you to use filectx-like functions on a file in an arbitrary
2448 location on disk, possibly not in the working directory.
2514 location on disk, possibly not in the working directory.
2449 """
2515 """
2450 def __init__(self, path, repo=None):
2516 def __init__(self, path, repo=None):
2451 # Repo is optional because contrib/simplemerge uses this class.
2517 # Repo is optional because contrib/simplemerge uses this class.
2452 self._repo = repo
2518 self._repo = repo
2453 self._path = path
2519 self._path = path
2454
2520
2455 def cmp(self, fctx):
2521 def cmp(self, fctx):
2456 # filecmp follows symlinks whereas `cmp` should not, so skip the fast
2522 # filecmp follows symlinks whereas `cmp` should not, so skip the fast
2457 # path if either side is a symlink.
2523 # path if either side is a symlink.
2458 symlinks = ('l' in self.flags() or 'l' in fctx.flags())
2524 symlinks = ('l' in self.flags() or 'l' in fctx.flags())
2459 if not symlinks and isinstance(fctx, workingfilectx) and self._repo:
2525 if not symlinks and isinstance(fctx, workingfilectx) and self._repo:
2460 # Add a fast-path for merge if both sides are disk-backed.
2526 # Add a fast-path for merge if both sides are disk-backed.
2461 # Note that filecmp uses the opposite return values (True if same)
2527 # Note that filecmp uses the opposite return values (True if same)
2462 # from our cmp functions (True if different).
2528 # from our cmp functions (True if different).
2463 return not filecmp.cmp(self.path(), self._repo.wjoin(fctx.path()))
2529 return not filecmp.cmp(self.path(), self._repo.wjoin(fctx.path()))
2464 return self.data() != fctx.data()
2530 return self.data() != fctx.data()
2465
2531
2466 def path(self):
2532 def path(self):
2467 return self._path
2533 return self._path
2468
2534
2469 def flags(self):
2535 def flags(self):
2470 return ''
2536 return ''
2471
2537
2472 def data(self):
2538 def data(self):
2473 return util.readfile(self._path)
2539 return util.readfile(self._path)
2474
2540
2475 def decodeddata(self):
2541 def decodeddata(self):
2476 with open(self._path, "rb") as f:
2542 with open(self._path, "rb") as f:
2477 return f.read()
2543 return f.read()
2478
2544
2479 def remove(self):
2545 def remove(self):
2480 util.unlink(self._path)
2546 util.unlink(self._path)
2481
2547
2482 def write(self, data, flags, **kwargs):
2548 def write(self, data, flags, **kwargs):
2483 assert not flags
2549 assert not flags
2484 with open(self._path, "wb") as f:
2550 with open(self._path, "wb") as f:
2485 f.write(data)
2551 f.write(data)
@@ -1,3398 +1,3420 b''
1 # debugcommands.py - command processing for debug* commands
1 # debugcommands.py - command processing for debug* commands
2 #
2 #
3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2016 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import codecs
10 import codecs
11 import collections
11 import collections
12 import difflib
12 import difflib
13 import errno
13 import errno
14 import operator
14 import operator
15 import os
15 import os
16 import random
16 import random
17 import re
17 import re
18 import socket
18 import socket
19 import ssl
19 import ssl
20 import stat
20 import stat
21 import string
21 import string
22 import subprocess
22 import subprocess
23 import sys
23 import sys
24 import time
24 import time
25
25
26 from .i18n import _
26 from .i18n import _
27 from .node import (
27 from .node import (
28 bin,
28 bin,
29 hex,
29 hex,
30 nullhex,
30 nullhex,
31 nullid,
31 nullid,
32 nullrev,
32 nullrev,
33 short,
33 short,
34 )
34 )
35 from . import (
35 from . import (
36 bundle2,
36 bundle2,
37 changegroup,
37 changegroup,
38 cmdutil,
38 cmdutil,
39 color,
39 color,
40 context,
40 context,
41 copies,
41 copies,
42 dagparser,
42 dagparser,
43 encoding,
43 encoding,
44 error,
44 error,
45 exchange,
45 exchange,
46 extensions,
46 extensions,
47 filemerge,
47 filemerge,
48 filesetlang,
48 filesetlang,
49 formatter,
49 formatter,
50 hg,
50 hg,
51 httppeer,
51 httppeer,
52 localrepo,
52 localrepo,
53 lock as lockmod,
53 lock as lockmod,
54 logcmdutil,
54 logcmdutil,
55 merge as mergemod,
55 merge as mergemod,
56 obsolete,
56 obsolete,
57 obsutil,
57 obsutil,
58 phases,
58 phases,
59 policy,
59 policy,
60 pvec,
60 pvec,
61 pycompat,
61 pycompat,
62 registrar,
62 registrar,
63 repair,
63 repair,
64 revlog,
64 revlog,
65 revset,
65 revset,
66 revsetlang,
66 revsetlang,
67 scmutil,
67 scmutil,
68 setdiscovery,
68 setdiscovery,
69 simplemerge,
69 simplemerge,
70 sshpeer,
70 sshpeer,
71 sslutil,
71 sslutil,
72 streamclone,
72 streamclone,
73 templater,
73 templater,
74 treediscovery,
74 treediscovery,
75 upgrade,
75 upgrade,
76 url as urlmod,
76 url as urlmod,
77 util,
77 util,
78 vfs as vfsmod,
78 vfs as vfsmod,
79 wireprotoframing,
79 wireprotoframing,
80 wireprotoserver,
80 wireprotoserver,
81 wireprotov2peer,
81 wireprotov2peer,
82 )
82 )
83 from .utils import (
83 from .utils import (
84 cborutil,
84 cborutil,
85 dateutil,
85 dateutil,
86 procutil,
86 procutil,
87 stringutil,
87 stringutil,
88 )
88 )
89
89
90 from .revlogutils import (
90 from .revlogutils import (
91 deltas as deltautil
91 deltas as deltautil
92 )
92 )
93
93
94 release = lockmod.release
94 release = lockmod.release
95
95
96 command = registrar.command()
96 command = registrar.command()
97
97
98 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
98 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
99 def debugancestor(ui, repo, *args):
99 def debugancestor(ui, repo, *args):
100 """find the ancestor revision of two revisions in a given index"""
100 """find the ancestor revision of two revisions in a given index"""
101 if len(args) == 3:
101 if len(args) == 3:
102 index, rev1, rev2 = args
102 index, rev1, rev2 = args
103 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
103 r = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False), index)
104 lookup = r.lookup
104 lookup = r.lookup
105 elif len(args) == 2:
105 elif len(args) == 2:
106 if not repo:
106 if not repo:
107 raise error.Abort(_('there is no Mercurial repository here '
107 raise error.Abort(_('there is no Mercurial repository here '
108 '(.hg not found)'))
108 '(.hg not found)'))
109 rev1, rev2 = args
109 rev1, rev2 = args
110 r = repo.changelog
110 r = repo.changelog
111 lookup = repo.lookup
111 lookup = repo.lookup
112 else:
112 else:
113 raise error.Abort(_('either two or three arguments required'))
113 raise error.Abort(_('either two or three arguments required'))
114 a = r.ancestor(lookup(rev1), lookup(rev2))
114 a = r.ancestor(lookup(rev1), lookup(rev2))
115 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
115 ui.write('%d:%s\n' % (r.rev(a), hex(a)))
116
116
117 @command('debugapplystreamclonebundle', [], 'FILE')
117 @command('debugapplystreamclonebundle', [], 'FILE')
118 def debugapplystreamclonebundle(ui, repo, fname):
118 def debugapplystreamclonebundle(ui, repo, fname):
119 """apply a stream clone bundle file"""
119 """apply a stream clone bundle file"""
120 f = hg.openpath(ui, fname)
120 f = hg.openpath(ui, fname)
121 gen = exchange.readbundle(ui, f, fname)
121 gen = exchange.readbundle(ui, f, fname)
122 gen.apply(repo)
122 gen.apply(repo)
123
123
124 @command('debugbuilddag',
124 @command('debugbuilddag',
125 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
125 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
126 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
126 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
127 ('n', 'new-file', None, _('add new file at each rev'))],
127 ('n', 'new-file', None, _('add new file at each rev'))],
128 _('[OPTION]... [TEXT]'))
128 _('[OPTION]... [TEXT]'))
129 def debugbuilddag(ui, repo, text=None,
129 def debugbuilddag(ui, repo, text=None,
130 mergeable_file=False,
130 mergeable_file=False,
131 overwritten_file=False,
131 overwritten_file=False,
132 new_file=False):
132 new_file=False):
133 """builds a repo with a given DAG from scratch in the current empty repo
133 """builds a repo with a given DAG from scratch in the current empty repo
134
134
135 The description of the DAG is read from stdin if not given on the
135 The description of the DAG is read from stdin if not given on the
136 command line.
136 command line.
137
137
138 Elements:
138 Elements:
139
139
140 - "+n" is a linear run of n nodes based on the current default parent
140 - "+n" is a linear run of n nodes based on the current default parent
141 - "." is a single node based on the current default parent
141 - "." is a single node based on the current default parent
142 - "$" resets the default parent to null (implied at the start);
142 - "$" resets the default parent to null (implied at the start);
143 otherwise the default parent is always the last node created
143 otherwise the default parent is always the last node created
144 - "<p" sets the default parent to the backref p
144 - "<p" sets the default parent to the backref p
145 - "*p" is a fork at parent p, which is a backref
145 - "*p" is a fork at parent p, which is a backref
146 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
146 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
147 - "/p2" is a merge of the preceding node and p2
147 - "/p2" is a merge of the preceding node and p2
148 - ":tag" defines a local tag for the preceding node
148 - ":tag" defines a local tag for the preceding node
149 - "@branch" sets the named branch for subsequent nodes
149 - "@branch" sets the named branch for subsequent nodes
150 - "#...\\n" is a comment up to the end of the line
150 - "#...\\n" is a comment up to the end of the line
151
151
152 Whitespace between the above elements is ignored.
152 Whitespace between the above elements is ignored.
153
153
154 A backref is either
154 A backref is either
155
155
156 - a number n, which references the node curr-n, where curr is the current
156 - a number n, which references the node curr-n, where curr is the current
157 node, or
157 node, or
158 - the name of a local tag you placed earlier using ":tag", or
158 - the name of a local tag you placed earlier using ":tag", or
159 - empty to denote the default parent.
159 - empty to denote the default parent.
160
160
161 All string valued-elements are either strictly alphanumeric, or must
161 All string valued-elements are either strictly alphanumeric, or must
162 be enclosed in double quotes ("..."), with "\\" as escape character.
162 be enclosed in double quotes ("..."), with "\\" as escape character.
163 """
163 """
164
164
165 if text is None:
165 if text is None:
166 ui.status(_("reading DAG from stdin\n"))
166 ui.status(_("reading DAG from stdin\n"))
167 text = ui.fin.read()
167 text = ui.fin.read()
168
168
169 cl = repo.changelog
169 cl = repo.changelog
170 if len(cl) > 0:
170 if len(cl) > 0:
171 raise error.Abort(_('repository is not empty'))
171 raise error.Abort(_('repository is not empty'))
172
172
173 # determine number of revs in DAG
173 # determine number of revs in DAG
174 total = 0
174 total = 0
175 for type, data in dagparser.parsedag(text):
175 for type, data in dagparser.parsedag(text):
176 if type == 'n':
176 if type == 'n':
177 total += 1
177 total += 1
178
178
179 if mergeable_file:
179 if mergeable_file:
180 linesperrev = 2
180 linesperrev = 2
181 # make a file with k lines per rev
181 # make a file with k lines per rev
182 initialmergedlines = ['%d' % i
182 initialmergedlines = ['%d' % i
183 for i in pycompat.xrange(0, total * linesperrev)]
183 for i in pycompat.xrange(0, total * linesperrev)]
184 initialmergedlines.append("")
184 initialmergedlines.append("")
185
185
186 tags = []
186 tags = []
187 progress = ui.makeprogress(_('building'), unit=_('revisions'),
187 progress = ui.makeprogress(_('building'), unit=_('revisions'),
188 total=total)
188 total=total)
189 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
189 with progress, repo.wlock(), repo.lock(), repo.transaction("builddag"):
190 at = -1
190 at = -1
191 atbranch = 'default'
191 atbranch = 'default'
192 nodeids = []
192 nodeids = []
193 id = 0
193 id = 0
194 progress.update(id)
194 progress.update(id)
195 for type, data in dagparser.parsedag(text):
195 for type, data in dagparser.parsedag(text):
196 if type == 'n':
196 if type == 'n':
197 ui.note(('node %s\n' % pycompat.bytestr(data)))
197 ui.note(('node %s\n' % pycompat.bytestr(data)))
198 id, ps = data
198 id, ps = data
199
199
200 files = []
200 files = []
201 filecontent = {}
201 filecontent = {}
202
202
203 p2 = None
203 p2 = None
204 if mergeable_file:
204 if mergeable_file:
205 fn = "mf"
205 fn = "mf"
206 p1 = repo[ps[0]]
206 p1 = repo[ps[0]]
207 if len(ps) > 1:
207 if len(ps) > 1:
208 p2 = repo[ps[1]]
208 p2 = repo[ps[1]]
209 pa = p1.ancestor(p2)
209 pa = p1.ancestor(p2)
210 base, local, other = [x[fn].data() for x in (pa, p1,
210 base, local, other = [x[fn].data() for x in (pa, p1,
211 p2)]
211 p2)]
212 m3 = simplemerge.Merge3Text(base, local, other)
212 m3 = simplemerge.Merge3Text(base, local, other)
213 ml = [l.strip() for l in m3.merge_lines()]
213 ml = [l.strip() for l in m3.merge_lines()]
214 ml.append("")
214 ml.append("")
215 elif at > 0:
215 elif at > 0:
216 ml = p1[fn].data().split("\n")
216 ml = p1[fn].data().split("\n")
217 else:
217 else:
218 ml = initialmergedlines
218 ml = initialmergedlines
219 ml[id * linesperrev] += " r%i" % id
219 ml[id * linesperrev] += " r%i" % id
220 mergedtext = "\n".join(ml)
220 mergedtext = "\n".join(ml)
221 files.append(fn)
221 files.append(fn)
222 filecontent[fn] = mergedtext
222 filecontent[fn] = mergedtext
223
223
224 if overwritten_file:
224 if overwritten_file:
225 fn = "of"
225 fn = "of"
226 files.append(fn)
226 files.append(fn)
227 filecontent[fn] = "r%i\n" % id
227 filecontent[fn] = "r%i\n" % id
228
228
229 if new_file:
229 if new_file:
230 fn = "nf%i" % id
230 fn = "nf%i" % id
231 files.append(fn)
231 files.append(fn)
232 filecontent[fn] = "r%i\n" % id
232 filecontent[fn] = "r%i\n" % id
233 if len(ps) > 1:
233 if len(ps) > 1:
234 if not p2:
234 if not p2:
235 p2 = repo[ps[1]]
235 p2 = repo[ps[1]]
236 for fn in p2:
236 for fn in p2:
237 if fn.startswith("nf"):
237 if fn.startswith("nf"):
238 files.append(fn)
238 files.append(fn)
239 filecontent[fn] = p2[fn].data()
239 filecontent[fn] = p2[fn].data()
240
240
241 def fctxfn(repo, cx, path):
241 def fctxfn(repo, cx, path):
242 if path in filecontent:
242 if path in filecontent:
243 return context.memfilectx(repo, cx, path,
243 return context.memfilectx(repo, cx, path,
244 filecontent[path])
244 filecontent[path])
245 return None
245 return None
246
246
247 if len(ps) == 0 or ps[0] < 0:
247 if len(ps) == 0 or ps[0] < 0:
248 pars = [None, None]
248 pars = [None, None]
249 elif len(ps) == 1:
249 elif len(ps) == 1:
250 pars = [nodeids[ps[0]], None]
250 pars = [nodeids[ps[0]], None]
251 else:
251 else:
252 pars = [nodeids[p] for p in ps]
252 pars = [nodeids[p] for p in ps]
253 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
253 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
254 date=(id, 0),
254 date=(id, 0),
255 user="debugbuilddag",
255 user="debugbuilddag",
256 extra={'branch': atbranch})
256 extra={'branch': atbranch})
257 nodeid = repo.commitctx(cx)
257 nodeid = repo.commitctx(cx)
258 nodeids.append(nodeid)
258 nodeids.append(nodeid)
259 at = id
259 at = id
260 elif type == 'l':
260 elif type == 'l':
261 id, name = data
261 id, name = data
262 ui.note(('tag %s\n' % name))
262 ui.note(('tag %s\n' % name))
263 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
263 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
264 elif type == 'a':
264 elif type == 'a':
265 ui.note(('branch %s\n' % data))
265 ui.note(('branch %s\n' % data))
266 atbranch = data
266 atbranch = data
267 progress.update(id)
267 progress.update(id)
268
268
269 if tags:
269 if tags:
270 repo.vfs.write("localtags", "".join(tags))
270 repo.vfs.write("localtags", "".join(tags))
271
271
272 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
272 def _debugchangegroup(ui, gen, all=None, indent=0, **opts):
273 indent_string = ' ' * indent
273 indent_string = ' ' * indent
274 if all:
274 if all:
275 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
275 ui.write(("%sformat: id, p1, p2, cset, delta base, len(delta)\n")
276 % indent_string)
276 % indent_string)
277
277
278 def showchunks(named):
278 def showchunks(named):
279 ui.write("\n%s%s\n" % (indent_string, named))
279 ui.write("\n%s%s\n" % (indent_string, named))
280 for deltadata in gen.deltaiter():
280 for deltadata in gen.deltaiter():
281 node, p1, p2, cs, deltabase, delta, flags = deltadata
281 node, p1, p2, cs, deltabase, delta, flags = deltadata
282 ui.write("%s%s %s %s %s %s %d\n" %
282 ui.write("%s%s %s %s %s %s %d\n" %
283 (indent_string, hex(node), hex(p1), hex(p2),
283 (indent_string, hex(node), hex(p1), hex(p2),
284 hex(cs), hex(deltabase), len(delta)))
284 hex(cs), hex(deltabase), len(delta)))
285
285
286 chunkdata = gen.changelogheader()
286 chunkdata = gen.changelogheader()
287 showchunks("changelog")
287 showchunks("changelog")
288 chunkdata = gen.manifestheader()
288 chunkdata = gen.manifestheader()
289 showchunks("manifest")
289 showchunks("manifest")
290 for chunkdata in iter(gen.filelogheader, {}):
290 for chunkdata in iter(gen.filelogheader, {}):
291 fname = chunkdata['filename']
291 fname = chunkdata['filename']
292 showchunks(fname)
292 showchunks(fname)
293 else:
293 else:
294 if isinstance(gen, bundle2.unbundle20):
294 if isinstance(gen, bundle2.unbundle20):
295 raise error.Abort(_('use debugbundle2 for this file'))
295 raise error.Abort(_('use debugbundle2 for this file'))
296 chunkdata = gen.changelogheader()
296 chunkdata = gen.changelogheader()
297 for deltadata in gen.deltaiter():
297 for deltadata in gen.deltaiter():
298 node, p1, p2, cs, deltabase, delta, flags = deltadata
298 node, p1, p2, cs, deltabase, delta, flags = deltadata
299 ui.write("%s%s\n" % (indent_string, hex(node)))
299 ui.write("%s%s\n" % (indent_string, hex(node)))
300
300
301 def _debugobsmarkers(ui, part, indent=0, **opts):
301 def _debugobsmarkers(ui, part, indent=0, **opts):
302 """display version and markers contained in 'data'"""
302 """display version and markers contained in 'data'"""
303 opts = pycompat.byteskwargs(opts)
303 opts = pycompat.byteskwargs(opts)
304 data = part.read()
304 data = part.read()
305 indent_string = ' ' * indent
305 indent_string = ' ' * indent
306 try:
306 try:
307 version, markers = obsolete._readmarkers(data)
307 version, markers = obsolete._readmarkers(data)
308 except error.UnknownVersion as exc:
308 except error.UnknownVersion as exc:
309 msg = "%sunsupported version: %s (%d bytes)\n"
309 msg = "%sunsupported version: %s (%d bytes)\n"
310 msg %= indent_string, exc.version, len(data)
310 msg %= indent_string, exc.version, len(data)
311 ui.write(msg)
311 ui.write(msg)
312 else:
312 else:
313 msg = "%sversion: %d (%d bytes)\n"
313 msg = "%sversion: %d (%d bytes)\n"
314 msg %= indent_string, version, len(data)
314 msg %= indent_string, version, len(data)
315 ui.write(msg)
315 ui.write(msg)
316 fm = ui.formatter('debugobsolete', opts)
316 fm = ui.formatter('debugobsolete', opts)
317 for rawmarker in sorted(markers):
317 for rawmarker in sorted(markers):
318 m = obsutil.marker(None, rawmarker)
318 m = obsutil.marker(None, rawmarker)
319 fm.startitem()
319 fm.startitem()
320 fm.plain(indent_string)
320 fm.plain(indent_string)
321 cmdutil.showmarker(fm, m)
321 cmdutil.showmarker(fm, m)
322 fm.end()
322 fm.end()
323
323
324 def _debugphaseheads(ui, data, indent=0):
324 def _debugphaseheads(ui, data, indent=0):
325 """display version and markers contained in 'data'"""
325 """display version and markers contained in 'data'"""
326 indent_string = ' ' * indent
326 indent_string = ' ' * indent
327 headsbyphase = phases.binarydecode(data)
327 headsbyphase = phases.binarydecode(data)
328 for phase in phases.allphases:
328 for phase in phases.allphases:
329 for head in headsbyphase[phase]:
329 for head in headsbyphase[phase]:
330 ui.write(indent_string)
330 ui.write(indent_string)
331 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
331 ui.write('%s %s\n' % (hex(head), phases.phasenames[phase]))
332
332
333 def _quasirepr(thing):
333 def _quasirepr(thing):
334 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
334 if isinstance(thing, (dict, util.sortdict, collections.OrderedDict)):
335 return '{%s}' % (
335 return '{%s}' % (
336 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
336 b', '.join(b'%s: %s' % (k, thing[k]) for k in sorted(thing)))
337 return pycompat.bytestr(repr(thing))
337 return pycompat.bytestr(repr(thing))
338
338
339 def _debugbundle2(ui, gen, all=None, **opts):
339 def _debugbundle2(ui, gen, all=None, **opts):
340 """lists the contents of a bundle2"""
340 """lists the contents of a bundle2"""
341 if not isinstance(gen, bundle2.unbundle20):
341 if not isinstance(gen, bundle2.unbundle20):
342 raise error.Abort(_('not a bundle2 file'))
342 raise error.Abort(_('not a bundle2 file'))
343 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
343 ui.write(('Stream params: %s\n' % _quasirepr(gen.params)))
344 parttypes = opts.get(r'part_type', [])
344 parttypes = opts.get(r'part_type', [])
345 for part in gen.iterparts():
345 for part in gen.iterparts():
346 if parttypes and part.type not in parttypes:
346 if parttypes and part.type not in parttypes:
347 continue
347 continue
348 msg = '%s -- %s (mandatory: %r)\n'
348 msg = '%s -- %s (mandatory: %r)\n'
349 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
349 ui.write((msg % (part.type, _quasirepr(part.params), part.mandatory)))
350 if part.type == 'changegroup':
350 if part.type == 'changegroup':
351 version = part.params.get('version', '01')
351 version = part.params.get('version', '01')
352 cg = changegroup.getunbundler(version, part, 'UN')
352 cg = changegroup.getunbundler(version, part, 'UN')
353 if not ui.quiet:
353 if not ui.quiet:
354 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
354 _debugchangegroup(ui, cg, all=all, indent=4, **opts)
355 if part.type == 'obsmarkers':
355 if part.type == 'obsmarkers':
356 if not ui.quiet:
356 if not ui.quiet:
357 _debugobsmarkers(ui, part, indent=4, **opts)
357 _debugobsmarkers(ui, part, indent=4, **opts)
358 if part.type == 'phase-heads':
358 if part.type == 'phase-heads':
359 if not ui.quiet:
359 if not ui.quiet:
360 _debugphaseheads(ui, part, indent=4)
360 _debugphaseheads(ui, part, indent=4)
361
361
362 @command('debugbundle',
362 @command('debugbundle',
363 [('a', 'all', None, _('show all details')),
363 [('a', 'all', None, _('show all details')),
364 ('', 'part-type', [], _('show only the named part type')),
364 ('', 'part-type', [], _('show only the named part type')),
365 ('', 'spec', None, _('print the bundlespec of the bundle'))],
365 ('', 'spec', None, _('print the bundlespec of the bundle'))],
366 _('FILE'),
366 _('FILE'),
367 norepo=True)
367 norepo=True)
368 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
368 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
369 """lists the contents of a bundle"""
369 """lists the contents of a bundle"""
370 with hg.openpath(ui, bundlepath) as f:
370 with hg.openpath(ui, bundlepath) as f:
371 if spec:
371 if spec:
372 spec = exchange.getbundlespec(ui, f)
372 spec = exchange.getbundlespec(ui, f)
373 ui.write('%s\n' % spec)
373 ui.write('%s\n' % spec)
374 return
374 return
375
375
376 gen = exchange.readbundle(ui, f, bundlepath)
376 gen = exchange.readbundle(ui, f, bundlepath)
377 if isinstance(gen, bundle2.unbundle20):
377 if isinstance(gen, bundle2.unbundle20):
378 return _debugbundle2(ui, gen, all=all, **opts)
378 return _debugbundle2(ui, gen, all=all, **opts)
379 _debugchangegroup(ui, gen, all=all, **opts)
379 _debugchangegroup(ui, gen, all=all, **opts)
380
380
381 @command('debugcapabilities',
381 @command('debugcapabilities',
382 [], _('PATH'),
382 [], _('PATH'),
383 norepo=True)
383 norepo=True)
384 def debugcapabilities(ui, path, **opts):
384 def debugcapabilities(ui, path, **opts):
385 """lists the capabilities of a remote peer"""
385 """lists the capabilities of a remote peer"""
386 opts = pycompat.byteskwargs(opts)
386 opts = pycompat.byteskwargs(opts)
387 peer = hg.peer(ui, opts, path)
387 peer = hg.peer(ui, opts, path)
388 caps = peer.capabilities()
388 caps = peer.capabilities()
389 ui.write(('Main capabilities:\n'))
389 ui.write(('Main capabilities:\n'))
390 for c in sorted(caps):
390 for c in sorted(caps):
391 ui.write((' %s\n') % c)
391 ui.write((' %s\n') % c)
392 b2caps = bundle2.bundle2caps(peer)
392 b2caps = bundle2.bundle2caps(peer)
393 if b2caps:
393 if b2caps:
394 ui.write(('Bundle2 capabilities:\n'))
394 ui.write(('Bundle2 capabilities:\n'))
395 for key, values in sorted(b2caps.iteritems()):
395 for key, values in sorted(b2caps.iteritems()):
396 ui.write((' %s\n') % key)
396 ui.write((' %s\n') % key)
397 for v in values:
397 for v in values:
398 ui.write((' %s\n') % v)
398 ui.write((' %s\n') % v)
399
399
400 @command('debugcheckstate', [], '')
400 @command('debugcheckstate', [], '')
401 def debugcheckstate(ui, repo):
401 def debugcheckstate(ui, repo):
402 """validate the correctness of the current dirstate"""
402 """validate the correctness of the current dirstate"""
403 parent1, parent2 = repo.dirstate.parents()
403 parent1, parent2 = repo.dirstate.parents()
404 m1 = repo[parent1].manifest()
404 m1 = repo[parent1].manifest()
405 m2 = repo[parent2].manifest()
405 m2 = repo[parent2].manifest()
406 errors = 0
406 errors = 0
407 for f in repo.dirstate:
407 for f in repo.dirstate:
408 state = repo.dirstate[f]
408 state = repo.dirstate[f]
409 if state in "nr" and f not in m1:
409 if state in "nr" and f not in m1:
410 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
410 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
411 errors += 1
411 errors += 1
412 if state in "a" and f in m1:
412 if state in "a" and f in m1:
413 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
413 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
414 errors += 1
414 errors += 1
415 if state in "m" and f not in m1 and f not in m2:
415 if state in "m" and f not in m1 and f not in m2:
416 ui.warn(_("%s in state %s, but not in either manifest\n") %
416 ui.warn(_("%s in state %s, but not in either manifest\n") %
417 (f, state))
417 (f, state))
418 errors += 1
418 errors += 1
419 for f in m1:
419 for f in m1:
420 state = repo.dirstate[f]
420 state = repo.dirstate[f]
421 if state not in "nrm":
421 if state not in "nrm":
422 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
422 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
423 errors += 1
423 errors += 1
424 if errors:
424 if errors:
425 error = _(".hg/dirstate inconsistent with current parent's manifest")
425 error = _(".hg/dirstate inconsistent with current parent's manifest")
426 raise error.Abort(error)
426 raise error.Abort(error)
427
427
428 @command('debugcolor',
428 @command('debugcolor',
429 [('', 'style', None, _('show all configured styles'))],
429 [('', 'style', None, _('show all configured styles'))],
430 'hg debugcolor')
430 'hg debugcolor')
431 def debugcolor(ui, repo, **opts):
431 def debugcolor(ui, repo, **opts):
432 """show available color, effects or style"""
432 """show available color, effects or style"""
433 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode))
433 ui.write(('color mode: %s\n') % stringutil.pprint(ui._colormode))
434 if opts.get(r'style'):
434 if opts.get(r'style'):
435 return _debugdisplaystyle(ui)
435 return _debugdisplaystyle(ui)
436 else:
436 else:
437 return _debugdisplaycolor(ui)
437 return _debugdisplaycolor(ui)
438
438
439 def _debugdisplaycolor(ui):
439 def _debugdisplaycolor(ui):
440 ui = ui.copy()
440 ui = ui.copy()
441 ui._styles.clear()
441 ui._styles.clear()
442 for effect in color._activeeffects(ui).keys():
442 for effect in color._activeeffects(ui).keys():
443 ui._styles[effect] = effect
443 ui._styles[effect] = effect
444 if ui._terminfoparams:
444 if ui._terminfoparams:
445 for k, v in ui.configitems('color'):
445 for k, v in ui.configitems('color'):
446 if k.startswith('color.'):
446 if k.startswith('color.'):
447 ui._styles[k] = k[6:]
447 ui._styles[k] = k[6:]
448 elif k.startswith('terminfo.'):
448 elif k.startswith('terminfo.'):
449 ui._styles[k] = k[9:]
449 ui._styles[k] = k[9:]
450 ui.write(_('available colors:\n'))
450 ui.write(_('available colors:\n'))
451 # sort label with a '_' after the other to group '_background' entry.
451 # sort label with a '_' after the other to group '_background' entry.
452 items = sorted(ui._styles.items(),
452 items = sorted(ui._styles.items(),
453 key=lambda i: ('_' in i[0], i[0], i[1]))
453 key=lambda i: ('_' in i[0], i[0], i[1]))
454 for colorname, label in items:
454 for colorname, label in items:
455 ui.write(('%s\n') % colorname, label=label)
455 ui.write(('%s\n') % colorname, label=label)
456
456
457 def _debugdisplaystyle(ui):
457 def _debugdisplaystyle(ui):
458 ui.write(_('available style:\n'))
458 ui.write(_('available style:\n'))
459 if not ui._styles:
459 if not ui._styles:
460 return
460 return
461 width = max(len(s) for s in ui._styles)
461 width = max(len(s) for s in ui._styles)
462 for label, effects in sorted(ui._styles.items()):
462 for label, effects in sorted(ui._styles.items()):
463 ui.write('%s' % label, label=label)
463 ui.write('%s' % label, label=label)
464 if effects:
464 if effects:
465 # 50
465 # 50
466 ui.write(': ')
466 ui.write(': ')
467 ui.write(' ' * (max(0, width - len(label))))
467 ui.write(' ' * (max(0, width - len(label))))
468 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
468 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
469 ui.write('\n')
469 ui.write('\n')
470
470
471 @command('debugcreatestreamclonebundle', [], 'FILE')
471 @command('debugcreatestreamclonebundle', [], 'FILE')
472 def debugcreatestreamclonebundle(ui, repo, fname):
472 def debugcreatestreamclonebundle(ui, repo, fname):
473 """create a stream clone bundle file
473 """create a stream clone bundle file
474
474
475 Stream bundles are special bundles that are essentially archives of
475 Stream bundles are special bundles that are essentially archives of
476 revlog files. They are commonly used for cloning very quickly.
476 revlog files. They are commonly used for cloning very quickly.
477 """
477 """
478 # TODO we may want to turn this into an abort when this functionality
478 # TODO we may want to turn this into an abort when this functionality
479 # is moved into `hg bundle`.
479 # is moved into `hg bundle`.
480 if phases.hassecret(repo):
480 if phases.hassecret(repo):
481 ui.warn(_('(warning: stream clone bundle will contain secret '
481 ui.warn(_('(warning: stream clone bundle will contain secret '
482 'revisions)\n'))
482 'revisions)\n'))
483
483
484 requirements, gen = streamclone.generatebundlev1(repo)
484 requirements, gen = streamclone.generatebundlev1(repo)
485 changegroup.writechunks(ui, gen, fname)
485 changegroup.writechunks(ui, gen, fname)
486
486
487 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
487 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
488
488
489 @command('debugdag',
489 @command('debugdag',
490 [('t', 'tags', None, _('use tags as labels')),
490 [('t', 'tags', None, _('use tags as labels')),
491 ('b', 'branches', None, _('annotate with branch names')),
491 ('b', 'branches', None, _('annotate with branch names')),
492 ('', 'dots', None, _('use dots for runs')),
492 ('', 'dots', None, _('use dots for runs')),
493 ('s', 'spaces', None, _('separate elements by spaces'))],
493 ('s', 'spaces', None, _('separate elements by spaces'))],
494 _('[OPTION]... [FILE [REV]...]'),
494 _('[OPTION]... [FILE [REV]...]'),
495 optionalrepo=True)
495 optionalrepo=True)
496 def debugdag(ui, repo, file_=None, *revs, **opts):
496 def debugdag(ui, repo, file_=None, *revs, **opts):
497 """format the changelog or an index DAG as a concise textual description
497 """format the changelog or an index DAG as a concise textual description
498
498
499 If you pass a revlog index, the revlog's DAG is emitted. If you list
499 If you pass a revlog index, the revlog's DAG is emitted. If you list
500 revision numbers, they get labeled in the output as rN.
500 revision numbers, they get labeled in the output as rN.
501
501
502 Otherwise, the changelog DAG of the current repo is emitted.
502 Otherwise, the changelog DAG of the current repo is emitted.
503 """
503 """
504 spaces = opts.get(r'spaces')
504 spaces = opts.get(r'spaces')
505 dots = opts.get(r'dots')
505 dots = opts.get(r'dots')
506 if file_:
506 if file_:
507 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False),
507 rlog = revlog.revlog(vfsmod.vfs(encoding.getcwd(), audit=False),
508 file_)
508 file_)
509 revs = set((int(r) for r in revs))
509 revs = set((int(r) for r in revs))
510 def events():
510 def events():
511 for r in rlog:
511 for r in rlog:
512 yield 'n', (r, list(p for p in rlog.parentrevs(r)
512 yield 'n', (r, list(p for p in rlog.parentrevs(r)
513 if p != -1))
513 if p != -1))
514 if r in revs:
514 if r in revs:
515 yield 'l', (r, "r%i" % r)
515 yield 'l', (r, "r%i" % r)
516 elif repo:
516 elif repo:
517 cl = repo.changelog
517 cl = repo.changelog
518 tags = opts.get(r'tags')
518 tags = opts.get(r'tags')
519 branches = opts.get(r'branches')
519 branches = opts.get(r'branches')
520 if tags:
520 if tags:
521 labels = {}
521 labels = {}
522 for l, n in repo.tags().items():
522 for l, n in repo.tags().items():
523 labels.setdefault(cl.rev(n), []).append(l)
523 labels.setdefault(cl.rev(n), []).append(l)
524 def events():
524 def events():
525 b = "default"
525 b = "default"
526 for r in cl:
526 for r in cl:
527 if branches:
527 if branches:
528 newb = cl.read(cl.node(r))[5]['branch']
528 newb = cl.read(cl.node(r))[5]['branch']
529 if newb != b:
529 if newb != b:
530 yield 'a', newb
530 yield 'a', newb
531 b = newb
531 b = newb
532 yield 'n', (r, list(p for p in cl.parentrevs(r)
532 yield 'n', (r, list(p for p in cl.parentrevs(r)
533 if p != -1))
533 if p != -1))
534 if tags:
534 if tags:
535 ls = labels.get(r)
535 ls = labels.get(r)
536 if ls:
536 if ls:
537 for l in ls:
537 for l in ls:
538 yield 'l', (r, l)
538 yield 'l', (r, l)
539 else:
539 else:
540 raise error.Abort(_('need repo for changelog dag'))
540 raise error.Abort(_('need repo for changelog dag'))
541
541
542 for line in dagparser.dagtextlines(events(),
542 for line in dagparser.dagtextlines(events(),
543 addspaces=spaces,
543 addspaces=spaces,
544 wraplabels=True,
544 wraplabels=True,
545 wrapannotations=True,
545 wrapannotations=True,
546 wrapnonlinear=dots,
546 wrapnonlinear=dots,
547 usedots=dots,
547 usedots=dots,
548 maxlinewidth=70):
548 maxlinewidth=70):
549 ui.write(line)
549 ui.write(line)
550 ui.write("\n")
550 ui.write("\n")
551
551
552 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
552 @command('debugdata', cmdutil.debugrevlogopts, _('-c|-m|FILE REV'))
553 def debugdata(ui, repo, file_, rev=None, **opts):
553 def debugdata(ui, repo, file_, rev=None, **opts):
554 """dump the contents of a data file revision"""
554 """dump the contents of a data file revision"""
555 opts = pycompat.byteskwargs(opts)
555 opts = pycompat.byteskwargs(opts)
556 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
556 if opts.get('changelog') or opts.get('manifest') or opts.get('dir'):
557 if rev is not None:
557 if rev is not None:
558 raise error.CommandError('debugdata', _('invalid arguments'))
558 raise error.CommandError('debugdata', _('invalid arguments'))
559 file_, rev = None, file_
559 file_, rev = None, file_
560 elif rev is None:
560 elif rev is None:
561 raise error.CommandError('debugdata', _('invalid arguments'))
561 raise error.CommandError('debugdata', _('invalid arguments'))
562 r = cmdutil.openstorage(repo, 'debugdata', file_, opts)
562 r = cmdutil.openstorage(repo, 'debugdata', file_, opts)
563 try:
563 try:
564 ui.write(r.revision(r.lookup(rev), raw=True))
564 ui.write(r.revision(r.lookup(rev), raw=True))
565 except KeyError:
565 except KeyError:
566 raise error.Abort(_('invalid revision identifier %s') % rev)
566 raise error.Abort(_('invalid revision identifier %s') % rev)
567
567
568 @command('debugdate',
568 @command('debugdate',
569 [('e', 'extended', None, _('try extended date formats'))],
569 [('e', 'extended', None, _('try extended date formats'))],
570 _('[-e] DATE [RANGE]'),
570 _('[-e] DATE [RANGE]'),
571 norepo=True, optionalrepo=True)
571 norepo=True, optionalrepo=True)
572 def debugdate(ui, date, range=None, **opts):
572 def debugdate(ui, date, range=None, **opts):
573 """parse and display a date"""
573 """parse and display a date"""
574 if opts[r"extended"]:
574 if opts[r"extended"]:
575 d = dateutil.parsedate(date, util.extendeddateformats)
575 d = dateutil.parsedate(date, util.extendeddateformats)
576 else:
576 else:
577 d = dateutil.parsedate(date)
577 d = dateutil.parsedate(date)
578 ui.write(("internal: %d %d\n") % d)
578 ui.write(("internal: %d %d\n") % d)
579 ui.write(("standard: %s\n") % dateutil.datestr(d))
579 ui.write(("standard: %s\n") % dateutil.datestr(d))
580 if range:
580 if range:
581 m = dateutil.matchdate(range)
581 m = dateutil.matchdate(range)
582 ui.write(("match: %s\n") % m(d[0]))
582 ui.write(("match: %s\n") % m(d[0]))
583
583
584 @command('debugdeltachain',
584 @command('debugdeltachain',
585 cmdutil.debugrevlogopts + cmdutil.formatteropts,
585 cmdutil.debugrevlogopts + cmdutil.formatteropts,
586 _('-c|-m|FILE'),
586 _('-c|-m|FILE'),
587 optionalrepo=True)
587 optionalrepo=True)
588 def debugdeltachain(ui, repo, file_=None, **opts):
588 def debugdeltachain(ui, repo, file_=None, **opts):
589 """dump information about delta chains in a revlog
589 """dump information about delta chains in a revlog
590
590
591 Output can be templatized. Available template keywords are:
591 Output can be templatized. Available template keywords are:
592
592
593 :``rev``: revision number
593 :``rev``: revision number
594 :``chainid``: delta chain identifier (numbered by unique base)
594 :``chainid``: delta chain identifier (numbered by unique base)
595 :``chainlen``: delta chain length to this revision
595 :``chainlen``: delta chain length to this revision
596 :``prevrev``: previous revision in delta chain
596 :``prevrev``: previous revision in delta chain
597 :``deltatype``: role of delta / how it was computed
597 :``deltatype``: role of delta / how it was computed
598 :``compsize``: compressed size of revision
598 :``compsize``: compressed size of revision
599 :``uncompsize``: uncompressed size of revision
599 :``uncompsize``: uncompressed size of revision
600 :``chainsize``: total size of compressed revisions in chain
600 :``chainsize``: total size of compressed revisions in chain
601 :``chainratio``: total chain size divided by uncompressed revision size
601 :``chainratio``: total chain size divided by uncompressed revision size
602 (new delta chains typically start at ratio 2.00)
602 (new delta chains typically start at ratio 2.00)
603 :``lindist``: linear distance from base revision in delta chain to end
603 :``lindist``: linear distance from base revision in delta chain to end
604 of this revision
604 of this revision
605 :``extradist``: total size of revisions not part of this delta chain from
605 :``extradist``: total size of revisions not part of this delta chain from
606 base of delta chain to end of this revision; a measurement
606 base of delta chain to end of this revision; a measurement
607 of how much extra data we need to read/seek across to read
607 of how much extra data we need to read/seek across to read
608 the delta chain for this revision
608 the delta chain for this revision
609 :``extraratio``: extradist divided by chainsize; another representation of
609 :``extraratio``: extradist divided by chainsize; another representation of
610 how much unrelated data is needed to load this delta chain
610 how much unrelated data is needed to load this delta chain
611
611
612 If the repository is configured to use the sparse read, additional keywords
612 If the repository is configured to use the sparse read, additional keywords
613 are available:
613 are available:
614
614
615 :``readsize``: total size of data read from the disk for a revision
615 :``readsize``: total size of data read from the disk for a revision
616 (sum of the sizes of all the blocks)
616 (sum of the sizes of all the blocks)
617 :``largestblock``: size of the largest block of data read from the disk
617 :``largestblock``: size of the largest block of data read from the disk
618 :``readdensity``: density of useful bytes in the data read from the disk
618 :``readdensity``: density of useful bytes in the data read from the disk
619 :``srchunks``: in how many data hunks the whole revision would be read
619 :``srchunks``: in how many data hunks the whole revision would be read
620
620
621 The sparse read can be enabled with experimental.sparse-read = True
621 The sparse read can be enabled with experimental.sparse-read = True
622 """
622 """
623 opts = pycompat.byteskwargs(opts)
623 opts = pycompat.byteskwargs(opts)
624 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
624 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
625 index = r.index
625 index = r.index
626 start = r.start
626 start = r.start
627 length = r.length
627 length = r.length
628 generaldelta = r.version & revlog.FLAG_GENERALDELTA
628 generaldelta = r.version & revlog.FLAG_GENERALDELTA
629 withsparseread = getattr(r, '_withsparseread', False)
629 withsparseread = getattr(r, '_withsparseread', False)
630
630
631 def revinfo(rev):
631 def revinfo(rev):
632 e = index[rev]
632 e = index[rev]
633 compsize = e[1]
633 compsize = e[1]
634 uncompsize = e[2]
634 uncompsize = e[2]
635 chainsize = 0
635 chainsize = 0
636
636
637 if generaldelta:
637 if generaldelta:
638 if e[3] == e[5]:
638 if e[3] == e[5]:
639 deltatype = 'p1'
639 deltatype = 'p1'
640 elif e[3] == e[6]:
640 elif e[3] == e[6]:
641 deltatype = 'p2'
641 deltatype = 'p2'
642 elif e[3] == rev - 1:
642 elif e[3] == rev - 1:
643 deltatype = 'prev'
643 deltatype = 'prev'
644 elif e[3] == rev:
644 elif e[3] == rev:
645 deltatype = 'base'
645 deltatype = 'base'
646 else:
646 else:
647 deltatype = 'other'
647 deltatype = 'other'
648 else:
648 else:
649 if e[3] == rev:
649 if e[3] == rev:
650 deltatype = 'base'
650 deltatype = 'base'
651 else:
651 else:
652 deltatype = 'prev'
652 deltatype = 'prev'
653
653
654 chain = r._deltachain(rev)[0]
654 chain = r._deltachain(rev)[0]
655 for iterrev in chain:
655 for iterrev in chain:
656 e = index[iterrev]
656 e = index[iterrev]
657 chainsize += e[1]
657 chainsize += e[1]
658
658
659 return compsize, uncompsize, deltatype, chain, chainsize
659 return compsize, uncompsize, deltatype, chain, chainsize
660
660
661 fm = ui.formatter('debugdeltachain', opts)
661 fm = ui.formatter('debugdeltachain', opts)
662
662
663 fm.plain(' rev chain# chainlen prev delta '
663 fm.plain(' rev chain# chainlen prev delta '
664 'size rawsize chainsize ratio lindist extradist '
664 'size rawsize chainsize ratio lindist extradist '
665 'extraratio')
665 'extraratio')
666 if withsparseread:
666 if withsparseread:
667 fm.plain(' readsize largestblk rddensity srchunks')
667 fm.plain(' readsize largestblk rddensity srchunks')
668 fm.plain('\n')
668 fm.plain('\n')
669
669
670 chainbases = {}
670 chainbases = {}
671 for rev in r:
671 for rev in r:
672 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
672 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
673 chainbase = chain[0]
673 chainbase = chain[0]
674 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
674 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
675 basestart = start(chainbase)
675 basestart = start(chainbase)
676 revstart = start(rev)
676 revstart = start(rev)
677 lineardist = revstart + comp - basestart
677 lineardist = revstart + comp - basestart
678 extradist = lineardist - chainsize
678 extradist = lineardist - chainsize
679 try:
679 try:
680 prevrev = chain[-2]
680 prevrev = chain[-2]
681 except IndexError:
681 except IndexError:
682 prevrev = -1
682 prevrev = -1
683
683
684 if uncomp != 0:
684 if uncomp != 0:
685 chainratio = float(chainsize) / float(uncomp)
685 chainratio = float(chainsize) / float(uncomp)
686 else:
686 else:
687 chainratio = chainsize
687 chainratio = chainsize
688
688
689 if chainsize != 0:
689 if chainsize != 0:
690 extraratio = float(extradist) / float(chainsize)
690 extraratio = float(extradist) / float(chainsize)
691 else:
691 else:
692 extraratio = extradist
692 extraratio = extradist
693
693
694 fm.startitem()
694 fm.startitem()
695 fm.write('rev chainid chainlen prevrev deltatype compsize '
695 fm.write('rev chainid chainlen prevrev deltatype compsize '
696 'uncompsize chainsize chainratio lindist extradist '
696 'uncompsize chainsize chainratio lindist extradist '
697 'extraratio',
697 'extraratio',
698 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
698 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f',
699 rev, chainid, len(chain), prevrev, deltatype, comp,
699 rev, chainid, len(chain), prevrev, deltatype, comp,
700 uncomp, chainsize, chainratio, lineardist, extradist,
700 uncomp, chainsize, chainratio, lineardist, extradist,
701 extraratio,
701 extraratio,
702 rev=rev, chainid=chainid, chainlen=len(chain),
702 rev=rev, chainid=chainid, chainlen=len(chain),
703 prevrev=prevrev, deltatype=deltatype, compsize=comp,
703 prevrev=prevrev, deltatype=deltatype, compsize=comp,
704 uncompsize=uncomp, chainsize=chainsize,
704 uncompsize=uncomp, chainsize=chainsize,
705 chainratio=chainratio, lindist=lineardist,
705 chainratio=chainratio, lindist=lineardist,
706 extradist=extradist, extraratio=extraratio)
706 extradist=extradist, extraratio=extraratio)
707 if withsparseread:
707 if withsparseread:
708 readsize = 0
708 readsize = 0
709 largestblock = 0
709 largestblock = 0
710 srchunks = 0
710 srchunks = 0
711
711
712 for revschunk in deltautil.slicechunk(r, chain):
712 for revschunk in deltautil.slicechunk(r, chain):
713 srchunks += 1
713 srchunks += 1
714 blkend = start(revschunk[-1]) + length(revschunk[-1])
714 blkend = start(revschunk[-1]) + length(revschunk[-1])
715 blksize = blkend - start(revschunk[0])
715 blksize = blkend - start(revschunk[0])
716
716
717 readsize += blksize
717 readsize += blksize
718 if largestblock < blksize:
718 if largestblock < blksize:
719 largestblock = blksize
719 largestblock = blksize
720
720
721 if readsize:
721 if readsize:
722 readdensity = float(chainsize) / float(readsize)
722 readdensity = float(chainsize) / float(readsize)
723 else:
723 else:
724 readdensity = 1
724 readdensity = 1
725
725
726 fm.write('readsize largestblock readdensity srchunks',
726 fm.write('readsize largestblock readdensity srchunks',
727 ' %10d %10d %9.5f %8d',
727 ' %10d %10d %9.5f %8d',
728 readsize, largestblock, readdensity, srchunks,
728 readsize, largestblock, readdensity, srchunks,
729 readsize=readsize, largestblock=largestblock,
729 readsize=readsize, largestblock=largestblock,
730 readdensity=readdensity, srchunks=srchunks)
730 readdensity=readdensity, srchunks=srchunks)
731
731
732 fm.plain('\n')
732 fm.plain('\n')
733
733
734 fm.end()
734 fm.end()
735
735
736 @command('debugdirstate|debugstate',
736 @command('debugdirstate|debugstate',
737 [('', 'nodates', None, _('do not display the saved mtime (DEPRECATED)')),
737 [('', 'nodates', None, _('do not display the saved mtime (DEPRECATED)')),
738 ('', 'dates', True, _('display the saved mtime')),
738 ('', 'dates', True, _('display the saved mtime')),
739 ('', 'datesort', None, _('sort by saved mtime'))],
739 ('', 'datesort', None, _('sort by saved mtime'))],
740 _('[OPTION]...'))
740 _('[OPTION]...'))
741 def debugstate(ui, repo, **opts):
741 def debugstate(ui, repo, **opts):
742 """show the contents of the current dirstate"""
742 """show the contents of the current dirstate"""
743
743
744 nodates = not opts[r'dates']
744 nodates = not opts[r'dates']
745 if opts.get(r'nodates') is not None:
745 if opts.get(r'nodates') is not None:
746 nodates = True
746 nodates = True
747 datesort = opts.get(r'datesort')
747 datesort = opts.get(r'datesort')
748
748
749 if datesort:
749 if datesort:
750 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
750 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
751 else:
751 else:
752 keyfunc = None # sort by filename
752 keyfunc = None # sort by filename
753 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
753 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
754 if ent[3] == -1:
754 if ent[3] == -1:
755 timestr = 'unset '
755 timestr = 'unset '
756 elif nodates:
756 elif nodates:
757 timestr = 'set '
757 timestr = 'set '
758 else:
758 else:
759 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
759 timestr = time.strftime(r"%Y-%m-%d %H:%M:%S ",
760 time.localtime(ent[3]))
760 time.localtime(ent[3]))
761 timestr = encoding.strtolocal(timestr)
761 timestr = encoding.strtolocal(timestr)
762 if ent[1] & 0o20000:
762 if ent[1] & 0o20000:
763 mode = 'lnk'
763 mode = 'lnk'
764 else:
764 else:
765 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
765 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
766 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
766 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
767 for f in repo.dirstate.copies():
767 for f in repo.dirstate.copies():
768 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
768 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
769
769
770 @command('debugdiscovery',
770 @command('debugdiscovery',
771 [('', 'old', None, _('use old-style discovery')),
771 [('', 'old', None, _('use old-style discovery')),
772 ('', 'nonheads', None,
772 ('', 'nonheads', None,
773 _('use old-style discovery with non-heads included')),
773 _('use old-style discovery with non-heads included')),
774 ('', 'rev', [], 'restrict discovery to this set of revs'),
774 ('', 'rev', [], 'restrict discovery to this set of revs'),
775 ] + cmdutil.remoteopts,
775 ] + cmdutil.remoteopts,
776 _('[--rev REV] [OTHER]'))
776 _('[--rev REV] [OTHER]'))
777 def debugdiscovery(ui, repo, remoteurl="default", **opts):
777 def debugdiscovery(ui, repo, remoteurl="default", **opts):
778 """runs the changeset discovery protocol in isolation"""
778 """runs the changeset discovery protocol in isolation"""
779 opts = pycompat.byteskwargs(opts)
779 opts = pycompat.byteskwargs(opts)
780 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
780 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl))
781 remote = hg.peer(repo, opts, remoteurl)
781 remote = hg.peer(repo, opts, remoteurl)
782 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
782 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
783
783
784 # make sure tests are repeatable
784 # make sure tests are repeatable
785 random.seed(12323)
785 random.seed(12323)
786
786
787 def doit(pushedrevs, remoteheads, remote=remote):
787 def doit(pushedrevs, remoteheads, remote=remote):
788 if opts.get('old'):
788 if opts.get('old'):
789 if not util.safehasattr(remote, 'branches'):
789 if not util.safehasattr(remote, 'branches'):
790 # enable in-client legacy support
790 # enable in-client legacy support
791 remote = localrepo.locallegacypeer(remote.local())
791 remote = localrepo.locallegacypeer(remote.local())
792 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
792 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
793 force=True)
793 force=True)
794 common = set(common)
794 common = set(common)
795 if not opts.get('nonheads'):
795 if not opts.get('nonheads'):
796 ui.write(("unpruned common: %s\n") %
796 ui.write(("unpruned common: %s\n") %
797 " ".join(sorted(short(n) for n in common)))
797 " ".join(sorted(short(n) for n in common)))
798
798
799 clnode = repo.changelog.node
799 clnode = repo.changelog.node
800 common = repo.revs('heads(::%ln)', common)
800 common = repo.revs('heads(::%ln)', common)
801 common = {clnode(r) for r in common}
801 common = {clnode(r) for r in common}
802 else:
802 else:
803 nodes = None
803 nodes = None
804 if pushedrevs:
804 if pushedrevs:
805 revs = scmutil.revrange(repo, pushedrevs)
805 revs = scmutil.revrange(repo, pushedrevs)
806 nodes = [repo[r].node() for r in revs]
806 nodes = [repo[r].node() for r in revs]
807 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
807 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote,
808 ancestorsof=nodes)
808 ancestorsof=nodes)
809 common = set(common)
809 common = set(common)
810 rheads = set(hds)
810 rheads = set(hds)
811 lheads = set(repo.heads())
811 lheads = set(repo.heads())
812 ui.write(("common heads: %s\n") %
812 ui.write(("common heads: %s\n") %
813 " ".join(sorted(short(n) for n in common)))
813 " ".join(sorted(short(n) for n in common)))
814 if lheads <= common:
814 if lheads <= common:
815 ui.write(("local is subset\n"))
815 ui.write(("local is subset\n"))
816 elif rheads <= common:
816 elif rheads <= common:
817 ui.write(("remote is subset\n"))
817 ui.write(("remote is subset\n"))
818
818
819 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
819 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches, revs=None)
820 localrevs = opts['rev']
820 localrevs = opts['rev']
821 doit(localrevs, remoterevs)
821 doit(localrevs, remoterevs)
822
822
823 _chunksize = 4 << 10
823 _chunksize = 4 << 10
824
824
825 @command('debugdownload',
825 @command('debugdownload',
826 [
826 [
827 ('o', 'output', '', _('path')),
827 ('o', 'output', '', _('path')),
828 ],
828 ],
829 optionalrepo=True)
829 optionalrepo=True)
830 def debugdownload(ui, repo, url, output=None, **opts):
830 def debugdownload(ui, repo, url, output=None, **opts):
831 """download a resource using Mercurial logic and config
831 """download a resource using Mercurial logic and config
832 """
832 """
833 fh = urlmod.open(ui, url, output)
833 fh = urlmod.open(ui, url, output)
834
834
835 dest = ui
835 dest = ui
836 if output:
836 if output:
837 dest = open(output, "wb", _chunksize)
837 dest = open(output, "wb", _chunksize)
838 try:
838 try:
839 data = fh.read(_chunksize)
839 data = fh.read(_chunksize)
840 while data:
840 while data:
841 dest.write(data)
841 dest.write(data)
842 data = fh.read(_chunksize)
842 data = fh.read(_chunksize)
843 finally:
843 finally:
844 if output:
844 if output:
845 dest.close()
845 dest.close()
846
846
847 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
847 @command('debugextensions', cmdutil.formatteropts, [], optionalrepo=True)
848 def debugextensions(ui, repo, **opts):
848 def debugextensions(ui, repo, **opts):
849 '''show information about active extensions'''
849 '''show information about active extensions'''
850 opts = pycompat.byteskwargs(opts)
850 opts = pycompat.byteskwargs(opts)
851 exts = extensions.extensions(ui)
851 exts = extensions.extensions(ui)
852 hgver = util.version()
852 hgver = util.version()
853 fm = ui.formatter('debugextensions', opts)
853 fm = ui.formatter('debugextensions', opts)
854 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
854 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
855 isinternal = extensions.ismoduleinternal(extmod)
855 isinternal = extensions.ismoduleinternal(extmod)
856 extsource = pycompat.fsencode(extmod.__file__)
856 extsource = pycompat.fsencode(extmod.__file__)
857 if isinternal:
857 if isinternal:
858 exttestedwith = [] # never expose magic string to users
858 exttestedwith = [] # never expose magic string to users
859 else:
859 else:
860 exttestedwith = getattr(extmod, 'testedwith', '').split()
860 exttestedwith = getattr(extmod, 'testedwith', '').split()
861 extbuglink = getattr(extmod, 'buglink', None)
861 extbuglink = getattr(extmod, 'buglink', None)
862
862
863 fm.startitem()
863 fm.startitem()
864
864
865 if ui.quiet or ui.verbose:
865 if ui.quiet or ui.verbose:
866 fm.write('name', '%s\n', extname)
866 fm.write('name', '%s\n', extname)
867 else:
867 else:
868 fm.write('name', '%s', extname)
868 fm.write('name', '%s', extname)
869 if isinternal or hgver in exttestedwith:
869 if isinternal or hgver in exttestedwith:
870 fm.plain('\n')
870 fm.plain('\n')
871 elif not exttestedwith:
871 elif not exttestedwith:
872 fm.plain(_(' (untested!)\n'))
872 fm.plain(_(' (untested!)\n'))
873 else:
873 else:
874 lasttestedversion = exttestedwith[-1]
874 lasttestedversion = exttestedwith[-1]
875 fm.plain(' (%s!)\n' % lasttestedversion)
875 fm.plain(' (%s!)\n' % lasttestedversion)
876
876
877 fm.condwrite(ui.verbose and extsource, 'source',
877 fm.condwrite(ui.verbose and extsource, 'source',
878 _(' location: %s\n'), extsource or "")
878 _(' location: %s\n'), extsource or "")
879
879
880 if ui.verbose:
880 if ui.verbose:
881 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
881 fm.plain(_(' bundled: %s\n') % ['no', 'yes'][isinternal])
882 fm.data(bundled=isinternal)
882 fm.data(bundled=isinternal)
883
883
884 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
884 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
885 _(' tested with: %s\n'),
885 _(' tested with: %s\n'),
886 fm.formatlist(exttestedwith, name='ver'))
886 fm.formatlist(exttestedwith, name='ver'))
887
887
888 fm.condwrite(ui.verbose and extbuglink, 'buglink',
888 fm.condwrite(ui.verbose and extbuglink, 'buglink',
889 _(' bug reporting: %s\n'), extbuglink or "")
889 _(' bug reporting: %s\n'), extbuglink or "")
890
890
891 fm.end()
891 fm.end()
892
892
893 @command('debugfileset',
893 @command('debugfileset',
894 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
894 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV')),
895 ('', 'all-files', False,
895 ('', 'all-files', False,
896 _('test files from all revisions and working directory')),
896 _('test files from all revisions and working directory')),
897 ('s', 'show-matcher', None,
897 ('s', 'show-matcher', None,
898 _('print internal representation of matcher')),
898 _('print internal representation of matcher')),
899 ('p', 'show-stage', [],
899 ('p', 'show-stage', [],
900 _('print parsed tree at the given stage'), _('NAME'))],
900 _('print parsed tree at the given stage'), _('NAME'))],
901 _('[-r REV] [--all-files] [OPTION]... FILESPEC'))
901 _('[-r REV] [--all-files] [OPTION]... FILESPEC'))
902 def debugfileset(ui, repo, expr, **opts):
902 def debugfileset(ui, repo, expr, **opts):
903 '''parse and apply a fileset specification'''
903 '''parse and apply a fileset specification'''
904 from . import fileset
904 from . import fileset
905 fileset.symbols # force import of fileset so we have predicates to optimize
905 fileset.symbols # force import of fileset so we have predicates to optimize
906 opts = pycompat.byteskwargs(opts)
906 opts = pycompat.byteskwargs(opts)
907 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
907 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
908
908
909 stages = [
909 stages = [
910 ('parsed', pycompat.identity),
910 ('parsed', pycompat.identity),
911 ('analyzed', filesetlang.analyze),
911 ('analyzed', filesetlang.analyze),
912 ('optimized', filesetlang.optimize),
912 ('optimized', filesetlang.optimize),
913 ]
913 ]
914 stagenames = set(n for n, f in stages)
914 stagenames = set(n for n, f in stages)
915
915
916 showalways = set()
916 showalways = set()
917 if ui.verbose and not opts['show_stage']:
917 if ui.verbose and not opts['show_stage']:
918 # show parsed tree by --verbose (deprecated)
918 # show parsed tree by --verbose (deprecated)
919 showalways.add('parsed')
919 showalways.add('parsed')
920 if opts['show_stage'] == ['all']:
920 if opts['show_stage'] == ['all']:
921 showalways.update(stagenames)
921 showalways.update(stagenames)
922 else:
922 else:
923 for n in opts['show_stage']:
923 for n in opts['show_stage']:
924 if n not in stagenames:
924 if n not in stagenames:
925 raise error.Abort(_('invalid stage name: %s') % n)
925 raise error.Abort(_('invalid stage name: %s') % n)
926 showalways.update(opts['show_stage'])
926 showalways.update(opts['show_stage'])
927
927
928 tree = filesetlang.parse(expr)
928 tree = filesetlang.parse(expr)
929 for n, f in stages:
929 for n, f in stages:
930 tree = f(tree)
930 tree = f(tree)
931 if n in showalways:
931 if n in showalways:
932 if opts['show_stage'] or n != 'parsed':
932 if opts['show_stage'] or n != 'parsed':
933 ui.write(("* %s:\n") % n)
933 ui.write(("* %s:\n") % n)
934 ui.write(filesetlang.prettyformat(tree), "\n")
934 ui.write(filesetlang.prettyformat(tree), "\n")
935
935
936 files = set()
936 files = set()
937 if opts['all_files']:
937 if opts['all_files']:
938 for r in repo:
938 for r in repo:
939 c = repo[r]
939 c = repo[r]
940 files.update(c.files())
940 files.update(c.files())
941 files.update(c.substate)
941 files.update(c.substate)
942 if opts['all_files'] or ctx.rev() is None:
942 if opts['all_files'] or ctx.rev() is None:
943 wctx = repo[None]
943 wctx = repo[None]
944 files.update(repo.dirstate.walk(scmutil.matchall(repo),
944 files.update(repo.dirstate.walk(scmutil.matchall(repo),
945 subrepos=list(wctx.substate),
945 subrepos=list(wctx.substate),
946 unknown=True, ignored=True))
946 unknown=True, ignored=True))
947 files.update(wctx.substate)
947 files.update(wctx.substate)
948 else:
948 else:
949 files.update(ctx.files())
949 files.update(ctx.files())
950 files.update(ctx.substate)
950 files.update(ctx.substate)
951
951
952 m = ctx.matchfileset(expr)
952 m = ctx.matchfileset(expr)
953 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
953 if opts['show_matcher'] or (opts['show_matcher'] is None and ui.verbose):
954 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
954 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
955 for f in sorted(files):
955 for f in sorted(files):
956 if not m(f):
956 if not m(f):
957 continue
957 continue
958 ui.write("%s\n" % f)
958 ui.write("%s\n" % f)
959
959
960 @command('debugformat',
960 @command('debugformat',
961 [] + cmdutil.formatteropts)
961 [] + cmdutil.formatteropts)
962 def debugformat(ui, repo, **opts):
962 def debugformat(ui, repo, **opts):
963 """display format information about the current repository
963 """display format information about the current repository
964
964
965 Use --verbose to get extra information about current config value and
965 Use --verbose to get extra information about current config value and
966 Mercurial default."""
966 Mercurial default."""
967 opts = pycompat.byteskwargs(opts)
967 opts = pycompat.byteskwargs(opts)
968 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
968 maxvariantlength = max(len(fv.name) for fv in upgrade.allformatvariant)
969 maxvariantlength = max(len('format-variant'), maxvariantlength)
969 maxvariantlength = max(len('format-variant'), maxvariantlength)
970
970
971 def makeformatname(name):
971 def makeformatname(name):
972 return '%s:' + (' ' * (maxvariantlength - len(name)))
972 return '%s:' + (' ' * (maxvariantlength - len(name)))
973
973
974 fm = ui.formatter('debugformat', opts)
974 fm = ui.formatter('debugformat', opts)
975 if fm.isplain():
975 if fm.isplain():
976 def formatvalue(value):
976 def formatvalue(value):
977 if util.safehasattr(value, 'startswith'):
977 if util.safehasattr(value, 'startswith'):
978 return value
978 return value
979 if value:
979 if value:
980 return 'yes'
980 return 'yes'
981 else:
981 else:
982 return 'no'
982 return 'no'
983 else:
983 else:
984 formatvalue = pycompat.identity
984 formatvalue = pycompat.identity
985
985
986 fm.plain('format-variant')
986 fm.plain('format-variant')
987 fm.plain(' ' * (maxvariantlength - len('format-variant')))
987 fm.plain(' ' * (maxvariantlength - len('format-variant')))
988 fm.plain(' repo')
988 fm.plain(' repo')
989 if ui.verbose:
989 if ui.verbose:
990 fm.plain(' config default')
990 fm.plain(' config default')
991 fm.plain('\n')
991 fm.plain('\n')
992 for fv in upgrade.allformatvariant:
992 for fv in upgrade.allformatvariant:
993 fm.startitem()
993 fm.startitem()
994 repovalue = fv.fromrepo(repo)
994 repovalue = fv.fromrepo(repo)
995 configvalue = fv.fromconfig(repo)
995 configvalue = fv.fromconfig(repo)
996
996
997 if repovalue != configvalue:
997 if repovalue != configvalue:
998 namelabel = 'formatvariant.name.mismatchconfig'
998 namelabel = 'formatvariant.name.mismatchconfig'
999 repolabel = 'formatvariant.repo.mismatchconfig'
999 repolabel = 'formatvariant.repo.mismatchconfig'
1000 elif repovalue != fv.default:
1000 elif repovalue != fv.default:
1001 namelabel = 'formatvariant.name.mismatchdefault'
1001 namelabel = 'formatvariant.name.mismatchdefault'
1002 repolabel = 'formatvariant.repo.mismatchdefault'
1002 repolabel = 'formatvariant.repo.mismatchdefault'
1003 else:
1003 else:
1004 namelabel = 'formatvariant.name.uptodate'
1004 namelabel = 'formatvariant.name.uptodate'
1005 repolabel = 'formatvariant.repo.uptodate'
1005 repolabel = 'formatvariant.repo.uptodate'
1006
1006
1007 fm.write('name', makeformatname(fv.name), fv.name,
1007 fm.write('name', makeformatname(fv.name), fv.name,
1008 label=namelabel)
1008 label=namelabel)
1009 fm.write('repo', ' %3s', formatvalue(repovalue),
1009 fm.write('repo', ' %3s', formatvalue(repovalue),
1010 label=repolabel)
1010 label=repolabel)
1011 if fv.default != configvalue:
1011 if fv.default != configvalue:
1012 configlabel = 'formatvariant.config.special'
1012 configlabel = 'formatvariant.config.special'
1013 else:
1013 else:
1014 configlabel = 'formatvariant.config.default'
1014 configlabel = 'formatvariant.config.default'
1015 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
1015 fm.condwrite(ui.verbose, 'config', ' %6s', formatvalue(configvalue),
1016 label=configlabel)
1016 label=configlabel)
1017 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
1017 fm.condwrite(ui.verbose, 'default', ' %7s', formatvalue(fv.default),
1018 label='formatvariant.default')
1018 label='formatvariant.default')
1019 fm.plain('\n')
1019 fm.plain('\n')
1020 fm.end()
1020 fm.end()
1021
1021
1022 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1022 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
1023 def debugfsinfo(ui, path="."):
1023 def debugfsinfo(ui, path="."):
1024 """show information detected about current filesystem"""
1024 """show information detected about current filesystem"""
1025 ui.write(('path: %s\n') % path)
1025 ui.write(('path: %s\n') % path)
1026 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
1026 ui.write(('mounted on: %s\n') % (util.getfsmountpoint(path) or '(unknown)'))
1027 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1027 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1028 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
1028 ui.write(('fstype: %s\n') % (util.getfstype(path) or '(unknown)'))
1029 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1029 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1030 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1030 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1031 casesensitive = '(unknown)'
1031 casesensitive = '(unknown)'
1032 try:
1032 try:
1033 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
1033 with pycompat.namedtempfile(prefix='.debugfsinfo', dir=path) as f:
1034 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
1034 casesensitive = util.fscasesensitive(f.name) and 'yes' or 'no'
1035 except OSError:
1035 except OSError:
1036 pass
1036 pass
1037 ui.write(('case-sensitive: %s\n') % casesensitive)
1037 ui.write(('case-sensitive: %s\n') % casesensitive)
1038
1038
1039 @command('debuggetbundle',
1039 @command('debuggetbundle',
1040 [('H', 'head', [], _('id of head node'), _('ID')),
1040 [('H', 'head', [], _('id of head node'), _('ID')),
1041 ('C', 'common', [], _('id of common node'), _('ID')),
1041 ('C', 'common', [], _('id of common node'), _('ID')),
1042 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1042 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1043 _('REPO FILE [-H|-C ID]...'),
1043 _('REPO FILE [-H|-C ID]...'),
1044 norepo=True)
1044 norepo=True)
1045 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1045 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1046 """retrieves a bundle from a repo
1046 """retrieves a bundle from a repo
1047
1047
1048 Every ID must be a full-length hex node id string. Saves the bundle to the
1048 Every ID must be a full-length hex node id string. Saves the bundle to the
1049 given file.
1049 given file.
1050 """
1050 """
1051 opts = pycompat.byteskwargs(opts)
1051 opts = pycompat.byteskwargs(opts)
1052 repo = hg.peer(ui, opts, repopath)
1052 repo = hg.peer(ui, opts, repopath)
1053 if not repo.capable('getbundle'):
1053 if not repo.capable('getbundle'):
1054 raise error.Abort("getbundle() not supported by target repository")
1054 raise error.Abort("getbundle() not supported by target repository")
1055 args = {}
1055 args = {}
1056 if common:
1056 if common:
1057 args[r'common'] = [bin(s) for s in common]
1057 args[r'common'] = [bin(s) for s in common]
1058 if head:
1058 if head:
1059 args[r'heads'] = [bin(s) for s in head]
1059 args[r'heads'] = [bin(s) for s in head]
1060 # TODO: get desired bundlecaps from command line.
1060 # TODO: get desired bundlecaps from command line.
1061 args[r'bundlecaps'] = None
1061 args[r'bundlecaps'] = None
1062 bundle = repo.getbundle('debug', **args)
1062 bundle = repo.getbundle('debug', **args)
1063
1063
1064 bundletype = opts.get('type', 'bzip2').lower()
1064 bundletype = opts.get('type', 'bzip2').lower()
1065 btypes = {'none': 'HG10UN',
1065 btypes = {'none': 'HG10UN',
1066 'bzip2': 'HG10BZ',
1066 'bzip2': 'HG10BZ',
1067 'gzip': 'HG10GZ',
1067 'gzip': 'HG10GZ',
1068 'bundle2': 'HG20'}
1068 'bundle2': 'HG20'}
1069 bundletype = btypes.get(bundletype)
1069 bundletype = btypes.get(bundletype)
1070 if bundletype not in bundle2.bundletypes:
1070 if bundletype not in bundle2.bundletypes:
1071 raise error.Abort(_('unknown bundle type specified with --type'))
1071 raise error.Abort(_('unknown bundle type specified with --type'))
1072 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1072 bundle2.writebundle(ui, bundle, bundlepath, bundletype)
1073
1073
1074 @command('debugignore', [], '[FILE]')
1074 @command('debugignore', [], '[FILE]')
1075 def debugignore(ui, repo, *files, **opts):
1075 def debugignore(ui, repo, *files, **opts):
1076 """display the combined ignore pattern and information about ignored files
1076 """display the combined ignore pattern and information about ignored files
1077
1077
1078 With no argument display the combined ignore pattern.
1078 With no argument display the combined ignore pattern.
1079
1079
1080 Given space separated file names, shows if the given file is ignored and
1080 Given space separated file names, shows if the given file is ignored and
1081 if so, show the ignore rule (file and line number) that matched it.
1081 if so, show the ignore rule (file and line number) that matched it.
1082 """
1082 """
1083 ignore = repo.dirstate._ignore
1083 ignore = repo.dirstate._ignore
1084 if not files:
1084 if not files:
1085 # Show all the patterns
1085 # Show all the patterns
1086 ui.write("%s\n" % pycompat.byterepr(ignore))
1086 ui.write("%s\n" % pycompat.byterepr(ignore))
1087 else:
1087 else:
1088 m = scmutil.match(repo[None], pats=files)
1088 m = scmutil.match(repo[None], pats=files)
1089 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1089 uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
1090 for f in m.files():
1090 for f in m.files():
1091 nf = util.normpath(f)
1091 nf = util.normpath(f)
1092 ignored = None
1092 ignored = None
1093 ignoredata = None
1093 ignoredata = None
1094 if nf != '.':
1094 if nf != '.':
1095 if ignore(nf):
1095 if ignore(nf):
1096 ignored = nf
1096 ignored = nf
1097 ignoredata = repo.dirstate._ignorefileandline(nf)
1097 ignoredata = repo.dirstate._ignorefileandline(nf)
1098 else:
1098 else:
1099 for p in util.finddirs(nf):
1099 for p in util.finddirs(nf):
1100 if ignore(p):
1100 if ignore(p):
1101 ignored = p
1101 ignored = p
1102 ignoredata = repo.dirstate._ignorefileandline(p)
1102 ignoredata = repo.dirstate._ignorefileandline(p)
1103 break
1103 break
1104 if ignored:
1104 if ignored:
1105 if ignored == nf:
1105 if ignored == nf:
1106 ui.write(_("%s is ignored\n") % uipathfn(f))
1106 ui.write(_("%s is ignored\n") % uipathfn(f))
1107 else:
1107 else:
1108 ui.write(_("%s is ignored because of "
1108 ui.write(_("%s is ignored because of "
1109 "containing folder %s\n")
1109 "containing folder %s\n")
1110 % (uipathfn(f), ignored))
1110 % (uipathfn(f), ignored))
1111 ignorefile, lineno, line = ignoredata
1111 ignorefile, lineno, line = ignoredata
1112 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1112 ui.write(_("(ignore rule in %s, line %d: '%s')\n")
1113 % (ignorefile, lineno, line))
1113 % (ignorefile, lineno, line))
1114 else:
1114 else:
1115 ui.write(_("%s is not ignored\n") % uipathfn(f))
1115 ui.write(_("%s is not ignored\n") % uipathfn(f))
1116
1116
1117 @command('debugindex', cmdutil.debugrevlogopts + cmdutil.formatteropts,
1117 @command('debugindex', cmdutil.debugrevlogopts + cmdutil.formatteropts,
1118 _('-c|-m|FILE'))
1118 _('-c|-m|FILE'))
1119 def debugindex(ui, repo, file_=None, **opts):
1119 def debugindex(ui, repo, file_=None, **opts):
1120 """dump index data for a storage primitive"""
1120 """dump index data for a storage primitive"""
1121 opts = pycompat.byteskwargs(opts)
1121 opts = pycompat.byteskwargs(opts)
1122 store = cmdutil.openstorage(repo, 'debugindex', file_, opts)
1122 store = cmdutil.openstorage(repo, 'debugindex', file_, opts)
1123
1123
1124 if ui.debugflag:
1124 if ui.debugflag:
1125 shortfn = hex
1125 shortfn = hex
1126 else:
1126 else:
1127 shortfn = short
1127 shortfn = short
1128
1128
1129 idlen = 12
1129 idlen = 12
1130 for i in store:
1130 for i in store:
1131 idlen = len(shortfn(store.node(i)))
1131 idlen = len(shortfn(store.node(i)))
1132 break
1132 break
1133
1133
1134 fm = ui.formatter('debugindex', opts)
1134 fm = ui.formatter('debugindex', opts)
1135 fm.plain(b' rev linkrev %s %s p2\n' % (
1135 fm.plain(b' rev linkrev %s %s p2\n' % (
1136 b'nodeid'.ljust(idlen),
1136 b'nodeid'.ljust(idlen),
1137 b'p1'.ljust(idlen)))
1137 b'p1'.ljust(idlen)))
1138
1138
1139 for rev in store:
1139 for rev in store:
1140 node = store.node(rev)
1140 node = store.node(rev)
1141 parents = store.parents(node)
1141 parents = store.parents(node)
1142
1142
1143 fm.startitem()
1143 fm.startitem()
1144 fm.write(b'rev', b'%6d ', rev)
1144 fm.write(b'rev', b'%6d ', rev)
1145 fm.write(b'linkrev', '%7d ', store.linkrev(rev))
1145 fm.write(b'linkrev', '%7d ', store.linkrev(rev))
1146 fm.write(b'node', '%s ', shortfn(node))
1146 fm.write(b'node', '%s ', shortfn(node))
1147 fm.write(b'p1', '%s ', shortfn(parents[0]))
1147 fm.write(b'p1', '%s ', shortfn(parents[0]))
1148 fm.write(b'p2', '%s', shortfn(parents[1]))
1148 fm.write(b'p2', '%s', shortfn(parents[1]))
1149 fm.plain(b'\n')
1149 fm.plain(b'\n')
1150
1150
1151 fm.end()
1151 fm.end()
1152
1152
1153 @command('debugindexdot', cmdutil.debugrevlogopts,
1153 @command('debugindexdot', cmdutil.debugrevlogopts,
1154 _('-c|-m|FILE'), optionalrepo=True)
1154 _('-c|-m|FILE'), optionalrepo=True)
1155 def debugindexdot(ui, repo, file_=None, **opts):
1155 def debugindexdot(ui, repo, file_=None, **opts):
1156 """dump an index DAG as a graphviz dot file"""
1156 """dump an index DAG as a graphviz dot file"""
1157 opts = pycompat.byteskwargs(opts)
1157 opts = pycompat.byteskwargs(opts)
1158 r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts)
1158 r = cmdutil.openstorage(repo, 'debugindexdot', file_, opts)
1159 ui.write(("digraph G {\n"))
1159 ui.write(("digraph G {\n"))
1160 for i in r:
1160 for i in r:
1161 node = r.node(i)
1161 node = r.node(i)
1162 pp = r.parents(node)
1162 pp = r.parents(node)
1163 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1163 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1164 if pp[1] != nullid:
1164 if pp[1] != nullid:
1165 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1165 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1166 ui.write("}\n")
1166 ui.write("}\n")
1167
1167
1168 @command('debugindexstats', [])
1168 @command('debugindexstats', [])
1169 def debugindexstats(ui, repo):
1169 def debugindexstats(ui, repo):
1170 """show stats related to the changelog index"""
1170 """show stats related to the changelog index"""
1171 repo.changelog.shortest(nullid, 1)
1171 repo.changelog.shortest(nullid, 1)
1172 index = repo.changelog.index
1172 index = repo.changelog.index
1173 if not util.safehasattr(index, 'stats'):
1173 if not util.safehasattr(index, 'stats'):
1174 raise error.Abort(_('debugindexstats only works with native code'))
1174 raise error.Abort(_('debugindexstats only works with native code'))
1175 for k, v in sorted(index.stats().items()):
1175 for k, v in sorted(index.stats().items()):
1176 ui.write('%s: %d\n' % (k, v))
1176 ui.write('%s: %d\n' % (k, v))
1177
1177
1178 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1178 @command('debuginstall', [] + cmdutil.formatteropts, '', norepo=True)
1179 def debuginstall(ui, **opts):
1179 def debuginstall(ui, **opts):
1180 '''test Mercurial installation
1180 '''test Mercurial installation
1181
1181
1182 Returns 0 on success.
1182 Returns 0 on success.
1183 '''
1183 '''
1184 opts = pycompat.byteskwargs(opts)
1184 opts = pycompat.byteskwargs(opts)
1185
1185
1186 problems = 0
1186 problems = 0
1187
1187
1188 fm = ui.formatter('debuginstall', opts)
1188 fm = ui.formatter('debuginstall', opts)
1189 fm.startitem()
1189 fm.startitem()
1190
1190
1191 # encoding
1191 # encoding
1192 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1192 fm.write('encoding', _("checking encoding (%s)...\n"), encoding.encoding)
1193 err = None
1193 err = None
1194 try:
1194 try:
1195 codecs.lookup(pycompat.sysstr(encoding.encoding))
1195 codecs.lookup(pycompat.sysstr(encoding.encoding))
1196 except LookupError as inst:
1196 except LookupError as inst:
1197 err = stringutil.forcebytestr(inst)
1197 err = stringutil.forcebytestr(inst)
1198 problems += 1
1198 problems += 1
1199 fm.condwrite(err, 'encodingerror', _(" %s\n"
1199 fm.condwrite(err, 'encodingerror', _(" %s\n"
1200 " (check that your locale is properly set)\n"), err)
1200 " (check that your locale is properly set)\n"), err)
1201
1201
1202 # Python
1202 # Python
1203 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1203 fm.write('pythonexe', _("checking Python executable (%s)\n"),
1204 pycompat.sysexecutable)
1204 pycompat.sysexecutable)
1205 fm.write('pythonver', _("checking Python version (%s)\n"),
1205 fm.write('pythonver', _("checking Python version (%s)\n"),
1206 ("%d.%d.%d" % sys.version_info[:3]))
1206 ("%d.%d.%d" % sys.version_info[:3]))
1207 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1207 fm.write('pythonlib', _("checking Python lib (%s)...\n"),
1208 os.path.dirname(pycompat.fsencode(os.__file__)))
1208 os.path.dirname(pycompat.fsencode(os.__file__)))
1209
1209
1210 security = set(sslutil.supportedprotocols)
1210 security = set(sslutil.supportedprotocols)
1211 if sslutil.hassni:
1211 if sslutil.hassni:
1212 security.add('sni')
1212 security.add('sni')
1213
1213
1214 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1214 fm.write('pythonsecurity', _("checking Python security support (%s)\n"),
1215 fm.formatlist(sorted(security), name='protocol',
1215 fm.formatlist(sorted(security), name='protocol',
1216 fmt='%s', sep=','))
1216 fmt='%s', sep=','))
1217
1217
1218 # These are warnings, not errors. So don't increment problem count. This
1218 # These are warnings, not errors. So don't increment problem count. This
1219 # may change in the future.
1219 # may change in the future.
1220 if 'tls1.2' not in security:
1220 if 'tls1.2' not in security:
1221 fm.plain(_(' TLS 1.2 not supported by Python install; '
1221 fm.plain(_(' TLS 1.2 not supported by Python install; '
1222 'network connections lack modern security\n'))
1222 'network connections lack modern security\n'))
1223 if 'sni' not in security:
1223 if 'sni' not in security:
1224 fm.plain(_(' SNI not supported by Python install; may have '
1224 fm.plain(_(' SNI not supported by Python install; may have '
1225 'connectivity issues with some servers\n'))
1225 'connectivity issues with some servers\n'))
1226
1226
1227 # TODO print CA cert info
1227 # TODO print CA cert info
1228
1228
1229 # hg version
1229 # hg version
1230 hgver = util.version()
1230 hgver = util.version()
1231 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1231 fm.write('hgver', _("checking Mercurial version (%s)\n"),
1232 hgver.split('+')[0])
1232 hgver.split('+')[0])
1233 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1233 fm.write('hgverextra', _("checking Mercurial custom build (%s)\n"),
1234 '+'.join(hgver.split('+')[1:]))
1234 '+'.join(hgver.split('+')[1:]))
1235
1235
1236 # compiled modules
1236 # compiled modules
1237 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1237 fm.write('hgmodulepolicy', _("checking module policy (%s)\n"),
1238 policy.policy)
1238 policy.policy)
1239 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1239 fm.write('hgmodules', _("checking installed modules (%s)...\n"),
1240 os.path.dirname(pycompat.fsencode(__file__)))
1240 os.path.dirname(pycompat.fsencode(__file__)))
1241
1241
1242 if policy.policy in ('c', 'allow'):
1242 if policy.policy in ('c', 'allow'):
1243 err = None
1243 err = None
1244 try:
1244 try:
1245 from .cext import (
1245 from .cext import (
1246 base85,
1246 base85,
1247 bdiff,
1247 bdiff,
1248 mpatch,
1248 mpatch,
1249 osutil,
1249 osutil,
1250 )
1250 )
1251 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1251 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1252 except Exception as inst:
1252 except Exception as inst:
1253 err = stringutil.forcebytestr(inst)
1253 err = stringutil.forcebytestr(inst)
1254 problems += 1
1254 problems += 1
1255 fm.condwrite(err, 'extensionserror', " %s\n", err)
1255 fm.condwrite(err, 'extensionserror', " %s\n", err)
1256
1256
1257 compengines = util.compengines._engines.values()
1257 compengines = util.compengines._engines.values()
1258 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1258 fm.write('compengines', _('checking registered compression engines (%s)\n'),
1259 fm.formatlist(sorted(e.name() for e in compengines),
1259 fm.formatlist(sorted(e.name() for e in compengines),
1260 name='compengine', fmt='%s', sep=', '))
1260 name='compengine', fmt='%s', sep=', '))
1261 fm.write('compenginesavail', _('checking available compression engines '
1261 fm.write('compenginesavail', _('checking available compression engines '
1262 '(%s)\n'),
1262 '(%s)\n'),
1263 fm.formatlist(sorted(e.name() for e in compengines
1263 fm.formatlist(sorted(e.name() for e in compengines
1264 if e.available()),
1264 if e.available()),
1265 name='compengine', fmt='%s', sep=', '))
1265 name='compengine', fmt='%s', sep=', '))
1266 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1266 wirecompengines = util.compengines.supportedwireengines(util.SERVERROLE)
1267 fm.write('compenginesserver', _('checking available compression engines '
1267 fm.write('compenginesserver', _('checking available compression engines '
1268 'for wire protocol (%s)\n'),
1268 'for wire protocol (%s)\n'),
1269 fm.formatlist([e.name() for e in wirecompengines
1269 fm.formatlist([e.name() for e in wirecompengines
1270 if e.wireprotosupport()],
1270 if e.wireprotosupport()],
1271 name='compengine', fmt='%s', sep=', '))
1271 name='compengine', fmt='%s', sep=', '))
1272 re2 = 'missing'
1272 re2 = 'missing'
1273 if util._re2:
1273 if util._re2:
1274 re2 = 'available'
1274 re2 = 'available'
1275 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1275 fm.plain(_('checking "re2" regexp engine (%s)\n') % re2)
1276 fm.data(re2=bool(util._re2))
1276 fm.data(re2=bool(util._re2))
1277
1277
1278 # templates
1278 # templates
1279 p = templater.templatepaths()
1279 p = templater.templatepaths()
1280 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1280 fm.write('templatedirs', 'checking templates (%s)...\n', ' '.join(p))
1281 fm.condwrite(not p, '', _(" no template directories found\n"))
1281 fm.condwrite(not p, '', _(" no template directories found\n"))
1282 if p:
1282 if p:
1283 m = templater.templatepath("map-cmdline.default")
1283 m = templater.templatepath("map-cmdline.default")
1284 if m:
1284 if m:
1285 # template found, check if it is working
1285 # template found, check if it is working
1286 err = None
1286 err = None
1287 try:
1287 try:
1288 templater.templater.frommapfile(m)
1288 templater.templater.frommapfile(m)
1289 except Exception as inst:
1289 except Exception as inst:
1290 err = stringutil.forcebytestr(inst)
1290 err = stringutil.forcebytestr(inst)
1291 p = None
1291 p = None
1292 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1292 fm.condwrite(err, 'defaulttemplateerror', " %s\n", err)
1293 else:
1293 else:
1294 p = None
1294 p = None
1295 fm.condwrite(p, 'defaulttemplate',
1295 fm.condwrite(p, 'defaulttemplate',
1296 _("checking default template (%s)\n"), m)
1296 _("checking default template (%s)\n"), m)
1297 fm.condwrite(not m, 'defaulttemplatenotfound',
1297 fm.condwrite(not m, 'defaulttemplatenotfound',
1298 _(" template '%s' not found\n"), "default")
1298 _(" template '%s' not found\n"), "default")
1299 if not p:
1299 if not p:
1300 problems += 1
1300 problems += 1
1301 fm.condwrite(not p, '',
1301 fm.condwrite(not p, '',
1302 _(" (templates seem to have been installed incorrectly)\n"))
1302 _(" (templates seem to have been installed incorrectly)\n"))
1303
1303
1304 # editor
1304 # editor
1305 editor = ui.geteditor()
1305 editor = ui.geteditor()
1306 editor = util.expandpath(editor)
1306 editor = util.expandpath(editor)
1307 editorbin = procutil.shellsplit(editor)[0]
1307 editorbin = procutil.shellsplit(editor)[0]
1308 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1308 fm.write('editor', _("checking commit editor... (%s)\n"), editorbin)
1309 cmdpath = procutil.findexe(editorbin)
1309 cmdpath = procutil.findexe(editorbin)
1310 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1310 fm.condwrite(not cmdpath and editor == 'vi', 'vinotfound',
1311 _(" No commit editor set and can't find %s in PATH\n"
1311 _(" No commit editor set and can't find %s in PATH\n"
1312 " (specify a commit editor in your configuration"
1312 " (specify a commit editor in your configuration"
1313 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1313 " file)\n"), not cmdpath and editor == 'vi' and editorbin)
1314 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1314 fm.condwrite(not cmdpath and editor != 'vi', 'editornotfound',
1315 _(" Can't find editor '%s' in PATH\n"
1315 _(" Can't find editor '%s' in PATH\n"
1316 " (specify a commit editor in your configuration"
1316 " (specify a commit editor in your configuration"
1317 " file)\n"), not cmdpath and editorbin)
1317 " file)\n"), not cmdpath and editorbin)
1318 if not cmdpath and editor != 'vi':
1318 if not cmdpath and editor != 'vi':
1319 problems += 1
1319 problems += 1
1320
1320
1321 # check username
1321 # check username
1322 username = None
1322 username = None
1323 err = None
1323 err = None
1324 try:
1324 try:
1325 username = ui.username()
1325 username = ui.username()
1326 except error.Abort as e:
1326 except error.Abort as e:
1327 err = stringutil.forcebytestr(e)
1327 err = stringutil.forcebytestr(e)
1328 problems += 1
1328 problems += 1
1329
1329
1330 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1330 fm.condwrite(username, 'username', _("checking username (%s)\n"), username)
1331 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1331 fm.condwrite(err, 'usernameerror', _("checking username...\n %s\n"
1332 " (specify a username in your configuration file)\n"), err)
1332 " (specify a username in your configuration file)\n"), err)
1333
1333
1334 fm.condwrite(not problems, '',
1334 fm.condwrite(not problems, '',
1335 _("no problems detected\n"))
1335 _("no problems detected\n"))
1336 if not problems:
1336 if not problems:
1337 fm.data(problems=problems)
1337 fm.data(problems=problems)
1338 fm.condwrite(problems, 'problems',
1338 fm.condwrite(problems, 'problems',
1339 _("%d problems detected,"
1339 _("%d problems detected,"
1340 " please check your install!\n"), problems)
1340 " please check your install!\n"), problems)
1341 fm.end()
1341 fm.end()
1342
1342
1343 return problems
1343 return problems
1344
1344
1345 @command('debugknown', [], _('REPO ID...'), norepo=True)
1345 @command('debugknown', [], _('REPO ID...'), norepo=True)
1346 def debugknown(ui, repopath, *ids, **opts):
1346 def debugknown(ui, repopath, *ids, **opts):
1347 """test whether node ids are known to a repo
1347 """test whether node ids are known to a repo
1348
1348
1349 Every ID must be a full-length hex node id string. Returns a list of 0s
1349 Every ID must be a full-length hex node id string. Returns a list of 0s
1350 and 1s indicating unknown/known.
1350 and 1s indicating unknown/known.
1351 """
1351 """
1352 opts = pycompat.byteskwargs(opts)
1352 opts = pycompat.byteskwargs(opts)
1353 repo = hg.peer(ui, opts, repopath)
1353 repo = hg.peer(ui, opts, repopath)
1354 if not repo.capable('known'):
1354 if not repo.capable('known'):
1355 raise error.Abort("known() not supported by target repository")
1355 raise error.Abort("known() not supported by target repository")
1356 flags = repo.known([bin(s) for s in ids])
1356 flags = repo.known([bin(s) for s in ids])
1357 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1357 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1358
1358
1359 @command('debuglabelcomplete', [], _('LABEL...'))
1359 @command('debuglabelcomplete', [], _('LABEL...'))
1360 def debuglabelcomplete(ui, repo, *args):
1360 def debuglabelcomplete(ui, repo, *args):
1361 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1361 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
1362 debugnamecomplete(ui, repo, *args)
1362 debugnamecomplete(ui, repo, *args)
1363
1363
1364 @command('debuglocks',
1364 @command('debuglocks',
1365 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1365 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
1366 ('W', 'force-wlock', None,
1366 ('W', 'force-wlock', None,
1367 _('free the working state lock (DANGEROUS)')),
1367 _('free the working state lock (DANGEROUS)')),
1368 ('s', 'set-lock', None, _('set the store lock until stopped')),
1368 ('s', 'set-lock', None, _('set the store lock until stopped')),
1369 ('S', 'set-wlock', None,
1369 ('S', 'set-wlock', None,
1370 _('set the working state lock until stopped'))],
1370 _('set the working state lock until stopped'))],
1371 _('[OPTION]...'))
1371 _('[OPTION]...'))
1372 def debuglocks(ui, repo, **opts):
1372 def debuglocks(ui, repo, **opts):
1373 """show or modify state of locks
1373 """show or modify state of locks
1374
1374
1375 By default, this command will show which locks are held. This
1375 By default, this command will show which locks are held. This
1376 includes the user and process holding the lock, the amount of time
1376 includes the user and process holding the lock, the amount of time
1377 the lock has been held, and the machine name where the process is
1377 the lock has been held, and the machine name where the process is
1378 running if it's not local.
1378 running if it's not local.
1379
1379
1380 Locks protect the integrity of Mercurial's data, so should be
1380 Locks protect the integrity of Mercurial's data, so should be
1381 treated with care. System crashes or other interruptions may cause
1381 treated with care. System crashes or other interruptions may cause
1382 locks to not be properly released, though Mercurial will usually
1382 locks to not be properly released, though Mercurial will usually
1383 detect and remove such stale locks automatically.
1383 detect and remove such stale locks automatically.
1384
1384
1385 However, detecting stale locks may not always be possible (for
1385 However, detecting stale locks may not always be possible (for
1386 instance, on a shared filesystem). Removing locks may also be
1386 instance, on a shared filesystem). Removing locks may also be
1387 blocked by filesystem permissions.
1387 blocked by filesystem permissions.
1388
1388
1389 Setting a lock will prevent other commands from changing the data.
1389 Setting a lock will prevent other commands from changing the data.
1390 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1390 The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs.
1391 The set locks are removed when the command exits.
1391 The set locks are removed when the command exits.
1392
1392
1393 Returns 0 if no locks are held.
1393 Returns 0 if no locks are held.
1394
1394
1395 """
1395 """
1396
1396
1397 if opts.get(r'force_lock'):
1397 if opts.get(r'force_lock'):
1398 repo.svfs.unlink('lock')
1398 repo.svfs.unlink('lock')
1399 if opts.get(r'force_wlock'):
1399 if opts.get(r'force_wlock'):
1400 repo.vfs.unlink('wlock')
1400 repo.vfs.unlink('wlock')
1401 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1401 if opts.get(r'force_lock') or opts.get(r'force_wlock'):
1402 return 0
1402 return 0
1403
1403
1404 locks = []
1404 locks = []
1405 try:
1405 try:
1406 if opts.get(r'set_wlock'):
1406 if opts.get(r'set_wlock'):
1407 try:
1407 try:
1408 locks.append(repo.wlock(False))
1408 locks.append(repo.wlock(False))
1409 except error.LockHeld:
1409 except error.LockHeld:
1410 raise error.Abort(_('wlock is already held'))
1410 raise error.Abort(_('wlock is already held'))
1411 if opts.get(r'set_lock'):
1411 if opts.get(r'set_lock'):
1412 try:
1412 try:
1413 locks.append(repo.lock(False))
1413 locks.append(repo.lock(False))
1414 except error.LockHeld:
1414 except error.LockHeld:
1415 raise error.Abort(_('lock is already held'))
1415 raise error.Abort(_('lock is already held'))
1416 if len(locks):
1416 if len(locks):
1417 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1417 ui.promptchoice(_("ready to release the lock (y)? $$ &Yes"))
1418 return 0
1418 return 0
1419 finally:
1419 finally:
1420 release(*locks)
1420 release(*locks)
1421
1421
1422 now = time.time()
1422 now = time.time()
1423 held = 0
1423 held = 0
1424
1424
1425 def report(vfs, name, method):
1425 def report(vfs, name, method):
1426 # this causes stale locks to get reaped for more accurate reporting
1426 # this causes stale locks to get reaped for more accurate reporting
1427 try:
1427 try:
1428 l = method(False)
1428 l = method(False)
1429 except error.LockHeld:
1429 except error.LockHeld:
1430 l = None
1430 l = None
1431
1431
1432 if l:
1432 if l:
1433 l.release()
1433 l.release()
1434 else:
1434 else:
1435 try:
1435 try:
1436 st = vfs.lstat(name)
1436 st = vfs.lstat(name)
1437 age = now - st[stat.ST_MTIME]
1437 age = now - st[stat.ST_MTIME]
1438 user = util.username(st.st_uid)
1438 user = util.username(st.st_uid)
1439 locker = vfs.readlock(name)
1439 locker = vfs.readlock(name)
1440 if ":" in locker:
1440 if ":" in locker:
1441 host, pid = locker.split(':')
1441 host, pid = locker.split(':')
1442 if host == socket.gethostname():
1442 if host == socket.gethostname():
1443 locker = 'user %s, process %s' % (user or b'None', pid)
1443 locker = 'user %s, process %s' % (user or b'None', pid)
1444 else:
1444 else:
1445 locker = 'user %s, process %s, host %s' \
1445 locker = 'user %s, process %s, host %s' \
1446 % (user or b'None', pid, host)
1446 % (user or b'None', pid, host)
1447 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1447 ui.write(("%-6s %s (%ds)\n") % (name + ":", locker, age))
1448 return 1
1448 return 1
1449 except OSError as e:
1449 except OSError as e:
1450 if e.errno != errno.ENOENT:
1450 if e.errno != errno.ENOENT:
1451 raise
1451 raise
1452
1452
1453 ui.write(("%-6s free\n") % (name + ":"))
1453 ui.write(("%-6s free\n") % (name + ":"))
1454 return 0
1454 return 0
1455
1455
1456 held += report(repo.svfs, "lock", repo.lock)
1456 held += report(repo.svfs, "lock", repo.lock)
1457 held += report(repo.vfs, "wlock", repo.wlock)
1457 held += report(repo.vfs, "wlock", repo.wlock)
1458
1458
1459 return held
1459 return held
1460
1460
1461 @command('debugmanifestfulltextcache', [
1461 @command('debugmanifestfulltextcache', [
1462 ('', 'clear', False, _('clear the cache')),
1462 ('', 'clear', False, _('clear the cache')),
1463 ('a', 'add', '', _('add the given manifest node to the cache'),
1463 ('a', 'add', '', _('add the given manifest node to the cache'),
1464 _('NODE'))
1464 _('NODE'))
1465 ], '')
1465 ], '')
1466 def debugmanifestfulltextcache(ui, repo, add=None, **opts):
1466 def debugmanifestfulltextcache(ui, repo, add=None, **opts):
1467 """show, clear or amend the contents of the manifest fulltext cache"""
1467 """show, clear or amend the contents of the manifest fulltext cache"""
1468 with repo.lock():
1468 with repo.lock():
1469 r = repo.manifestlog.getstorage(b'')
1469 r = repo.manifestlog.getstorage(b'')
1470 try:
1470 try:
1471 cache = r._fulltextcache
1471 cache = r._fulltextcache
1472 except AttributeError:
1472 except AttributeError:
1473 ui.warn(_(
1473 ui.warn(_(
1474 "Current revlog implementation doesn't appear to have a "
1474 "Current revlog implementation doesn't appear to have a "
1475 'manifest fulltext cache\n'))
1475 'manifest fulltext cache\n'))
1476 return
1476 return
1477
1477
1478 if opts.get(r'clear'):
1478 if opts.get(r'clear'):
1479 cache.clear()
1479 cache.clear()
1480
1480
1481 if add:
1481 if add:
1482 try:
1482 try:
1483 manifest = repo.manifestlog[r.lookup(add)]
1483 manifest = repo.manifestlog[r.lookup(add)]
1484 except error.LookupError as e:
1484 except error.LookupError as e:
1485 raise error.Abort(e, hint="Check your manifest node id")
1485 raise error.Abort(e, hint="Check your manifest node id")
1486 manifest.read() # stores revisision in cache too
1486 manifest.read() # stores revisision in cache too
1487
1487
1488 if not len(cache):
1488 if not len(cache):
1489 ui.write(_('Cache empty'))
1489 ui.write(_('Cache empty'))
1490 else:
1490 else:
1491 ui.write(
1491 ui.write(
1492 _('Cache contains %d manifest entries, in order of most to '
1492 _('Cache contains %d manifest entries, in order of most to '
1493 'least recent:\n') % (len(cache),))
1493 'least recent:\n') % (len(cache),))
1494 totalsize = 0
1494 totalsize = 0
1495 for nodeid in cache:
1495 for nodeid in cache:
1496 # Use cache.get to not update the LRU order
1496 # Use cache.get to not update the LRU order
1497 data = cache.get(nodeid)
1497 data = cache.get(nodeid)
1498 size = len(data)
1498 size = len(data)
1499 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1499 totalsize += size + 24 # 20 bytes nodeid, 4 bytes size
1500 ui.write(_('id: %s, size %s\n') % (
1500 ui.write(_('id: %s, size %s\n') % (
1501 hex(nodeid), util.bytecount(size)))
1501 hex(nodeid), util.bytecount(size)))
1502 ondisk = cache._opener.stat('manifestfulltextcache').st_size
1502 ondisk = cache._opener.stat('manifestfulltextcache').st_size
1503 ui.write(
1503 ui.write(
1504 _('Total cache data size %s, on-disk %s\n') % (
1504 _('Total cache data size %s, on-disk %s\n') % (
1505 util.bytecount(totalsize), util.bytecount(ondisk))
1505 util.bytecount(totalsize), util.bytecount(ondisk))
1506 )
1506 )
1507
1507
1508 @command('debugmergestate', [], '')
1508 @command('debugmergestate', [], '')
1509 def debugmergestate(ui, repo, *args):
1509 def debugmergestate(ui, repo, *args):
1510 """print merge state
1510 """print merge state
1511
1511
1512 Use --verbose to print out information about whether v1 or v2 merge state
1512 Use --verbose to print out information about whether v1 or v2 merge state
1513 was chosen."""
1513 was chosen."""
1514 def _hashornull(h):
1514 def _hashornull(h):
1515 if h == nullhex:
1515 if h == nullhex:
1516 return 'null'
1516 return 'null'
1517 else:
1517 else:
1518 return h
1518 return h
1519
1519
1520 def printrecords(version):
1520 def printrecords(version):
1521 ui.write(('* version %d records\n') % version)
1521 ui.write(('* version %d records\n') % version)
1522 if version == 1:
1522 if version == 1:
1523 records = v1records
1523 records = v1records
1524 else:
1524 else:
1525 records = v2records
1525 records = v2records
1526
1526
1527 for rtype, record in records:
1527 for rtype, record in records:
1528 # pretty print some record types
1528 # pretty print some record types
1529 if rtype == 'L':
1529 if rtype == 'L':
1530 ui.write(('local: %s\n') % record)
1530 ui.write(('local: %s\n') % record)
1531 elif rtype == 'O':
1531 elif rtype == 'O':
1532 ui.write(('other: %s\n') % record)
1532 ui.write(('other: %s\n') % record)
1533 elif rtype == 'm':
1533 elif rtype == 'm':
1534 driver, mdstate = record.split('\0', 1)
1534 driver, mdstate = record.split('\0', 1)
1535 ui.write(('merge driver: %s (state "%s")\n')
1535 ui.write(('merge driver: %s (state "%s")\n')
1536 % (driver, mdstate))
1536 % (driver, mdstate))
1537 elif rtype in 'FDC':
1537 elif rtype in 'FDC':
1538 r = record.split('\0')
1538 r = record.split('\0')
1539 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1539 f, state, hash, lfile, afile, anode, ofile = r[0:7]
1540 if version == 1:
1540 if version == 1:
1541 onode = 'not stored in v1 format'
1541 onode = 'not stored in v1 format'
1542 flags = r[7]
1542 flags = r[7]
1543 else:
1543 else:
1544 onode, flags = r[7:9]
1544 onode, flags = r[7:9]
1545 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1545 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
1546 % (f, rtype, state, _hashornull(hash)))
1546 % (f, rtype, state, _hashornull(hash)))
1547 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1547 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
1548 ui.write((' ancestor path: %s (node %s)\n')
1548 ui.write((' ancestor path: %s (node %s)\n')
1549 % (afile, _hashornull(anode)))
1549 % (afile, _hashornull(anode)))
1550 ui.write((' other path: %s (node %s)\n')
1550 ui.write((' other path: %s (node %s)\n')
1551 % (ofile, _hashornull(onode)))
1551 % (ofile, _hashornull(onode)))
1552 elif rtype == 'f':
1552 elif rtype == 'f':
1553 filename, rawextras = record.split('\0', 1)
1553 filename, rawextras = record.split('\0', 1)
1554 extras = rawextras.split('\0')
1554 extras = rawextras.split('\0')
1555 i = 0
1555 i = 0
1556 extrastrings = []
1556 extrastrings = []
1557 while i < len(extras):
1557 while i < len(extras):
1558 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1558 extrastrings.append('%s = %s' % (extras[i], extras[i + 1]))
1559 i += 2
1559 i += 2
1560
1560
1561 ui.write(('file extras: %s (%s)\n')
1561 ui.write(('file extras: %s (%s)\n')
1562 % (filename, ', '.join(extrastrings)))
1562 % (filename, ', '.join(extrastrings)))
1563 elif rtype == 'l':
1563 elif rtype == 'l':
1564 labels = record.split('\0', 2)
1564 labels = record.split('\0', 2)
1565 labels = [l for l in labels if len(l) > 0]
1565 labels = [l for l in labels if len(l) > 0]
1566 ui.write(('labels:\n'))
1566 ui.write(('labels:\n'))
1567 ui.write((' local: %s\n' % labels[0]))
1567 ui.write((' local: %s\n' % labels[0]))
1568 ui.write((' other: %s\n' % labels[1]))
1568 ui.write((' other: %s\n' % labels[1]))
1569 if len(labels) > 2:
1569 if len(labels) > 2:
1570 ui.write((' base: %s\n' % labels[2]))
1570 ui.write((' base: %s\n' % labels[2]))
1571 else:
1571 else:
1572 ui.write(('unrecognized entry: %s\t%s\n')
1572 ui.write(('unrecognized entry: %s\t%s\n')
1573 % (rtype, record.replace('\0', '\t')))
1573 % (rtype, record.replace('\0', '\t')))
1574
1574
1575 # Avoid mergestate.read() since it may raise an exception for unsupported
1575 # Avoid mergestate.read() since it may raise an exception for unsupported
1576 # merge state records. We shouldn't be doing this, but this is OK since this
1576 # merge state records. We shouldn't be doing this, but this is OK since this
1577 # command is pretty low-level.
1577 # command is pretty low-level.
1578 ms = mergemod.mergestate(repo)
1578 ms = mergemod.mergestate(repo)
1579
1579
1580 # sort so that reasonable information is on top
1580 # sort so that reasonable information is on top
1581 v1records = ms._readrecordsv1()
1581 v1records = ms._readrecordsv1()
1582 v2records = ms._readrecordsv2()
1582 v2records = ms._readrecordsv2()
1583 order = 'LOml'
1583 order = 'LOml'
1584 def key(r):
1584 def key(r):
1585 idx = order.find(r[0])
1585 idx = order.find(r[0])
1586 if idx == -1:
1586 if idx == -1:
1587 return (1, r[1])
1587 return (1, r[1])
1588 else:
1588 else:
1589 return (0, idx)
1589 return (0, idx)
1590 v1records.sort(key=key)
1590 v1records.sort(key=key)
1591 v2records.sort(key=key)
1591 v2records.sort(key=key)
1592
1592
1593 if not v1records and not v2records:
1593 if not v1records and not v2records:
1594 ui.write(('no merge state found\n'))
1594 ui.write(('no merge state found\n'))
1595 elif not v2records:
1595 elif not v2records:
1596 ui.note(('no version 2 merge state\n'))
1596 ui.note(('no version 2 merge state\n'))
1597 printrecords(1)
1597 printrecords(1)
1598 elif ms._v1v2match(v1records, v2records):
1598 elif ms._v1v2match(v1records, v2records):
1599 ui.note(('v1 and v2 states match: using v2\n'))
1599 ui.note(('v1 and v2 states match: using v2\n'))
1600 printrecords(2)
1600 printrecords(2)
1601 else:
1601 else:
1602 ui.note(('v1 and v2 states mismatch: using v1\n'))
1602 ui.note(('v1 and v2 states mismatch: using v1\n'))
1603 printrecords(1)
1603 printrecords(1)
1604 if ui.verbose:
1604 if ui.verbose:
1605 printrecords(2)
1605 printrecords(2)
1606
1606
1607 @command('debugnamecomplete', [], _('NAME...'))
1607 @command('debugnamecomplete', [], _('NAME...'))
1608 def debugnamecomplete(ui, repo, *args):
1608 def debugnamecomplete(ui, repo, *args):
1609 '''complete "names" - tags, open branch names, bookmark names'''
1609 '''complete "names" - tags, open branch names, bookmark names'''
1610
1610
1611 names = set()
1611 names = set()
1612 # since we previously only listed open branches, we will handle that
1612 # since we previously only listed open branches, we will handle that
1613 # specially (after this for loop)
1613 # specially (after this for loop)
1614 for name, ns in repo.names.iteritems():
1614 for name, ns in repo.names.iteritems():
1615 if name != 'branches':
1615 if name != 'branches':
1616 names.update(ns.listnames(repo))
1616 names.update(ns.listnames(repo))
1617 names.update(tag for (tag, heads, tip, closed)
1617 names.update(tag for (tag, heads, tip, closed)
1618 in repo.branchmap().iterbranches() if not closed)
1618 in repo.branchmap().iterbranches() if not closed)
1619 completions = set()
1619 completions = set()
1620 if not args:
1620 if not args:
1621 args = ['']
1621 args = ['']
1622 for a in args:
1622 for a in args:
1623 completions.update(n for n in names if n.startswith(a))
1623 completions.update(n for n in names if n.startswith(a))
1624 ui.write('\n'.join(sorted(completions)))
1624 ui.write('\n'.join(sorted(completions)))
1625 ui.write('\n')
1625 ui.write('\n')
1626
1626
1627 @command('debugobsolete',
1627 @command('debugobsolete',
1628 [('', 'flags', 0, _('markers flag')),
1628 [('', 'flags', 0, _('markers flag')),
1629 ('', 'record-parents', False,
1629 ('', 'record-parents', False,
1630 _('record parent information for the precursor')),
1630 _('record parent information for the precursor')),
1631 ('r', 'rev', [], _('display markers relevant to REV')),
1631 ('r', 'rev', [], _('display markers relevant to REV')),
1632 ('', 'exclusive', False, _('restrict display to markers only '
1632 ('', 'exclusive', False, _('restrict display to markers only '
1633 'relevant to REV')),
1633 'relevant to REV')),
1634 ('', 'index', False, _('display index of the marker')),
1634 ('', 'index', False, _('display index of the marker')),
1635 ('', 'delete', [], _('delete markers specified by indices')),
1635 ('', 'delete', [], _('delete markers specified by indices')),
1636 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1636 ] + cmdutil.commitopts2 + cmdutil.formatteropts,
1637 _('[OBSOLETED [REPLACEMENT ...]]'))
1637 _('[OBSOLETED [REPLACEMENT ...]]'))
1638 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1638 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
1639 """create arbitrary obsolete marker
1639 """create arbitrary obsolete marker
1640
1640
1641 With no arguments, displays the list of obsolescence markers."""
1641 With no arguments, displays the list of obsolescence markers."""
1642
1642
1643 opts = pycompat.byteskwargs(opts)
1643 opts = pycompat.byteskwargs(opts)
1644
1644
1645 def parsenodeid(s):
1645 def parsenodeid(s):
1646 try:
1646 try:
1647 # We do not use revsingle/revrange functions here to accept
1647 # We do not use revsingle/revrange functions here to accept
1648 # arbitrary node identifiers, possibly not present in the
1648 # arbitrary node identifiers, possibly not present in the
1649 # local repository.
1649 # local repository.
1650 n = bin(s)
1650 n = bin(s)
1651 if len(n) != len(nullid):
1651 if len(n) != len(nullid):
1652 raise TypeError()
1652 raise TypeError()
1653 return n
1653 return n
1654 except TypeError:
1654 except TypeError:
1655 raise error.Abort('changeset references must be full hexadecimal '
1655 raise error.Abort('changeset references must be full hexadecimal '
1656 'node identifiers')
1656 'node identifiers')
1657
1657
1658 if opts.get('delete'):
1658 if opts.get('delete'):
1659 indices = []
1659 indices = []
1660 for v in opts.get('delete'):
1660 for v in opts.get('delete'):
1661 try:
1661 try:
1662 indices.append(int(v))
1662 indices.append(int(v))
1663 except ValueError:
1663 except ValueError:
1664 raise error.Abort(_('invalid index value: %r') % v,
1664 raise error.Abort(_('invalid index value: %r') % v,
1665 hint=_('use integers for indices'))
1665 hint=_('use integers for indices'))
1666
1666
1667 if repo.currenttransaction():
1667 if repo.currenttransaction():
1668 raise error.Abort(_('cannot delete obsmarkers in the middle '
1668 raise error.Abort(_('cannot delete obsmarkers in the middle '
1669 'of transaction.'))
1669 'of transaction.'))
1670
1670
1671 with repo.lock():
1671 with repo.lock():
1672 n = repair.deleteobsmarkers(repo.obsstore, indices)
1672 n = repair.deleteobsmarkers(repo.obsstore, indices)
1673 ui.write(_('deleted %i obsolescence markers\n') % n)
1673 ui.write(_('deleted %i obsolescence markers\n') % n)
1674
1674
1675 return
1675 return
1676
1676
1677 if precursor is not None:
1677 if precursor is not None:
1678 if opts['rev']:
1678 if opts['rev']:
1679 raise error.Abort('cannot select revision when creating marker')
1679 raise error.Abort('cannot select revision when creating marker')
1680 metadata = {}
1680 metadata = {}
1681 metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
1681 metadata['user'] = encoding.fromlocal(opts['user'] or ui.username())
1682 succs = tuple(parsenodeid(succ) for succ in successors)
1682 succs = tuple(parsenodeid(succ) for succ in successors)
1683 l = repo.lock()
1683 l = repo.lock()
1684 try:
1684 try:
1685 tr = repo.transaction('debugobsolete')
1685 tr = repo.transaction('debugobsolete')
1686 try:
1686 try:
1687 date = opts.get('date')
1687 date = opts.get('date')
1688 if date:
1688 if date:
1689 date = dateutil.parsedate(date)
1689 date = dateutil.parsedate(date)
1690 else:
1690 else:
1691 date = None
1691 date = None
1692 prec = parsenodeid(precursor)
1692 prec = parsenodeid(precursor)
1693 parents = None
1693 parents = None
1694 if opts['record_parents']:
1694 if opts['record_parents']:
1695 if prec not in repo.unfiltered():
1695 if prec not in repo.unfiltered():
1696 raise error.Abort('cannot used --record-parents on '
1696 raise error.Abort('cannot used --record-parents on '
1697 'unknown changesets')
1697 'unknown changesets')
1698 parents = repo.unfiltered()[prec].parents()
1698 parents = repo.unfiltered()[prec].parents()
1699 parents = tuple(p.node() for p in parents)
1699 parents = tuple(p.node() for p in parents)
1700 repo.obsstore.create(tr, prec, succs, opts['flags'],
1700 repo.obsstore.create(tr, prec, succs, opts['flags'],
1701 parents=parents, date=date,
1701 parents=parents, date=date,
1702 metadata=metadata, ui=ui)
1702 metadata=metadata, ui=ui)
1703 tr.close()
1703 tr.close()
1704 except ValueError as exc:
1704 except ValueError as exc:
1705 raise error.Abort(_('bad obsmarker input: %s') %
1705 raise error.Abort(_('bad obsmarker input: %s') %
1706 pycompat.bytestr(exc))
1706 pycompat.bytestr(exc))
1707 finally:
1707 finally:
1708 tr.release()
1708 tr.release()
1709 finally:
1709 finally:
1710 l.release()
1710 l.release()
1711 else:
1711 else:
1712 if opts['rev']:
1712 if opts['rev']:
1713 revs = scmutil.revrange(repo, opts['rev'])
1713 revs = scmutil.revrange(repo, opts['rev'])
1714 nodes = [repo[r].node() for r in revs]
1714 nodes = [repo[r].node() for r in revs]
1715 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1715 markers = list(obsutil.getmarkers(repo, nodes=nodes,
1716 exclusive=opts['exclusive']))
1716 exclusive=opts['exclusive']))
1717 markers.sort(key=lambda x: x._data)
1717 markers.sort(key=lambda x: x._data)
1718 else:
1718 else:
1719 markers = obsutil.getmarkers(repo)
1719 markers = obsutil.getmarkers(repo)
1720
1720
1721 markerstoiter = markers
1721 markerstoiter = markers
1722 isrelevant = lambda m: True
1722 isrelevant = lambda m: True
1723 if opts.get('rev') and opts.get('index'):
1723 if opts.get('rev') and opts.get('index'):
1724 markerstoiter = obsutil.getmarkers(repo)
1724 markerstoiter = obsutil.getmarkers(repo)
1725 markerset = set(markers)
1725 markerset = set(markers)
1726 isrelevant = lambda m: m in markerset
1726 isrelevant = lambda m: m in markerset
1727
1727
1728 fm = ui.formatter('debugobsolete', opts)
1728 fm = ui.formatter('debugobsolete', opts)
1729 for i, m in enumerate(markerstoiter):
1729 for i, m in enumerate(markerstoiter):
1730 if not isrelevant(m):
1730 if not isrelevant(m):
1731 # marker can be irrelevant when we're iterating over a set
1731 # marker can be irrelevant when we're iterating over a set
1732 # of markers (markerstoiter) which is bigger than the set
1732 # of markers (markerstoiter) which is bigger than the set
1733 # of markers we want to display (markers)
1733 # of markers we want to display (markers)
1734 # this can happen if both --index and --rev options are
1734 # this can happen if both --index and --rev options are
1735 # provided and thus we need to iterate over all of the markers
1735 # provided and thus we need to iterate over all of the markers
1736 # to get the correct indices, but only display the ones that
1736 # to get the correct indices, but only display the ones that
1737 # are relevant to --rev value
1737 # are relevant to --rev value
1738 continue
1738 continue
1739 fm.startitem()
1739 fm.startitem()
1740 ind = i if opts.get('index') else None
1740 ind = i if opts.get('index') else None
1741 cmdutil.showmarker(fm, m, index=ind)
1741 cmdutil.showmarker(fm, m, index=ind)
1742 fm.end()
1742 fm.end()
1743
1743
1744 @command('debugp1copies',
1745 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1746 _('[-r REV]'))
1747 def debugp1copies(ui, repo, **opts):
1748 """dump copy information compared to p1"""
1749
1750 opts = pycompat.byteskwargs(opts)
1751 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
1752 for dst, src in ctx.p1copies().items():
1753 ui.write('%s -> %s\n' % (src, dst))
1754
1755 @command('debugp2copies',
1756 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1757 _('[-r REV]'))
1758 def debugp1copies(ui, repo, **opts):
1759 """dump copy information compared to p2"""
1760
1761 opts = pycompat.byteskwargs(opts)
1762 ctx = scmutil.revsingle(repo, opts.get('rev'), default=None)
1763 for dst, src in ctx.p2copies().items():
1764 ui.write('%s -> %s\n' % (src, dst))
1765
1744 @command('debugpathcomplete',
1766 @command('debugpathcomplete',
1745 [('f', 'full', None, _('complete an entire path')),
1767 [('f', 'full', None, _('complete an entire path')),
1746 ('n', 'normal', None, _('show only normal files')),
1768 ('n', 'normal', None, _('show only normal files')),
1747 ('a', 'added', None, _('show only added files')),
1769 ('a', 'added', None, _('show only added files')),
1748 ('r', 'removed', None, _('show only removed files'))],
1770 ('r', 'removed', None, _('show only removed files'))],
1749 _('FILESPEC...'))
1771 _('FILESPEC...'))
1750 def debugpathcomplete(ui, repo, *specs, **opts):
1772 def debugpathcomplete(ui, repo, *specs, **opts):
1751 '''complete part or all of a tracked path
1773 '''complete part or all of a tracked path
1752
1774
1753 This command supports shells that offer path name completion. It
1775 This command supports shells that offer path name completion. It
1754 currently completes only files already known to the dirstate.
1776 currently completes only files already known to the dirstate.
1755
1777
1756 Completion extends only to the next path segment unless
1778 Completion extends only to the next path segment unless
1757 --full is specified, in which case entire paths are used.'''
1779 --full is specified, in which case entire paths are used.'''
1758
1780
1759 def complete(path, acceptable):
1781 def complete(path, acceptable):
1760 dirstate = repo.dirstate
1782 dirstate = repo.dirstate
1761 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
1783 spec = os.path.normpath(os.path.join(encoding.getcwd(), path))
1762 rootdir = repo.root + pycompat.ossep
1784 rootdir = repo.root + pycompat.ossep
1763 if spec != repo.root and not spec.startswith(rootdir):
1785 if spec != repo.root and not spec.startswith(rootdir):
1764 return [], []
1786 return [], []
1765 if os.path.isdir(spec):
1787 if os.path.isdir(spec):
1766 spec += '/'
1788 spec += '/'
1767 spec = spec[len(rootdir):]
1789 spec = spec[len(rootdir):]
1768 fixpaths = pycompat.ossep != '/'
1790 fixpaths = pycompat.ossep != '/'
1769 if fixpaths:
1791 if fixpaths:
1770 spec = spec.replace(pycompat.ossep, '/')
1792 spec = spec.replace(pycompat.ossep, '/')
1771 speclen = len(spec)
1793 speclen = len(spec)
1772 fullpaths = opts[r'full']
1794 fullpaths = opts[r'full']
1773 files, dirs = set(), set()
1795 files, dirs = set(), set()
1774 adddir, addfile = dirs.add, files.add
1796 adddir, addfile = dirs.add, files.add
1775 for f, st in dirstate.iteritems():
1797 for f, st in dirstate.iteritems():
1776 if f.startswith(spec) and st[0] in acceptable:
1798 if f.startswith(spec) and st[0] in acceptable:
1777 if fixpaths:
1799 if fixpaths:
1778 f = f.replace('/', pycompat.ossep)
1800 f = f.replace('/', pycompat.ossep)
1779 if fullpaths:
1801 if fullpaths:
1780 addfile(f)
1802 addfile(f)
1781 continue
1803 continue
1782 s = f.find(pycompat.ossep, speclen)
1804 s = f.find(pycompat.ossep, speclen)
1783 if s >= 0:
1805 if s >= 0:
1784 adddir(f[:s])
1806 adddir(f[:s])
1785 else:
1807 else:
1786 addfile(f)
1808 addfile(f)
1787 return files, dirs
1809 return files, dirs
1788
1810
1789 acceptable = ''
1811 acceptable = ''
1790 if opts[r'normal']:
1812 if opts[r'normal']:
1791 acceptable += 'nm'
1813 acceptable += 'nm'
1792 if opts[r'added']:
1814 if opts[r'added']:
1793 acceptable += 'a'
1815 acceptable += 'a'
1794 if opts[r'removed']:
1816 if opts[r'removed']:
1795 acceptable += 'r'
1817 acceptable += 'r'
1796 cwd = repo.getcwd()
1818 cwd = repo.getcwd()
1797 if not specs:
1819 if not specs:
1798 specs = ['.']
1820 specs = ['.']
1799
1821
1800 files, dirs = set(), set()
1822 files, dirs = set(), set()
1801 for spec in specs:
1823 for spec in specs:
1802 f, d = complete(spec, acceptable or 'nmar')
1824 f, d = complete(spec, acceptable or 'nmar')
1803 files.update(f)
1825 files.update(f)
1804 dirs.update(d)
1826 dirs.update(d)
1805 files.update(dirs)
1827 files.update(dirs)
1806 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1828 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
1807 ui.write('\n')
1829 ui.write('\n')
1808
1830
1809 @command('debugpathcopies',
1831 @command('debugpathcopies',
1810 cmdutil.walkopts,
1832 cmdutil.walkopts,
1811 'hg debugpathcopies REV1 REV2 [FILE]',
1833 'hg debugpathcopies REV1 REV2 [FILE]',
1812 inferrepo=True)
1834 inferrepo=True)
1813 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
1835 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
1814 """show copies between two revisions"""
1836 """show copies between two revisions"""
1815 ctx1 = scmutil.revsingle(repo, rev1)
1837 ctx1 = scmutil.revsingle(repo, rev1)
1816 ctx2 = scmutil.revsingle(repo, rev2)
1838 ctx2 = scmutil.revsingle(repo, rev2)
1817 m = scmutil.match(ctx1, pats, opts)
1839 m = scmutil.match(ctx1, pats, opts)
1818 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
1840 for dst, src in sorted(copies.pathcopies(ctx1, ctx2, m).items()):
1819 ui.write('%s -> %s\n' % (src, dst))
1841 ui.write('%s -> %s\n' % (src, dst))
1820
1842
1821 @command('debugpeer', [], _('PATH'), norepo=True)
1843 @command('debugpeer', [], _('PATH'), norepo=True)
1822 def debugpeer(ui, path):
1844 def debugpeer(ui, path):
1823 """establish a connection to a peer repository"""
1845 """establish a connection to a peer repository"""
1824 # Always enable peer request logging. Requires --debug to display
1846 # Always enable peer request logging. Requires --debug to display
1825 # though.
1847 # though.
1826 overrides = {
1848 overrides = {
1827 ('devel', 'debug.peer-request'): True,
1849 ('devel', 'debug.peer-request'): True,
1828 }
1850 }
1829
1851
1830 with ui.configoverride(overrides):
1852 with ui.configoverride(overrides):
1831 peer = hg.peer(ui, {}, path)
1853 peer = hg.peer(ui, {}, path)
1832
1854
1833 local = peer.local() is not None
1855 local = peer.local() is not None
1834 canpush = peer.canpush()
1856 canpush = peer.canpush()
1835
1857
1836 ui.write(_('url: %s\n') % peer.url())
1858 ui.write(_('url: %s\n') % peer.url())
1837 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1859 ui.write(_('local: %s\n') % (_('yes') if local else _('no')))
1838 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1860 ui.write(_('pushable: %s\n') % (_('yes') if canpush else _('no')))
1839
1861
1840 @command('debugpickmergetool',
1862 @command('debugpickmergetool',
1841 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1863 [('r', 'rev', '', _('check for files in this revision'), _('REV')),
1842 ('', 'changedelete', None, _('emulate merging change and delete')),
1864 ('', 'changedelete', None, _('emulate merging change and delete')),
1843 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1865 ] + cmdutil.walkopts + cmdutil.mergetoolopts,
1844 _('[PATTERN]...'),
1866 _('[PATTERN]...'),
1845 inferrepo=True)
1867 inferrepo=True)
1846 def debugpickmergetool(ui, repo, *pats, **opts):
1868 def debugpickmergetool(ui, repo, *pats, **opts):
1847 """examine which merge tool is chosen for specified file
1869 """examine which merge tool is chosen for specified file
1848
1870
1849 As described in :hg:`help merge-tools`, Mercurial examines
1871 As described in :hg:`help merge-tools`, Mercurial examines
1850 configurations below in this order to decide which merge tool is
1872 configurations below in this order to decide which merge tool is
1851 chosen for specified file.
1873 chosen for specified file.
1852
1874
1853 1. ``--tool`` option
1875 1. ``--tool`` option
1854 2. ``HGMERGE`` environment variable
1876 2. ``HGMERGE`` environment variable
1855 3. configurations in ``merge-patterns`` section
1877 3. configurations in ``merge-patterns`` section
1856 4. configuration of ``ui.merge``
1878 4. configuration of ``ui.merge``
1857 5. configurations in ``merge-tools`` section
1879 5. configurations in ``merge-tools`` section
1858 6. ``hgmerge`` tool (for historical reason only)
1880 6. ``hgmerge`` tool (for historical reason only)
1859 7. default tool for fallback (``:merge`` or ``:prompt``)
1881 7. default tool for fallback (``:merge`` or ``:prompt``)
1860
1882
1861 This command writes out examination result in the style below::
1883 This command writes out examination result in the style below::
1862
1884
1863 FILE = MERGETOOL
1885 FILE = MERGETOOL
1864
1886
1865 By default, all files known in the first parent context of the
1887 By default, all files known in the first parent context of the
1866 working directory are examined. Use file patterns and/or -I/-X
1888 working directory are examined. Use file patterns and/or -I/-X
1867 options to limit target files. -r/--rev is also useful to examine
1889 options to limit target files. -r/--rev is also useful to examine
1868 files in another context without actual updating to it.
1890 files in another context without actual updating to it.
1869
1891
1870 With --debug, this command shows warning messages while matching
1892 With --debug, this command shows warning messages while matching
1871 against ``merge-patterns`` and so on, too. It is recommended to
1893 against ``merge-patterns`` and so on, too. It is recommended to
1872 use this option with explicit file patterns and/or -I/-X options,
1894 use this option with explicit file patterns and/or -I/-X options,
1873 because this option increases amount of output per file according
1895 because this option increases amount of output per file according
1874 to configurations in hgrc.
1896 to configurations in hgrc.
1875
1897
1876 With -v/--verbose, this command shows configurations below at
1898 With -v/--verbose, this command shows configurations below at
1877 first (only if specified).
1899 first (only if specified).
1878
1900
1879 - ``--tool`` option
1901 - ``--tool`` option
1880 - ``HGMERGE`` environment variable
1902 - ``HGMERGE`` environment variable
1881 - configuration of ``ui.merge``
1903 - configuration of ``ui.merge``
1882
1904
1883 If merge tool is chosen before matching against
1905 If merge tool is chosen before matching against
1884 ``merge-patterns``, this command can't show any helpful
1906 ``merge-patterns``, this command can't show any helpful
1885 information, even with --debug. In such case, information above is
1907 information, even with --debug. In such case, information above is
1886 useful to know why a merge tool is chosen.
1908 useful to know why a merge tool is chosen.
1887 """
1909 """
1888 opts = pycompat.byteskwargs(opts)
1910 opts = pycompat.byteskwargs(opts)
1889 overrides = {}
1911 overrides = {}
1890 if opts['tool']:
1912 if opts['tool']:
1891 overrides[('ui', 'forcemerge')] = opts['tool']
1913 overrides[('ui', 'forcemerge')] = opts['tool']
1892 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1914 ui.note(('with --tool %r\n') % (pycompat.bytestr(opts['tool'])))
1893
1915
1894 with ui.configoverride(overrides, 'debugmergepatterns'):
1916 with ui.configoverride(overrides, 'debugmergepatterns'):
1895 hgmerge = encoding.environ.get("HGMERGE")
1917 hgmerge = encoding.environ.get("HGMERGE")
1896 if hgmerge is not None:
1918 if hgmerge is not None:
1897 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1919 ui.note(('with HGMERGE=%r\n') % (pycompat.bytestr(hgmerge)))
1898 uimerge = ui.config("ui", "merge")
1920 uimerge = ui.config("ui", "merge")
1899 if uimerge:
1921 if uimerge:
1900 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1922 ui.note(('with ui.merge=%r\n') % (pycompat.bytestr(uimerge)))
1901
1923
1902 ctx = scmutil.revsingle(repo, opts.get('rev'))
1924 ctx = scmutil.revsingle(repo, opts.get('rev'))
1903 m = scmutil.match(ctx, pats, opts)
1925 m = scmutil.match(ctx, pats, opts)
1904 changedelete = opts['changedelete']
1926 changedelete = opts['changedelete']
1905 for path in ctx.walk(m):
1927 for path in ctx.walk(m):
1906 fctx = ctx[path]
1928 fctx = ctx[path]
1907 try:
1929 try:
1908 if not ui.debugflag:
1930 if not ui.debugflag:
1909 ui.pushbuffer(error=True)
1931 ui.pushbuffer(error=True)
1910 tool, toolpath = filemerge._picktool(repo, ui, path,
1932 tool, toolpath = filemerge._picktool(repo, ui, path,
1911 fctx.isbinary(),
1933 fctx.isbinary(),
1912 'l' in fctx.flags(),
1934 'l' in fctx.flags(),
1913 changedelete)
1935 changedelete)
1914 finally:
1936 finally:
1915 if not ui.debugflag:
1937 if not ui.debugflag:
1916 ui.popbuffer()
1938 ui.popbuffer()
1917 ui.write(('%s = %s\n') % (path, tool))
1939 ui.write(('%s = %s\n') % (path, tool))
1918
1940
1919 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1941 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
1920 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1942 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1921 '''access the pushkey key/value protocol
1943 '''access the pushkey key/value protocol
1922
1944
1923 With two args, list the keys in the given namespace.
1945 With two args, list the keys in the given namespace.
1924
1946
1925 With five args, set a key to new if it currently is set to old.
1947 With five args, set a key to new if it currently is set to old.
1926 Reports success or failure.
1948 Reports success or failure.
1927 '''
1949 '''
1928
1950
1929 target = hg.peer(ui, {}, repopath)
1951 target = hg.peer(ui, {}, repopath)
1930 if keyinfo:
1952 if keyinfo:
1931 key, old, new = keyinfo
1953 key, old, new = keyinfo
1932 with target.commandexecutor() as e:
1954 with target.commandexecutor() as e:
1933 r = e.callcommand('pushkey', {
1955 r = e.callcommand('pushkey', {
1934 'namespace': namespace,
1956 'namespace': namespace,
1935 'key': key,
1957 'key': key,
1936 'old': old,
1958 'old': old,
1937 'new': new,
1959 'new': new,
1938 }).result()
1960 }).result()
1939
1961
1940 ui.status(pycompat.bytestr(r) + '\n')
1962 ui.status(pycompat.bytestr(r) + '\n')
1941 return not r
1963 return not r
1942 else:
1964 else:
1943 for k, v in sorted(target.listkeys(namespace).iteritems()):
1965 for k, v in sorted(target.listkeys(namespace).iteritems()):
1944 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1966 ui.write("%s\t%s\n" % (stringutil.escapestr(k),
1945 stringutil.escapestr(v)))
1967 stringutil.escapestr(v)))
1946
1968
1947 @command('debugpvec', [], _('A B'))
1969 @command('debugpvec', [], _('A B'))
1948 def debugpvec(ui, repo, a, b=None):
1970 def debugpvec(ui, repo, a, b=None):
1949 ca = scmutil.revsingle(repo, a)
1971 ca = scmutil.revsingle(repo, a)
1950 cb = scmutil.revsingle(repo, b)
1972 cb = scmutil.revsingle(repo, b)
1951 pa = pvec.ctxpvec(ca)
1973 pa = pvec.ctxpvec(ca)
1952 pb = pvec.ctxpvec(cb)
1974 pb = pvec.ctxpvec(cb)
1953 if pa == pb:
1975 if pa == pb:
1954 rel = "="
1976 rel = "="
1955 elif pa > pb:
1977 elif pa > pb:
1956 rel = ">"
1978 rel = ">"
1957 elif pa < pb:
1979 elif pa < pb:
1958 rel = "<"
1980 rel = "<"
1959 elif pa | pb:
1981 elif pa | pb:
1960 rel = "|"
1982 rel = "|"
1961 ui.write(_("a: %s\n") % pa)
1983 ui.write(_("a: %s\n") % pa)
1962 ui.write(_("b: %s\n") % pb)
1984 ui.write(_("b: %s\n") % pb)
1963 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1985 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
1964 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1986 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
1965 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1987 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
1966 pa.distance(pb), rel))
1988 pa.distance(pb), rel))
1967
1989
1968 @command('debugrebuilddirstate|debugrebuildstate',
1990 @command('debugrebuilddirstate|debugrebuildstate',
1969 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1991 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
1970 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1992 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
1971 'the working copy parent')),
1993 'the working copy parent')),
1972 ],
1994 ],
1973 _('[-r REV]'))
1995 _('[-r REV]'))
1974 def debugrebuilddirstate(ui, repo, rev, **opts):
1996 def debugrebuilddirstate(ui, repo, rev, **opts):
1975 """rebuild the dirstate as it would look like for the given revision
1997 """rebuild the dirstate as it would look like for the given revision
1976
1998
1977 If no revision is specified the first current parent will be used.
1999 If no revision is specified the first current parent will be used.
1978
2000
1979 The dirstate will be set to the files of the given revision.
2001 The dirstate will be set to the files of the given revision.
1980 The actual working directory content or existing dirstate
2002 The actual working directory content or existing dirstate
1981 information such as adds or removes is not considered.
2003 information such as adds or removes is not considered.
1982
2004
1983 ``minimal`` will only rebuild the dirstate status for files that claim to be
2005 ``minimal`` will only rebuild the dirstate status for files that claim to be
1984 tracked but are not in the parent manifest, or that exist in the parent
2006 tracked but are not in the parent manifest, or that exist in the parent
1985 manifest but are not in the dirstate. It will not change adds, removes, or
2007 manifest but are not in the dirstate. It will not change adds, removes, or
1986 modified files that are in the working copy parent.
2008 modified files that are in the working copy parent.
1987
2009
1988 One use of this command is to make the next :hg:`status` invocation
2010 One use of this command is to make the next :hg:`status` invocation
1989 check the actual file content.
2011 check the actual file content.
1990 """
2012 """
1991 ctx = scmutil.revsingle(repo, rev)
2013 ctx = scmutil.revsingle(repo, rev)
1992 with repo.wlock():
2014 with repo.wlock():
1993 dirstate = repo.dirstate
2015 dirstate = repo.dirstate
1994 changedfiles = None
2016 changedfiles = None
1995 # See command doc for what minimal does.
2017 # See command doc for what minimal does.
1996 if opts.get(r'minimal'):
2018 if opts.get(r'minimal'):
1997 manifestfiles = set(ctx.manifest().keys())
2019 manifestfiles = set(ctx.manifest().keys())
1998 dirstatefiles = set(dirstate)
2020 dirstatefiles = set(dirstate)
1999 manifestonly = manifestfiles - dirstatefiles
2021 manifestonly = manifestfiles - dirstatefiles
2000 dsonly = dirstatefiles - manifestfiles
2022 dsonly = dirstatefiles - manifestfiles
2001 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2023 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
2002 changedfiles = manifestonly | dsnotadded
2024 changedfiles = manifestonly | dsnotadded
2003
2025
2004 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2026 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
2005
2027
2006 @command('debugrebuildfncache', [], '')
2028 @command('debugrebuildfncache', [], '')
2007 def debugrebuildfncache(ui, repo):
2029 def debugrebuildfncache(ui, repo):
2008 """rebuild the fncache file"""
2030 """rebuild the fncache file"""
2009 repair.rebuildfncache(ui, repo)
2031 repair.rebuildfncache(ui, repo)
2010
2032
2011 @command('debugrename',
2033 @command('debugrename',
2012 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2034 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2013 _('[-r REV] [FILE]...'))
2035 _('[-r REV] [FILE]...'))
2014 def debugrename(ui, repo, *pats, **opts):
2036 def debugrename(ui, repo, *pats, **opts):
2015 """dump rename information"""
2037 """dump rename information"""
2016
2038
2017 opts = pycompat.byteskwargs(opts)
2039 opts = pycompat.byteskwargs(opts)
2018 ctx = scmutil.revsingle(repo, opts.get('rev'))
2040 ctx = scmutil.revsingle(repo, opts.get('rev'))
2019 m = scmutil.match(ctx, pats, opts)
2041 m = scmutil.match(ctx, pats, opts)
2020 for abs in ctx.walk(m):
2042 for abs in ctx.walk(m):
2021 fctx = ctx[abs]
2043 fctx = ctx[abs]
2022 o = fctx.filelog().renamed(fctx.filenode())
2044 o = fctx.filelog().renamed(fctx.filenode())
2023 rel = repo.pathto(abs)
2045 rel = repo.pathto(abs)
2024 if o:
2046 if o:
2025 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2047 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2026 else:
2048 else:
2027 ui.write(_("%s not renamed\n") % rel)
2049 ui.write(_("%s not renamed\n") % rel)
2028
2050
2029 @command('debugrevlog', cmdutil.debugrevlogopts +
2051 @command('debugrevlog', cmdutil.debugrevlogopts +
2030 [('d', 'dump', False, _('dump index data'))],
2052 [('d', 'dump', False, _('dump index data'))],
2031 _('-c|-m|FILE'),
2053 _('-c|-m|FILE'),
2032 optionalrepo=True)
2054 optionalrepo=True)
2033 def debugrevlog(ui, repo, file_=None, **opts):
2055 def debugrevlog(ui, repo, file_=None, **opts):
2034 """show data and statistics about a revlog"""
2056 """show data and statistics about a revlog"""
2035 opts = pycompat.byteskwargs(opts)
2057 opts = pycompat.byteskwargs(opts)
2036 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2058 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2037
2059
2038 if opts.get("dump"):
2060 if opts.get("dump"):
2039 numrevs = len(r)
2061 numrevs = len(r)
2040 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2062 ui.write(("# rev p1rev p2rev start end deltastart base p1 p2"
2041 " rawsize totalsize compression heads chainlen\n"))
2063 " rawsize totalsize compression heads chainlen\n"))
2042 ts = 0
2064 ts = 0
2043 heads = set()
2065 heads = set()
2044
2066
2045 for rev in pycompat.xrange(numrevs):
2067 for rev in pycompat.xrange(numrevs):
2046 dbase = r.deltaparent(rev)
2068 dbase = r.deltaparent(rev)
2047 if dbase == -1:
2069 if dbase == -1:
2048 dbase = rev
2070 dbase = rev
2049 cbase = r.chainbase(rev)
2071 cbase = r.chainbase(rev)
2050 clen = r.chainlen(rev)
2072 clen = r.chainlen(rev)
2051 p1, p2 = r.parentrevs(rev)
2073 p1, p2 = r.parentrevs(rev)
2052 rs = r.rawsize(rev)
2074 rs = r.rawsize(rev)
2053 ts = ts + rs
2075 ts = ts + rs
2054 heads -= set(r.parentrevs(rev))
2076 heads -= set(r.parentrevs(rev))
2055 heads.add(rev)
2077 heads.add(rev)
2056 try:
2078 try:
2057 compression = ts / r.end(rev)
2079 compression = ts / r.end(rev)
2058 except ZeroDivisionError:
2080 except ZeroDivisionError:
2059 compression = 0
2081 compression = 0
2060 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2082 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2061 "%11d %5d %8d\n" %
2083 "%11d %5d %8d\n" %
2062 (rev, p1, p2, r.start(rev), r.end(rev),
2084 (rev, p1, p2, r.start(rev), r.end(rev),
2063 r.start(dbase), r.start(cbase),
2085 r.start(dbase), r.start(cbase),
2064 r.start(p1), r.start(p2),
2086 r.start(p1), r.start(p2),
2065 rs, ts, compression, len(heads), clen))
2087 rs, ts, compression, len(heads), clen))
2066 return 0
2088 return 0
2067
2089
2068 v = r.version
2090 v = r.version
2069 format = v & 0xFFFF
2091 format = v & 0xFFFF
2070 flags = []
2092 flags = []
2071 gdelta = False
2093 gdelta = False
2072 if v & revlog.FLAG_INLINE_DATA:
2094 if v & revlog.FLAG_INLINE_DATA:
2073 flags.append('inline')
2095 flags.append('inline')
2074 if v & revlog.FLAG_GENERALDELTA:
2096 if v & revlog.FLAG_GENERALDELTA:
2075 gdelta = True
2097 gdelta = True
2076 flags.append('generaldelta')
2098 flags.append('generaldelta')
2077 if not flags:
2099 if not flags:
2078 flags = ['(none)']
2100 flags = ['(none)']
2079
2101
2080 ### tracks merge vs single parent
2102 ### tracks merge vs single parent
2081 nummerges = 0
2103 nummerges = 0
2082
2104
2083 ### tracks ways the "delta" are build
2105 ### tracks ways the "delta" are build
2084 # nodelta
2106 # nodelta
2085 numempty = 0
2107 numempty = 0
2086 numemptytext = 0
2108 numemptytext = 0
2087 numemptydelta = 0
2109 numemptydelta = 0
2088 # full file content
2110 # full file content
2089 numfull = 0
2111 numfull = 0
2090 # intermediate snapshot against a prior snapshot
2112 # intermediate snapshot against a prior snapshot
2091 numsemi = 0
2113 numsemi = 0
2092 # snapshot count per depth
2114 # snapshot count per depth
2093 numsnapdepth = collections.defaultdict(lambda: 0)
2115 numsnapdepth = collections.defaultdict(lambda: 0)
2094 # delta against previous revision
2116 # delta against previous revision
2095 numprev = 0
2117 numprev = 0
2096 # delta against first or second parent (not prev)
2118 # delta against first or second parent (not prev)
2097 nump1 = 0
2119 nump1 = 0
2098 nump2 = 0
2120 nump2 = 0
2099 # delta against neither prev nor parents
2121 # delta against neither prev nor parents
2100 numother = 0
2122 numother = 0
2101 # delta against prev that are also first or second parent
2123 # delta against prev that are also first or second parent
2102 # (details of `numprev`)
2124 # (details of `numprev`)
2103 nump1prev = 0
2125 nump1prev = 0
2104 nump2prev = 0
2126 nump2prev = 0
2105
2127
2106 # data about delta chain of each revs
2128 # data about delta chain of each revs
2107 chainlengths = []
2129 chainlengths = []
2108 chainbases = []
2130 chainbases = []
2109 chainspans = []
2131 chainspans = []
2110
2132
2111 # data about each revision
2133 # data about each revision
2112 datasize = [None, 0, 0]
2134 datasize = [None, 0, 0]
2113 fullsize = [None, 0, 0]
2135 fullsize = [None, 0, 0]
2114 semisize = [None, 0, 0]
2136 semisize = [None, 0, 0]
2115 # snapshot count per depth
2137 # snapshot count per depth
2116 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
2138 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
2117 deltasize = [None, 0, 0]
2139 deltasize = [None, 0, 0]
2118 chunktypecounts = {}
2140 chunktypecounts = {}
2119 chunktypesizes = {}
2141 chunktypesizes = {}
2120
2142
2121 def addsize(size, l):
2143 def addsize(size, l):
2122 if l[0] is None or size < l[0]:
2144 if l[0] is None or size < l[0]:
2123 l[0] = size
2145 l[0] = size
2124 if size > l[1]:
2146 if size > l[1]:
2125 l[1] = size
2147 l[1] = size
2126 l[2] += size
2148 l[2] += size
2127
2149
2128 numrevs = len(r)
2150 numrevs = len(r)
2129 for rev in pycompat.xrange(numrevs):
2151 for rev in pycompat.xrange(numrevs):
2130 p1, p2 = r.parentrevs(rev)
2152 p1, p2 = r.parentrevs(rev)
2131 delta = r.deltaparent(rev)
2153 delta = r.deltaparent(rev)
2132 if format > 0:
2154 if format > 0:
2133 addsize(r.rawsize(rev), datasize)
2155 addsize(r.rawsize(rev), datasize)
2134 if p2 != nullrev:
2156 if p2 != nullrev:
2135 nummerges += 1
2157 nummerges += 1
2136 size = r.length(rev)
2158 size = r.length(rev)
2137 if delta == nullrev:
2159 if delta == nullrev:
2138 chainlengths.append(0)
2160 chainlengths.append(0)
2139 chainbases.append(r.start(rev))
2161 chainbases.append(r.start(rev))
2140 chainspans.append(size)
2162 chainspans.append(size)
2141 if size == 0:
2163 if size == 0:
2142 numempty += 1
2164 numempty += 1
2143 numemptytext += 1
2165 numemptytext += 1
2144 else:
2166 else:
2145 numfull += 1
2167 numfull += 1
2146 numsnapdepth[0] += 1
2168 numsnapdepth[0] += 1
2147 addsize(size, fullsize)
2169 addsize(size, fullsize)
2148 addsize(size, snapsizedepth[0])
2170 addsize(size, snapsizedepth[0])
2149 else:
2171 else:
2150 chainlengths.append(chainlengths[delta] + 1)
2172 chainlengths.append(chainlengths[delta] + 1)
2151 baseaddr = chainbases[delta]
2173 baseaddr = chainbases[delta]
2152 revaddr = r.start(rev)
2174 revaddr = r.start(rev)
2153 chainbases.append(baseaddr)
2175 chainbases.append(baseaddr)
2154 chainspans.append((revaddr - baseaddr) + size)
2176 chainspans.append((revaddr - baseaddr) + size)
2155 if size == 0:
2177 if size == 0:
2156 numempty += 1
2178 numempty += 1
2157 numemptydelta += 1
2179 numemptydelta += 1
2158 elif r.issnapshot(rev):
2180 elif r.issnapshot(rev):
2159 addsize(size, semisize)
2181 addsize(size, semisize)
2160 numsemi += 1
2182 numsemi += 1
2161 depth = r.snapshotdepth(rev)
2183 depth = r.snapshotdepth(rev)
2162 numsnapdepth[depth] += 1
2184 numsnapdepth[depth] += 1
2163 addsize(size, snapsizedepth[depth])
2185 addsize(size, snapsizedepth[depth])
2164 else:
2186 else:
2165 addsize(size, deltasize)
2187 addsize(size, deltasize)
2166 if delta == rev - 1:
2188 if delta == rev - 1:
2167 numprev += 1
2189 numprev += 1
2168 if delta == p1:
2190 if delta == p1:
2169 nump1prev += 1
2191 nump1prev += 1
2170 elif delta == p2:
2192 elif delta == p2:
2171 nump2prev += 1
2193 nump2prev += 1
2172 elif delta == p1:
2194 elif delta == p1:
2173 nump1 += 1
2195 nump1 += 1
2174 elif delta == p2:
2196 elif delta == p2:
2175 nump2 += 1
2197 nump2 += 1
2176 elif delta != nullrev:
2198 elif delta != nullrev:
2177 numother += 1
2199 numother += 1
2178
2200
2179 # Obtain data on the raw chunks in the revlog.
2201 # Obtain data on the raw chunks in the revlog.
2180 if util.safehasattr(r, '_getsegmentforrevs'):
2202 if util.safehasattr(r, '_getsegmentforrevs'):
2181 segment = r._getsegmentforrevs(rev, rev)[1]
2203 segment = r._getsegmentforrevs(rev, rev)[1]
2182 else:
2204 else:
2183 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
2205 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
2184 if segment:
2206 if segment:
2185 chunktype = bytes(segment[0:1])
2207 chunktype = bytes(segment[0:1])
2186 else:
2208 else:
2187 chunktype = 'empty'
2209 chunktype = 'empty'
2188
2210
2189 if chunktype not in chunktypecounts:
2211 if chunktype not in chunktypecounts:
2190 chunktypecounts[chunktype] = 0
2212 chunktypecounts[chunktype] = 0
2191 chunktypesizes[chunktype] = 0
2213 chunktypesizes[chunktype] = 0
2192
2214
2193 chunktypecounts[chunktype] += 1
2215 chunktypecounts[chunktype] += 1
2194 chunktypesizes[chunktype] += size
2216 chunktypesizes[chunktype] += size
2195
2217
2196 # Adjust size min value for empty cases
2218 # Adjust size min value for empty cases
2197 for size in (datasize, fullsize, semisize, deltasize):
2219 for size in (datasize, fullsize, semisize, deltasize):
2198 if size[0] is None:
2220 if size[0] is None:
2199 size[0] = 0
2221 size[0] = 0
2200
2222
2201 numdeltas = numrevs - numfull - numempty - numsemi
2223 numdeltas = numrevs - numfull - numempty - numsemi
2202 numoprev = numprev - nump1prev - nump2prev
2224 numoprev = numprev - nump1prev - nump2prev
2203 totalrawsize = datasize[2]
2225 totalrawsize = datasize[2]
2204 datasize[2] /= numrevs
2226 datasize[2] /= numrevs
2205 fulltotal = fullsize[2]
2227 fulltotal = fullsize[2]
2206 fullsize[2] /= numfull
2228 fullsize[2] /= numfull
2207 semitotal = semisize[2]
2229 semitotal = semisize[2]
2208 snaptotal = {}
2230 snaptotal = {}
2209 if numsemi > 0:
2231 if numsemi > 0:
2210 semisize[2] /= numsemi
2232 semisize[2] /= numsemi
2211 for depth in snapsizedepth:
2233 for depth in snapsizedepth:
2212 snaptotal[depth] = snapsizedepth[depth][2]
2234 snaptotal[depth] = snapsizedepth[depth][2]
2213 snapsizedepth[depth][2] /= numsnapdepth[depth]
2235 snapsizedepth[depth][2] /= numsnapdepth[depth]
2214
2236
2215 deltatotal = deltasize[2]
2237 deltatotal = deltasize[2]
2216 if numdeltas > 0:
2238 if numdeltas > 0:
2217 deltasize[2] /= numdeltas
2239 deltasize[2] /= numdeltas
2218 totalsize = fulltotal + semitotal + deltatotal
2240 totalsize = fulltotal + semitotal + deltatotal
2219 avgchainlen = sum(chainlengths) / numrevs
2241 avgchainlen = sum(chainlengths) / numrevs
2220 maxchainlen = max(chainlengths)
2242 maxchainlen = max(chainlengths)
2221 maxchainspan = max(chainspans)
2243 maxchainspan = max(chainspans)
2222 compratio = 1
2244 compratio = 1
2223 if totalsize:
2245 if totalsize:
2224 compratio = totalrawsize / totalsize
2246 compratio = totalrawsize / totalsize
2225
2247
2226 basedfmtstr = '%%%dd\n'
2248 basedfmtstr = '%%%dd\n'
2227 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2249 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2228
2250
2229 def dfmtstr(max):
2251 def dfmtstr(max):
2230 return basedfmtstr % len(str(max))
2252 return basedfmtstr % len(str(max))
2231 def pcfmtstr(max, padding=0):
2253 def pcfmtstr(max, padding=0):
2232 return basepcfmtstr % (len(str(max)), ' ' * padding)
2254 return basepcfmtstr % (len(str(max)), ' ' * padding)
2233
2255
2234 def pcfmt(value, total):
2256 def pcfmt(value, total):
2235 if total:
2257 if total:
2236 return (value, 100 * float(value) / total)
2258 return (value, 100 * float(value) / total)
2237 else:
2259 else:
2238 return value, 100.0
2260 return value, 100.0
2239
2261
2240 ui.write(('format : %d\n') % format)
2262 ui.write(('format : %d\n') % format)
2241 ui.write(('flags : %s\n') % ', '.join(flags))
2263 ui.write(('flags : %s\n') % ', '.join(flags))
2242
2264
2243 ui.write('\n')
2265 ui.write('\n')
2244 fmt = pcfmtstr(totalsize)
2266 fmt = pcfmtstr(totalsize)
2245 fmt2 = dfmtstr(totalsize)
2267 fmt2 = dfmtstr(totalsize)
2246 ui.write(('revisions : ') + fmt2 % numrevs)
2268 ui.write(('revisions : ') + fmt2 % numrevs)
2247 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2269 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2248 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2270 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2249 ui.write(('revisions : ') + fmt2 % numrevs)
2271 ui.write(('revisions : ') + fmt2 % numrevs)
2250 ui.write((' empty : ') + fmt % pcfmt(numempty, numrevs))
2272 ui.write((' empty : ') + fmt % pcfmt(numempty, numrevs))
2251 ui.write((' text : ')
2273 ui.write((' text : ')
2252 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta))
2274 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta))
2253 ui.write((' delta : ')
2275 ui.write((' delta : ')
2254 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta))
2276 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta))
2255 ui.write((' snapshot : ') + fmt % pcfmt(numfull + numsemi, numrevs))
2277 ui.write((' snapshot : ') + fmt % pcfmt(numfull + numsemi, numrevs))
2256 for depth in sorted(numsnapdepth):
2278 for depth in sorted(numsnapdepth):
2257 ui.write((' lvl-%-3d : ' % depth)
2279 ui.write((' lvl-%-3d : ' % depth)
2258 + fmt % pcfmt(numsnapdepth[depth], numrevs))
2280 + fmt % pcfmt(numsnapdepth[depth], numrevs))
2259 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2281 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2260 ui.write(('revision size : ') + fmt2 % totalsize)
2282 ui.write(('revision size : ') + fmt2 % totalsize)
2261 ui.write((' snapshot : ')
2283 ui.write((' snapshot : ')
2262 + fmt % pcfmt(fulltotal + semitotal, totalsize))
2284 + fmt % pcfmt(fulltotal + semitotal, totalsize))
2263 for depth in sorted(numsnapdepth):
2285 for depth in sorted(numsnapdepth):
2264 ui.write((' lvl-%-3d : ' % depth)
2286 ui.write((' lvl-%-3d : ' % depth)
2265 + fmt % pcfmt(snaptotal[depth], totalsize))
2287 + fmt % pcfmt(snaptotal[depth], totalsize))
2266 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2288 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2267
2289
2268 def fmtchunktype(chunktype):
2290 def fmtchunktype(chunktype):
2269 if chunktype == 'empty':
2291 if chunktype == 'empty':
2270 return ' %s : ' % chunktype
2292 return ' %s : ' % chunktype
2271 elif chunktype in pycompat.bytestr(string.ascii_letters):
2293 elif chunktype in pycompat.bytestr(string.ascii_letters):
2272 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2294 return ' 0x%s (%s) : ' % (hex(chunktype), chunktype)
2273 else:
2295 else:
2274 return ' 0x%s : ' % hex(chunktype)
2296 return ' 0x%s : ' % hex(chunktype)
2275
2297
2276 ui.write('\n')
2298 ui.write('\n')
2277 ui.write(('chunks : ') + fmt2 % numrevs)
2299 ui.write(('chunks : ') + fmt2 % numrevs)
2278 for chunktype in sorted(chunktypecounts):
2300 for chunktype in sorted(chunktypecounts):
2279 ui.write(fmtchunktype(chunktype))
2301 ui.write(fmtchunktype(chunktype))
2280 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2302 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
2281 ui.write(('chunks size : ') + fmt2 % totalsize)
2303 ui.write(('chunks size : ') + fmt2 % totalsize)
2282 for chunktype in sorted(chunktypecounts):
2304 for chunktype in sorted(chunktypecounts):
2283 ui.write(fmtchunktype(chunktype))
2305 ui.write(fmtchunktype(chunktype))
2284 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2306 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
2285
2307
2286 ui.write('\n')
2308 ui.write('\n')
2287 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2309 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
2288 ui.write(('avg chain length : ') + fmt % avgchainlen)
2310 ui.write(('avg chain length : ') + fmt % avgchainlen)
2289 ui.write(('max chain length : ') + fmt % maxchainlen)
2311 ui.write(('max chain length : ') + fmt % maxchainlen)
2290 ui.write(('max chain reach : ') + fmt % maxchainspan)
2312 ui.write(('max chain reach : ') + fmt % maxchainspan)
2291 ui.write(('compression ratio : ') + fmt % compratio)
2313 ui.write(('compression ratio : ') + fmt % compratio)
2292
2314
2293 if format > 0:
2315 if format > 0:
2294 ui.write('\n')
2316 ui.write('\n')
2295 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2317 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2296 % tuple(datasize))
2318 % tuple(datasize))
2297 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2319 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2298 % tuple(fullsize))
2320 % tuple(fullsize))
2299 ui.write(('inter-snapshot size (min/max/avg) : %d / %d / %d\n')
2321 ui.write(('inter-snapshot size (min/max/avg) : %d / %d / %d\n')
2300 % tuple(semisize))
2322 % tuple(semisize))
2301 for depth in sorted(snapsizedepth):
2323 for depth in sorted(snapsizedepth):
2302 if depth == 0:
2324 if depth == 0:
2303 continue
2325 continue
2304 ui.write((' level-%-3d (min/max/avg) : %d / %d / %d\n')
2326 ui.write((' level-%-3d (min/max/avg) : %d / %d / %d\n')
2305 % ((depth,) + tuple(snapsizedepth[depth])))
2327 % ((depth,) + tuple(snapsizedepth[depth])))
2306 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2328 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2307 % tuple(deltasize))
2329 % tuple(deltasize))
2308
2330
2309 if numdeltas > 0:
2331 if numdeltas > 0:
2310 ui.write('\n')
2332 ui.write('\n')
2311 fmt = pcfmtstr(numdeltas)
2333 fmt = pcfmtstr(numdeltas)
2312 fmt2 = pcfmtstr(numdeltas, 4)
2334 fmt2 = pcfmtstr(numdeltas, 4)
2313 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2335 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2314 if numprev > 0:
2336 if numprev > 0:
2315 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2337 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2316 numprev))
2338 numprev))
2317 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2339 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2318 numprev))
2340 numprev))
2319 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2341 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2320 numprev))
2342 numprev))
2321 if gdelta:
2343 if gdelta:
2322 ui.write(('deltas against p1 : ')
2344 ui.write(('deltas against p1 : ')
2323 + fmt % pcfmt(nump1, numdeltas))
2345 + fmt % pcfmt(nump1, numdeltas))
2324 ui.write(('deltas against p2 : ')
2346 ui.write(('deltas against p2 : ')
2325 + fmt % pcfmt(nump2, numdeltas))
2347 + fmt % pcfmt(nump2, numdeltas))
2326 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2348 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2327 numdeltas))
2349 numdeltas))
2328
2350
2329 @command('debugrevlogindex', cmdutil.debugrevlogopts +
2351 @command('debugrevlogindex', cmdutil.debugrevlogopts +
2330 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2352 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2331 _('[-f FORMAT] -c|-m|FILE'),
2353 _('[-f FORMAT] -c|-m|FILE'),
2332 optionalrepo=True)
2354 optionalrepo=True)
2333 def debugrevlogindex(ui, repo, file_=None, **opts):
2355 def debugrevlogindex(ui, repo, file_=None, **opts):
2334 """dump the contents of a revlog index"""
2356 """dump the contents of a revlog index"""
2335 opts = pycompat.byteskwargs(opts)
2357 opts = pycompat.byteskwargs(opts)
2336 r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts)
2358 r = cmdutil.openrevlog(repo, 'debugrevlogindex', file_, opts)
2337 format = opts.get('format', 0)
2359 format = opts.get('format', 0)
2338 if format not in (0, 1):
2360 if format not in (0, 1):
2339 raise error.Abort(_("unknown format %d") % format)
2361 raise error.Abort(_("unknown format %d") % format)
2340
2362
2341 if ui.debugflag:
2363 if ui.debugflag:
2342 shortfn = hex
2364 shortfn = hex
2343 else:
2365 else:
2344 shortfn = short
2366 shortfn = short
2345
2367
2346 # There might not be anything in r, so have a sane default
2368 # There might not be anything in r, so have a sane default
2347 idlen = 12
2369 idlen = 12
2348 for i in r:
2370 for i in r:
2349 idlen = len(shortfn(r.node(i)))
2371 idlen = len(shortfn(r.node(i)))
2350 break
2372 break
2351
2373
2352 if format == 0:
2374 if format == 0:
2353 if ui.verbose:
2375 if ui.verbose:
2354 ui.write((" rev offset length linkrev"
2376 ui.write((" rev offset length linkrev"
2355 " %s %s p2\n") % ("nodeid".ljust(idlen),
2377 " %s %s p2\n") % ("nodeid".ljust(idlen),
2356 "p1".ljust(idlen)))
2378 "p1".ljust(idlen)))
2357 else:
2379 else:
2358 ui.write((" rev linkrev %s %s p2\n") % (
2380 ui.write((" rev linkrev %s %s p2\n") % (
2359 "nodeid".ljust(idlen), "p1".ljust(idlen)))
2381 "nodeid".ljust(idlen), "p1".ljust(idlen)))
2360 elif format == 1:
2382 elif format == 1:
2361 if ui.verbose:
2383 if ui.verbose:
2362 ui.write((" rev flag offset length size link p1"
2384 ui.write((" rev flag offset length size link p1"
2363 " p2 %s\n") % "nodeid".rjust(idlen))
2385 " p2 %s\n") % "nodeid".rjust(idlen))
2364 else:
2386 else:
2365 ui.write((" rev flag size link p1 p2 %s\n") %
2387 ui.write((" rev flag size link p1 p2 %s\n") %
2366 "nodeid".rjust(idlen))
2388 "nodeid".rjust(idlen))
2367
2389
2368 for i in r:
2390 for i in r:
2369 node = r.node(i)
2391 node = r.node(i)
2370 if format == 0:
2392 if format == 0:
2371 try:
2393 try:
2372 pp = r.parents(node)
2394 pp = r.parents(node)
2373 except Exception:
2395 except Exception:
2374 pp = [nullid, nullid]
2396 pp = [nullid, nullid]
2375 if ui.verbose:
2397 if ui.verbose:
2376 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
2398 ui.write("% 6d % 9d % 7d % 7d %s %s %s\n" % (
2377 i, r.start(i), r.length(i), r.linkrev(i),
2399 i, r.start(i), r.length(i), r.linkrev(i),
2378 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2400 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2379 else:
2401 else:
2380 ui.write("% 6d % 7d %s %s %s\n" % (
2402 ui.write("% 6d % 7d %s %s %s\n" % (
2381 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
2403 i, r.linkrev(i), shortfn(node), shortfn(pp[0]),
2382 shortfn(pp[1])))
2404 shortfn(pp[1])))
2383 elif format == 1:
2405 elif format == 1:
2384 pr = r.parentrevs(i)
2406 pr = r.parentrevs(i)
2385 if ui.verbose:
2407 if ui.verbose:
2386 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
2408 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d %s\n" % (
2387 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2409 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2388 r.linkrev(i), pr[0], pr[1], shortfn(node)))
2410 r.linkrev(i), pr[0], pr[1], shortfn(node)))
2389 else:
2411 else:
2390 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
2412 ui.write("% 6d %04x % 8d % 6d % 6d % 6d %s\n" % (
2391 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
2413 i, r.flags(i), r.rawsize(i), r.linkrev(i), pr[0], pr[1],
2392 shortfn(node)))
2414 shortfn(node)))
2393
2415
2394 @command('debugrevspec',
2416 @command('debugrevspec',
2395 [('', 'optimize', None,
2417 [('', 'optimize', None,
2396 _('print parsed tree after optimizing (DEPRECATED)')),
2418 _('print parsed tree after optimizing (DEPRECATED)')),
2397 ('', 'show-revs', True, _('print list of result revisions (default)')),
2419 ('', 'show-revs', True, _('print list of result revisions (default)')),
2398 ('s', 'show-set', None, _('print internal representation of result set')),
2420 ('s', 'show-set', None, _('print internal representation of result set')),
2399 ('p', 'show-stage', [],
2421 ('p', 'show-stage', [],
2400 _('print parsed tree at the given stage'), _('NAME')),
2422 _('print parsed tree at the given stage'), _('NAME')),
2401 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2423 ('', 'no-optimized', False, _('evaluate tree without optimization')),
2402 ('', 'verify-optimized', False, _('verify optimized result')),
2424 ('', 'verify-optimized', False, _('verify optimized result')),
2403 ],
2425 ],
2404 ('REVSPEC'))
2426 ('REVSPEC'))
2405 def debugrevspec(ui, repo, expr, **opts):
2427 def debugrevspec(ui, repo, expr, **opts):
2406 """parse and apply a revision specification
2428 """parse and apply a revision specification
2407
2429
2408 Use -p/--show-stage option to print the parsed tree at the given stages.
2430 Use -p/--show-stage option to print the parsed tree at the given stages.
2409 Use -p all to print tree at every stage.
2431 Use -p all to print tree at every stage.
2410
2432
2411 Use --no-show-revs option with -s or -p to print only the set
2433 Use --no-show-revs option with -s or -p to print only the set
2412 representation or the parsed tree respectively.
2434 representation or the parsed tree respectively.
2413
2435
2414 Use --verify-optimized to compare the optimized result with the unoptimized
2436 Use --verify-optimized to compare the optimized result with the unoptimized
2415 one. Returns 1 if the optimized result differs.
2437 one. Returns 1 if the optimized result differs.
2416 """
2438 """
2417 opts = pycompat.byteskwargs(opts)
2439 opts = pycompat.byteskwargs(opts)
2418 aliases = ui.configitems('revsetalias')
2440 aliases = ui.configitems('revsetalias')
2419 stages = [
2441 stages = [
2420 ('parsed', lambda tree: tree),
2442 ('parsed', lambda tree: tree),
2421 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2443 ('expanded', lambda tree: revsetlang.expandaliases(tree, aliases,
2422 ui.warn)),
2444 ui.warn)),
2423 ('concatenated', revsetlang.foldconcat),
2445 ('concatenated', revsetlang.foldconcat),
2424 ('analyzed', revsetlang.analyze),
2446 ('analyzed', revsetlang.analyze),
2425 ('optimized', revsetlang.optimize),
2447 ('optimized', revsetlang.optimize),
2426 ]
2448 ]
2427 if opts['no_optimized']:
2449 if opts['no_optimized']:
2428 stages = stages[:-1]
2450 stages = stages[:-1]
2429 if opts['verify_optimized'] and opts['no_optimized']:
2451 if opts['verify_optimized'] and opts['no_optimized']:
2430 raise error.Abort(_('cannot use --verify-optimized with '
2452 raise error.Abort(_('cannot use --verify-optimized with '
2431 '--no-optimized'))
2453 '--no-optimized'))
2432 stagenames = set(n for n, f in stages)
2454 stagenames = set(n for n, f in stages)
2433
2455
2434 showalways = set()
2456 showalways = set()
2435 showchanged = set()
2457 showchanged = set()
2436 if ui.verbose and not opts['show_stage']:
2458 if ui.verbose and not opts['show_stage']:
2437 # show parsed tree by --verbose (deprecated)
2459 # show parsed tree by --verbose (deprecated)
2438 showalways.add('parsed')
2460 showalways.add('parsed')
2439 showchanged.update(['expanded', 'concatenated'])
2461 showchanged.update(['expanded', 'concatenated'])
2440 if opts['optimize']:
2462 if opts['optimize']:
2441 showalways.add('optimized')
2463 showalways.add('optimized')
2442 if opts['show_stage'] and opts['optimize']:
2464 if opts['show_stage'] and opts['optimize']:
2443 raise error.Abort(_('cannot use --optimize with --show-stage'))
2465 raise error.Abort(_('cannot use --optimize with --show-stage'))
2444 if opts['show_stage'] == ['all']:
2466 if opts['show_stage'] == ['all']:
2445 showalways.update(stagenames)
2467 showalways.update(stagenames)
2446 else:
2468 else:
2447 for n in opts['show_stage']:
2469 for n in opts['show_stage']:
2448 if n not in stagenames:
2470 if n not in stagenames:
2449 raise error.Abort(_('invalid stage name: %s') % n)
2471 raise error.Abort(_('invalid stage name: %s') % n)
2450 showalways.update(opts['show_stage'])
2472 showalways.update(opts['show_stage'])
2451
2473
2452 treebystage = {}
2474 treebystage = {}
2453 printedtree = None
2475 printedtree = None
2454 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2476 tree = revsetlang.parse(expr, lookup=revset.lookupfn(repo))
2455 for n, f in stages:
2477 for n, f in stages:
2456 treebystage[n] = tree = f(tree)
2478 treebystage[n] = tree = f(tree)
2457 if n in showalways or (n in showchanged and tree != printedtree):
2479 if n in showalways or (n in showchanged and tree != printedtree):
2458 if opts['show_stage'] or n != 'parsed':
2480 if opts['show_stage'] or n != 'parsed':
2459 ui.write(("* %s:\n") % n)
2481 ui.write(("* %s:\n") % n)
2460 ui.write(revsetlang.prettyformat(tree), "\n")
2482 ui.write(revsetlang.prettyformat(tree), "\n")
2461 printedtree = tree
2483 printedtree = tree
2462
2484
2463 if opts['verify_optimized']:
2485 if opts['verify_optimized']:
2464 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2486 arevs = revset.makematcher(treebystage['analyzed'])(repo)
2465 brevs = revset.makematcher(treebystage['optimized'])(repo)
2487 brevs = revset.makematcher(treebystage['optimized'])(repo)
2466 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2488 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2467 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
2489 ui.write(("* analyzed set:\n"), stringutil.prettyrepr(arevs), "\n")
2468 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
2490 ui.write(("* optimized set:\n"), stringutil.prettyrepr(brevs), "\n")
2469 arevs = list(arevs)
2491 arevs = list(arevs)
2470 brevs = list(brevs)
2492 brevs = list(brevs)
2471 if arevs == brevs:
2493 if arevs == brevs:
2472 return 0
2494 return 0
2473 ui.write(('--- analyzed\n'), label='diff.file_a')
2495 ui.write(('--- analyzed\n'), label='diff.file_a')
2474 ui.write(('+++ optimized\n'), label='diff.file_b')
2496 ui.write(('+++ optimized\n'), label='diff.file_b')
2475 sm = difflib.SequenceMatcher(None, arevs, brevs)
2497 sm = difflib.SequenceMatcher(None, arevs, brevs)
2476 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2498 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2477 if tag in (r'delete', r'replace'):
2499 if tag in (r'delete', r'replace'):
2478 for c in arevs[alo:ahi]:
2500 for c in arevs[alo:ahi]:
2479 ui.write('-%d\n' % c, label='diff.deleted')
2501 ui.write('-%d\n' % c, label='diff.deleted')
2480 if tag in (r'insert', r'replace'):
2502 if tag in (r'insert', r'replace'):
2481 for c in brevs[blo:bhi]:
2503 for c in brevs[blo:bhi]:
2482 ui.write('+%d\n' % c, label='diff.inserted')
2504 ui.write('+%d\n' % c, label='diff.inserted')
2483 if tag == r'equal':
2505 if tag == r'equal':
2484 for c in arevs[alo:ahi]:
2506 for c in arevs[alo:ahi]:
2485 ui.write(' %d\n' % c)
2507 ui.write(' %d\n' % c)
2486 return 1
2508 return 1
2487
2509
2488 func = revset.makematcher(tree)
2510 func = revset.makematcher(tree)
2489 revs = func(repo)
2511 revs = func(repo)
2490 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2512 if opts['show_set'] or (opts['show_set'] is None and ui.verbose):
2491 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
2513 ui.write(("* set:\n"), stringutil.prettyrepr(revs), "\n")
2492 if not opts['show_revs']:
2514 if not opts['show_revs']:
2493 return
2515 return
2494 for c in revs:
2516 for c in revs:
2495 ui.write("%d\n" % c)
2517 ui.write("%d\n" % c)
2496
2518
2497 @command('debugserve', [
2519 @command('debugserve', [
2498 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2520 ('', 'sshstdio', False, _('run an SSH server bound to process handles')),
2499 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2521 ('', 'logiofd', '', _('file descriptor to log server I/O to')),
2500 ('', 'logiofile', '', _('file to log server I/O to')),
2522 ('', 'logiofile', '', _('file to log server I/O to')),
2501 ], '')
2523 ], '')
2502 def debugserve(ui, repo, **opts):
2524 def debugserve(ui, repo, **opts):
2503 """run a server with advanced settings
2525 """run a server with advanced settings
2504
2526
2505 This command is similar to :hg:`serve`. It exists partially as a
2527 This command is similar to :hg:`serve`. It exists partially as a
2506 workaround to the fact that ``hg serve --stdio`` must have specific
2528 workaround to the fact that ``hg serve --stdio`` must have specific
2507 arguments for security reasons.
2529 arguments for security reasons.
2508 """
2530 """
2509 opts = pycompat.byteskwargs(opts)
2531 opts = pycompat.byteskwargs(opts)
2510
2532
2511 if not opts['sshstdio']:
2533 if not opts['sshstdio']:
2512 raise error.Abort(_('only --sshstdio is currently supported'))
2534 raise error.Abort(_('only --sshstdio is currently supported'))
2513
2535
2514 logfh = None
2536 logfh = None
2515
2537
2516 if opts['logiofd'] and opts['logiofile']:
2538 if opts['logiofd'] and opts['logiofile']:
2517 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2539 raise error.Abort(_('cannot use both --logiofd and --logiofile'))
2518
2540
2519 if opts['logiofd']:
2541 if opts['logiofd']:
2520 # Line buffered because output is line based.
2542 # Line buffered because output is line based.
2521 try:
2543 try:
2522 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2544 logfh = os.fdopen(int(opts['logiofd']), r'ab', 1)
2523 except OSError as e:
2545 except OSError as e:
2524 if e.errno != errno.ESPIPE:
2546 if e.errno != errno.ESPIPE:
2525 raise
2547 raise
2526 # can't seek a pipe, so `ab` mode fails on py3
2548 # can't seek a pipe, so `ab` mode fails on py3
2527 logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
2549 logfh = os.fdopen(int(opts['logiofd']), r'wb', 1)
2528 elif opts['logiofile']:
2550 elif opts['logiofile']:
2529 logfh = open(opts['logiofile'], 'ab', 1)
2551 logfh = open(opts['logiofile'], 'ab', 1)
2530
2552
2531 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2553 s = wireprotoserver.sshserver(ui, repo, logfh=logfh)
2532 s.serve_forever()
2554 s.serve_forever()
2533
2555
2534 @command('debugsetparents', [], _('REV1 [REV2]'))
2556 @command('debugsetparents', [], _('REV1 [REV2]'))
2535 def debugsetparents(ui, repo, rev1, rev2=None):
2557 def debugsetparents(ui, repo, rev1, rev2=None):
2536 """manually set the parents of the current working directory
2558 """manually set the parents of the current working directory
2537
2559
2538 This is useful for writing repository conversion tools, but should
2560 This is useful for writing repository conversion tools, but should
2539 be used with care. For example, neither the working directory nor the
2561 be used with care. For example, neither the working directory nor the
2540 dirstate is updated, so file status may be incorrect after running this
2562 dirstate is updated, so file status may be incorrect after running this
2541 command.
2563 command.
2542
2564
2543 Returns 0 on success.
2565 Returns 0 on success.
2544 """
2566 """
2545
2567
2546 node1 = scmutil.revsingle(repo, rev1).node()
2568 node1 = scmutil.revsingle(repo, rev1).node()
2547 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2569 node2 = scmutil.revsingle(repo, rev2, 'null').node()
2548
2570
2549 with repo.wlock():
2571 with repo.wlock():
2550 repo.setparents(node1, node2)
2572 repo.setparents(node1, node2)
2551
2573
2552 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2574 @command('debugssl', [], '[SOURCE]', optionalrepo=True)
2553 def debugssl(ui, repo, source=None, **opts):
2575 def debugssl(ui, repo, source=None, **opts):
2554 '''test a secure connection to a server
2576 '''test a secure connection to a server
2555
2577
2556 This builds the certificate chain for the server on Windows, installing the
2578 This builds the certificate chain for the server on Windows, installing the
2557 missing intermediates and trusted root via Windows Update if necessary. It
2579 missing intermediates and trusted root via Windows Update if necessary. It
2558 does nothing on other platforms.
2580 does nothing on other platforms.
2559
2581
2560 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2582 If SOURCE is omitted, the 'default' path will be used. If a URL is given,
2561 that server is used. See :hg:`help urls` for more information.
2583 that server is used. See :hg:`help urls` for more information.
2562
2584
2563 If the update succeeds, retry the original operation. Otherwise, the cause
2585 If the update succeeds, retry the original operation. Otherwise, the cause
2564 of the SSL error is likely another issue.
2586 of the SSL error is likely another issue.
2565 '''
2587 '''
2566 if not pycompat.iswindows:
2588 if not pycompat.iswindows:
2567 raise error.Abort(_('certificate chain building is only possible on '
2589 raise error.Abort(_('certificate chain building is only possible on '
2568 'Windows'))
2590 'Windows'))
2569
2591
2570 if not source:
2592 if not source:
2571 if not repo:
2593 if not repo:
2572 raise error.Abort(_("there is no Mercurial repository here, and no "
2594 raise error.Abort(_("there is no Mercurial repository here, and no "
2573 "server specified"))
2595 "server specified"))
2574 source = "default"
2596 source = "default"
2575
2597
2576 source, branches = hg.parseurl(ui.expandpath(source))
2598 source, branches = hg.parseurl(ui.expandpath(source))
2577 url = util.url(source)
2599 url = util.url(source)
2578
2600
2579 defaultport = {'https': 443, 'ssh': 22}
2601 defaultport = {'https': 443, 'ssh': 22}
2580 if url.scheme in defaultport:
2602 if url.scheme in defaultport:
2581 try:
2603 try:
2582 addr = (url.host, int(url.port or defaultport[url.scheme]))
2604 addr = (url.host, int(url.port or defaultport[url.scheme]))
2583 except ValueError:
2605 except ValueError:
2584 raise error.Abort(_("malformed port number in URL"))
2606 raise error.Abort(_("malformed port number in URL"))
2585 else:
2607 else:
2586 raise error.Abort(_("only https and ssh connections are supported"))
2608 raise error.Abort(_("only https and ssh connections are supported"))
2587
2609
2588 from . import win32
2610 from . import win32
2589
2611
2590 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2612 s = ssl.wrap_socket(socket.socket(), ssl_version=ssl.PROTOCOL_TLS,
2591 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2613 cert_reqs=ssl.CERT_NONE, ca_certs=None)
2592
2614
2593 try:
2615 try:
2594 s.connect(addr)
2616 s.connect(addr)
2595 cert = s.getpeercert(True)
2617 cert = s.getpeercert(True)
2596
2618
2597 ui.status(_('checking the certificate chain for %s\n') % url.host)
2619 ui.status(_('checking the certificate chain for %s\n') % url.host)
2598
2620
2599 complete = win32.checkcertificatechain(cert, build=False)
2621 complete = win32.checkcertificatechain(cert, build=False)
2600
2622
2601 if not complete:
2623 if not complete:
2602 ui.status(_('certificate chain is incomplete, updating... '))
2624 ui.status(_('certificate chain is incomplete, updating... '))
2603
2625
2604 if not win32.checkcertificatechain(cert):
2626 if not win32.checkcertificatechain(cert):
2605 ui.status(_('failed.\n'))
2627 ui.status(_('failed.\n'))
2606 else:
2628 else:
2607 ui.status(_('done.\n'))
2629 ui.status(_('done.\n'))
2608 else:
2630 else:
2609 ui.status(_('full certificate chain is available\n'))
2631 ui.status(_('full certificate chain is available\n'))
2610 finally:
2632 finally:
2611 s.close()
2633 s.close()
2612
2634
2613 @command('debugsub',
2635 @command('debugsub',
2614 [('r', 'rev', '',
2636 [('r', 'rev', '',
2615 _('revision to check'), _('REV'))],
2637 _('revision to check'), _('REV'))],
2616 _('[-r REV] [REV]'))
2638 _('[-r REV] [REV]'))
2617 def debugsub(ui, repo, rev=None):
2639 def debugsub(ui, repo, rev=None):
2618 ctx = scmutil.revsingle(repo, rev, None)
2640 ctx = scmutil.revsingle(repo, rev, None)
2619 for k, v in sorted(ctx.substate.items()):
2641 for k, v in sorted(ctx.substate.items()):
2620 ui.write(('path %s\n') % k)
2642 ui.write(('path %s\n') % k)
2621 ui.write((' source %s\n') % v[0])
2643 ui.write((' source %s\n') % v[0])
2622 ui.write((' revision %s\n') % v[1])
2644 ui.write((' revision %s\n') % v[1])
2623
2645
2624 @command('debugsuccessorssets',
2646 @command('debugsuccessorssets',
2625 [('', 'closest', False, _('return closest successors sets only'))],
2647 [('', 'closest', False, _('return closest successors sets only'))],
2626 _('[REV]'))
2648 _('[REV]'))
2627 def debugsuccessorssets(ui, repo, *revs, **opts):
2649 def debugsuccessorssets(ui, repo, *revs, **opts):
2628 """show set of successors for revision
2650 """show set of successors for revision
2629
2651
2630 A successors set of changeset A is a consistent group of revisions that
2652 A successors set of changeset A is a consistent group of revisions that
2631 succeed A. It contains non-obsolete changesets only unless closests
2653 succeed A. It contains non-obsolete changesets only unless closests
2632 successors set is set.
2654 successors set is set.
2633
2655
2634 In most cases a changeset A has a single successors set containing a single
2656 In most cases a changeset A has a single successors set containing a single
2635 successor (changeset A replaced by A').
2657 successor (changeset A replaced by A').
2636
2658
2637 A changeset that is made obsolete with no successors are called "pruned".
2659 A changeset that is made obsolete with no successors are called "pruned".
2638 Such changesets have no successors sets at all.
2660 Such changesets have no successors sets at all.
2639
2661
2640 A changeset that has been "split" will have a successors set containing
2662 A changeset that has been "split" will have a successors set containing
2641 more than one successor.
2663 more than one successor.
2642
2664
2643 A changeset that has been rewritten in multiple different ways is called
2665 A changeset that has been rewritten in multiple different ways is called
2644 "divergent". Such changesets have multiple successor sets (each of which
2666 "divergent". Such changesets have multiple successor sets (each of which
2645 may also be split, i.e. have multiple successors).
2667 may also be split, i.e. have multiple successors).
2646
2668
2647 Results are displayed as follows::
2669 Results are displayed as follows::
2648
2670
2649 <rev1>
2671 <rev1>
2650 <successors-1A>
2672 <successors-1A>
2651 <rev2>
2673 <rev2>
2652 <successors-2A>
2674 <successors-2A>
2653 <successors-2B1> <successors-2B2> <successors-2B3>
2675 <successors-2B1> <successors-2B2> <successors-2B3>
2654
2676
2655 Here rev2 has two possible (i.e. divergent) successors sets. The first
2677 Here rev2 has two possible (i.e. divergent) successors sets. The first
2656 holds one element, whereas the second holds three (i.e. the changeset has
2678 holds one element, whereas the second holds three (i.e. the changeset has
2657 been split).
2679 been split).
2658 """
2680 """
2659 # passed to successorssets caching computation from one call to another
2681 # passed to successorssets caching computation from one call to another
2660 cache = {}
2682 cache = {}
2661 ctx2str = bytes
2683 ctx2str = bytes
2662 node2str = short
2684 node2str = short
2663 for rev in scmutil.revrange(repo, revs):
2685 for rev in scmutil.revrange(repo, revs):
2664 ctx = repo[rev]
2686 ctx = repo[rev]
2665 ui.write('%s\n'% ctx2str(ctx))
2687 ui.write('%s\n'% ctx2str(ctx))
2666 for succsset in obsutil.successorssets(repo, ctx.node(),
2688 for succsset in obsutil.successorssets(repo, ctx.node(),
2667 closest=opts[r'closest'],
2689 closest=opts[r'closest'],
2668 cache=cache):
2690 cache=cache):
2669 if succsset:
2691 if succsset:
2670 ui.write(' ')
2692 ui.write(' ')
2671 ui.write(node2str(succsset[0]))
2693 ui.write(node2str(succsset[0]))
2672 for node in succsset[1:]:
2694 for node in succsset[1:]:
2673 ui.write(' ')
2695 ui.write(' ')
2674 ui.write(node2str(node))
2696 ui.write(node2str(node))
2675 ui.write('\n')
2697 ui.write('\n')
2676
2698
2677 @command('debugtemplate',
2699 @command('debugtemplate',
2678 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2700 [('r', 'rev', [], _('apply template on changesets'), _('REV')),
2679 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2701 ('D', 'define', [], _('define template keyword'), _('KEY=VALUE'))],
2680 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2702 _('[-r REV]... [-D KEY=VALUE]... TEMPLATE'),
2681 optionalrepo=True)
2703 optionalrepo=True)
2682 def debugtemplate(ui, repo, tmpl, **opts):
2704 def debugtemplate(ui, repo, tmpl, **opts):
2683 """parse and apply a template
2705 """parse and apply a template
2684
2706
2685 If -r/--rev is given, the template is processed as a log template and
2707 If -r/--rev is given, the template is processed as a log template and
2686 applied to the given changesets. Otherwise, it is processed as a generic
2708 applied to the given changesets. Otherwise, it is processed as a generic
2687 template.
2709 template.
2688
2710
2689 Use --verbose to print the parsed tree.
2711 Use --verbose to print the parsed tree.
2690 """
2712 """
2691 revs = None
2713 revs = None
2692 if opts[r'rev']:
2714 if opts[r'rev']:
2693 if repo is None:
2715 if repo is None:
2694 raise error.RepoError(_('there is no Mercurial repository here '
2716 raise error.RepoError(_('there is no Mercurial repository here '
2695 '(.hg not found)'))
2717 '(.hg not found)'))
2696 revs = scmutil.revrange(repo, opts[r'rev'])
2718 revs = scmutil.revrange(repo, opts[r'rev'])
2697
2719
2698 props = {}
2720 props = {}
2699 for d in opts[r'define']:
2721 for d in opts[r'define']:
2700 try:
2722 try:
2701 k, v = (e.strip() for e in d.split('=', 1))
2723 k, v = (e.strip() for e in d.split('=', 1))
2702 if not k or k == 'ui':
2724 if not k or k == 'ui':
2703 raise ValueError
2725 raise ValueError
2704 props[k] = v
2726 props[k] = v
2705 except ValueError:
2727 except ValueError:
2706 raise error.Abort(_('malformed keyword definition: %s') % d)
2728 raise error.Abort(_('malformed keyword definition: %s') % d)
2707
2729
2708 if ui.verbose:
2730 if ui.verbose:
2709 aliases = ui.configitems('templatealias')
2731 aliases = ui.configitems('templatealias')
2710 tree = templater.parse(tmpl)
2732 tree = templater.parse(tmpl)
2711 ui.note(templater.prettyformat(tree), '\n')
2733 ui.note(templater.prettyformat(tree), '\n')
2712 newtree = templater.expandaliases(tree, aliases)
2734 newtree = templater.expandaliases(tree, aliases)
2713 if newtree != tree:
2735 if newtree != tree:
2714 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2736 ui.note(("* expanded:\n"), templater.prettyformat(newtree), '\n')
2715
2737
2716 if revs is None:
2738 if revs is None:
2717 tres = formatter.templateresources(ui, repo)
2739 tres = formatter.templateresources(ui, repo)
2718 t = formatter.maketemplater(ui, tmpl, resources=tres)
2740 t = formatter.maketemplater(ui, tmpl, resources=tres)
2719 if ui.verbose:
2741 if ui.verbose:
2720 kwds, funcs = t.symbolsuseddefault()
2742 kwds, funcs = t.symbolsuseddefault()
2721 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2743 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2722 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2744 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2723 ui.write(t.renderdefault(props))
2745 ui.write(t.renderdefault(props))
2724 else:
2746 else:
2725 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2747 displayer = logcmdutil.maketemplater(ui, repo, tmpl)
2726 if ui.verbose:
2748 if ui.verbose:
2727 kwds, funcs = displayer.t.symbolsuseddefault()
2749 kwds, funcs = displayer.t.symbolsuseddefault()
2728 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2750 ui.write(("* keywords: %s\n") % ', '.join(sorted(kwds)))
2729 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2751 ui.write(("* functions: %s\n") % ', '.join(sorted(funcs)))
2730 for r in revs:
2752 for r in revs:
2731 displayer.show(repo[r], **pycompat.strkwargs(props))
2753 displayer.show(repo[r], **pycompat.strkwargs(props))
2732 displayer.close()
2754 displayer.close()
2733
2755
2734 @command('debuguigetpass', [
2756 @command('debuguigetpass', [
2735 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2757 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2736 ], _('[-p TEXT]'), norepo=True)
2758 ], _('[-p TEXT]'), norepo=True)
2737 def debuguigetpass(ui, prompt=''):
2759 def debuguigetpass(ui, prompt=''):
2738 """show prompt to type password"""
2760 """show prompt to type password"""
2739 r = ui.getpass(prompt)
2761 r = ui.getpass(prompt)
2740 ui.write(('respose: %s\n') % r)
2762 ui.write(('respose: %s\n') % r)
2741
2763
2742 @command('debuguiprompt', [
2764 @command('debuguiprompt', [
2743 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2765 ('p', 'prompt', '', _('prompt text'), _('TEXT')),
2744 ], _('[-p TEXT]'), norepo=True)
2766 ], _('[-p TEXT]'), norepo=True)
2745 def debuguiprompt(ui, prompt=''):
2767 def debuguiprompt(ui, prompt=''):
2746 """show plain prompt"""
2768 """show plain prompt"""
2747 r = ui.prompt(prompt)
2769 r = ui.prompt(prompt)
2748 ui.write(('response: %s\n') % r)
2770 ui.write(('response: %s\n') % r)
2749
2771
2750 @command('debugupdatecaches', [])
2772 @command('debugupdatecaches', [])
2751 def debugupdatecaches(ui, repo, *pats, **opts):
2773 def debugupdatecaches(ui, repo, *pats, **opts):
2752 """warm all known caches in the repository"""
2774 """warm all known caches in the repository"""
2753 with repo.wlock(), repo.lock():
2775 with repo.wlock(), repo.lock():
2754 repo.updatecaches(full=True)
2776 repo.updatecaches(full=True)
2755
2777
2756 @command('debugupgraderepo', [
2778 @command('debugupgraderepo', [
2757 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2779 ('o', 'optimize', [], _('extra optimization to perform'), _('NAME')),
2758 ('', 'run', False, _('performs an upgrade')),
2780 ('', 'run', False, _('performs an upgrade')),
2759 ('', 'backup', True, _('keep the old repository content around')),
2781 ('', 'backup', True, _('keep the old repository content around')),
2760 ])
2782 ])
2761 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True):
2783 def debugupgraderepo(ui, repo, run=False, optimize=None, backup=True):
2762 """upgrade a repository to use different features
2784 """upgrade a repository to use different features
2763
2785
2764 If no arguments are specified, the repository is evaluated for upgrade
2786 If no arguments are specified, the repository is evaluated for upgrade
2765 and a list of problems and potential optimizations is printed.
2787 and a list of problems and potential optimizations is printed.
2766
2788
2767 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2789 With ``--run``, a repository upgrade is performed. Behavior of the upgrade
2768 can be influenced via additional arguments. More details will be provided
2790 can be influenced via additional arguments. More details will be provided
2769 by the command output when run without ``--run``.
2791 by the command output when run without ``--run``.
2770
2792
2771 During the upgrade, the repository will be locked and no writes will be
2793 During the upgrade, the repository will be locked and no writes will be
2772 allowed.
2794 allowed.
2773
2795
2774 At the end of the upgrade, the repository may not be readable while new
2796 At the end of the upgrade, the repository may not be readable while new
2775 repository data is swapped in. This window will be as long as it takes to
2797 repository data is swapped in. This window will be as long as it takes to
2776 rename some directories inside the ``.hg`` directory. On most machines, this
2798 rename some directories inside the ``.hg`` directory. On most machines, this
2777 should complete almost instantaneously and the chances of a consumer being
2799 should complete almost instantaneously and the chances of a consumer being
2778 unable to access the repository should be low.
2800 unable to access the repository should be low.
2779 """
2801 """
2780 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize,
2802 return upgrade.upgraderepo(ui, repo, run=run, optimize=optimize,
2781 backup=backup)
2803 backup=backup)
2782
2804
2783 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2805 @command('debugwalk', cmdutil.walkopts, _('[OPTION]... [FILE]...'),
2784 inferrepo=True)
2806 inferrepo=True)
2785 def debugwalk(ui, repo, *pats, **opts):
2807 def debugwalk(ui, repo, *pats, **opts):
2786 """show how files match on given patterns"""
2808 """show how files match on given patterns"""
2787 opts = pycompat.byteskwargs(opts)
2809 opts = pycompat.byteskwargs(opts)
2788 m = scmutil.match(repo[None], pats, opts)
2810 m = scmutil.match(repo[None], pats, opts)
2789 if ui.verbose:
2811 if ui.verbose:
2790 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
2812 ui.write(('* matcher:\n'), stringutil.prettyrepr(m), '\n')
2791 items = list(repo[None].walk(m))
2813 items = list(repo[None].walk(m))
2792 if not items:
2814 if not items:
2793 return
2815 return
2794 f = lambda fn: fn
2816 f = lambda fn: fn
2795 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2817 if ui.configbool('ui', 'slash') and pycompat.ossep != '/':
2796 f = lambda fn: util.normpath(fn)
2818 f = lambda fn: util.normpath(fn)
2797 fmt = 'f %%-%ds %%-%ds %%s' % (
2819 fmt = 'f %%-%ds %%-%ds %%s' % (
2798 max([len(abs) for abs in items]),
2820 max([len(abs) for abs in items]),
2799 max([len(repo.pathto(abs)) for abs in items]))
2821 max([len(repo.pathto(abs)) for abs in items]))
2800 for abs in items:
2822 for abs in items:
2801 line = fmt % (abs, f(repo.pathto(abs)), m.exact(abs) and 'exact' or '')
2823 line = fmt % (abs, f(repo.pathto(abs)), m.exact(abs) and 'exact' or '')
2802 ui.write("%s\n" % line.rstrip())
2824 ui.write("%s\n" % line.rstrip())
2803
2825
2804 @command('debugwhyunstable', [], _('REV'))
2826 @command('debugwhyunstable', [], _('REV'))
2805 def debugwhyunstable(ui, repo, rev):
2827 def debugwhyunstable(ui, repo, rev):
2806 """explain instabilities of a changeset"""
2828 """explain instabilities of a changeset"""
2807 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2829 for entry in obsutil.whyunstable(repo, scmutil.revsingle(repo, rev)):
2808 dnodes = ''
2830 dnodes = ''
2809 if entry.get('divergentnodes'):
2831 if entry.get('divergentnodes'):
2810 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2832 dnodes = ' '.join('%s (%s)' % (ctx.hex(), ctx.phasestr())
2811 for ctx in entry['divergentnodes']) + ' '
2833 for ctx in entry['divergentnodes']) + ' '
2812 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2834 ui.write('%s: %s%s %s\n' % (entry['instability'], dnodes,
2813 entry['reason'], entry['node']))
2835 entry['reason'], entry['node']))
2814
2836
2815 @command('debugwireargs',
2837 @command('debugwireargs',
2816 [('', 'three', '', 'three'),
2838 [('', 'three', '', 'three'),
2817 ('', 'four', '', 'four'),
2839 ('', 'four', '', 'four'),
2818 ('', 'five', '', 'five'),
2840 ('', 'five', '', 'five'),
2819 ] + cmdutil.remoteopts,
2841 ] + cmdutil.remoteopts,
2820 _('REPO [OPTIONS]... [ONE [TWO]]'),
2842 _('REPO [OPTIONS]... [ONE [TWO]]'),
2821 norepo=True)
2843 norepo=True)
2822 def debugwireargs(ui, repopath, *vals, **opts):
2844 def debugwireargs(ui, repopath, *vals, **opts):
2823 opts = pycompat.byteskwargs(opts)
2845 opts = pycompat.byteskwargs(opts)
2824 repo = hg.peer(ui, opts, repopath)
2846 repo = hg.peer(ui, opts, repopath)
2825 for opt in cmdutil.remoteopts:
2847 for opt in cmdutil.remoteopts:
2826 del opts[opt[1]]
2848 del opts[opt[1]]
2827 args = {}
2849 args = {}
2828 for k, v in opts.iteritems():
2850 for k, v in opts.iteritems():
2829 if v:
2851 if v:
2830 args[k] = v
2852 args[k] = v
2831 args = pycompat.strkwargs(args)
2853 args = pycompat.strkwargs(args)
2832 # run twice to check that we don't mess up the stream for the next command
2854 # run twice to check that we don't mess up the stream for the next command
2833 res1 = repo.debugwireargs(*vals, **args)
2855 res1 = repo.debugwireargs(*vals, **args)
2834 res2 = repo.debugwireargs(*vals, **args)
2856 res2 = repo.debugwireargs(*vals, **args)
2835 ui.write("%s\n" % res1)
2857 ui.write("%s\n" % res1)
2836 if res1 != res2:
2858 if res1 != res2:
2837 ui.warn("%s\n" % res2)
2859 ui.warn("%s\n" % res2)
2838
2860
2839 def _parsewirelangblocks(fh):
2861 def _parsewirelangblocks(fh):
2840 activeaction = None
2862 activeaction = None
2841 blocklines = []
2863 blocklines = []
2842 lastindent = 0
2864 lastindent = 0
2843
2865
2844 for line in fh:
2866 for line in fh:
2845 line = line.rstrip()
2867 line = line.rstrip()
2846 if not line:
2868 if not line:
2847 continue
2869 continue
2848
2870
2849 if line.startswith(b'#'):
2871 if line.startswith(b'#'):
2850 continue
2872 continue
2851
2873
2852 if not line.startswith(b' '):
2874 if not line.startswith(b' '):
2853 # New block. Flush previous one.
2875 # New block. Flush previous one.
2854 if activeaction:
2876 if activeaction:
2855 yield activeaction, blocklines
2877 yield activeaction, blocklines
2856
2878
2857 activeaction = line
2879 activeaction = line
2858 blocklines = []
2880 blocklines = []
2859 lastindent = 0
2881 lastindent = 0
2860 continue
2882 continue
2861
2883
2862 # Else we start with an indent.
2884 # Else we start with an indent.
2863
2885
2864 if not activeaction:
2886 if not activeaction:
2865 raise error.Abort(_('indented line outside of block'))
2887 raise error.Abort(_('indented line outside of block'))
2866
2888
2867 indent = len(line) - len(line.lstrip())
2889 indent = len(line) - len(line.lstrip())
2868
2890
2869 # If this line is indented more than the last line, concatenate it.
2891 # If this line is indented more than the last line, concatenate it.
2870 if indent > lastindent and blocklines:
2892 if indent > lastindent and blocklines:
2871 blocklines[-1] += line.lstrip()
2893 blocklines[-1] += line.lstrip()
2872 else:
2894 else:
2873 blocklines.append(line)
2895 blocklines.append(line)
2874 lastindent = indent
2896 lastindent = indent
2875
2897
2876 # Flush last block.
2898 # Flush last block.
2877 if activeaction:
2899 if activeaction:
2878 yield activeaction, blocklines
2900 yield activeaction, blocklines
2879
2901
2880 @command('debugwireproto',
2902 @command('debugwireproto',
2881 [
2903 [
2882 ('', 'localssh', False, _('start an SSH server for this repo')),
2904 ('', 'localssh', False, _('start an SSH server for this repo')),
2883 ('', 'peer', '', _('construct a specific version of the peer')),
2905 ('', 'peer', '', _('construct a specific version of the peer')),
2884 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2906 ('', 'noreadstderr', False, _('do not read from stderr of the remote')),
2885 ('', 'nologhandshake', False,
2907 ('', 'nologhandshake', False,
2886 _('do not log I/O related to the peer handshake')),
2908 _('do not log I/O related to the peer handshake')),
2887 ] + cmdutil.remoteopts,
2909 ] + cmdutil.remoteopts,
2888 _('[PATH]'),
2910 _('[PATH]'),
2889 optionalrepo=True)
2911 optionalrepo=True)
2890 def debugwireproto(ui, repo, path=None, **opts):
2912 def debugwireproto(ui, repo, path=None, **opts):
2891 """send wire protocol commands to a server
2913 """send wire protocol commands to a server
2892
2914
2893 This command can be used to issue wire protocol commands to remote
2915 This command can be used to issue wire protocol commands to remote
2894 peers and to debug the raw data being exchanged.
2916 peers and to debug the raw data being exchanged.
2895
2917
2896 ``--localssh`` will start an SSH server against the current repository
2918 ``--localssh`` will start an SSH server against the current repository
2897 and connect to that. By default, the connection will perform a handshake
2919 and connect to that. By default, the connection will perform a handshake
2898 and establish an appropriate peer instance.
2920 and establish an appropriate peer instance.
2899
2921
2900 ``--peer`` can be used to bypass the handshake protocol and construct a
2922 ``--peer`` can be used to bypass the handshake protocol and construct a
2901 peer instance using the specified class type. Valid values are ``raw``,
2923 peer instance using the specified class type. Valid values are ``raw``,
2902 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2924 ``http2``, ``ssh1``, and ``ssh2``. ``raw`` instances only allow sending
2903 raw data payloads and don't support higher-level command actions.
2925 raw data payloads and don't support higher-level command actions.
2904
2926
2905 ``--noreadstderr`` can be used to disable automatic reading from stderr
2927 ``--noreadstderr`` can be used to disable automatic reading from stderr
2906 of the peer (for SSH connections only). Disabling automatic reading of
2928 of the peer (for SSH connections only). Disabling automatic reading of
2907 stderr is useful for making output more deterministic.
2929 stderr is useful for making output more deterministic.
2908
2930
2909 Commands are issued via a mini language which is specified via stdin.
2931 Commands are issued via a mini language which is specified via stdin.
2910 The language consists of individual actions to perform. An action is
2932 The language consists of individual actions to perform. An action is
2911 defined by a block. A block is defined as a line with no leading
2933 defined by a block. A block is defined as a line with no leading
2912 space followed by 0 or more lines with leading space. Blocks are
2934 space followed by 0 or more lines with leading space. Blocks are
2913 effectively a high-level command with additional metadata.
2935 effectively a high-level command with additional metadata.
2914
2936
2915 Lines beginning with ``#`` are ignored.
2937 Lines beginning with ``#`` are ignored.
2916
2938
2917 The following sections denote available actions.
2939 The following sections denote available actions.
2918
2940
2919 raw
2941 raw
2920 ---
2942 ---
2921
2943
2922 Send raw data to the server.
2944 Send raw data to the server.
2923
2945
2924 The block payload contains the raw data to send as one atomic send
2946 The block payload contains the raw data to send as one atomic send
2925 operation. The data may not actually be delivered in a single system
2947 operation. The data may not actually be delivered in a single system
2926 call: it depends on the abilities of the transport being used.
2948 call: it depends on the abilities of the transport being used.
2927
2949
2928 Each line in the block is de-indented and concatenated. Then, that
2950 Each line in the block is de-indented and concatenated. Then, that
2929 value is evaluated as a Python b'' literal. This allows the use of
2951 value is evaluated as a Python b'' literal. This allows the use of
2930 backslash escaping, etc.
2952 backslash escaping, etc.
2931
2953
2932 raw+
2954 raw+
2933 ----
2955 ----
2934
2956
2935 Behaves like ``raw`` except flushes output afterwards.
2957 Behaves like ``raw`` except flushes output afterwards.
2936
2958
2937 command <X>
2959 command <X>
2938 -----------
2960 -----------
2939
2961
2940 Send a request to run a named command, whose name follows the ``command``
2962 Send a request to run a named command, whose name follows the ``command``
2941 string.
2963 string.
2942
2964
2943 Arguments to the command are defined as lines in this block. The format of
2965 Arguments to the command are defined as lines in this block. The format of
2944 each line is ``<key> <value>``. e.g.::
2966 each line is ``<key> <value>``. e.g.::
2945
2967
2946 command listkeys
2968 command listkeys
2947 namespace bookmarks
2969 namespace bookmarks
2948
2970
2949 If the value begins with ``eval:``, it will be interpreted as a Python
2971 If the value begins with ``eval:``, it will be interpreted as a Python
2950 literal expression. Otherwise values are interpreted as Python b'' literals.
2972 literal expression. Otherwise values are interpreted as Python b'' literals.
2951 This allows sending complex types and encoding special byte sequences via
2973 This allows sending complex types and encoding special byte sequences via
2952 backslash escaping.
2974 backslash escaping.
2953
2975
2954 The following arguments have special meaning:
2976 The following arguments have special meaning:
2955
2977
2956 ``PUSHFILE``
2978 ``PUSHFILE``
2957 When defined, the *push* mechanism of the peer will be used instead
2979 When defined, the *push* mechanism of the peer will be used instead
2958 of the static request-response mechanism and the content of the
2980 of the static request-response mechanism and the content of the
2959 file specified in the value of this argument will be sent as the
2981 file specified in the value of this argument will be sent as the
2960 command payload.
2982 command payload.
2961
2983
2962 This can be used to submit a local bundle file to the remote.
2984 This can be used to submit a local bundle file to the remote.
2963
2985
2964 batchbegin
2986 batchbegin
2965 ----------
2987 ----------
2966
2988
2967 Instruct the peer to begin a batched send.
2989 Instruct the peer to begin a batched send.
2968
2990
2969 All ``command`` blocks are queued for execution until the next
2991 All ``command`` blocks are queued for execution until the next
2970 ``batchsubmit`` block.
2992 ``batchsubmit`` block.
2971
2993
2972 batchsubmit
2994 batchsubmit
2973 -----------
2995 -----------
2974
2996
2975 Submit previously queued ``command`` blocks as a batch request.
2997 Submit previously queued ``command`` blocks as a batch request.
2976
2998
2977 This action MUST be paired with a ``batchbegin`` action.
2999 This action MUST be paired with a ``batchbegin`` action.
2978
3000
2979 httprequest <method> <path>
3001 httprequest <method> <path>
2980 ---------------------------
3002 ---------------------------
2981
3003
2982 (HTTP peer only)
3004 (HTTP peer only)
2983
3005
2984 Send an HTTP request to the peer.
3006 Send an HTTP request to the peer.
2985
3007
2986 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
3008 The HTTP request line follows the ``httprequest`` action. e.g. ``GET /foo``.
2987
3009
2988 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
3010 Arguments of the form ``<key>: <value>`` are interpreted as HTTP request
2989 headers to add to the request. e.g. ``Accept: foo``.
3011 headers to add to the request. e.g. ``Accept: foo``.
2990
3012
2991 The following arguments are special:
3013 The following arguments are special:
2992
3014
2993 ``BODYFILE``
3015 ``BODYFILE``
2994 The content of the file defined as the value to this argument will be
3016 The content of the file defined as the value to this argument will be
2995 transferred verbatim as the HTTP request body.
3017 transferred verbatim as the HTTP request body.
2996
3018
2997 ``frame <type> <flags> <payload>``
3019 ``frame <type> <flags> <payload>``
2998 Send a unified protocol frame as part of the request body.
3020 Send a unified protocol frame as part of the request body.
2999
3021
3000 All frames will be collected and sent as the body to the HTTP
3022 All frames will be collected and sent as the body to the HTTP
3001 request.
3023 request.
3002
3024
3003 close
3025 close
3004 -----
3026 -----
3005
3027
3006 Close the connection to the server.
3028 Close the connection to the server.
3007
3029
3008 flush
3030 flush
3009 -----
3031 -----
3010
3032
3011 Flush data written to the server.
3033 Flush data written to the server.
3012
3034
3013 readavailable
3035 readavailable
3014 -------------
3036 -------------
3015
3037
3016 Close the write end of the connection and read all available data from
3038 Close the write end of the connection and read all available data from
3017 the server.
3039 the server.
3018
3040
3019 If the connection to the server encompasses multiple pipes, we poll both
3041 If the connection to the server encompasses multiple pipes, we poll both
3020 pipes and read available data.
3042 pipes and read available data.
3021
3043
3022 readline
3044 readline
3023 --------
3045 --------
3024
3046
3025 Read a line of output from the server. If there are multiple output
3047 Read a line of output from the server. If there are multiple output
3026 pipes, reads only the main pipe.
3048 pipes, reads only the main pipe.
3027
3049
3028 ereadline
3050 ereadline
3029 ---------
3051 ---------
3030
3052
3031 Like ``readline``, but read from the stderr pipe, if available.
3053 Like ``readline``, but read from the stderr pipe, if available.
3032
3054
3033 read <X>
3055 read <X>
3034 --------
3056 --------
3035
3057
3036 ``read()`` N bytes from the server's main output pipe.
3058 ``read()`` N bytes from the server's main output pipe.
3037
3059
3038 eread <X>
3060 eread <X>
3039 ---------
3061 ---------
3040
3062
3041 ``read()`` N bytes from the server's stderr pipe, if available.
3063 ``read()`` N bytes from the server's stderr pipe, if available.
3042
3064
3043 Specifying Unified Frame-Based Protocol Frames
3065 Specifying Unified Frame-Based Protocol Frames
3044 ----------------------------------------------
3066 ----------------------------------------------
3045
3067
3046 It is possible to emit a *Unified Frame-Based Protocol* by using special
3068 It is possible to emit a *Unified Frame-Based Protocol* by using special
3047 syntax.
3069 syntax.
3048
3070
3049 A frame is composed as a type, flags, and payload. These can be parsed
3071 A frame is composed as a type, flags, and payload. These can be parsed
3050 from a string of the form:
3072 from a string of the form:
3051
3073
3052 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
3074 <request-id> <stream-id> <stream-flags> <type> <flags> <payload>
3053
3075
3054 ``request-id`` and ``stream-id`` are integers defining the request and
3076 ``request-id`` and ``stream-id`` are integers defining the request and
3055 stream identifiers.
3077 stream identifiers.
3056
3078
3057 ``type`` can be an integer value for the frame type or the string name
3079 ``type`` can be an integer value for the frame type or the string name
3058 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
3080 of the type. The strings are defined in ``wireprotoframing.py``. e.g.
3059 ``command-name``.
3081 ``command-name``.
3060
3082
3061 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
3083 ``stream-flags`` and ``flags`` are a ``|`` delimited list of flag
3062 components. Each component (and there can be just one) can be an integer
3084 components. Each component (and there can be just one) can be an integer
3063 or a flag name for stream flags or frame flags, respectively. Values are
3085 or a flag name for stream flags or frame flags, respectively. Values are
3064 resolved to integers and then bitwise OR'd together.
3086 resolved to integers and then bitwise OR'd together.
3065
3087
3066 ``payload`` represents the raw frame payload. If it begins with
3088 ``payload`` represents the raw frame payload. If it begins with
3067 ``cbor:``, the following string is evaluated as Python code and the
3089 ``cbor:``, the following string is evaluated as Python code and the
3068 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
3090 resulting object is fed into a CBOR encoder. Otherwise it is interpreted
3069 as a Python byte string literal.
3091 as a Python byte string literal.
3070 """
3092 """
3071 opts = pycompat.byteskwargs(opts)
3093 opts = pycompat.byteskwargs(opts)
3072
3094
3073 if opts['localssh'] and not repo:
3095 if opts['localssh'] and not repo:
3074 raise error.Abort(_('--localssh requires a repository'))
3096 raise error.Abort(_('--localssh requires a repository'))
3075
3097
3076 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
3098 if opts['peer'] and opts['peer'] not in ('raw', 'http2', 'ssh1', 'ssh2'):
3077 raise error.Abort(_('invalid value for --peer'),
3099 raise error.Abort(_('invalid value for --peer'),
3078 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
3100 hint=_('valid values are "raw", "ssh1", and "ssh2"'))
3079
3101
3080 if path and opts['localssh']:
3102 if path and opts['localssh']:
3081 raise error.Abort(_('cannot specify --localssh with an explicit '
3103 raise error.Abort(_('cannot specify --localssh with an explicit '
3082 'path'))
3104 'path'))
3083
3105
3084 if ui.interactive():
3106 if ui.interactive():
3085 ui.write(_('(waiting for commands on stdin)\n'))
3107 ui.write(_('(waiting for commands on stdin)\n'))
3086
3108
3087 blocks = list(_parsewirelangblocks(ui.fin))
3109 blocks = list(_parsewirelangblocks(ui.fin))
3088
3110
3089 proc = None
3111 proc = None
3090 stdin = None
3112 stdin = None
3091 stdout = None
3113 stdout = None
3092 stderr = None
3114 stderr = None
3093 opener = None
3115 opener = None
3094
3116
3095 if opts['localssh']:
3117 if opts['localssh']:
3096 # We start the SSH server in its own process so there is process
3118 # We start the SSH server in its own process so there is process
3097 # separation. This prevents a whole class of potential bugs around
3119 # separation. This prevents a whole class of potential bugs around
3098 # shared state from interfering with server operation.
3120 # shared state from interfering with server operation.
3099 args = procutil.hgcmd() + [
3121 args = procutil.hgcmd() + [
3100 '-R', repo.root,
3122 '-R', repo.root,
3101 'debugserve', '--sshstdio',
3123 'debugserve', '--sshstdio',
3102 ]
3124 ]
3103 proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr, args),
3125 proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr, args),
3104 stdin=subprocess.PIPE,
3126 stdin=subprocess.PIPE,
3105 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
3127 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
3106 bufsize=0)
3128 bufsize=0)
3107
3129
3108 stdin = proc.stdin
3130 stdin = proc.stdin
3109 stdout = proc.stdout
3131 stdout = proc.stdout
3110 stderr = proc.stderr
3132 stderr = proc.stderr
3111
3133
3112 # We turn the pipes into observers so we can log I/O.
3134 # We turn the pipes into observers so we can log I/O.
3113 if ui.verbose or opts['peer'] == 'raw':
3135 if ui.verbose or opts['peer'] == 'raw':
3114 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
3136 stdin = util.makeloggingfileobject(ui, proc.stdin, b'i',
3115 logdata=True)
3137 logdata=True)
3116 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
3138 stdout = util.makeloggingfileobject(ui, proc.stdout, b'o',
3117 logdata=True)
3139 logdata=True)
3118 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
3140 stderr = util.makeloggingfileobject(ui, proc.stderr, b'e',
3119 logdata=True)
3141 logdata=True)
3120
3142
3121 # --localssh also implies the peer connection settings.
3143 # --localssh also implies the peer connection settings.
3122
3144
3123 url = 'ssh://localserver'
3145 url = 'ssh://localserver'
3124 autoreadstderr = not opts['noreadstderr']
3146 autoreadstderr = not opts['noreadstderr']
3125
3147
3126 if opts['peer'] == 'ssh1':
3148 if opts['peer'] == 'ssh1':
3127 ui.write(_('creating ssh peer for wire protocol version 1\n'))
3149 ui.write(_('creating ssh peer for wire protocol version 1\n'))
3128 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
3150 peer = sshpeer.sshv1peer(ui, url, proc, stdin, stdout, stderr,
3129 None, autoreadstderr=autoreadstderr)
3151 None, autoreadstderr=autoreadstderr)
3130 elif opts['peer'] == 'ssh2':
3152 elif opts['peer'] == 'ssh2':
3131 ui.write(_('creating ssh peer for wire protocol version 2\n'))
3153 ui.write(_('creating ssh peer for wire protocol version 2\n'))
3132 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
3154 peer = sshpeer.sshv2peer(ui, url, proc, stdin, stdout, stderr,
3133 None, autoreadstderr=autoreadstderr)
3155 None, autoreadstderr=autoreadstderr)
3134 elif opts['peer'] == 'raw':
3156 elif opts['peer'] == 'raw':
3135 ui.write(_('using raw connection to peer\n'))
3157 ui.write(_('using raw connection to peer\n'))
3136 peer = None
3158 peer = None
3137 else:
3159 else:
3138 ui.write(_('creating ssh peer from handshake results\n'))
3160 ui.write(_('creating ssh peer from handshake results\n'))
3139 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
3161 peer = sshpeer.makepeer(ui, url, proc, stdin, stdout, stderr,
3140 autoreadstderr=autoreadstderr)
3162 autoreadstderr=autoreadstderr)
3141
3163
3142 elif path:
3164 elif path:
3143 # We bypass hg.peer() so we can proxy the sockets.
3165 # We bypass hg.peer() so we can proxy the sockets.
3144 # TODO consider not doing this because we skip
3166 # TODO consider not doing this because we skip
3145 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
3167 # ``hg.wirepeersetupfuncs`` and potentially other useful functionality.
3146 u = util.url(path)
3168 u = util.url(path)
3147 if u.scheme != 'http':
3169 if u.scheme != 'http':
3148 raise error.Abort(_('only http:// paths are currently supported'))
3170 raise error.Abort(_('only http:// paths are currently supported'))
3149
3171
3150 url, authinfo = u.authinfo()
3172 url, authinfo = u.authinfo()
3151 openerargs = {
3173 openerargs = {
3152 r'useragent': b'Mercurial debugwireproto',
3174 r'useragent': b'Mercurial debugwireproto',
3153 }
3175 }
3154
3176
3155 # Turn pipes/sockets into observers so we can log I/O.
3177 # Turn pipes/sockets into observers so we can log I/O.
3156 if ui.verbose:
3178 if ui.verbose:
3157 openerargs.update({
3179 openerargs.update({
3158 r'loggingfh': ui,
3180 r'loggingfh': ui,
3159 r'loggingname': b's',
3181 r'loggingname': b's',
3160 r'loggingopts': {
3182 r'loggingopts': {
3161 r'logdata': True,
3183 r'logdata': True,
3162 r'logdataapis': False,
3184 r'logdataapis': False,
3163 },
3185 },
3164 })
3186 })
3165
3187
3166 if ui.debugflag:
3188 if ui.debugflag:
3167 openerargs[r'loggingopts'][r'logdataapis'] = True
3189 openerargs[r'loggingopts'][r'logdataapis'] = True
3168
3190
3169 # Don't send default headers when in raw mode. This allows us to
3191 # Don't send default headers when in raw mode. This allows us to
3170 # bypass most of the behavior of our URL handling code so we can
3192 # bypass most of the behavior of our URL handling code so we can
3171 # have near complete control over what's sent on the wire.
3193 # have near complete control over what's sent on the wire.
3172 if opts['peer'] == 'raw':
3194 if opts['peer'] == 'raw':
3173 openerargs[r'sendaccept'] = False
3195 openerargs[r'sendaccept'] = False
3174
3196
3175 opener = urlmod.opener(ui, authinfo, **openerargs)
3197 opener = urlmod.opener(ui, authinfo, **openerargs)
3176
3198
3177 if opts['peer'] == 'http2':
3199 if opts['peer'] == 'http2':
3178 ui.write(_('creating http peer for wire protocol version 2\n'))
3200 ui.write(_('creating http peer for wire protocol version 2\n'))
3179 # We go through makepeer() because we need an API descriptor for
3201 # We go through makepeer() because we need an API descriptor for
3180 # the peer instance to be useful.
3202 # the peer instance to be useful.
3181 with ui.configoverride({
3203 with ui.configoverride({
3182 ('experimental', 'httppeer.advertise-v2'): True}):
3204 ('experimental', 'httppeer.advertise-v2'): True}):
3183 if opts['nologhandshake']:
3205 if opts['nologhandshake']:
3184 ui.pushbuffer()
3206 ui.pushbuffer()
3185
3207
3186 peer = httppeer.makepeer(ui, path, opener=opener)
3208 peer = httppeer.makepeer(ui, path, opener=opener)
3187
3209
3188 if opts['nologhandshake']:
3210 if opts['nologhandshake']:
3189 ui.popbuffer()
3211 ui.popbuffer()
3190
3212
3191 if not isinstance(peer, httppeer.httpv2peer):
3213 if not isinstance(peer, httppeer.httpv2peer):
3192 raise error.Abort(_('could not instantiate HTTP peer for '
3214 raise error.Abort(_('could not instantiate HTTP peer for '
3193 'wire protocol version 2'),
3215 'wire protocol version 2'),
3194 hint=_('the server may not have the feature '
3216 hint=_('the server may not have the feature '
3195 'enabled or is not allowing this '
3217 'enabled or is not allowing this '
3196 'client version'))
3218 'client version'))
3197
3219
3198 elif opts['peer'] == 'raw':
3220 elif opts['peer'] == 'raw':
3199 ui.write(_('using raw connection to peer\n'))
3221 ui.write(_('using raw connection to peer\n'))
3200 peer = None
3222 peer = None
3201 elif opts['peer']:
3223 elif opts['peer']:
3202 raise error.Abort(_('--peer %s not supported with HTTP peers') %
3224 raise error.Abort(_('--peer %s not supported with HTTP peers') %
3203 opts['peer'])
3225 opts['peer'])
3204 else:
3226 else:
3205 peer = httppeer.makepeer(ui, path, opener=opener)
3227 peer = httppeer.makepeer(ui, path, opener=opener)
3206
3228
3207 # We /could/ populate stdin/stdout with sock.makefile()...
3229 # We /could/ populate stdin/stdout with sock.makefile()...
3208 else:
3230 else:
3209 raise error.Abort(_('unsupported connection configuration'))
3231 raise error.Abort(_('unsupported connection configuration'))
3210
3232
3211 batchedcommands = None
3233 batchedcommands = None
3212
3234
3213 # Now perform actions based on the parsed wire language instructions.
3235 # Now perform actions based on the parsed wire language instructions.
3214 for action, lines in blocks:
3236 for action, lines in blocks:
3215 if action in ('raw', 'raw+'):
3237 if action in ('raw', 'raw+'):
3216 if not stdin:
3238 if not stdin:
3217 raise error.Abort(_('cannot call raw/raw+ on this peer'))
3239 raise error.Abort(_('cannot call raw/raw+ on this peer'))
3218
3240
3219 # Concatenate the data together.
3241 # Concatenate the data together.
3220 data = ''.join(l.lstrip() for l in lines)
3242 data = ''.join(l.lstrip() for l in lines)
3221 data = stringutil.unescapestr(data)
3243 data = stringutil.unescapestr(data)
3222 stdin.write(data)
3244 stdin.write(data)
3223
3245
3224 if action == 'raw+':
3246 if action == 'raw+':
3225 stdin.flush()
3247 stdin.flush()
3226 elif action == 'flush':
3248 elif action == 'flush':
3227 if not stdin:
3249 if not stdin:
3228 raise error.Abort(_('cannot call flush on this peer'))
3250 raise error.Abort(_('cannot call flush on this peer'))
3229 stdin.flush()
3251 stdin.flush()
3230 elif action.startswith('command'):
3252 elif action.startswith('command'):
3231 if not peer:
3253 if not peer:
3232 raise error.Abort(_('cannot send commands unless peer instance '
3254 raise error.Abort(_('cannot send commands unless peer instance '
3233 'is available'))
3255 'is available'))
3234
3256
3235 command = action.split(' ', 1)[1]
3257 command = action.split(' ', 1)[1]
3236
3258
3237 args = {}
3259 args = {}
3238 for line in lines:
3260 for line in lines:
3239 # We need to allow empty values.
3261 # We need to allow empty values.
3240 fields = line.lstrip().split(' ', 1)
3262 fields = line.lstrip().split(' ', 1)
3241 if len(fields) == 1:
3263 if len(fields) == 1:
3242 key = fields[0]
3264 key = fields[0]
3243 value = ''
3265 value = ''
3244 else:
3266 else:
3245 key, value = fields
3267 key, value = fields
3246
3268
3247 if value.startswith('eval:'):
3269 if value.startswith('eval:'):
3248 value = stringutil.evalpythonliteral(value[5:])
3270 value = stringutil.evalpythonliteral(value[5:])
3249 else:
3271 else:
3250 value = stringutil.unescapestr(value)
3272 value = stringutil.unescapestr(value)
3251
3273
3252 args[key] = value
3274 args[key] = value
3253
3275
3254 if batchedcommands is not None:
3276 if batchedcommands is not None:
3255 batchedcommands.append((command, args))
3277 batchedcommands.append((command, args))
3256 continue
3278 continue
3257
3279
3258 ui.status(_('sending %s command\n') % command)
3280 ui.status(_('sending %s command\n') % command)
3259
3281
3260 if 'PUSHFILE' in args:
3282 if 'PUSHFILE' in args:
3261 with open(args['PUSHFILE'], r'rb') as fh:
3283 with open(args['PUSHFILE'], r'rb') as fh:
3262 del args['PUSHFILE']
3284 del args['PUSHFILE']
3263 res, output = peer._callpush(command, fh,
3285 res, output = peer._callpush(command, fh,
3264 **pycompat.strkwargs(args))
3286 **pycompat.strkwargs(args))
3265 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3287 ui.status(_('result: %s\n') % stringutil.escapestr(res))
3266 ui.status(_('remote output: %s\n') %
3288 ui.status(_('remote output: %s\n') %
3267 stringutil.escapestr(output))
3289 stringutil.escapestr(output))
3268 else:
3290 else:
3269 with peer.commandexecutor() as e:
3291 with peer.commandexecutor() as e:
3270 res = e.callcommand(command, args).result()
3292 res = e.callcommand(command, args).result()
3271
3293
3272 if isinstance(res, wireprotov2peer.commandresponse):
3294 if isinstance(res, wireprotov2peer.commandresponse):
3273 val = res.objects()
3295 val = res.objects()
3274 ui.status(_('response: %s\n') %
3296 ui.status(_('response: %s\n') %
3275 stringutil.pprint(val, bprefix=True, indent=2))
3297 stringutil.pprint(val, bprefix=True, indent=2))
3276 else:
3298 else:
3277 ui.status(_('response: %s\n') %
3299 ui.status(_('response: %s\n') %
3278 stringutil.pprint(res, bprefix=True, indent=2))
3300 stringutil.pprint(res, bprefix=True, indent=2))
3279
3301
3280 elif action == 'batchbegin':
3302 elif action == 'batchbegin':
3281 if batchedcommands is not None:
3303 if batchedcommands is not None:
3282 raise error.Abort(_('nested batchbegin not allowed'))
3304 raise error.Abort(_('nested batchbegin not allowed'))
3283
3305
3284 batchedcommands = []
3306 batchedcommands = []
3285 elif action == 'batchsubmit':
3307 elif action == 'batchsubmit':
3286 # There is a batching API we could go through. But it would be
3308 # There is a batching API we could go through. But it would be
3287 # difficult to normalize requests into function calls. It is easier
3309 # difficult to normalize requests into function calls. It is easier
3288 # to bypass this layer and normalize to commands + args.
3310 # to bypass this layer and normalize to commands + args.
3289 ui.status(_('sending batch with %d sub-commands\n') %
3311 ui.status(_('sending batch with %d sub-commands\n') %
3290 len(batchedcommands))
3312 len(batchedcommands))
3291 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3313 for i, chunk in enumerate(peer._submitbatch(batchedcommands)):
3292 ui.status(_('response #%d: %s\n') %
3314 ui.status(_('response #%d: %s\n') %
3293 (i, stringutil.escapestr(chunk)))
3315 (i, stringutil.escapestr(chunk)))
3294
3316
3295 batchedcommands = None
3317 batchedcommands = None
3296
3318
3297 elif action.startswith('httprequest '):
3319 elif action.startswith('httprequest '):
3298 if not opener:
3320 if not opener:
3299 raise error.Abort(_('cannot use httprequest without an HTTP '
3321 raise error.Abort(_('cannot use httprequest without an HTTP '
3300 'peer'))
3322 'peer'))
3301
3323
3302 request = action.split(' ', 2)
3324 request = action.split(' ', 2)
3303 if len(request) != 3:
3325 if len(request) != 3:
3304 raise error.Abort(_('invalid httprequest: expected format is '
3326 raise error.Abort(_('invalid httprequest: expected format is '
3305 '"httprequest <method> <path>'))
3327 '"httprequest <method> <path>'))
3306
3328
3307 method, httppath = request[1:]
3329 method, httppath = request[1:]
3308 headers = {}
3330 headers = {}
3309 body = None
3331 body = None
3310 frames = []
3332 frames = []
3311 for line in lines:
3333 for line in lines:
3312 line = line.lstrip()
3334 line = line.lstrip()
3313 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3335 m = re.match(b'^([a-zA-Z0-9_-]+): (.*)$', line)
3314 if m:
3336 if m:
3315 # Headers need to use native strings.
3337 # Headers need to use native strings.
3316 key = pycompat.strurl(m.group(1))
3338 key = pycompat.strurl(m.group(1))
3317 value = pycompat.strurl(m.group(2))
3339 value = pycompat.strurl(m.group(2))
3318 headers[key] = value
3340 headers[key] = value
3319 continue
3341 continue
3320
3342
3321 if line.startswith(b'BODYFILE '):
3343 if line.startswith(b'BODYFILE '):
3322 with open(line.split(b' ', 1), 'rb') as fh:
3344 with open(line.split(b' ', 1), 'rb') as fh:
3323 body = fh.read()
3345 body = fh.read()
3324 elif line.startswith(b'frame '):
3346 elif line.startswith(b'frame '):
3325 frame = wireprotoframing.makeframefromhumanstring(
3347 frame = wireprotoframing.makeframefromhumanstring(
3326 line[len(b'frame '):])
3348 line[len(b'frame '):])
3327
3349
3328 frames.append(frame)
3350 frames.append(frame)
3329 else:
3351 else:
3330 raise error.Abort(_('unknown argument to httprequest: %s') %
3352 raise error.Abort(_('unknown argument to httprequest: %s') %
3331 line)
3353 line)
3332
3354
3333 url = path + httppath
3355 url = path + httppath
3334
3356
3335 if frames:
3357 if frames:
3336 body = b''.join(bytes(f) for f in frames)
3358 body = b''.join(bytes(f) for f in frames)
3337
3359
3338 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3360 req = urlmod.urlreq.request(pycompat.strurl(url), body, headers)
3339
3361
3340 # urllib.Request insists on using has_data() as a proxy for
3362 # urllib.Request insists on using has_data() as a proxy for
3341 # determining the request method. Override that to use our
3363 # determining the request method. Override that to use our
3342 # explicitly requested method.
3364 # explicitly requested method.
3343 req.get_method = lambda: pycompat.sysstr(method)
3365 req.get_method = lambda: pycompat.sysstr(method)
3344
3366
3345 try:
3367 try:
3346 res = opener.open(req)
3368 res = opener.open(req)
3347 body = res.read()
3369 body = res.read()
3348 except util.urlerr.urlerror as e:
3370 except util.urlerr.urlerror as e:
3349 # read() method must be called, but only exists in Python 2
3371 # read() method must be called, but only exists in Python 2
3350 getattr(e, 'read', lambda: None)()
3372 getattr(e, 'read', lambda: None)()
3351 continue
3373 continue
3352
3374
3353 ct = res.headers.get(r'Content-Type')
3375 ct = res.headers.get(r'Content-Type')
3354 if ct == r'application/mercurial-cbor':
3376 if ct == r'application/mercurial-cbor':
3355 ui.write(_('cbor> %s\n') %
3377 ui.write(_('cbor> %s\n') %
3356 stringutil.pprint(cborutil.decodeall(body),
3378 stringutil.pprint(cborutil.decodeall(body),
3357 bprefix=True,
3379 bprefix=True,
3358 indent=2))
3380 indent=2))
3359
3381
3360 elif action == 'close':
3382 elif action == 'close':
3361 peer.close()
3383 peer.close()
3362 elif action == 'readavailable':
3384 elif action == 'readavailable':
3363 if not stdout or not stderr:
3385 if not stdout or not stderr:
3364 raise error.Abort(_('readavailable not available on this peer'))
3386 raise error.Abort(_('readavailable not available on this peer'))
3365
3387
3366 stdin.close()
3388 stdin.close()
3367 stdout.read()
3389 stdout.read()
3368 stderr.read()
3390 stderr.read()
3369
3391
3370 elif action == 'readline':
3392 elif action == 'readline':
3371 if not stdout:
3393 if not stdout:
3372 raise error.Abort(_('readline not available on this peer'))
3394 raise error.Abort(_('readline not available on this peer'))
3373 stdout.readline()
3395 stdout.readline()
3374 elif action == 'ereadline':
3396 elif action == 'ereadline':
3375 if not stderr:
3397 if not stderr:
3376 raise error.Abort(_('ereadline not available on this peer'))
3398 raise error.Abort(_('ereadline not available on this peer'))
3377 stderr.readline()
3399 stderr.readline()
3378 elif action.startswith('read '):
3400 elif action.startswith('read '):
3379 count = int(action.split(' ', 1)[1])
3401 count = int(action.split(' ', 1)[1])
3380 if not stdout:
3402 if not stdout:
3381 raise error.Abort(_('read not available on this peer'))
3403 raise error.Abort(_('read not available on this peer'))
3382 stdout.read(count)
3404 stdout.read(count)
3383 elif action.startswith('eread '):
3405 elif action.startswith('eread '):
3384 count = int(action.split(' ', 1)[1])
3406 count = int(action.split(' ', 1)[1])
3385 if not stderr:
3407 if not stderr:
3386 raise error.Abort(_('eread not available on this peer'))
3408 raise error.Abort(_('eread not available on this peer'))
3387 stderr.read(count)
3409 stderr.read(count)
3388 else:
3410 else:
3389 raise error.Abort(_('unknown action: %s') % action)
3411 raise error.Abort(_('unknown action: %s') % action)
3390
3412
3391 if batchedcommands is not None:
3413 if batchedcommands is not None:
3392 raise error.Abort(_('unclosed "batchbegin" request'))
3414 raise error.Abort(_('unclosed "batchbegin" request'))
3393
3415
3394 if peer:
3416 if peer:
3395 peer.close()
3417 peer.close()
3396
3418
3397 if proc:
3419 if proc:
3398 proc.kill()
3420 proc.kill()
@@ -1,410 +1,414 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugapplystreamclonebundle
72 debugapplystreamclonebundle
73 debugbuilddag
73 debugbuilddag
74 debugbundle
74 debugbundle
75 debugcapabilities
75 debugcapabilities
76 debugcheckstate
76 debugcheckstate
77 debugcolor
77 debugcolor
78 debugcommands
78 debugcommands
79 debugcomplete
79 debugcomplete
80 debugconfig
80 debugconfig
81 debugcreatestreamclonebundle
81 debugcreatestreamclonebundle
82 debugdag
82 debugdag
83 debugdata
83 debugdata
84 debugdate
84 debugdate
85 debugdeltachain
85 debugdeltachain
86 debugdirstate
86 debugdirstate
87 debugdiscovery
87 debugdiscovery
88 debugdownload
88 debugdownload
89 debugextensions
89 debugextensions
90 debugfileset
90 debugfileset
91 debugformat
91 debugformat
92 debugfsinfo
92 debugfsinfo
93 debuggetbundle
93 debuggetbundle
94 debugignore
94 debugignore
95 debugindex
95 debugindex
96 debugindexdot
96 debugindexdot
97 debugindexstats
97 debugindexstats
98 debuginstall
98 debuginstall
99 debugknown
99 debugknown
100 debuglabelcomplete
100 debuglabelcomplete
101 debuglocks
101 debuglocks
102 debugmanifestfulltextcache
102 debugmanifestfulltextcache
103 debugmergestate
103 debugmergestate
104 debugnamecomplete
104 debugnamecomplete
105 debugobsolete
105 debugobsolete
106 debugp1copies
107 debugp2copies
106 debugpathcomplete
108 debugpathcomplete
107 debugpathcopies
109 debugpathcopies
108 debugpeer
110 debugpeer
109 debugpickmergetool
111 debugpickmergetool
110 debugpushkey
112 debugpushkey
111 debugpvec
113 debugpvec
112 debugrebuilddirstate
114 debugrebuilddirstate
113 debugrebuildfncache
115 debugrebuildfncache
114 debugrename
116 debugrename
115 debugrevlog
117 debugrevlog
116 debugrevlogindex
118 debugrevlogindex
117 debugrevspec
119 debugrevspec
118 debugserve
120 debugserve
119 debugsetparents
121 debugsetparents
120 debugssl
122 debugssl
121 debugsub
123 debugsub
122 debugsuccessorssets
124 debugsuccessorssets
123 debugtemplate
125 debugtemplate
124 debuguigetpass
126 debuguigetpass
125 debuguiprompt
127 debuguiprompt
126 debugupdatecaches
128 debugupdatecaches
127 debugupgraderepo
129 debugupgraderepo
128 debugwalk
130 debugwalk
129 debugwhyunstable
131 debugwhyunstable
130 debugwireargs
132 debugwireargs
131 debugwireproto
133 debugwireproto
132
134
133 Do not show the alias of a debug command if there are other candidates
135 Do not show the alias of a debug command if there are other candidates
134 (this should hide rawcommit)
136 (this should hide rawcommit)
135 $ hg debugcomplete r
137 $ hg debugcomplete r
136 recover
138 recover
137 remove
139 remove
138 rename
140 rename
139 resolve
141 resolve
140 revert
142 revert
141 rollback
143 rollback
142 root
144 root
143 Show the alias of a debug command if there are no other candidates
145 Show the alias of a debug command if there are no other candidates
144 $ hg debugcomplete rawc
146 $ hg debugcomplete rawc
145
147
146
148
147 Show the global options
149 Show the global options
148 $ hg debugcomplete --options | sort
150 $ hg debugcomplete --options | sort
149 --color
151 --color
150 --config
152 --config
151 --cwd
153 --cwd
152 --debug
154 --debug
153 --debugger
155 --debugger
154 --encoding
156 --encoding
155 --encodingmode
157 --encodingmode
156 --help
158 --help
157 --hidden
159 --hidden
158 --noninteractive
160 --noninteractive
159 --pager
161 --pager
160 --profile
162 --profile
161 --quiet
163 --quiet
162 --repository
164 --repository
163 --time
165 --time
164 --traceback
166 --traceback
165 --verbose
167 --verbose
166 --version
168 --version
167 -R
169 -R
168 -h
170 -h
169 -q
171 -q
170 -v
172 -v
171 -y
173 -y
172
174
173 Show the options for the "serve" command
175 Show the options for the "serve" command
174 $ hg debugcomplete --options serve | sort
176 $ hg debugcomplete --options serve | sort
175 --accesslog
177 --accesslog
176 --address
178 --address
177 --certificate
179 --certificate
178 --cmdserver
180 --cmdserver
179 --color
181 --color
180 --config
182 --config
181 --cwd
183 --cwd
182 --daemon
184 --daemon
183 --daemon-postexec
185 --daemon-postexec
184 --debug
186 --debug
185 --debugger
187 --debugger
186 --encoding
188 --encoding
187 --encodingmode
189 --encodingmode
188 --errorlog
190 --errorlog
189 --help
191 --help
190 --hidden
192 --hidden
191 --ipv6
193 --ipv6
192 --name
194 --name
193 --noninteractive
195 --noninteractive
194 --pager
196 --pager
195 --pid-file
197 --pid-file
196 --port
198 --port
197 --prefix
199 --prefix
198 --print-url
200 --print-url
199 --profile
201 --profile
200 --quiet
202 --quiet
201 --repository
203 --repository
202 --stdio
204 --stdio
203 --style
205 --style
204 --subrepos
206 --subrepos
205 --templates
207 --templates
206 --time
208 --time
207 --traceback
209 --traceback
208 --verbose
210 --verbose
209 --version
211 --version
210 --web-conf
212 --web-conf
211 -6
213 -6
212 -A
214 -A
213 -E
215 -E
214 -R
216 -R
215 -S
217 -S
216 -a
218 -a
217 -d
219 -d
218 -h
220 -h
219 -n
221 -n
220 -p
222 -p
221 -q
223 -q
222 -t
224 -t
223 -v
225 -v
224 -y
226 -y
225
227
226 Show an error if we use --options with an ambiguous abbreviation
228 Show an error if we use --options with an ambiguous abbreviation
227 $ hg debugcomplete --options s
229 $ hg debugcomplete --options s
228 hg: command 's' is ambiguous:
230 hg: command 's' is ambiguous:
229 serve showconfig status summary
231 serve showconfig status summary
230 [255]
232 [255]
231
233
232 Show all commands + options
234 Show all commands + options
233 $ hg debugcommands
235 $ hg debugcommands
234 add: include, exclude, subrepos, dry-run
236 add: include, exclude, subrepos, dry-run
235 addremove: similarity, subrepos, include, exclude, dry-run
237 addremove: similarity, subrepos, include, exclude, dry-run
236 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
238 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
237 archive: no-decode, prefix, rev, type, subrepos, include, exclude
239 archive: no-decode, prefix, rev, type, subrepos, include, exclude
238 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
240 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
239 bisect: reset, good, bad, skip, extend, command, noupdate
241 bisect: reset, good, bad, skip, extend, command, noupdate
240 bookmarks: force, rev, delete, rename, inactive, list, template
242 bookmarks: force, rev, delete, rename, inactive, list, template
241 branch: force, clean, rev
243 branch: force, clean, rev
242 branches: active, closed, rev, template
244 branches: active, closed, rev, template
243 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
245 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
244 cat: output, rev, decode, include, exclude, template
246 cat: output, rev, decode, include, exclude, template
245 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
247 clone: noupdate, updaterev, rev, branch, pull, uncompressed, stream, ssh, remotecmd, insecure
246 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
248 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
247 config: untrusted, edit, local, global, template
249 config: untrusted, edit, local, global, template
248 copy: after, force, include, exclude, dry-run
250 copy: after, force, include, exclude, dry-run
249 debugancestor:
251 debugancestor:
250 debugapplystreamclonebundle:
252 debugapplystreamclonebundle:
251 debugbuilddag: mergeable-file, overwritten-file, new-file
253 debugbuilddag: mergeable-file, overwritten-file, new-file
252 debugbundle: all, part-type, spec
254 debugbundle: all, part-type, spec
253 debugcapabilities:
255 debugcapabilities:
254 debugcheckstate:
256 debugcheckstate:
255 debugcolor: style
257 debugcolor: style
256 debugcommands:
258 debugcommands:
257 debugcomplete: options
259 debugcomplete: options
258 debugcreatestreamclonebundle:
260 debugcreatestreamclonebundle:
259 debugdag: tags, branches, dots, spaces
261 debugdag: tags, branches, dots, spaces
260 debugdata: changelog, manifest, dir
262 debugdata: changelog, manifest, dir
261 debugdate: extended
263 debugdate: extended
262 debugdeltachain: changelog, manifest, dir, template
264 debugdeltachain: changelog, manifest, dir, template
263 debugdirstate: nodates, dates, datesort
265 debugdirstate: nodates, dates, datesort
264 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
266 debugdiscovery: old, nonheads, rev, ssh, remotecmd, insecure
265 debugdownload: output
267 debugdownload: output
266 debugextensions: template
268 debugextensions: template
267 debugfileset: rev, all-files, show-matcher, show-stage
269 debugfileset: rev, all-files, show-matcher, show-stage
268 debugformat: template
270 debugformat: template
269 debugfsinfo:
271 debugfsinfo:
270 debuggetbundle: head, common, type
272 debuggetbundle: head, common, type
271 debugignore:
273 debugignore:
272 debugindex: changelog, manifest, dir, template
274 debugindex: changelog, manifest, dir, template
273 debugindexdot: changelog, manifest, dir
275 debugindexdot: changelog, manifest, dir
274 debugindexstats:
276 debugindexstats:
275 debuginstall: template
277 debuginstall: template
276 debugknown:
278 debugknown:
277 debuglabelcomplete:
279 debuglabelcomplete:
278 debuglocks: force-lock, force-wlock, set-lock, set-wlock
280 debuglocks: force-lock, force-wlock, set-lock, set-wlock
279 debugmanifestfulltextcache: clear, add
281 debugmanifestfulltextcache: clear, add
280 debugmergestate:
282 debugmergestate:
281 debugnamecomplete:
283 debugnamecomplete:
282 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
284 debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template
285 debugp1copies: rev
286 debugp2copies: rev
283 debugpathcomplete: full, normal, added, removed
287 debugpathcomplete: full, normal, added, removed
284 debugpathcopies: include, exclude
288 debugpathcopies: include, exclude
285 debugpeer:
289 debugpeer:
286 debugpickmergetool: rev, changedelete, include, exclude, tool
290 debugpickmergetool: rev, changedelete, include, exclude, tool
287 debugpushkey:
291 debugpushkey:
288 debugpvec:
292 debugpvec:
289 debugrebuilddirstate: rev, minimal
293 debugrebuilddirstate: rev, minimal
290 debugrebuildfncache:
294 debugrebuildfncache:
291 debugrename: rev
295 debugrename: rev
292 debugrevlog: changelog, manifest, dir, dump
296 debugrevlog: changelog, manifest, dir, dump
293 debugrevlogindex: changelog, manifest, dir, format
297 debugrevlogindex: changelog, manifest, dir, format
294 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
298 debugrevspec: optimize, show-revs, show-set, show-stage, no-optimized, verify-optimized
295 debugserve: sshstdio, logiofd, logiofile
299 debugserve: sshstdio, logiofd, logiofile
296 debugsetparents:
300 debugsetparents:
297 debugssl:
301 debugssl:
298 debugsub: rev
302 debugsub: rev
299 debugsuccessorssets: closest
303 debugsuccessorssets: closest
300 debugtemplate: rev, define
304 debugtemplate: rev, define
301 debuguigetpass: prompt
305 debuguigetpass: prompt
302 debuguiprompt: prompt
306 debuguiprompt: prompt
303 debugupdatecaches:
307 debugupdatecaches:
304 debugupgraderepo: optimize, run, backup
308 debugupgraderepo: optimize, run, backup
305 debugwalk: include, exclude
309 debugwalk: include, exclude
306 debugwhyunstable:
310 debugwhyunstable:
307 debugwireargs: three, four, five, ssh, remotecmd, insecure
311 debugwireargs: three, four, five, ssh, remotecmd, insecure
308 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
312 debugwireproto: localssh, peer, noreadstderr, nologhandshake, ssh, remotecmd, insecure
309 diff: rev, 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
313 diff: rev, 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
310 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
314 export: bookmark, output, switch-parent, rev, text, git, binary, nodates, template
311 files: rev, print0, include, exclude, template, subrepos
315 files: rev, print0, include, exclude, template, subrepos
312 forget: interactive, include, exclude, dry-run
316 forget: interactive, include, exclude, dry-run
313 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
317 graft: rev, base, continue, stop, abort, edit, log, no-commit, force, currentdate, currentuser, date, user, tool, dry-run
314 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
318 grep: print0, all, diff, text, follow, ignore-case, files-with-matches, line-number, rev, all-files, user, date, template, include, exclude
315 heads: rev, topo, active, closed, style, template
319 heads: rev, topo, active, closed, style, template
316 help: extension, command, keyword, system
320 help: extension, command, keyword, system
317 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
321 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure, template
318 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
322 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
319 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
323 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
320 init: ssh, remotecmd, insecure
324 init: ssh, remotecmd, insecure
321 locate: rev, print0, fullpath, include, exclude
325 locate: rev, print0, fullpath, include, exclude
322 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
326 log: follow, follow-first, date, copies, keyword, rev, line-range, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
323 manifest: rev, all, template
327 manifest: rev, all, template
324 merge: force, rev, preview, abort, tool
328 merge: force, rev, preview, abort, tool
325 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
329 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
326 parents: rev, style, template
330 parents: rev, style, template
327 paths: template
331 paths: template
328 phase: public, draft, secret, force, rev
332 phase: public, draft, secret, force, rev
329 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
333 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
330 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
334 push: force, rev, bookmark, branch, new-branch, pushvars, publish, ssh, remotecmd, insecure
331 recover:
335 recover:
332 remove: after, force, subrepos, include, exclude, dry-run
336 remove: after, force, subrepos, include, exclude, dry-run
333 rename: after, force, include, exclude, dry-run
337 rename: after, force, include, exclude, dry-run
334 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
338 resolve: all, list, mark, unmark, no-status, re-merge, tool, include, exclude, template
335 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
339 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
336 rollback: dry-run, force
340 rollback: dry-run, force
337 root:
341 root:
338 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
342 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
339 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
343 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, terse, copies, print0, rev, change, include, exclude, subrepos, template
340 summary: remote
344 summary: remote
341 tag: force, local, rev, remove, edit, message, date, user
345 tag: force, local, rev, remove, edit, message, date, user
342 tags: template
346 tags: template
343 tip: patch, git, style, template
347 tip: patch, git, style, template
344 unbundle: update
348 unbundle: update
345 update: clean, check, merge, date, rev, tool
349 update: clean, check, merge, date, rev, tool
346 verify:
350 verify:
347 version: template
351 version: template
348
352
349 $ hg init a
353 $ hg init a
350 $ cd a
354 $ cd a
351 $ echo fee > fee
355 $ echo fee > fee
352 $ hg ci -q -Amfee
356 $ hg ci -q -Amfee
353 $ hg tag fee
357 $ hg tag fee
354 $ mkdir fie
358 $ mkdir fie
355 $ echo dead > fie/dead
359 $ echo dead > fie/dead
356 $ echo live > fie/live
360 $ echo live > fie/live
357 $ hg bookmark fo
361 $ hg bookmark fo
358 $ hg branch -q fie
362 $ hg branch -q fie
359 $ hg ci -q -Amfie
363 $ hg ci -q -Amfie
360 $ echo fo > fo
364 $ echo fo > fo
361 $ hg branch -qf default
365 $ hg branch -qf default
362 $ hg ci -q -Amfo
366 $ hg ci -q -Amfo
363 $ echo Fum > Fum
367 $ echo Fum > Fum
364 $ hg ci -q -AmFum
368 $ hg ci -q -AmFum
365 $ hg bookmark Fum
369 $ hg bookmark Fum
366
370
367 Test debugpathcomplete
371 Test debugpathcomplete
368
372
369 $ hg debugpathcomplete f
373 $ hg debugpathcomplete f
370 fee
374 fee
371 fie
375 fie
372 fo
376 fo
373 $ hg debugpathcomplete -f f
377 $ hg debugpathcomplete -f f
374 fee
378 fee
375 fie/dead
379 fie/dead
376 fie/live
380 fie/live
377 fo
381 fo
378
382
379 $ hg rm Fum
383 $ hg rm Fum
380 $ hg debugpathcomplete -r F
384 $ hg debugpathcomplete -r F
381 Fum
385 Fum
382
386
383 Test debugnamecomplete
387 Test debugnamecomplete
384
388
385 $ hg debugnamecomplete
389 $ hg debugnamecomplete
386 Fum
390 Fum
387 default
391 default
388 fee
392 fee
389 fie
393 fie
390 fo
394 fo
391 tip
395 tip
392 $ hg debugnamecomplete f
396 $ hg debugnamecomplete f
393 fee
397 fee
394 fie
398 fie
395 fo
399 fo
396
400
397 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
401 Test debuglabelcomplete, a deprecated name for debugnamecomplete that is still
398 used for completions in some shells.
402 used for completions in some shells.
399
403
400 $ hg debuglabelcomplete
404 $ hg debuglabelcomplete
401 Fum
405 Fum
402 default
406 default
403 fee
407 fee
404 fie
408 fie
405 fo
409 fo
406 tip
410 tip
407 $ hg debuglabelcomplete f
411 $ hg debuglabelcomplete f
408 fee
412 fee
409 fie
413 fie
410 fo
414 fo
@@ -1,431 +1,484 b''
1
1
2 $ cat >> $HGRCPATH << EOF
2 $ cat >> $HGRCPATH << EOF
3 > [alias]
3 > [alias]
4 > l = log -G -T '{rev} {desc}\n{files}\n'
4 > l = log -G -T '{rev} {desc}\n{files}\n'
5 > EOF
5 > EOF
6
6
7 $ REPONUM=0
7 $ REPONUM=0
8 $ newrepo() {
8 $ newrepo() {
9 > cd $TESTTMP
9 > cd $TESTTMP
10 > REPONUM=`expr $REPONUM + 1`
10 > REPONUM=`expr $REPONUM + 1`
11 > hg init repo-$REPONUM
11 > hg init repo-$REPONUM
12 > cd repo-$REPONUM
12 > cd repo-$REPONUM
13 > }
13 > }
14
14
15 Simple rename case
15 Simple rename case
16 $ newrepo
16 $ newrepo
17 $ echo x > x
17 $ echo x > x
18 $ hg ci -Aqm 'add x'
18 $ hg ci -Aqm 'add x'
19 $ hg mv x y
19 $ hg mv x y
20 $ hg debugp1copies
21 x -> y
22 $ hg debugp2copies
20 $ hg ci -m 'rename x to y'
23 $ hg ci -m 'rename x to y'
21 $ hg l
24 $ hg l
22 @ 1 rename x to y
25 @ 1 rename x to y
23 | x y
26 | x y
24 o 0 add x
27 o 0 add x
25 x
28 x
29 $ hg debugp1copies -r 1
30 x -> y
26 $ hg debugpathcopies 0 1
31 $ hg debugpathcopies 0 1
27 x -> y
32 x -> y
28 $ hg debugpathcopies 1 0
33 $ hg debugpathcopies 1 0
29 y -> x
34 y -> x
30 Test filtering copies by path. We do filtering by destination.
35 Test filtering copies by path. We do filtering by destination.
31 $ hg debugpathcopies 0 1 x
36 $ hg debugpathcopies 0 1 x
32 $ hg debugpathcopies 1 0 x
37 $ hg debugpathcopies 1 0 x
33 y -> x
38 y -> x
34 $ hg debugpathcopies 0 1 y
39 $ hg debugpathcopies 0 1 y
35 x -> y
40 x -> y
36 $ hg debugpathcopies 1 0 y
41 $ hg debugpathcopies 1 0 y
37
42
38 Copy a file onto another file
43 Copy a file onto another file
39 $ newrepo
44 $ newrepo
40 $ echo x > x
45 $ echo x > x
41 $ echo y > y
46 $ echo y > y
42 $ hg ci -Aqm 'add x and y'
47 $ hg ci -Aqm 'add x and y'
43 $ hg cp -f x y
48 $ hg cp -f x y
49 $ hg debugp1copies
50 x -> y
51 $ hg debugp2copies
44 $ hg ci -m 'copy x onto y'
52 $ hg ci -m 'copy x onto y'
45 $ hg l
53 $ hg l
46 @ 1 copy x onto y
54 @ 1 copy x onto y
47 | y
55 | y
48 o 0 add x and y
56 o 0 add x and y
49 x y
57 x y
58 $ hg debugp1copies -r 1
59 x -> y
50 Incorrectly doesn't show the rename
60 Incorrectly doesn't show the rename
51 $ hg debugpathcopies 0 1
61 $ hg debugpathcopies 0 1
52
62
53 Copy a file onto another file with same content. If metadata is stored in changeset, this does not
63 Copy a file onto another file with same content. If metadata is stored in changeset, this does not
54 produce a new filelog entry. The changeset's "files" entry should still list the file.
64 produce a new filelog entry. The changeset's "files" entry should still list the file.
55 $ newrepo
65 $ newrepo
56 $ echo x > x
66 $ echo x > x
57 $ echo x > x2
67 $ echo x > x2
58 $ hg ci -Aqm 'add x and x2 with same content'
68 $ hg ci -Aqm 'add x and x2 with same content'
59 $ hg cp -f x x2
69 $ hg cp -f x x2
60 $ hg ci -m 'copy x onto x2'
70 $ hg ci -m 'copy x onto x2'
61 $ hg l
71 $ hg l
62 @ 1 copy x onto x2
72 @ 1 copy x onto x2
63 | x2
73 | x2
64 o 0 add x and x2 with same content
74 o 0 add x and x2 with same content
65 x x2
75 x x2
76 $ hg debugp1copies -r 1
77 x -> x2
66 Incorrectly doesn't show the rename
78 Incorrectly doesn't show the rename
67 $ hg debugpathcopies 0 1
79 $ hg debugpathcopies 0 1
68
80
69 Copy a file, then delete destination, then copy again. This does not create a new filelog entry.
81 Copy a file, then delete destination, then copy again. This does not create a new filelog entry.
70 $ newrepo
82 $ newrepo
71 $ echo x > x
83 $ echo x > x
72 $ hg ci -Aqm 'add x'
84 $ hg ci -Aqm 'add x'
73 $ hg cp x y
85 $ hg cp x y
74 $ hg ci -m 'copy x to y'
86 $ hg ci -m 'copy x to y'
75 $ hg rm y
87 $ hg rm y
76 $ hg ci -m 'remove y'
88 $ hg ci -m 'remove y'
77 $ hg cp -f x y
89 $ hg cp -f x y
78 $ hg ci -m 'copy x onto y (again)'
90 $ hg ci -m 'copy x onto y (again)'
79 $ hg l
91 $ hg l
80 @ 3 copy x onto y (again)
92 @ 3 copy x onto y (again)
81 | y
93 | y
82 o 2 remove y
94 o 2 remove y
83 | y
95 | y
84 o 1 copy x to y
96 o 1 copy x to y
85 | y
97 | y
86 o 0 add x
98 o 0 add x
87 x
99 x
100 $ hg debugp1copies -r 3
101 x -> y
88 $ hg debugpathcopies 0 3
102 $ hg debugpathcopies 0 3
89 x -> y
103 x -> y
90
104
91 Rename file in a loop: x->y->z->x
105 Rename file in a loop: x->y->z->x
92 $ newrepo
106 $ newrepo
93 $ echo x > x
107 $ echo x > x
94 $ hg ci -Aqm 'add x'
108 $ hg ci -Aqm 'add x'
95 $ hg mv x y
109 $ hg mv x y
110 $ hg debugp1copies
111 x -> y
112 $ hg debugp2copies
96 $ hg ci -m 'rename x to y'
113 $ hg ci -m 'rename x to y'
97 $ hg mv y z
114 $ hg mv y z
98 $ hg ci -m 'rename y to z'
115 $ hg ci -m 'rename y to z'
99 $ hg mv z x
116 $ hg mv z x
100 $ hg ci -m 'rename z to x'
117 $ hg ci -m 'rename z to x'
101 $ hg l
118 $ hg l
102 @ 3 rename z to x
119 @ 3 rename z to x
103 | x z
120 | x z
104 o 2 rename y to z
121 o 2 rename y to z
105 | y z
122 | y z
106 o 1 rename x to y
123 o 1 rename x to y
107 | x y
124 | x y
108 o 0 add x
125 o 0 add x
109 x
126 x
110 $ hg debugpathcopies 0 3
127 $ hg debugpathcopies 0 3
111
128
112 Copy x to y, then remove y, then add back y. With copy metadata in the changeset, this could easily
129 Copy x to y, then remove y, then add back y. With copy metadata in the changeset, this could easily
113 end up reporting y as copied from x (if we don't unmark it as a copy when it's removed).
130 end up reporting y as copied from x (if we don't unmark it as a copy when it's removed).
114 $ newrepo
131 $ newrepo
115 $ echo x > x
132 $ echo x > x
116 $ hg ci -Aqm 'add x'
133 $ hg ci -Aqm 'add x'
117 $ hg mv x y
134 $ hg mv x y
118 $ hg ci -m 'rename x to y'
135 $ hg ci -m 'rename x to y'
119 $ hg rm y
136 $ hg rm y
120 $ hg ci -qm 'remove y'
137 $ hg ci -qm 'remove y'
121 $ echo x > y
138 $ echo x > y
122 $ hg ci -Aqm 'add back y'
139 $ hg ci -Aqm 'add back y'
123 $ hg l
140 $ hg l
124 @ 3 add back y
141 @ 3 add back y
125 | y
142 | y
126 o 2 remove y
143 o 2 remove y
127 | y
144 | y
128 o 1 rename x to y
145 o 1 rename x to y
129 | x y
146 | x y
130 o 0 add x
147 o 0 add x
131 x
148 x
149 $ hg debugp1copies -r 3
132 $ hg debugpathcopies 0 3
150 $ hg debugpathcopies 0 3
133
151
134 Copy x to z, then remove z, then copy x2 (same content as x) to z. With copy metadata in the
152 Copy x to z, then remove z, then copy x2 (same content as x) to z. With copy metadata in the
135 changeset, the two copies here will have the same filelog entry, so ctx['z'].introrev() might point
153 changeset, the two copies here will have the same filelog entry, so ctx['z'].introrev() might point
136 to the first commit that added the file. We should still report the copy as being from x2.
154 to the first commit that added the file. We should still report the copy as being from x2.
137 $ newrepo
155 $ newrepo
138 $ echo x > x
156 $ echo x > x
139 $ echo x > x2
157 $ echo x > x2
140 $ hg ci -Aqm 'add x and x2 with same content'
158 $ hg ci -Aqm 'add x and x2 with same content'
141 $ hg cp x z
159 $ hg cp x z
142 $ hg ci -qm 'copy x to z'
160 $ hg ci -qm 'copy x to z'
143 $ hg rm z
161 $ hg rm z
144 $ hg ci -m 'remove z'
162 $ hg ci -m 'remove z'
145 $ hg cp x2 z
163 $ hg cp x2 z
146 $ hg ci -m 'copy x2 to z'
164 $ hg ci -m 'copy x2 to z'
147 $ hg l
165 $ hg l
148 @ 3 copy x2 to z
166 @ 3 copy x2 to z
149 | z
167 | z
150 o 2 remove z
168 o 2 remove z
151 | z
169 | z
152 o 1 copy x to z
170 o 1 copy x to z
153 | z
171 | z
154 o 0 add x and x2 with same content
172 o 0 add x and x2 with same content
155 x x2
173 x x2
174 $ hg debugp1copies -r 3
175 x2 -> z
156 $ hg debugpathcopies 0 3
176 $ hg debugpathcopies 0 3
157 x2 -> z
177 x2 -> z
158
178
159 Create x and y, then rename them both to the same name, but on different sides of a fork
179 Create x and y, then rename them both to the same name, but on different sides of a fork
160 $ newrepo
180 $ newrepo
161 $ echo x > x
181 $ echo x > x
162 $ echo y > y
182 $ echo y > y
163 $ hg ci -Aqm 'add x and y'
183 $ hg ci -Aqm 'add x and y'
164 $ hg mv x z
184 $ hg mv x z
165 $ hg ci -qm 'rename x to z'
185 $ hg ci -qm 'rename x to z'
166 $ hg co -q 0
186 $ hg co -q 0
167 $ hg mv y z
187 $ hg mv y z
168 $ hg ci -qm 'rename y to z'
188 $ hg ci -qm 'rename y to z'
169 $ hg l
189 $ hg l
170 @ 2 rename y to z
190 @ 2 rename y to z
171 | y z
191 | y z
172 | o 1 rename x to z
192 | o 1 rename x to z
173 |/ x z
193 |/ x z
174 o 0 add x and y
194 o 0 add x and y
175 x y
195 x y
176 $ hg debugpathcopies 1 2
196 $ hg debugpathcopies 1 2
177 z -> x
197 z -> x
178 y -> z
198 y -> z
179
199
180 Fork renames x to y on one side and removes x on the other
200 Fork renames x to y on one side and removes x on the other
181 $ newrepo
201 $ newrepo
182 $ echo x > x
202 $ echo x > x
183 $ hg ci -Aqm 'add x'
203 $ hg ci -Aqm 'add x'
184 $ hg mv x y
204 $ hg mv x y
185 $ hg ci -m 'rename x to y'
205 $ hg ci -m 'rename x to y'
186 $ hg co -q 0
206 $ hg co -q 0
187 $ hg rm x
207 $ hg rm x
188 $ hg ci -m 'remove x'
208 $ hg ci -m 'remove x'
189 created new head
209 created new head
190 $ hg l
210 $ hg l
191 @ 2 remove x
211 @ 2 remove x
192 | x
212 | x
193 | o 1 rename x to y
213 | o 1 rename x to y
194 |/ x y
214 |/ x y
195 o 0 add x
215 o 0 add x
196 x
216 x
197 $ hg debugpathcopies 1 2
217 $ hg debugpathcopies 1 2
198
218
199 Copies via null revision (there shouldn't be any)
219 Copies via null revision (there shouldn't be any)
200 $ newrepo
220 $ newrepo
201 $ echo x > x
221 $ echo x > x
202 $ hg ci -Aqm 'add x'
222 $ hg ci -Aqm 'add x'
203 $ hg cp x y
223 $ hg cp x y
204 $ hg ci -m 'copy x to y'
224 $ hg ci -m 'copy x to y'
205 $ hg co -q null
225 $ hg co -q null
206 $ echo x > x
226 $ echo x > x
207 $ hg ci -Aqm 'add x (again)'
227 $ hg ci -Aqm 'add x (again)'
208 $ hg l
228 $ hg l
209 @ 2 add x (again)
229 @ 2 add x (again)
210 x
230 x
211 o 1 copy x to y
231 o 1 copy x to y
212 | y
232 | y
213 o 0 add x
233 o 0 add x
214 x
234 x
215 $ hg debugpathcopies 1 2
235 $ hg debugpathcopies 1 2
216 $ hg debugpathcopies 2 1
236 $ hg debugpathcopies 2 1
217
237
218 Merge rename from other branch
238 Merge rename from other branch
219 $ newrepo
239 $ newrepo
220 $ echo x > x
240 $ echo x > x
221 $ hg ci -Aqm 'add x'
241 $ hg ci -Aqm 'add x'
222 $ hg mv x y
242 $ hg mv x y
223 $ hg ci -m 'rename x to y'
243 $ hg ci -m 'rename x to y'
224 $ hg co -q 0
244 $ hg co -q 0
225 $ echo z > z
245 $ echo z > z
226 $ hg ci -Aqm 'add z'
246 $ hg ci -Aqm 'add z'
227 $ hg merge -q 1
247 $ hg merge -q 1
248 $ hg debugp1copies
249 $ hg debugp2copies
228 $ hg ci -m 'merge rename from p2'
250 $ hg ci -m 'merge rename from p2'
229 $ hg l
251 $ hg l
230 @ 3 merge rename from p2
252 @ 3 merge rename from p2
231 |\ x
253 |\ x
232 | o 2 add z
254 | o 2 add z
233 | | z
255 | | z
234 o | 1 rename x to y
256 o | 1 rename x to y
235 |/ x y
257 |/ x y
236 o 0 add x
258 o 0 add x
237 x
259 x
238 Perhaps we should indicate the rename here, but `hg status` is documented to be weird during
260 Perhaps we should indicate the rename here, but `hg status` is documented to be weird during
239 merges, so...
261 merges, so...
262 $ hg debugp1copies -r 3
263 $ hg debugp2copies -r 3
240 $ hg debugpathcopies 0 3
264 $ hg debugpathcopies 0 3
241 x -> y
265 x -> y
242 $ hg debugpathcopies 1 2
266 $ hg debugpathcopies 1 2
243 y -> x
267 y -> x
244 $ hg debugpathcopies 1 3
268 $ hg debugpathcopies 1 3
245 $ hg debugpathcopies 2 3
269 $ hg debugpathcopies 2 3
246 x -> y
270 x -> y
247
271
248 Copy file from either side in a merge
272 Copy file from either side in a merge
249 $ newrepo
273 $ newrepo
250 $ echo x > x
274 $ echo x > x
251 $ hg ci -Aqm 'add x'
275 $ hg ci -Aqm 'add x'
252 $ hg co -q null
276 $ hg co -q null
253 $ echo y > y
277 $ echo y > y
254 $ hg ci -Aqm 'add y'
278 $ hg ci -Aqm 'add y'
255 $ hg merge -q 0
279 $ hg merge -q 0
256 $ hg cp y z
280 $ hg cp y z
281 $ hg debugp1copies
282 y -> z
283 $ hg debugp2copies
257 $ hg ci -m 'copy file from p1 in merge'
284 $ hg ci -m 'copy file from p1 in merge'
258 $ hg co -q 1
285 $ hg co -q 1
259 $ hg merge -q 0
286 $ hg merge -q 0
260 $ hg cp x z
287 $ hg cp x z
288 $ hg debugp1copies
289 $ hg debugp2copies
290 x -> z
261 $ hg ci -qm 'copy file from p2 in merge'
291 $ hg ci -qm 'copy file from p2 in merge'
262 $ hg l
292 $ hg l
263 @ 3 copy file from p2 in merge
293 @ 3 copy file from p2 in merge
264 |\ z
294 |\ z
265 +---o 2 copy file from p1 in merge
295 +---o 2 copy file from p1 in merge
266 | |/ z
296 | |/ z
267 | o 1 add y
297 | o 1 add y
268 | y
298 | y
269 o 0 add x
299 o 0 add x
270 x
300 x
301 $ hg debugp1copies -r 2
302 y -> z
303 $ hg debugp2copies -r 2
271 $ hg debugpathcopies 1 2
304 $ hg debugpathcopies 1 2
272 y -> z
305 y -> z
273 $ hg debugpathcopies 0 2
306 $ hg debugpathcopies 0 2
307 $ hg debugp1copies -r 3
308 $ hg debugp2copies -r 3
309 x -> z
274 $ hg debugpathcopies 1 3
310 $ hg debugpathcopies 1 3
275 $ hg debugpathcopies 0 3
311 $ hg debugpathcopies 0 3
276 x -> z
312 x -> z
277
313
278 Copy file that exists on both sides of the merge, same content on both sides
314 Copy file that exists on both sides of the merge, same content on both sides
279 $ newrepo
315 $ newrepo
280 $ echo x > x
316 $ echo x > x
281 $ hg ci -Aqm 'add x on branch 1'
317 $ hg ci -Aqm 'add x on branch 1'
282 $ hg co -q null
318 $ hg co -q null
283 $ echo x > x
319 $ echo x > x
284 $ hg ci -Aqm 'add x on branch 2'
320 $ hg ci -Aqm 'add x on branch 2'
285 $ hg merge -q 0
321 $ hg merge -q 0
286 $ hg cp x z
322 $ hg cp x z
323 $ hg debugp1copies
324 x -> z
325 $ hg debugp2copies
287 $ hg ci -qm 'merge'
326 $ hg ci -qm 'merge'
288 $ hg l
327 $ hg l
289 @ 2 merge
328 @ 2 merge
290 |\ z
329 |\ z
291 | o 1 add x on branch 2
330 | o 1 add x on branch 2
292 | x
331 | x
293 o 0 add x on branch 1
332 o 0 add x on branch 1
294 x
333 x
334 $ hg debugp1copies -r 2
335 x -> z
336 $ hg debugp2copies -r 2
295 It's a little weird that it shows up on both sides
337 It's a little weird that it shows up on both sides
296 $ hg debugpathcopies 1 2
338 $ hg debugpathcopies 1 2
297 x -> z
339 x -> z
298 $ hg debugpathcopies 0 2
340 $ hg debugpathcopies 0 2
299 x -> z
341 x -> z
300
342
301 Copy file that exists on both sides of the merge, different content
343 Copy file that exists on both sides of the merge, different content
302 $ newrepo
344 $ newrepo
303 $ echo branch1 > x
345 $ echo branch1 > x
304 $ hg ci -Aqm 'add x on branch 1'
346 $ hg ci -Aqm 'add x on branch 1'
305 $ hg co -q null
347 $ hg co -q null
306 $ echo branch2 > x
348 $ echo branch2 > x
307 $ hg ci -Aqm 'add x on branch 2'
349 $ hg ci -Aqm 'add x on branch 2'
308 $ hg merge -q 0
350 $ hg merge -q 0
309 warning: conflicts while merging x! (edit, then use 'hg resolve --mark')
351 warning: conflicts while merging x! (edit, then use 'hg resolve --mark')
310 [1]
352 [1]
311 $ echo resolved > x
353 $ echo resolved > x
312 $ hg resolve -m x
354 $ hg resolve -m x
313 (no more unresolved files)
355 (no more unresolved files)
314 $ hg cp x z
356 $ hg cp x z
357 $ hg debugp1copies
358 x -> z
359 $ hg debugp2copies
315 $ hg ci -qm 'merge'
360 $ hg ci -qm 'merge'
316 $ hg l
361 $ hg l
317 @ 2 merge
362 @ 2 merge
318 |\ x z
363 |\ x z
319 | o 1 add x on branch 2
364 | o 1 add x on branch 2
320 | x
365 | x
321 o 0 add x on branch 1
366 o 0 add x on branch 1
322 x
367 x
368 $ hg debugp1copies -r 2
369 $ hg debugp2copies -r 2
370 x -> z
323 $ hg debugpathcopies 1 2
371 $ hg debugpathcopies 1 2
324 $ hg debugpathcopies 0 2
372 $ hg debugpathcopies 0 2
325 x -> z
373 x -> z
326
374
327 Copy x->y on one side of merge and copy x->z on the other side. Pathcopies from one parent
375 Copy x->y on one side of merge and copy x->z on the other side. Pathcopies from one parent
328 of the merge to the merge should include the copy from the other side.
376 of the merge to the merge should include the copy from the other side.
329 $ newrepo
377 $ newrepo
330 $ echo x > x
378 $ echo x > x
331 $ hg ci -Aqm 'add x'
379 $ hg ci -Aqm 'add x'
332 $ hg cp x y
380 $ hg cp x y
333 $ hg ci -qm 'copy x to y'
381 $ hg ci -qm 'copy x to y'
334 $ hg co -q 0
382 $ hg co -q 0
335 $ hg cp x z
383 $ hg cp x z
336 $ hg ci -qm 'copy x to z'
384 $ hg ci -qm 'copy x to z'
337 $ hg merge -q 1
385 $ hg merge -q 1
338 $ hg ci -m 'merge copy x->y and copy x->z'
386 $ hg ci -m 'merge copy x->y and copy x->z'
339 $ hg l
387 $ hg l
340 @ 3 merge copy x->y and copy x->z
388 @ 3 merge copy x->y and copy x->z
341 |\
389 |\
342 | o 2 copy x to z
390 | o 2 copy x to z
343 | | z
391 | | z
344 o | 1 copy x to y
392 o | 1 copy x to y
345 |/ y
393 |/ y
346 o 0 add x
394 o 0 add x
347 x
395 x
396 $ hg debugp1copies -r 3
397 $ hg debugp2copies -r 3
348 $ hg debugpathcopies 2 3
398 $ hg debugpathcopies 2 3
349 x -> y
399 x -> y
350 $ hg debugpathcopies 1 3
400 $ hg debugpathcopies 1 3
351 x -> z
401 x -> z
352
402
353 Copy x to y on one side of merge, create y and rename to z on the other side. Pathcopies from the
403 Copy x to y on one side of merge, create y and rename to z on the other side. Pathcopies from the
354 first side should not include the y->z rename since y didn't exist in the merge base.
404 first side should not include the y->z rename since y didn't exist in the merge base.
355 $ newrepo
405 $ newrepo
356 $ echo x > x
406 $ echo x > x
357 $ hg ci -Aqm 'add x'
407 $ hg ci -Aqm 'add x'
358 $ hg cp x y
408 $ hg cp x y
359 $ hg ci -qm 'copy x to y'
409 $ hg ci -qm 'copy x to y'
360 $ hg co -q 0
410 $ hg co -q 0
361 $ echo y > y
411 $ echo y > y
362 $ hg ci -Aqm 'add y'
412 $ hg ci -Aqm 'add y'
363 $ hg mv y z
413 $ hg mv y z
364 $ hg ci -m 'rename y to z'
414 $ hg ci -m 'rename y to z'
365 $ hg merge -q 1
415 $ hg merge -q 1
366 $ hg ci -m 'merge'
416 $ hg ci -m 'merge'
367 $ hg l
417 $ hg l
368 @ 4 merge
418 @ 4 merge
369 |\
419 |\
370 | o 3 rename y to z
420 | o 3 rename y to z
371 | | y z
421 | | y z
372 | o 2 add y
422 | o 2 add y
373 | | y
423 | | y
374 o | 1 copy x to y
424 o | 1 copy x to y
375 |/ y
425 |/ y
376 o 0 add x
426 o 0 add x
377 x
427 x
428 $ hg debugp1copies -r 3
429 y -> z
430 $ hg debugp2copies -r 3
378 $ hg debugpathcopies 2 3
431 $ hg debugpathcopies 2 3
379 y -> z
432 y -> z
380 $ hg debugpathcopies 1 3
433 $ hg debugpathcopies 1 3
381
434
382 Create x and y, then rename x to z on one side of merge, and rename y to z and modify z on the
435 Create x and y, then rename x to z on one side of merge, and rename y to z and modify z on the
383 other side.
436 other side.
384 $ newrepo
437 $ newrepo
385 $ echo x > x
438 $ echo x > x
386 $ echo y > y
439 $ echo y > y
387 $ hg ci -Aqm 'add x and y'
440 $ hg ci -Aqm 'add x and y'
388 $ hg mv x z
441 $ hg mv x z
389 $ hg ci -qm 'rename x to z'
442 $ hg ci -qm 'rename x to z'
390 $ hg co -q 0
443 $ hg co -q 0
391 $ hg mv y z
444 $ hg mv y z
392 $ hg ci -qm 'rename y to z'
445 $ hg ci -qm 'rename y to z'
393 $ echo z >> z
446 $ echo z >> z
394 $ hg ci -m 'modify z'
447 $ hg ci -m 'modify z'
395 $ hg merge -q 1
448 $ hg merge -q 1
396 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
449 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
397 [1]
450 [1]
398 $ echo z > z
451 $ echo z > z
399 $ hg resolve -qm z
452 $ hg resolve -qm z
400 $ hg ci -m 'merge 1 into 3'
453 $ hg ci -m 'merge 1 into 3'
401 Try merging the other direction too
454 Try merging the other direction too
402 $ hg co -q 1
455 $ hg co -q 1
403 $ hg merge -q 3
456 $ hg merge -q 3
404 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
457 warning: conflicts while merging z! (edit, then use 'hg resolve --mark')
405 [1]
458 [1]
406 $ echo z > z
459 $ echo z > z
407 $ hg resolve -qm z
460 $ hg resolve -qm z
408 $ hg ci -m 'merge 3 into 1'
461 $ hg ci -m 'merge 3 into 1'
409 created new head
462 created new head
410 $ hg l
463 $ hg l
411 @ 5 merge 3 into 1
464 @ 5 merge 3 into 1
412 |\ y z
465 |\ y z
413 +---o 4 merge 1 into 3
466 +---o 4 merge 1 into 3
414 | |/ x z
467 | |/ x z
415 | o 3 modify z
468 | o 3 modify z
416 | | z
469 | | z
417 | o 2 rename y to z
470 | o 2 rename y to z
418 | | y z
471 | | y z
419 o | 1 rename x to z
472 o | 1 rename x to z
420 |/ x z
473 |/ x z
421 o 0 add x and y
474 o 0 add x and y
422 x y
475 x y
423 $ hg debugpathcopies 1 4
476 $ hg debugpathcopies 1 4
424 $ hg debugpathcopies 2 4
477 $ hg debugpathcopies 2 4
425 $ hg debugpathcopies 0 4
478 $ hg debugpathcopies 0 4
426 x -> z
479 x -> z
427 $ hg debugpathcopies 1 5
480 $ hg debugpathcopies 1 5
428 $ hg debugpathcopies 2 5
481 $ hg debugpathcopies 2 5
429 $ hg debugpathcopies 0 5
482 $ hg debugpathcopies 0 5
430 x -> z
483 x -> z
431
484
@@ -1,3829 +1,3833 b''
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 revision history for a pattern in specified files
95 grep search revision history 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 remove remove the specified files on the next commit
110 remove remove the specified files on the next commit
111 rename rename files; equivalent of copy + remove
111 rename rename files; equivalent of copy + remove
112 resolve redo merges or set/view the merge status of files
112 resolve redo merges or set/view the merge status of files
113 revert restore files to their checkout state
113 revert restore files to their checkout state
114 root print the root (top) of the current working directory
114 root print the root (top) of the current working directory
115 status show changed files in the working directory
115 status show changed files in the working directory
116 summary summarize working directory state
116 summary summarize working directory state
117 update update working directory (or switch revisions)
117 update update working directory (or switch revisions)
118
118
119 Change import/export:
119 Change import/export:
120
120
121 archive create an unversioned archive of a repository revision
121 archive create an unversioned archive of a repository revision
122 bundle create a bundle file
122 bundle create a bundle file
123 export dump the header and diffs for one or more changesets
123 export dump the header and diffs for one or more changesets
124 import import an ordered set of patches
124 import import an ordered set of patches
125 unbundle apply one or more bundle files
125 unbundle apply one or more bundle files
126
126
127 Repository maintenance:
127 Repository maintenance:
128
128
129 manifest output the current or given revision of the project manifest
129 manifest output the current or given revision of the project manifest
130 recover roll back an interrupted transaction
130 recover roll back an interrupted transaction
131 verify verify the integrity of the repository
131 verify verify the integrity of the repository
132
132
133 Help:
133 Help:
134
134
135 config show combined config settings from all hgrc files
135 config show combined config settings from all hgrc files
136 help show help for a given topic or a help overview
136 help show help for a given topic or a help overview
137 version output version and copyright information
137 version output version and copyright information
138
138
139 additional help topics:
139 additional help topics:
140
140
141 Mercurial identifiers:
141 Mercurial identifiers:
142
142
143 filesets Specifying File Sets
143 filesets Specifying File Sets
144 hgignore Syntax for Mercurial Ignore Files
144 hgignore Syntax for Mercurial Ignore Files
145 patterns File Name Patterns
145 patterns File Name Patterns
146 revisions Specifying Revisions
146 revisions Specifying Revisions
147 urls URL Paths
147 urls URL Paths
148
148
149 Mercurial output:
149 Mercurial output:
150
150
151 color Colorizing Outputs
151 color Colorizing Outputs
152 dates Date Formats
152 dates Date Formats
153 diffs Diff Formats
153 diffs Diff Formats
154 templating Template Usage
154 templating Template Usage
155
155
156 Mercurial configuration:
156 Mercurial configuration:
157
157
158 config Configuration Files
158 config Configuration Files
159 environment Environment Variables
159 environment Environment Variables
160 extensions Using Additional Features
160 extensions Using Additional Features
161 flags Command-line flags
161 flags Command-line flags
162 hgweb Configuring hgweb
162 hgweb Configuring hgweb
163 merge-tools Merge Tools
163 merge-tools Merge Tools
164 pager Pager Support
164 pager Pager Support
165
165
166 Concepts:
166 Concepts:
167
167
168 bundlespec Bundle File Formats
168 bundlespec Bundle File Formats
169 glossary Glossary
169 glossary Glossary
170 phases Working with Phases
170 phases Working with Phases
171 subrepos Subrepositories
171 subrepos Subrepositories
172
172
173 Miscellaneous:
173 Miscellaneous:
174
174
175 deprecated Deprecated Features
175 deprecated Deprecated Features
176 internals Technical implementation topics
176 internals Technical implementation topics
177 scripting Using Mercurial from scripts and automation
177 scripting Using Mercurial from scripts and automation
178
178
179 (use 'hg help -v' to show built-in aliases and global options)
179 (use 'hg help -v' to show built-in aliases and global options)
180
180
181 $ hg -q help
181 $ hg -q help
182 Repository creation:
182 Repository creation:
183
183
184 clone make a copy of an existing repository
184 clone make a copy of an existing repository
185 init create a new repository in the given directory
185 init create a new repository in the given directory
186
186
187 Remote repository management:
187 Remote repository management:
188
188
189 incoming show new changesets found in source
189 incoming show new changesets found in source
190 outgoing show changesets not found in the destination
190 outgoing show changesets not found in the destination
191 paths show aliases for remote repositories
191 paths show aliases for remote repositories
192 pull pull changes from the specified source
192 pull pull changes from the specified source
193 push push changes to the specified destination
193 push push changes to the specified destination
194 serve start stand-alone webserver
194 serve start stand-alone webserver
195
195
196 Change creation:
196 Change creation:
197
197
198 commit commit the specified files or all outstanding changes
198 commit commit the specified files or all outstanding changes
199
199
200 Change manipulation:
200 Change manipulation:
201
201
202 backout reverse effect of earlier changeset
202 backout reverse effect of earlier changeset
203 graft copy changes from other branches onto the current branch
203 graft copy changes from other branches onto the current branch
204 merge merge another revision into working directory
204 merge merge another revision into working directory
205
205
206 Change organization:
206 Change organization:
207
207
208 bookmarks create a new bookmark or list existing bookmarks
208 bookmarks create a new bookmark or list existing bookmarks
209 branch set or show the current branch name
209 branch set or show the current branch name
210 branches list repository named branches
210 branches list repository named branches
211 phase set or show the current phase name
211 phase set or show the current phase name
212 tag add one or more tags for the current or given revision
212 tag add one or more tags for the current or given revision
213 tags list repository tags
213 tags list repository tags
214
214
215 File content management:
215 File content management:
216
216
217 annotate show changeset information by line for each file
217 annotate show changeset information by line for each file
218 cat output the current or given revision of files
218 cat output the current or given revision of files
219 copy mark files as copied for the next commit
219 copy mark files as copied for the next commit
220 diff diff repository (or selected files)
220 diff diff repository (or selected files)
221 grep search revision history for a pattern in specified files
221 grep search revision history for a pattern in specified files
222
222
223 Change navigation:
223 Change navigation:
224
224
225 bisect subdivision search of changesets
225 bisect subdivision search of changesets
226 heads show branch heads
226 heads show branch heads
227 identify identify the working directory or specified revision
227 identify identify the working directory or specified revision
228 log show revision history of entire repository or files
228 log show revision history of entire repository or files
229
229
230 Working directory management:
230 Working directory management:
231
231
232 add add the specified files on the next commit
232 add add the specified files on the next commit
233 addremove add all new files, delete all missing files
233 addremove add all new files, delete all missing files
234 files list tracked files
234 files list tracked files
235 forget forget the specified files on the next commit
235 forget forget the specified files on the next commit
236 remove remove the specified files on the next commit
236 remove remove the specified files on the next commit
237 rename rename files; equivalent of copy + remove
237 rename rename files; equivalent of copy + remove
238 resolve redo merges or set/view the merge status of files
238 resolve redo merges or set/view the merge status of files
239 revert restore files to their checkout state
239 revert restore files to their checkout state
240 root print the root (top) of the current working directory
240 root print the root (top) of the current working directory
241 status show changed files in the working directory
241 status show changed files in the working directory
242 summary summarize working directory state
242 summary summarize working directory state
243 update update working directory (or switch revisions)
243 update update working directory (or switch revisions)
244
244
245 Change import/export:
245 Change import/export:
246
246
247 archive create an unversioned archive of a repository revision
247 archive create an unversioned archive of a repository revision
248 bundle create a bundle file
248 bundle create a bundle file
249 export dump the header and diffs for one or more changesets
249 export dump the header and diffs for one or more changesets
250 import import an ordered set of patches
250 import import an ordered set of patches
251 unbundle apply one or more bundle files
251 unbundle apply one or more bundle files
252
252
253 Repository maintenance:
253 Repository maintenance:
254
254
255 manifest output the current or given revision of the project manifest
255 manifest output the current or given revision of the project manifest
256 recover roll back an interrupted transaction
256 recover roll back an interrupted transaction
257 verify verify the integrity of the repository
257 verify verify the integrity of the repository
258
258
259 Help:
259 Help:
260
260
261 config show combined config settings from all hgrc files
261 config show combined config settings from all hgrc files
262 help show help for a given topic or a help overview
262 help show help for a given topic or a help overview
263 version output version and copyright information
263 version output version and copyright information
264
264
265 additional help topics:
265 additional help topics:
266
266
267 Mercurial identifiers:
267 Mercurial identifiers:
268
268
269 filesets Specifying File Sets
269 filesets Specifying File Sets
270 hgignore Syntax for Mercurial Ignore Files
270 hgignore Syntax for Mercurial Ignore Files
271 patterns File Name Patterns
271 patterns File Name Patterns
272 revisions Specifying Revisions
272 revisions Specifying Revisions
273 urls URL Paths
273 urls URL Paths
274
274
275 Mercurial output:
275 Mercurial output:
276
276
277 color Colorizing Outputs
277 color Colorizing Outputs
278 dates Date Formats
278 dates Date Formats
279 diffs Diff Formats
279 diffs Diff Formats
280 templating Template Usage
280 templating Template Usage
281
281
282 Mercurial configuration:
282 Mercurial configuration:
283
283
284 config Configuration Files
284 config Configuration Files
285 environment Environment Variables
285 environment Environment Variables
286 extensions Using Additional Features
286 extensions Using Additional Features
287 flags Command-line flags
287 flags Command-line flags
288 hgweb Configuring hgweb
288 hgweb Configuring hgweb
289 merge-tools Merge Tools
289 merge-tools Merge Tools
290 pager Pager Support
290 pager Pager Support
291
291
292 Concepts:
292 Concepts:
293
293
294 bundlespec Bundle File Formats
294 bundlespec Bundle File Formats
295 glossary Glossary
295 glossary Glossary
296 phases Working with Phases
296 phases Working with Phases
297 subrepos Subrepositories
297 subrepos Subrepositories
298
298
299 Miscellaneous:
299 Miscellaneous:
300
300
301 deprecated Deprecated Features
301 deprecated Deprecated Features
302 internals Technical implementation topics
302 internals Technical implementation topics
303 scripting Using Mercurial from scripts and automation
303 scripting Using Mercurial from scripts and automation
304
304
305 Test extension help:
305 Test extension help:
306 $ hg help extensions --config extensions.rebase= --config extensions.children=
306 $ hg help extensions --config extensions.rebase= --config extensions.children=
307 Using Additional Features
307 Using Additional Features
308 """""""""""""""""""""""""
308 """""""""""""""""""""""""
309
309
310 Mercurial has the ability to add new features through the use of
310 Mercurial has the ability to add new features through the use of
311 extensions. Extensions may add new commands, add options to existing
311 extensions. Extensions may add new commands, add options to existing
312 commands, change the default behavior of commands, or implement hooks.
312 commands, change the default behavior of commands, or implement hooks.
313
313
314 To enable the "foo" extension, either shipped with Mercurial or in the
314 To enable the "foo" extension, either shipped with Mercurial or in the
315 Python search path, create an entry for it in your configuration file,
315 Python search path, create an entry for it in your configuration file,
316 like this:
316 like this:
317
317
318 [extensions]
318 [extensions]
319 foo =
319 foo =
320
320
321 You may also specify the full path to an extension:
321 You may also specify the full path to an extension:
322
322
323 [extensions]
323 [extensions]
324 myfeature = ~/.hgext/myfeature.py
324 myfeature = ~/.hgext/myfeature.py
325
325
326 See 'hg help config' for more information on configuration files.
326 See 'hg help config' for more information on configuration files.
327
327
328 Extensions are not loaded by default for a variety of reasons: they can
328 Extensions are not loaded by default for a variety of reasons: they can
329 increase startup overhead; they may be meant for advanced usage only; they
329 increase startup overhead; they may be meant for advanced usage only; they
330 may provide potentially dangerous abilities (such as letting you destroy
330 may provide potentially dangerous abilities (such as letting you destroy
331 or modify history); they might not be ready for prime time; or they may
331 or modify history); they might not be ready for prime time; or they may
332 alter some usual behaviors of stock Mercurial. It is thus up to the user
332 alter some usual behaviors of stock Mercurial. It is thus up to the user
333 to activate extensions as needed.
333 to activate extensions as needed.
334
334
335 To explicitly disable an extension enabled in a configuration file of
335 To explicitly disable an extension enabled in a configuration file of
336 broader scope, prepend its path with !:
336 broader scope, prepend its path with !:
337
337
338 [extensions]
338 [extensions]
339 # disabling extension bar residing in /path/to/extension/bar.py
339 # disabling extension bar residing in /path/to/extension/bar.py
340 bar = !/path/to/extension/bar.py
340 bar = !/path/to/extension/bar.py
341 # ditto, but no path was supplied for extension baz
341 # ditto, but no path was supplied for extension baz
342 baz = !
342 baz = !
343
343
344 enabled extensions:
344 enabled extensions:
345
345
346 children command to display child changesets (DEPRECATED)
346 children command to display child changesets (DEPRECATED)
347 rebase command to move sets of revisions to a different ancestor
347 rebase command to move sets of revisions to a different ancestor
348
348
349 disabled extensions:
349 disabled extensions:
350
350
351 acl hooks for controlling repository access
351 acl hooks for controlling repository access
352 blackbox log repository events to a blackbox for debugging
352 blackbox log repository events to a blackbox for debugging
353 bugzilla hooks for integrating with the Bugzilla bug tracker
353 bugzilla hooks for integrating with the Bugzilla bug tracker
354 censor erase file content at a given revision
354 censor erase file content at a given revision
355 churn command to display statistics about repository history
355 churn command to display statistics about repository history
356 clonebundles advertise pre-generated bundles to seed clones
356 clonebundles advertise pre-generated bundles to seed clones
357 closehead close arbitrary heads without checking them out first
357 closehead close arbitrary heads without checking them out first
358 convert import revisions from foreign VCS repositories into
358 convert import revisions from foreign VCS repositories into
359 Mercurial
359 Mercurial
360 eol automatically manage newlines in repository files
360 eol automatically manage newlines in repository files
361 extdiff command to allow external programs to compare revisions
361 extdiff command to allow external programs to compare revisions
362 factotum http authentication with factotum
362 factotum http authentication with factotum
363 githelp try mapping git commands to Mercurial commands
363 githelp try mapping git commands to Mercurial commands
364 gpg commands to sign and verify changesets
364 gpg commands to sign and verify changesets
365 hgk browse the repository in a graphical way
365 hgk browse the repository in a graphical way
366 highlight syntax highlighting for hgweb (requires Pygments)
366 highlight syntax highlighting for hgweb (requires Pygments)
367 histedit interactive history editing
367 histedit interactive history editing
368 keyword expand keywords in tracked files
368 keyword expand keywords in tracked files
369 largefiles track large binary files
369 largefiles track large binary files
370 mq manage a stack of patches
370 mq manage a stack of patches
371 notify hooks for sending email push notifications
371 notify hooks for sending email push notifications
372 patchbomb command to send changesets as (a series of) patch emails
372 patchbomb command to send changesets as (a series of) patch emails
373 purge command to delete untracked files from the working
373 purge command to delete untracked files from the working
374 directory
374 directory
375 relink recreates hardlinks between repository clones
375 relink recreates hardlinks between repository clones
376 schemes extend schemes with shortcuts to repository swarms
376 schemes extend schemes with shortcuts to repository swarms
377 share share a common history between several working directories
377 share share a common history between several working directories
378 shelve save and restore changes to the working directory
378 shelve save and restore changes to the working directory
379 strip strip changesets and their descendants from history
379 strip strip changesets and their descendants from history
380 transplant command to transplant changesets from another branch
380 transplant command to transplant changesets from another branch
381 win32mbcs allow the use of MBCS paths with problematic encodings
381 win32mbcs allow the use of MBCS paths with problematic encodings
382 zeroconf discover and advertise repositories on the local network
382 zeroconf discover and advertise repositories on the local network
383
383
384 #endif
384 #endif
385
385
386 Verify that deprecated extensions are included if --verbose:
386 Verify that deprecated extensions are included if --verbose:
387
387
388 $ hg -v help extensions | grep children
388 $ hg -v help extensions | grep children
389 children command to display child changesets (DEPRECATED)
389 children command to display child changesets (DEPRECATED)
390
390
391 Verify that extension keywords appear in help templates
391 Verify that extension keywords appear in help templates
392
392
393 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
393 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
394
394
395 Test short command list with verbose option
395 Test short command list with verbose option
396
396
397 $ hg -v help shortlist
397 $ hg -v help shortlist
398 Mercurial Distributed SCM
398 Mercurial Distributed SCM
399
399
400 basic commands:
400 basic commands:
401
401
402 add add the specified files on the next commit
402 add add the specified files on the next commit
403 annotate, blame
403 annotate, blame
404 show changeset information by line for each file
404 show changeset information by line for each file
405 clone make a copy of an existing repository
405 clone make a copy of an existing repository
406 commit, ci commit the specified files or all outstanding changes
406 commit, ci commit the specified files or all outstanding changes
407 diff diff repository (or selected files)
407 diff diff repository (or selected files)
408 export dump the header and diffs for one or more changesets
408 export dump the header and diffs for one or more changesets
409 forget forget the specified files on the next commit
409 forget forget the specified files on the next commit
410 init create a new repository in the given directory
410 init create a new repository in the given directory
411 log, history show revision history of entire repository or files
411 log, history show revision history of entire repository or files
412 merge merge another revision into working directory
412 merge merge another revision into working directory
413 pull pull changes from the specified source
413 pull pull changes from the specified source
414 push push changes to the specified destination
414 push push changes to the specified destination
415 remove, rm remove the specified files on the next commit
415 remove, rm remove the specified files on the next commit
416 serve start stand-alone webserver
416 serve start stand-alone webserver
417 status, st show changed files in the working directory
417 status, st show changed files in the working directory
418 summary, sum summarize working directory state
418 summary, sum summarize working directory state
419 update, up, checkout, co
419 update, up, checkout, co
420 update working directory (or switch revisions)
420 update working directory (or switch revisions)
421
421
422 global options ([+] can be repeated):
422 global options ([+] can be repeated):
423
423
424 -R --repository REPO repository root directory or name of overlay bundle
424 -R --repository REPO repository root directory or name of overlay bundle
425 file
425 file
426 --cwd DIR change working directory
426 --cwd DIR change working directory
427 -y --noninteractive do not prompt, automatically pick the first choice for
427 -y --noninteractive do not prompt, automatically pick the first choice for
428 all prompts
428 all prompts
429 -q --quiet suppress output
429 -q --quiet suppress output
430 -v --verbose enable additional output
430 -v --verbose enable additional output
431 --color TYPE when to colorize (boolean, always, auto, never, or
431 --color TYPE when to colorize (boolean, always, auto, never, or
432 debug)
432 debug)
433 --config CONFIG [+] set/override config option (use 'section.name=value')
433 --config CONFIG [+] set/override config option (use 'section.name=value')
434 --debug enable debugging output
434 --debug enable debugging output
435 --debugger start debugger
435 --debugger start debugger
436 --encoding ENCODE set the charset encoding (default: ascii)
436 --encoding ENCODE set the charset encoding (default: ascii)
437 --encodingmode MODE set the charset encoding mode (default: strict)
437 --encodingmode MODE set the charset encoding mode (default: strict)
438 --traceback always print a traceback on exception
438 --traceback always print a traceback on exception
439 --time time how long the command takes
439 --time time how long the command takes
440 --profile print command execution profile
440 --profile print command execution profile
441 --version output version information and exit
441 --version output version information and exit
442 -h --help display help and exit
442 -h --help display help and exit
443 --hidden consider hidden changesets
443 --hidden consider hidden changesets
444 --pager TYPE when to paginate (boolean, always, auto, or never)
444 --pager TYPE when to paginate (boolean, always, auto, or never)
445 (default: auto)
445 (default: auto)
446
446
447 (use 'hg help' for the full list of commands)
447 (use 'hg help' for the full list of commands)
448
448
449 $ hg add -h
449 $ hg add -h
450 hg add [OPTION]... [FILE]...
450 hg add [OPTION]... [FILE]...
451
451
452 add the specified files on the next commit
452 add the specified files on the next commit
453
453
454 Schedule files to be version controlled and added to the repository.
454 Schedule files to be version controlled and added to the repository.
455
455
456 The files will be added to the repository at the next commit. To undo an
456 The files will be added to the repository at the next commit. To undo an
457 add before that, see 'hg forget'.
457 add before that, see 'hg forget'.
458
458
459 If no names are given, add all files to the repository (except files
459 If no names are given, add all files to the repository (except files
460 matching ".hgignore").
460 matching ".hgignore").
461
461
462 Returns 0 if all files are successfully added.
462 Returns 0 if all files are successfully added.
463
463
464 options ([+] can be repeated):
464 options ([+] can be repeated):
465
465
466 -I --include PATTERN [+] include names matching the given patterns
466 -I --include PATTERN [+] include names matching the given patterns
467 -X --exclude PATTERN [+] exclude names matching the given patterns
467 -X --exclude PATTERN [+] exclude names matching the given patterns
468 -S --subrepos recurse into subrepositories
468 -S --subrepos recurse into subrepositories
469 -n --dry-run do not perform actions, just print output
469 -n --dry-run do not perform actions, just print output
470
470
471 (some details hidden, use --verbose to show complete help)
471 (some details hidden, use --verbose to show complete help)
472
472
473 Verbose help for add
473 Verbose help for add
474
474
475 $ hg add -hv
475 $ hg add -hv
476 hg add [OPTION]... [FILE]...
476 hg add [OPTION]... [FILE]...
477
477
478 add the specified files on the next commit
478 add the specified files on the next commit
479
479
480 Schedule files to be version controlled and added to the repository.
480 Schedule files to be version controlled and added to the repository.
481
481
482 The files will be added to the repository at the next commit. To undo an
482 The files will be added to the repository at the next commit. To undo an
483 add before that, see 'hg forget'.
483 add before that, see 'hg forget'.
484
484
485 If no names are given, add all files to the repository (except files
485 If no names are given, add all files to the repository (except files
486 matching ".hgignore").
486 matching ".hgignore").
487
487
488 Examples:
488 Examples:
489
489
490 - New (unknown) files are added automatically by 'hg add':
490 - New (unknown) files are added automatically by 'hg add':
491
491
492 $ ls
492 $ ls
493 foo.c
493 foo.c
494 $ hg status
494 $ hg status
495 ? foo.c
495 ? foo.c
496 $ hg add
496 $ hg add
497 adding foo.c
497 adding foo.c
498 $ hg status
498 $ hg status
499 A foo.c
499 A foo.c
500
500
501 - Specific files to be added can be specified:
501 - Specific files to be added can be specified:
502
502
503 $ ls
503 $ ls
504 bar.c foo.c
504 bar.c foo.c
505 $ hg status
505 $ hg status
506 ? bar.c
506 ? bar.c
507 ? foo.c
507 ? foo.c
508 $ hg add bar.c
508 $ hg add bar.c
509 $ hg status
509 $ hg status
510 A bar.c
510 A bar.c
511 ? foo.c
511 ? foo.c
512
512
513 Returns 0 if all files are successfully added.
513 Returns 0 if all files are successfully added.
514
514
515 options ([+] can be repeated):
515 options ([+] can be repeated):
516
516
517 -I --include PATTERN [+] include names matching the given patterns
517 -I --include PATTERN [+] include names matching the given patterns
518 -X --exclude PATTERN [+] exclude names matching the given patterns
518 -X --exclude PATTERN [+] exclude names matching the given patterns
519 -S --subrepos recurse into subrepositories
519 -S --subrepos recurse into subrepositories
520 -n --dry-run do not perform actions, just print output
520 -n --dry-run do not perform actions, just print output
521
521
522 global options ([+] can be repeated):
522 global options ([+] can be repeated):
523
523
524 -R --repository REPO repository root directory or name of overlay bundle
524 -R --repository REPO repository root directory or name of overlay bundle
525 file
525 file
526 --cwd DIR change working directory
526 --cwd DIR change working directory
527 -y --noninteractive do not prompt, automatically pick the first choice for
527 -y --noninteractive do not prompt, automatically pick the first choice for
528 all prompts
528 all prompts
529 -q --quiet suppress output
529 -q --quiet suppress output
530 -v --verbose enable additional output
530 -v --verbose enable additional output
531 --color TYPE when to colorize (boolean, always, auto, never, or
531 --color TYPE when to colorize (boolean, always, auto, never, or
532 debug)
532 debug)
533 --config CONFIG [+] set/override config option (use 'section.name=value')
533 --config CONFIG [+] set/override config option (use 'section.name=value')
534 --debug enable debugging output
534 --debug enable debugging output
535 --debugger start debugger
535 --debugger start debugger
536 --encoding ENCODE set the charset encoding (default: ascii)
536 --encoding ENCODE set the charset encoding (default: ascii)
537 --encodingmode MODE set the charset encoding mode (default: strict)
537 --encodingmode MODE set the charset encoding mode (default: strict)
538 --traceback always print a traceback on exception
538 --traceback always print a traceback on exception
539 --time time how long the command takes
539 --time time how long the command takes
540 --profile print command execution profile
540 --profile print command execution profile
541 --version output version information and exit
541 --version output version information and exit
542 -h --help display help and exit
542 -h --help display help and exit
543 --hidden consider hidden changesets
543 --hidden consider hidden changesets
544 --pager TYPE when to paginate (boolean, always, auto, or never)
544 --pager TYPE when to paginate (boolean, always, auto, or never)
545 (default: auto)
545 (default: auto)
546
546
547 Test the textwidth config option
547 Test the textwidth config option
548
548
549 $ hg root -h --config ui.textwidth=50
549 $ hg root -h --config ui.textwidth=50
550 hg root
550 hg root
551
551
552 print the root (top) of the current working
552 print the root (top) of the current working
553 directory
553 directory
554
554
555 Print the root directory of the current
555 Print the root directory of the current
556 repository.
556 repository.
557
557
558 Returns 0 on success.
558 Returns 0 on success.
559
559
560 (some details hidden, use --verbose to show
560 (some details hidden, use --verbose to show
561 complete help)
561 complete help)
562
562
563 Test help option with version option
563 Test help option with version option
564
564
565 $ hg add -h --version
565 $ hg add -h --version
566 Mercurial Distributed SCM (version *) (glob)
566 Mercurial Distributed SCM (version *) (glob)
567 (see https://mercurial-scm.org for more information)
567 (see https://mercurial-scm.org for more information)
568
568
569 Copyright (C) 2005-* Matt Mackall and others (glob)
569 Copyright (C) 2005-* Matt Mackall and others (glob)
570 This is free software; see the source for copying conditions. There is NO
570 This is free software; see the source for copying conditions. There is NO
571 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
571 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
572
572
573 $ hg add --skjdfks
573 $ hg add --skjdfks
574 hg add: option --skjdfks not recognized
574 hg add: option --skjdfks not recognized
575 hg add [OPTION]... [FILE]...
575 hg add [OPTION]... [FILE]...
576
576
577 add the specified files on the next commit
577 add the specified files on the next commit
578
578
579 options ([+] can be repeated):
579 options ([+] can be repeated):
580
580
581 -I --include PATTERN [+] include names matching the given patterns
581 -I --include PATTERN [+] include names matching the given patterns
582 -X --exclude PATTERN [+] exclude names matching the given patterns
582 -X --exclude PATTERN [+] exclude names matching the given patterns
583 -S --subrepos recurse into subrepositories
583 -S --subrepos recurse into subrepositories
584 -n --dry-run do not perform actions, just print output
584 -n --dry-run do not perform actions, just print output
585
585
586 (use 'hg add -h' to show more help)
586 (use 'hg add -h' to show more help)
587 [255]
587 [255]
588
588
589 Test ambiguous command help
589 Test ambiguous command help
590
590
591 $ hg help ad
591 $ hg help ad
592 list of commands:
592 list of commands:
593
593
594 add add the specified files on the next commit
594 add add the specified files on the next commit
595 addremove add all new files, delete all missing files
595 addremove add all new files, delete all missing files
596
596
597 (use 'hg help -v ad' to show built-in aliases and global options)
597 (use 'hg help -v ad' to show built-in aliases and global options)
598
598
599 Test command without options
599 Test command without options
600
600
601 $ hg help verify
601 $ hg help verify
602 hg verify
602 hg verify
603
603
604 verify the integrity of the repository
604 verify the integrity of the repository
605
605
606 Verify the integrity of the current repository.
606 Verify the integrity of the current repository.
607
607
608 This will perform an extensive check of the repository's integrity,
608 This will perform an extensive check of the repository's integrity,
609 validating the hashes and checksums of each entry in the changelog,
609 validating the hashes and checksums of each entry in the changelog,
610 manifest, and tracked files, as well as the integrity of their crosslinks
610 manifest, and tracked files, as well as the integrity of their crosslinks
611 and indices.
611 and indices.
612
612
613 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
613 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
614 information about recovery from corruption of the repository.
614 information about recovery from corruption of the repository.
615
615
616 Returns 0 on success, 1 if errors are encountered.
616 Returns 0 on success, 1 if errors are encountered.
617
617
618 (some details hidden, use --verbose to show complete help)
618 (some details hidden, use --verbose to show complete help)
619
619
620 $ hg help diff
620 $ hg help diff
621 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
621 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
622
622
623 diff repository (or selected files)
623 diff repository (or selected files)
624
624
625 Show differences between revisions for the specified files.
625 Show differences between revisions for the specified files.
626
626
627 Differences between files are shown using the unified diff format.
627 Differences between files are shown using the unified diff format.
628
628
629 Note:
629 Note:
630 'hg diff' may generate unexpected results for merges, as it will
630 'hg diff' may generate unexpected results for merges, as it will
631 default to comparing against the working directory's first parent
631 default to comparing against the working directory's first parent
632 changeset if no revisions are specified.
632 changeset if no revisions are specified.
633
633
634 When two revision arguments are given, then changes are shown between
634 When two revision arguments are given, then changes are shown between
635 those revisions. If only one revision is specified then that revision is
635 those revisions. If only one revision is specified then that revision is
636 compared to the working directory, and, when no revisions are specified,
636 compared to the working directory, and, when no revisions are specified,
637 the working directory files are compared to its first parent.
637 the working directory files are compared to its first parent.
638
638
639 Alternatively you can specify -c/--change with a revision to see the
639 Alternatively you can specify -c/--change with a revision to see the
640 changes in that changeset relative to its first parent.
640 changes in that changeset relative to its first parent.
641
641
642 Without the -a/--text option, diff will avoid generating diffs of files it
642 Without the -a/--text option, diff will avoid generating diffs of files it
643 detects as binary. With -a, diff will generate a diff anyway, probably
643 detects as binary. With -a, diff will generate a diff anyway, probably
644 with undesirable results.
644 with undesirable results.
645
645
646 Use the -g/--git option to generate diffs in the git extended diff format.
646 Use the -g/--git option to generate diffs in the git extended diff format.
647 For more information, read 'hg help diffs'.
647 For more information, read 'hg help diffs'.
648
648
649 Returns 0 on success.
649 Returns 0 on success.
650
650
651 options ([+] can be repeated):
651 options ([+] can be repeated):
652
652
653 -r --rev REV [+] revision
653 -r --rev REV [+] revision
654 -c --change REV change made by revision
654 -c --change REV change made by revision
655 -a --text treat all files as text
655 -a --text treat all files as text
656 -g --git use git extended diff format
656 -g --git use git extended diff format
657 --binary generate binary diffs in git mode (default)
657 --binary generate binary diffs in git mode (default)
658 --nodates omit dates from diff headers
658 --nodates omit dates from diff headers
659 --noprefix omit a/ and b/ prefixes from filenames
659 --noprefix omit a/ and b/ prefixes from filenames
660 -p --show-function show which function each change is in
660 -p --show-function show which function each change is in
661 --reverse produce a diff that undoes the changes
661 --reverse produce a diff that undoes the changes
662 -w --ignore-all-space ignore white space when comparing lines
662 -w --ignore-all-space ignore white space when comparing lines
663 -b --ignore-space-change ignore changes in the amount of white space
663 -b --ignore-space-change ignore changes in the amount of white space
664 -B --ignore-blank-lines ignore changes whose lines are all blank
664 -B --ignore-blank-lines ignore changes whose lines are all blank
665 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
665 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
666 -U --unified NUM number of lines of context to show
666 -U --unified NUM number of lines of context to show
667 --stat output diffstat-style summary of changes
667 --stat output diffstat-style summary of changes
668 --root DIR produce diffs relative to subdirectory
668 --root DIR produce diffs relative to subdirectory
669 -I --include PATTERN [+] include names matching the given patterns
669 -I --include PATTERN [+] include names matching the given patterns
670 -X --exclude PATTERN [+] exclude names matching the given patterns
670 -X --exclude PATTERN [+] exclude names matching the given patterns
671 -S --subrepos recurse into subrepositories
671 -S --subrepos recurse into subrepositories
672
672
673 (some details hidden, use --verbose to show complete help)
673 (some details hidden, use --verbose to show complete help)
674
674
675 $ hg help status
675 $ hg help status
676 hg status [OPTION]... [FILE]...
676 hg status [OPTION]... [FILE]...
677
677
678 aliases: st
678 aliases: st
679
679
680 show changed files in the working directory
680 show changed files in the working directory
681
681
682 Show status of files in the repository. If names are given, only files
682 Show status of files in the repository. If names are given, only files
683 that match are shown. Files that are clean or ignored or the source of a
683 that match are shown. Files that are clean or ignored or the source of a
684 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
684 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
685 -C/--copies or -A/--all are given. Unless options described with "show
685 -C/--copies or -A/--all are given. Unless options described with "show
686 only ..." are given, the options -mardu are used.
686 only ..." are given, the options -mardu are used.
687
687
688 Option -q/--quiet hides untracked (unknown and ignored) files unless
688 Option -q/--quiet hides untracked (unknown and ignored) files unless
689 explicitly requested with -u/--unknown or -i/--ignored.
689 explicitly requested with -u/--unknown or -i/--ignored.
690
690
691 Note:
691 Note:
692 'hg status' may appear to disagree with diff if permissions have
692 'hg status' may appear to disagree with diff if permissions have
693 changed or a merge has occurred. The standard diff format does not
693 changed or a merge has occurred. The standard diff format does not
694 report permission changes and diff only reports changes relative to one
694 report permission changes and diff only reports changes relative to one
695 merge parent.
695 merge parent.
696
696
697 If one revision is given, it is used as the base revision. If two
697 If one revision is given, it is used as the base revision. If two
698 revisions are given, the differences between them are shown. The --change
698 revisions are given, the differences between them are shown. The --change
699 option can also be used as a shortcut to list the changed files of a
699 option can also be used as a shortcut to list the changed files of a
700 revision from its first parent.
700 revision from its first parent.
701
701
702 The codes used to show the status of files are:
702 The codes used to show the status of files are:
703
703
704 M = modified
704 M = modified
705 A = added
705 A = added
706 R = removed
706 R = removed
707 C = clean
707 C = clean
708 ! = missing (deleted by non-hg command, but still tracked)
708 ! = missing (deleted by non-hg command, but still tracked)
709 ? = not tracked
709 ? = not tracked
710 I = ignored
710 I = ignored
711 = origin of the previous file (with --copies)
711 = origin of the previous file (with --copies)
712
712
713 Returns 0 on success.
713 Returns 0 on success.
714
714
715 options ([+] can be repeated):
715 options ([+] can be repeated):
716
716
717 -A --all show status of all files
717 -A --all show status of all files
718 -m --modified show only modified files
718 -m --modified show only modified files
719 -a --added show only added files
719 -a --added show only added files
720 -r --removed show only removed files
720 -r --removed show only removed files
721 -d --deleted show only deleted (but tracked) files
721 -d --deleted show only deleted (but tracked) files
722 -c --clean show only files without changes
722 -c --clean show only files without changes
723 -u --unknown show only unknown (not tracked) files
723 -u --unknown show only unknown (not tracked) files
724 -i --ignored show only ignored files
724 -i --ignored show only ignored files
725 -n --no-status hide status prefix
725 -n --no-status hide status prefix
726 -C --copies show source of copied files
726 -C --copies show source of copied files
727 -0 --print0 end filenames with NUL, for use with xargs
727 -0 --print0 end filenames with NUL, for use with xargs
728 --rev REV [+] show difference from revision
728 --rev REV [+] show difference from revision
729 --change REV list the changed files of a revision
729 --change REV list the changed files of a revision
730 -I --include PATTERN [+] include names matching the given patterns
730 -I --include PATTERN [+] include names matching the given patterns
731 -X --exclude PATTERN [+] exclude names matching the given patterns
731 -X --exclude PATTERN [+] exclude names matching the given patterns
732 -S --subrepos recurse into subrepositories
732 -S --subrepos recurse into subrepositories
733 -T --template TEMPLATE display with template
733 -T --template TEMPLATE display with template
734
734
735 (some details hidden, use --verbose to show complete help)
735 (some details hidden, use --verbose to show complete help)
736
736
737 $ hg -q help status
737 $ hg -q help status
738 hg status [OPTION]... [FILE]...
738 hg status [OPTION]... [FILE]...
739
739
740 show changed files in the working directory
740 show changed files in the working directory
741
741
742 $ hg help foo
742 $ hg help foo
743 abort: no such help topic: foo
743 abort: no such help topic: foo
744 (try 'hg help --keyword foo')
744 (try 'hg help --keyword foo')
745 [255]
745 [255]
746
746
747 $ hg skjdfks
747 $ hg skjdfks
748 hg: unknown command 'skjdfks'
748 hg: unknown command 'skjdfks'
749 (use 'hg help' for a list of commands)
749 (use 'hg help' for a list of commands)
750 [255]
750 [255]
751
751
752 Typoed command gives suggestion
752 Typoed command gives suggestion
753 $ hg puls
753 $ hg puls
754 hg: unknown command 'puls'
754 hg: unknown command 'puls'
755 (did you mean one of pull, push?)
755 (did you mean one of pull, push?)
756 [255]
756 [255]
757
757
758 Not enabled extension gets suggested
758 Not enabled extension gets suggested
759
759
760 $ hg rebase
760 $ hg rebase
761 hg: unknown command 'rebase'
761 hg: unknown command 'rebase'
762 'rebase' is provided by the following extension:
762 'rebase' is provided by the following extension:
763
763
764 rebase command to move sets of revisions to a different ancestor
764 rebase command to move sets of revisions to a different ancestor
765
765
766 (use 'hg help extensions' for information on enabling extensions)
766 (use 'hg help extensions' for information on enabling extensions)
767 [255]
767 [255]
768
768
769 Disabled extension gets suggested
769 Disabled extension gets suggested
770 $ hg --config extensions.rebase=! rebase
770 $ hg --config extensions.rebase=! rebase
771 hg: unknown command 'rebase'
771 hg: unknown command 'rebase'
772 'rebase' is provided by the following extension:
772 'rebase' is provided by the following extension:
773
773
774 rebase command to move sets of revisions to a different ancestor
774 rebase command to move sets of revisions to a different ancestor
775
775
776 (use 'hg help extensions' for information on enabling extensions)
776 (use 'hg help extensions' for information on enabling extensions)
777 [255]
777 [255]
778
778
779 Make sure that we don't run afoul of the help system thinking that
779 Make sure that we don't run afoul of the help system thinking that
780 this is a section and erroring out weirdly.
780 this is a section and erroring out weirdly.
781
781
782 $ hg .log
782 $ hg .log
783 hg: unknown command '.log'
783 hg: unknown command '.log'
784 (did you mean log?)
784 (did you mean log?)
785 [255]
785 [255]
786
786
787 $ hg log.
787 $ hg log.
788 hg: unknown command 'log.'
788 hg: unknown command 'log.'
789 (did you mean log?)
789 (did you mean log?)
790 [255]
790 [255]
791 $ hg pu.lh
791 $ hg pu.lh
792 hg: unknown command 'pu.lh'
792 hg: unknown command 'pu.lh'
793 (did you mean one of pull, push?)
793 (did you mean one of pull, push?)
794 [255]
794 [255]
795
795
796 $ cat > helpext.py <<EOF
796 $ cat > helpext.py <<EOF
797 > import os
797 > import os
798 > from mercurial import commands, fancyopts, registrar
798 > from mercurial import commands, fancyopts, registrar
799 >
799 >
800 > def func(arg):
800 > def func(arg):
801 > return '%sfoo' % arg
801 > return '%sfoo' % arg
802 > class customopt(fancyopts.customopt):
802 > class customopt(fancyopts.customopt):
803 > def newstate(self, oldstate, newparam, abort):
803 > def newstate(self, oldstate, newparam, abort):
804 > return '%sbar' % oldstate
804 > return '%sbar' % oldstate
805 > cmdtable = {}
805 > cmdtable = {}
806 > command = registrar.command(cmdtable)
806 > command = registrar.command(cmdtable)
807 >
807 >
808 > @command(b'nohelp',
808 > @command(b'nohelp',
809 > [(b'', b'longdesc', 3, b'x'*67),
809 > [(b'', b'longdesc', 3, b'x'*67),
810 > (b'n', b'', None, b'normal desc'),
810 > (b'n', b'', None, b'normal desc'),
811 > (b'', b'newline', b'', b'line1\nline2'),
811 > (b'', b'newline', b'', b'line1\nline2'),
812 > (b'', b'default-off', False, b'enable X'),
812 > (b'', b'default-off', False, b'enable X'),
813 > (b'', b'default-on', True, b'enable Y'),
813 > (b'', b'default-on', True, b'enable Y'),
814 > (b'', b'callableopt', func, b'adds foo'),
814 > (b'', b'callableopt', func, b'adds foo'),
815 > (b'', b'customopt', customopt(''), b'adds bar'),
815 > (b'', b'customopt', customopt(''), b'adds bar'),
816 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
816 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
817 > b'hg nohelp',
817 > b'hg nohelp',
818 > norepo=True)
818 > norepo=True)
819 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
819 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
820 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
820 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
821 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
821 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
822 > def nohelp(ui, *args, **kwargs):
822 > def nohelp(ui, *args, **kwargs):
823 > pass
823 > pass
824 >
824 >
825 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
825 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
826 > def hashelp(ui, *args, **kwargs):
826 > def hashelp(ui, *args, **kwargs):
827 > """Extension command's help"""
827 > """Extension command's help"""
828 >
828 >
829 > def uisetup(ui):
829 > def uisetup(ui):
830 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
830 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
831 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
831 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
832 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
832 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
833 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
833 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
834 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
834 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
835 >
835 >
836 > EOF
836 > EOF
837 $ echo '[extensions]' >> $HGRCPATH
837 $ echo '[extensions]' >> $HGRCPATH
838 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
838 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
839
839
840 Test for aliases
840 Test for aliases
841
841
842 $ hg help | grep hgalias
842 $ hg help | grep hgalias
843 hgalias My doc
843 hgalias My doc
844
844
845 $ hg help hgalias
845 $ hg help hgalias
846 hg hgalias [--remote]
846 hg hgalias [--remote]
847
847
848 alias for: hg summary
848 alias for: hg summary
849
849
850 My doc
850 My doc
851
851
852 defined by: helpext
852 defined by: helpext
853
853
854 options:
854 options:
855
855
856 --remote check for push and pull
856 --remote check for push and pull
857
857
858 (some details hidden, use --verbose to show complete help)
858 (some details hidden, use --verbose to show complete help)
859 $ hg help hgaliasnodoc
859 $ hg help hgaliasnodoc
860 hg hgaliasnodoc [--remote]
860 hg hgaliasnodoc [--remote]
861
861
862 alias for: hg summary
862 alias for: hg summary
863
863
864 summarize working directory state
864 summarize working directory state
865
865
866 This generates a brief summary of the working directory state, including
866 This generates a brief summary of the working directory state, including
867 parents, branch, commit status, phase and available updates.
867 parents, branch, commit status, phase and available updates.
868
868
869 With the --remote option, this will check the default paths for incoming
869 With the --remote option, this will check the default paths for incoming
870 and outgoing changes. This can be time-consuming.
870 and outgoing changes. This can be time-consuming.
871
871
872 Returns 0 on success.
872 Returns 0 on success.
873
873
874 defined by: helpext
874 defined by: helpext
875
875
876 options:
876 options:
877
877
878 --remote check for push and pull
878 --remote check for push and pull
879
879
880 (some details hidden, use --verbose to show complete help)
880 (some details hidden, use --verbose to show complete help)
881
881
882 $ hg help shellalias
882 $ hg help shellalias
883 hg shellalias
883 hg shellalias
884
884
885 shell alias for: echo hi
885 shell alias for: echo hi
886
886
887 (no help text available)
887 (no help text available)
888
888
889 defined by: helpext
889 defined by: helpext
890
890
891 (some details hidden, use --verbose to show complete help)
891 (some details hidden, use --verbose to show complete help)
892
892
893 Test command with no help text
893 Test command with no help text
894
894
895 $ hg help nohelp
895 $ hg help nohelp
896 hg nohelp
896 hg nohelp
897
897
898 (no help text available)
898 (no help text available)
899
899
900 options:
900 options:
901
901
902 --longdesc VALUE
902 --longdesc VALUE
903 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
903 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
904 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
904 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
905 -n -- normal desc
905 -n -- normal desc
906 --newline VALUE line1 line2
906 --newline VALUE line1 line2
907 --default-off enable X
907 --default-off enable X
908 --[no-]default-on enable Y (default: on)
908 --[no-]default-on enable Y (default: on)
909 --callableopt VALUE adds foo
909 --callableopt VALUE adds foo
910 --customopt VALUE adds bar
910 --customopt VALUE adds bar
911 --customopt-withdefault VALUE adds bar (default: foo)
911 --customopt-withdefault VALUE adds bar (default: foo)
912
912
913 (some details hidden, use --verbose to show complete help)
913 (some details hidden, use --verbose to show complete help)
914
914
915 Test that default list of commands includes extension commands that have help,
915 Test that default list of commands includes extension commands that have help,
916 but not those that don't, except in verbose mode, when a keyword is passed, or
916 but not those that don't, except in verbose mode, when a keyword is passed, or
917 when help about the extension is requested.
917 when help about the extension is requested.
918
918
919 #if no-extraextensions
919 #if no-extraextensions
920
920
921 $ hg help | grep hashelp
921 $ hg help | grep hashelp
922 hashelp Extension command's help
922 hashelp Extension command's help
923 $ hg help | grep nohelp
923 $ hg help | grep nohelp
924 [1]
924 [1]
925 $ hg help -v | grep nohelp
925 $ hg help -v | grep nohelp
926 nohelp (no help text available)
926 nohelp (no help text available)
927
927
928 $ hg help -k nohelp
928 $ hg help -k nohelp
929 Commands:
929 Commands:
930
930
931 nohelp hg nohelp
931 nohelp hg nohelp
932
932
933 Extension Commands:
933 Extension Commands:
934
934
935 nohelp (no help text available)
935 nohelp (no help text available)
936
936
937 $ hg help helpext
937 $ hg help helpext
938 helpext extension - no help text available
938 helpext extension - no help text available
939
939
940 list of commands:
940 list of commands:
941
941
942 hashelp Extension command's help
942 hashelp Extension command's help
943 nohelp (no help text available)
943 nohelp (no help text available)
944
944
945 (use 'hg help -v helpext' to show built-in aliases and global options)
945 (use 'hg help -v helpext' to show built-in aliases and global options)
946
946
947 #endif
947 #endif
948
948
949 Test list of internal help commands
949 Test list of internal help commands
950
950
951 $ hg help debug
951 $ hg help debug
952 debug commands (internal and unsupported):
952 debug commands (internal and unsupported):
953
953
954 debugancestor
954 debugancestor
955 find the ancestor revision of two revisions in a given index
955 find the ancestor revision of two revisions in a given index
956 debugapplystreamclonebundle
956 debugapplystreamclonebundle
957 apply a stream clone bundle file
957 apply a stream clone bundle file
958 debugbuilddag
958 debugbuilddag
959 builds a repo with a given DAG from scratch in the current
959 builds a repo with a given DAG from scratch in the current
960 empty repo
960 empty repo
961 debugbundle lists the contents of a bundle
961 debugbundle lists the contents of a bundle
962 debugcapabilities
962 debugcapabilities
963 lists the capabilities of a remote peer
963 lists the capabilities of a remote peer
964 debugcheckstate
964 debugcheckstate
965 validate the correctness of the current dirstate
965 validate the correctness of the current dirstate
966 debugcolor show available color, effects or style
966 debugcolor show available color, effects or style
967 debugcommands
967 debugcommands
968 list all available commands and options
968 list all available commands and options
969 debugcomplete
969 debugcomplete
970 returns the completion list associated with the given command
970 returns the completion list associated with the given command
971 debugcreatestreamclonebundle
971 debugcreatestreamclonebundle
972 create a stream clone bundle file
972 create a stream clone bundle file
973 debugdag format the changelog or an index DAG as a concise textual
973 debugdag format the changelog or an index DAG as a concise textual
974 description
974 description
975 debugdata dump the contents of a data file revision
975 debugdata dump the contents of a data file revision
976 debugdate parse and display a date
976 debugdate parse and display a date
977 debugdeltachain
977 debugdeltachain
978 dump information about delta chains in a revlog
978 dump information about delta chains in a revlog
979 debugdirstate
979 debugdirstate
980 show the contents of the current dirstate
980 show the contents of the current dirstate
981 debugdiscovery
981 debugdiscovery
982 runs the changeset discovery protocol in isolation
982 runs the changeset discovery protocol in isolation
983 debugdownload
983 debugdownload
984 download a resource using Mercurial logic and config
984 download a resource using Mercurial logic and config
985 debugextensions
985 debugextensions
986 show information about active extensions
986 show information about active extensions
987 debugfileset parse and apply a fileset specification
987 debugfileset parse and apply a fileset specification
988 debugformat display format information about the current repository
988 debugformat display format information about the current repository
989 debugfsinfo show information detected about current filesystem
989 debugfsinfo show information detected about current filesystem
990 debuggetbundle
990 debuggetbundle
991 retrieves a bundle from a repo
991 retrieves a bundle from a repo
992 debugignore display the combined ignore pattern and information about
992 debugignore display the combined ignore pattern and information about
993 ignored files
993 ignored files
994 debugindex dump index data for a storage primitive
994 debugindex dump index data for a storage primitive
995 debugindexdot
995 debugindexdot
996 dump an index DAG as a graphviz dot file
996 dump an index DAG as a graphviz dot file
997 debugindexstats
997 debugindexstats
998 show stats related to the changelog index
998 show stats related to the changelog index
999 debuginstall test Mercurial installation
999 debuginstall test Mercurial installation
1000 debugknown test whether node ids are known to a repo
1000 debugknown test whether node ids are known to a repo
1001 debuglocks show or modify state of locks
1001 debuglocks show or modify state of locks
1002 debugmanifestfulltextcache
1002 debugmanifestfulltextcache
1003 show, clear or amend the contents of the manifest fulltext
1003 show, clear or amend the contents of the manifest fulltext
1004 cache
1004 cache
1005 debugmergestate
1005 debugmergestate
1006 print merge state
1006 print merge state
1007 debugnamecomplete
1007 debugnamecomplete
1008 complete "names" - tags, open branch names, bookmark names
1008 complete "names" - tags, open branch names, bookmark names
1009 debugobsolete
1009 debugobsolete
1010 create arbitrary obsolete marker
1010 create arbitrary obsolete marker
1011 debugoptADV (no help text available)
1011 debugoptADV (no help text available)
1012 debugoptDEP (no help text available)
1012 debugoptDEP (no help text available)
1013 debugoptEXP (no help text available)
1013 debugoptEXP (no help text available)
1014 debugp1copies
1015 dump copy information compared to p1
1016 debugp2copies
1017 dump copy information compared to p2
1014 debugpathcomplete
1018 debugpathcomplete
1015 complete part or all of a tracked path
1019 complete part or all of a tracked path
1016 debugpathcopies
1020 debugpathcopies
1017 show copies between two revisions
1021 show copies between two revisions
1018 debugpeer establish a connection to a peer repository
1022 debugpeer establish a connection to a peer repository
1019 debugpickmergetool
1023 debugpickmergetool
1020 examine which merge tool is chosen for specified file
1024 examine which merge tool is chosen for specified file
1021 debugpushkey access the pushkey key/value protocol
1025 debugpushkey access the pushkey key/value protocol
1022 debugpvec (no help text available)
1026 debugpvec (no help text available)
1023 debugrebuilddirstate
1027 debugrebuilddirstate
1024 rebuild the dirstate as it would look like for the given
1028 rebuild the dirstate as it would look like for the given
1025 revision
1029 revision
1026 debugrebuildfncache
1030 debugrebuildfncache
1027 rebuild the fncache file
1031 rebuild the fncache file
1028 debugrename dump rename information
1032 debugrename dump rename information
1029 debugrevlog show data and statistics about a revlog
1033 debugrevlog show data and statistics about a revlog
1030 debugrevlogindex
1034 debugrevlogindex
1031 dump the contents of a revlog index
1035 dump the contents of a revlog index
1032 debugrevspec parse and apply a revision specification
1036 debugrevspec parse and apply a revision specification
1033 debugserve run a server with advanced settings
1037 debugserve run a server with advanced settings
1034 debugsetparents
1038 debugsetparents
1035 manually set the parents of the current working directory
1039 manually set the parents of the current working directory
1036 debugssl test a secure connection to a server
1040 debugssl test a secure connection to a server
1037 debugsub (no help text available)
1041 debugsub (no help text available)
1038 debugsuccessorssets
1042 debugsuccessorssets
1039 show set of successors for revision
1043 show set of successors for revision
1040 debugtemplate
1044 debugtemplate
1041 parse and apply a template
1045 parse and apply a template
1042 debuguigetpass
1046 debuguigetpass
1043 show prompt to type password
1047 show prompt to type password
1044 debuguiprompt
1048 debuguiprompt
1045 show plain prompt
1049 show plain prompt
1046 debugupdatecaches
1050 debugupdatecaches
1047 warm all known caches in the repository
1051 warm all known caches in the repository
1048 debugupgraderepo
1052 debugupgraderepo
1049 upgrade a repository to use different features
1053 upgrade a repository to use different features
1050 debugwalk show how files match on given patterns
1054 debugwalk show how files match on given patterns
1051 debugwhyunstable
1055 debugwhyunstable
1052 explain instabilities of a changeset
1056 explain instabilities of a changeset
1053 debugwireargs
1057 debugwireargs
1054 (no help text available)
1058 (no help text available)
1055 debugwireproto
1059 debugwireproto
1056 send wire protocol commands to a server
1060 send wire protocol commands to a server
1057
1061
1058 (use 'hg help -v debug' to show built-in aliases and global options)
1062 (use 'hg help -v debug' to show built-in aliases and global options)
1059
1063
1060 internals topic renders index of available sub-topics
1064 internals topic renders index of available sub-topics
1061
1065
1062 $ hg help internals
1066 $ hg help internals
1063 Technical implementation topics
1067 Technical implementation topics
1064 """""""""""""""""""""""""""""""
1068 """""""""""""""""""""""""""""""
1065
1069
1066 To access a subtopic, use "hg help internals.{subtopic-name}"
1070 To access a subtopic, use "hg help internals.{subtopic-name}"
1067
1071
1068 bundle2 Bundle2
1072 bundle2 Bundle2
1069 bundles Bundles
1073 bundles Bundles
1070 cbor CBOR
1074 cbor CBOR
1071 censor Censor
1075 censor Censor
1072 changegroups Changegroups
1076 changegroups Changegroups
1073 config Config Registrar
1077 config Config Registrar
1074 extensions Extension API
1078 extensions Extension API
1075 requirements Repository Requirements
1079 requirements Repository Requirements
1076 revlogs Revision Logs
1080 revlogs Revision Logs
1077 wireprotocol Wire Protocol
1081 wireprotocol Wire Protocol
1078 wireprotocolrpc
1082 wireprotocolrpc
1079 Wire Protocol RPC
1083 Wire Protocol RPC
1080 wireprotocolv2
1084 wireprotocolv2
1081 Wire Protocol Version 2
1085 Wire Protocol Version 2
1082
1086
1083 sub-topics can be accessed
1087 sub-topics can be accessed
1084
1088
1085 $ hg help internals.changegroups
1089 $ hg help internals.changegroups
1086 Changegroups
1090 Changegroups
1087 """"""""""""
1091 """"""""""""
1088
1092
1089 Changegroups are representations of repository revlog data, specifically
1093 Changegroups are representations of repository revlog data, specifically
1090 the changelog data, root/flat manifest data, treemanifest data, and
1094 the changelog data, root/flat manifest data, treemanifest data, and
1091 filelogs.
1095 filelogs.
1092
1096
1093 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1097 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1094 level, versions "1" and "2" are almost exactly the same, with the only
1098 level, versions "1" and "2" are almost exactly the same, with the only
1095 difference being an additional item in the *delta header*. Version "3"
1099 difference being an additional item in the *delta header*. Version "3"
1096 adds support for storage flags in the *delta header* and optionally
1100 adds support for storage flags in the *delta header* and optionally
1097 exchanging treemanifests (enabled by setting an option on the
1101 exchanging treemanifests (enabled by setting an option on the
1098 "changegroup" part in the bundle2).
1102 "changegroup" part in the bundle2).
1099
1103
1100 Changegroups when not exchanging treemanifests consist of 3 logical
1104 Changegroups when not exchanging treemanifests consist of 3 logical
1101 segments:
1105 segments:
1102
1106
1103 +---------------------------------+
1107 +---------------------------------+
1104 | | | |
1108 | | | |
1105 | changeset | manifest | filelogs |
1109 | changeset | manifest | filelogs |
1106 | | | |
1110 | | | |
1107 | | | |
1111 | | | |
1108 +---------------------------------+
1112 +---------------------------------+
1109
1113
1110 When exchanging treemanifests, there are 4 logical segments:
1114 When exchanging treemanifests, there are 4 logical segments:
1111
1115
1112 +-------------------------------------------------+
1116 +-------------------------------------------------+
1113 | | | | |
1117 | | | | |
1114 | changeset | root | treemanifests | filelogs |
1118 | changeset | root | treemanifests | filelogs |
1115 | | manifest | | |
1119 | | manifest | | |
1116 | | | | |
1120 | | | | |
1117 +-------------------------------------------------+
1121 +-------------------------------------------------+
1118
1122
1119 The principle building block of each segment is a *chunk*. A *chunk* is a
1123 The principle building block of each segment is a *chunk*. A *chunk* is a
1120 framed piece of data:
1124 framed piece of data:
1121
1125
1122 +---------------------------------------+
1126 +---------------------------------------+
1123 | | |
1127 | | |
1124 | length | data |
1128 | length | data |
1125 | (4 bytes) | (<length - 4> bytes) |
1129 | (4 bytes) | (<length - 4> bytes) |
1126 | | |
1130 | | |
1127 +---------------------------------------+
1131 +---------------------------------------+
1128
1132
1129 All integers are big-endian signed integers. Each chunk starts with a
1133 All integers are big-endian signed integers. Each chunk starts with a
1130 32-bit integer indicating the length of the entire chunk (including the
1134 32-bit integer indicating the length of the entire chunk (including the
1131 length field itself).
1135 length field itself).
1132
1136
1133 There is a special case chunk that has a value of 0 for the length
1137 There is a special case chunk that has a value of 0 for the length
1134 ("0x00000000"). We call this an *empty chunk*.
1138 ("0x00000000"). We call this an *empty chunk*.
1135
1139
1136 Delta Groups
1140 Delta Groups
1137 ============
1141 ============
1138
1142
1139 A *delta group* expresses the content of a revlog as a series of deltas,
1143 A *delta group* expresses the content of a revlog as a series of deltas,
1140 or patches against previous revisions.
1144 or patches against previous revisions.
1141
1145
1142 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1146 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1143 to signal the end of the delta group:
1147 to signal the end of the delta group:
1144
1148
1145 +------------------------------------------------------------------------+
1149 +------------------------------------------------------------------------+
1146 | | | | | |
1150 | | | | | |
1147 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1151 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1148 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1152 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1149 | | | | | |
1153 | | | | | |
1150 +------------------------------------------------------------------------+
1154 +------------------------------------------------------------------------+
1151
1155
1152 Each *chunk*'s data consists of the following:
1156 Each *chunk*'s data consists of the following:
1153
1157
1154 +---------------------------------------+
1158 +---------------------------------------+
1155 | | |
1159 | | |
1156 | delta header | delta data |
1160 | delta header | delta data |
1157 | (various by version) | (various) |
1161 | (various by version) | (various) |
1158 | | |
1162 | | |
1159 +---------------------------------------+
1163 +---------------------------------------+
1160
1164
1161 The *delta data* is a series of *delta*s that describe a diff from an
1165 The *delta data* is a series of *delta*s that describe a diff from an
1162 existing entry (either that the recipient already has, or previously
1166 existing entry (either that the recipient already has, or previously
1163 specified in the bundle/changegroup).
1167 specified in the bundle/changegroup).
1164
1168
1165 The *delta header* is different between versions "1", "2", and "3" of the
1169 The *delta header* is different between versions "1", "2", and "3" of the
1166 changegroup format.
1170 changegroup format.
1167
1171
1168 Version 1 (headerlen=80):
1172 Version 1 (headerlen=80):
1169
1173
1170 +------------------------------------------------------+
1174 +------------------------------------------------------+
1171 | | | | |
1175 | | | | |
1172 | node | p1 node | p2 node | link node |
1176 | node | p1 node | p2 node | link node |
1173 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1177 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1174 | | | | |
1178 | | | | |
1175 +------------------------------------------------------+
1179 +------------------------------------------------------+
1176
1180
1177 Version 2 (headerlen=100):
1181 Version 2 (headerlen=100):
1178
1182
1179 +------------------------------------------------------------------+
1183 +------------------------------------------------------------------+
1180 | | | | | |
1184 | | | | | |
1181 | node | p1 node | p2 node | base node | link node |
1185 | node | p1 node | p2 node | base node | link node |
1182 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1186 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1183 | | | | | |
1187 | | | | | |
1184 +------------------------------------------------------------------+
1188 +------------------------------------------------------------------+
1185
1189
1186 Version 3 (headerlen=102):
1190 Version 3 (headerlen=102):
1187
1191
1188 +------------------------------------------------------------------------------+
1192 +------------------------------------------------------------------------------+
1189 | | | | | | |
1193 | | | | | | |
1190 | node | p1 node | p2 node | base node | link node | flags |
1194 | node | p1 node | p2 node | base node | link node | flags |
1191 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1195 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1192 | | | | | | |
1196 | | | | | | |
1193 +------------------------------------------------------------------------------+
1197 +------------------------------------------------------------------------------+
1194
1198
1195 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1199 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1196 contain a series of *delta*s, densely packed (no separators). These deltas
1200 contain a series of *delta*s, densely packed (no separators). These deltas
1197 describe a diff from an existing entry (either that the recipient already
1201 describe a diff from an existing entry (either that the recipient already
1198 has, or previously specified in the bundle/changegroup). The format is
1202 has, or previously specified in the bundle/changegroup). The format is
1199 described more fully in "hg help internals.bdiff", but briefly:
1203 described more fully in "hg help internals.bdiff", but briefly:
1200
1204
1201 +---------------------------------------------------------------+
1205 +---------------------------------------------------------------+
1202 | | | | |
1206 | | | | |
1203 | start offset | end offset | new length | content |
1207 | start offset | end offset | new length | content |
1204 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1208 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1205 | | | | |
1209 | | | | |
1206 +---------------------------------------------------------------+
1210 +---------------------------------------------------------------+
1207
1211
1208 Please note that the length field in the delta data does *not* include
1212 Please note that the length field in the delta data does *not* include
1209 itself.
1213 itself.
1210
1214
1211 In version 1, the delta is always applied against the previous node from
1215 In version 1, the delta is always applied against the previous node from
1212 the changegroup or the first parent if this is the first entry in the
1216 the changegroup or the first parent if this is the first entry in the
1213 changegroup.
1217 changegroup.
1214
1218
1215 In version 2 and up, the delta base node is encoded in the entry in the
1219 In version 2 and up, the delta base node is encoded in the entry in the
1216 changegroup. This allows the delta to be expressed against any parent,
1220 changegroup. This allows the delta to be expressed against any parent,
1217 which can result in smaller deltas and more efficient encoding of data.
1221 which can result in smaller deltas and more efficient encoding of data.
1218
1222
1219 The *flags* field holds bitwise flags affecting the processing of revision
1223 The *flags* field holds bitwise flags affecting the processing of revision
1220 data. The following flags are defined:
1224 data. The following flags are defined:
1221
1225
1222 32768
1226 32768
1223 Censored revision. The revision's fulltext has been replaced by censor
1227 Censored revision. The revision's fulltext has been replaced by censor
1224 metadata. May only occur on file revisions.
1228 metadata. May only occur on file revisions.
1225
1229
1226 16384
1230 16384
1227 Ellipsis revision. Revision hash does not match data (likely due to
1231 Ellipsis revision. Revision hash does not match data (likely due to
1228 rewritten parents).
1232 rewritten parents).
1229
1233
1230 8192
1234 8192
1231 Externally stored. The revision fulltext contains "key:value" "\n"
1235 Externally stored. The revision fulltext contains "key:value" "\n"
1232 delimited metadata defining an object stored elsewhere. Used by the LFS
1236 delimited metadata defining an object stored elsewhere. Used by the LFS
1233 extension.
1237 extension.
1234
1238
1235 For historical reasons, the integer values are identical to revlog version
1239 For historical reasons, the integer values are identical to revlog version
1236 1 per-revision storage flags and correspond to bits being set in this
1240 1 per-revision storage flags and correspond to bits being set in this
1237 2-byte field. Bits were allocated starting from the most-significant bit,
1241 2-byte field. Bits were allocated starting from the most-significant bit,
1238 hence the reverse ordering and allocation of these flags.
1242 hence the reverse ordering and allocation of these flags.
1239
1243
1240 Changeset Segment
1244 Changeset Segment
1241 =================
1245 =================
1242
1246
1243 The *changeset segment* consists of a single *delta group* holding
1247 The *changeset segment* consists of a single *delta group* holding
1244 changelog data. The *empty chunk* at the end of the *delta group* denotes
1248 changelog data. The *empty chunk* at the end of the *delta group* denotes
1245 the boundary to the *manifest segment*.
1249 the boundary to the *manifest segment*.
1246
1250
1247 Manifest Segment
1251 Manifest Segment
1248 ================
1252 ================
1249
1253
1250 The *manifest segment* consists of a single *delta group* holding manifest
1254 The *manifest segment* consists of a single *delta group* holding manifest
1251 data. If treemanifests are in use, it contains only the manifest for the
1255 data. If treemanifests are in use, it contains only the manifest for the
1252 root directory of the repository. Otherwise, it contains the entire
1256 root directory of the repository. Otherwise, it contains the entire
1253 manifest data. The *empty chunk* at the end of the *delta group* denotes
1257 manifest data. The *empty chunk* at the end of the *delta group* denotes
1254 the boundary to the next segment (either the *treemanifests segment* or
1258 the boundary to the next segment (either the *treemanifests segment* or
1255 the *filelogs segment*, depending on version and the request options).
1259 the *filelogs segment*, depending on version and the request options).
1256
1260
1257 Treemanifests Segment
1261 Treemanifests Segment
1258 ---------------------
1262 ---------------------
1259
1263
1260 The *treemanifests segment* only exists in changegroup version "3", and
1264 The *treemanifests segment* only exists in changegroup version "3", and
1261 only if the 'treemanifest' param is part of the bundle2 changegroup part
1265 only if the 'treemanifest' param is part of the bundle2 changegroup part
1262 (it is not possible to use changegroup version 3 outside of bundle2).
1266 (it is not possible to use changegroup version 3 outside of bundle2).
1263 Aside from the filenames in the *treemanifests segment* containing a
1267 Aside from the filenames in the *treemanifests segment* containing a
1264 trailing "/" character, it behaves identically to the *filelogs segment*
1268 trailing "/" character, it behaves identically to the *filelogs segment*
1265 (see below). The final sub-segment is followed by an *empty chunk*
1269 (see below). The final sub-segment is followed by an *empty chunk*
1266 (logically, a sub-segment with filename size 0). This denotes the boundary
1270 (logically, a sub-segment with filename size 0). This denotes the boundary
1267 to the *filelogs segment*.
1271 to the *filelogs segment*.
1268
1272
1269 Filelogs Segment
1273 Filelogs Segment
1270 ================
1274 ================
1271
1275
1272 The *filelogs segment* consists of multiple sub-segments, each
1276 The *filelogs segment* consists of multiple sub-segments, each
1273 corresponding to an individual file whose data is being described:
1277 corresponding to an individual file whose data is being described:
1274
1278
1275 +--------------------------------------------------+
1279 +--------------------------------------------------+
1276 | | | | | |
1280 | | | | | |
1277 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1281 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1278 | | | | | (4 bytes) |
1282 | | | | | (4 bytes) |
1279 | | | | | |
1283 | | | | | |
1280 +--------------------------------------------------+
1284 +--------------------------------------------------+
1281
1285
1282 The final filelog sub-segment is followed by an *empty chunk* (logically,
1286 The final filelog sub-segment is followed by an *empty chunk* (logically,
1283 a sub-segment with filename size 0). This denotes the end of the segment
1287 a sub-segment with filename size 0). This denotes the end of the segment
1284 and of the overall changegroup.
1288 and of the overall changegroup.
1285
1289
1286 Each filelog sub-segment consists of the following:
1290 Each filelog sub-segment consists of the following:
1287
1291
1288 +------------------------------------------------------+
1292 +------------------------------------------------------+
1289 | | | |
1293 | | | |
1290 | filename length | filename | delta group |
1294 | filename length | filename | delta group |
1291 | (4 bytes) | (<length - 4> bytes) | (various) |
1295 | (4 bytes) | (<length - 4> bytes) | (various) |
1292 | | | |
1296 | | | |
1293 +------------------------------------------------------+
1297 +------------------------------------------------------+
1294
1298
1295 That is, a *chunk* consisting of the filename (not terminated or padded)
1299 That is, a *chunk* consisting of the filename (not terminated or padded)
1296 followed by N chunks constituting the *delta group* for this file. The
1300 followed by N chunks constituting the *delta group* for this file. The
1297 *empty chunk* at the end of each *delta group* denotes the boundary to the
1301 *empty chunk* at the end of each *delta group* denotes the boundary to the
1298 next filelog sub-segment.
1302 next filelog sub-segment.
1299
1303
1300 test advanced, deprecated and experimental options are hidden in command help
1304 test advanced, deprecated and experimental options are hidden in command help
1301 $ hg help debugoptADV
1305 $ hg help debugoptADV
1302 hg debugoptADV
1306 hg debugoptADV
1303
1307
1304 (no help text available)
1308 (no help text available)
1305
1309
1306 options:
1310 options:
1307
1311
1308 (some details hidden, use --verbose to show complete help)
1312 (some details hidden, use --verbose to show complete help)
1309 $ hg help debugoptDEP
1313 $ hg help debugoptDEP
1310 hg debugoptDEP
1314 hg debugoptDEP
1311
1315
1312 (no help text available)
1316 (no help text available)
1313
1317
1314 options:
1318 options:
1315
1319
1316 (some details hidden, use --verbose to show complete help)
1320 (some details hidden, use --verbose to show complete help)
1317
1321
1318 $ hg help debugoptEXP
1322 $ hg help debugoptEXP
1319 hg debugoptEXP
1323 hg debugoptEXP
1320
1324
1321 (no help text available)
1325 (no help text available)
1322
1326
1323 options:
1327 options:
1324
1328
1325 (some details hidden, use --verbose to show complete help)
1329 (some details hidden, use --verbose to show complete help)
1326
1330
1327 test advanced, deprecated and experimental options are shown with -v
1331 test advanced, deprecated and experimental options are shown with -v
1328 $ hg help -v debugoptADV | grep aopt
1332 $ hg help -v debugoptADV | grep aopt
1329 --aopt option is (ADVANCED)
1333 --aopt option is (ADVANCED)
1330 $ hg help -v debugoptDEP | grep dopt
1334 $ hg help -v debugoptDEP | grep dopt
1331 --dopt option is (DEPRECATED)
1335 --dopt option is (DEPRECATED)
1332 $ hg help -v debugoptEXP | grep eopt
1336 $ hg help -v debugoptEXP | grep eopt
1333 --eopt option is (EXPERIMENTAL)
1337 --eopt option is (EXPERIMENTAL)
1334
1338
1335 #if gettext
1339 #if gettext
1336 test deprecated option is hidden with translation with untranslated description
1340 test deprecated option is hidden with translation with untranslated description
1337 (use many globy for not failing on changed transaction)
1341 (use many globy for not failing on changed transaction)
1338 $ LANGUAGE=sv hg help debugoptDEP
1342 $ LANGUAGE=sv hg help debugoptDEP
1339 hg debugoptDEP
1343 hg debugoptDEP
1340
1344
1341 (*) (glob)
1345 (*) (glob)
1342
1346
1343 options:
1347 options:
1344
1348
1345 (some details hidden, use --verbose to show complete help)
1349 (some details hidden, use --verbose to show complete help)
1346 #endif
1350 #endif
1347
1351
1348 Test commands that collide with topics (issue4240)
1352 Test commands that collide with topics (issue4240)
1349
1353
1350 $ hg config -hq
1354 $ hg config -hq
1351 hg config [-u] [NAME]...
1355 hg config [-u] [NAME]...
1352
1356
1353 show combined config settings from all hgrc files
1357 show combined config settings from all hgrc files
1354 $ hg showconfig -hq
1358 $ hg showconfig -hq
1355 hg config [-u] [NAME]...
1359 hg config [-u] [NAME]...
1356
1360
1357 show combined config settings from all hgrc files
1361 show combined config settings from all hgrc files
1358
1362
1359 Test a help topic
1363 Test a help topic
1360
1364
1361 $ hg help dates
1365 $ hg help dates
1362 Date Formats
1366 Date Formats
1363 """"""""""""
1367 """"""""""""
1364
1368
1365 Some commands allow the user to specify a date, e.g.:
1369 Some commands allow the user to specify a date, e.g.:
1366
1370
1367 - backout, commit, import, tag: Specify the commit date.
1371 - backout, commit, import, tag: Specify the commit date.
1368 - log, revert, update: Select revision(s) by date.
1372 - log, revert, update: Select revision(s) by date.
1369
1373
1370 Many date formats are valid. Here are some examples:
1374 Many date formats are valid. Here are some examples:
1371
1375
1372 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1376 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1373 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1377 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1374 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1378 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1375 - "Dec 6" (midnight)
1379 - "Dec 6" (midnight)
1376 - "13:18" (today assumed)
1380 - "13:18" (today assumed)
1377 - "3:39" (3:39AM assumed)
1381 - "3:39" (3:39AM assumed)
1378 - "3:39pm" (15:39)
1382 - "3:39pm" (15:39)
1379 - "2006-12-06 13:18:29" (ISO 8601 format)
1383 - "2006-12-06 13:18:29" (ISO 8601 format)
1380 - "2006-12-6 13:18"
1384 - "2006-12-6 13:18"
1381 - "2006-12-6"
1385 - "2006-12-6"
1382 - "12-6"
1386 - "12-6"
1383 - "12/6"
1387 - "12/6"
1384 - "12/6/6" (Dec 6 2006)
1388 - "12/6/6" (Dec 6 2006)
1385 - "today" (midnight)
1389 - "today" (midnight)
1386 - "yesterday" (midnight)
1390 - "yesterday" (midnight)
1387 - "now" - right now
1391 - "now" - right now
1388
1392
1389 Lastly, there is Mercurial's internal format:
1393 Lastly, there is Mercurial's internal format:
1390
1394
1391 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1395 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1392
1396
1393 This is the internal representation format for dates. The first number is
1397 This is the internal representation format for dates. The first number is
1394 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1398 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1395 is the offset of the local timezone, in seconds west of UTC (negative if
1399 is the offset of the local timezone, in seconds west of UTC (negative if
1396 the timezone is east of UTC).
1400 the timezone is east of UTC).
1397
1401
1398 The log command also accepts date ranges:
1402 The log command also accepts date ranges:
1399
1403
1400 - "<DATE" - at or before a given date/time
1404 - "<DATE" - at or before a given date/time
1401 - ">DATE" - on or after a given date/time
1405 - ">DATE" - on or after a given date/time
1402 - "DATE to DATE" - a date range, inclusive
1406 - "DATE to DATE" - a date range, inclusive
1403 - "-DAYS" - within a given number of days of today
1407 - "-DAYS" - within a given number of days of today
1404
1408
1405 Test repeated config section name
1409 Test repeated config section name
1406
1410
1407 $ hg help config.host
1411 $ hg help config.host
1408 "http_proxy.host"
1412 "http_proxy.host"
1409 Host name and (optional) port of the proxy server, for example
1413 Host name and (optional) port of the proxy server, for example
1410 "myproxy:8000".
1414 "myproxy:8000".
1411
1415
1412 "smtp.host"
1416 "smtp.host"
1413 Host name of mail server, e.g. "mail.example.com".
1417 Host name of mail server, e.g. "mail.example.com".
1414
1418
1415
1419
1416 Test section name with dot
1420 Test section name with dot
1417
1421
1418 $ hg help config.ui.username
1422 $ hg help config.ui.username
1419 "ui.username"
1423 "ui.username"
1420 The committer of a changeset created when running "commit". Typically
1424 The committer of a changeset created when running "commit". Typically
1421 a person's name and email address, e.g. "Fred Widget
1425 a person's name and email address, e.g. "Fred Widget
1422 <fred@example.com>". Environment variables in the username are
1426 <fred@example.com>". Environment variables in the username are
1423 expanded.
1427 expanded.
1424
1428
1425 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1429 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1426 empty, e.g. if the system admin set "username =" in the system hgrc,
1430 empty, e.g. if the system admin set "username =" in the system hgrc,
1427 it has to be specified manually or in a different hgrc file)
1431 it has to be specified manually or in a different hgrc file)
1428
1432
1429
1433
1430 $ hg help config.annotate.git
1434 $ hg help config.annotate.git
1431 abort: help section not found: config.annotate.git
1435 abort: help section not found: config.annotate.git
1432 [255]
1436 [255]
1433
1437
1434 $ hg help config.update.check
1438 $ hg help config.update.check
1435 "commands.update.check"
1439 "commands.update.check"
1436 Determines what level of checking 'hg update' will perform before
1440 Determines what level of checking 'hg update' will perform before
1437 moving to a destination revision. Valid values are "abort", "none",
1441 moving to a destination revision. Valid values are "abort", "none",
1438 "linear", and "noconflict". "abort" always fails if the working
1442 "linear", and "noconflict". "abort" always fails if the working
1439 directory has uncommitted changes. "none" performs no checking, and
1443 directory has uncommitted changes. "none" performs no checking, and
1440 may result in a merge with uncommitted changes. "linear" allows any
1444 may result in a merge with uncommitted changes. "linear" allows any
1441 update as long as it follows a straight line in the revision history,
1445 update as long as it follows a straight line in the revision history,
1442 and may trigger a merge with uncommitted changes. "noconflict" will
1446 and may trigger a merge with uncommitted changes. "noconflict" will
1443 allow any update which would not trigger a merge with uncommitted
1447 allow any update which would not trigger a merge with uncommitted
1444 changes, if any are present. (default: "linear")
1448 changes, if any are present. (default: "linear")
1445
1449
1446
1450
1447 $ hg help config.commands.update.check
1451 $ hg help config.commands.update.check
1448 "commands.update.check"
1452 "commands.update.check"
1449 Determines what level of checking 'hg update' will perform before
1453 Determines what level of checking 'hg update' will perform before
1450 moving to a destination revision. Valid values are "abort", "none",
1454 moving to a destination revision. Valid values are "abort", "none",
1451 "linear", and "noconflict". "abort" always fails if the working
1455 "linear", and "noconflict". "abort" always fails if the working
1452 directory has uncommitted changes. "none" performs no checking, and
1456 directory has uncommitted changes. "none" performs no checking, and
1453 may result in a merge with uncommitted changes. "linear" allows any
1457 may result in a merge with uncommitted changes. "linear" allows any
1454 update as long as it follows a straight line in the revision history,
1458 update as long as it follows a straight line in the revision history,
1455 and may trigger a merge with uncommitted changes. "noconflict" will
1459 and may trigger a merge with uncommitted changes. "noconflict" will
1456 allow any update which would not trigger a merge with uncommitted
1460 allow any update which would not trigger a merge with uncommitted
1457 changes, if any are present. (default: "linear")
1461 changes, if any are present. (default: "linear")
1458
1462
1459
1463
1460 $ hg help config.ommands.update.check
1464 $ hg help config.ommands.update.check
1461 abort: help section not found: config.ommands.update.check
1465 abort: help section not found: config.ommands.update.check
1462 [255]
1466 [255]
1463
1467
1464 Unrelated trailing paragraphs shouldn't be included
1468 Unrelated trailing paragraphs shouldn't be included
1465
1469
1466 $ hg help config.extramsg | grep '^$'
1470 $ hg help config.extramsg | grep '^$'
1467
1471
1468
1472
1469 Test capitalized section name
1473 Test capitalized section name
1470
1474
1471 $ hg help scripting.HGPLAIN > /dev/null
1475 $ hg help scripting.HGPLAIN > /dev/null
1472
1476
1473 Help subsection:
1477 Help subsection:
1474
1478
1475 $ hg help config.charsets |grep "Email example:" > /dev/null
1479 $ hg help config.charsets |grep "Email example:" > /dev/null
1476 [1]
1480 [1]
1477
1481
1478 Show nested definitions
1482 Show nested definitions
1479 ("profiling.type"[break]"ls"[break]"stat"[break])
1483 ("profiling.type"[break]"ls"[break]"stat"[break])
1480
1484
1481 $ hg help config.type | egrep '^$'|wc -l
1485 $ hg help config.type | egrep '^$'|wc -l
1482 \s*3 (re)
1486 \s*3 (re)
1483
1487
1484 $ hg help config.profiling.type.ls
1488 $ hg help config.profiling.type.ls
1485 "profiling.type.ls"
1489 "profiling.type.ls"
1486 Use Python's built-in instrumenting profiler. This profiler works on
1490 Use Python's built-in instrumenting profiler. This profiler works on
1487 all platforms, but each line number it reports is the first line of
1491 all platforms, but each line number it reports is the first line of
1488 a function. This restriction makes it difficult to identify the
1492 a function. This restriction makes it difficult to identify the
1489 expensive parts of a non-trivial function.
1493 expensive parts of a non-trivial function.
1490
1494
1491
1495
1492 Separate sections from subsections
1496 Separate sections from subsections
1493
1497
1494 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1498 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1495 "format"
1499 "format"
1496 --------
1500 --------
1497
1501
1498 "usegeneraldelta"
1502 "usegeneraldelta"
1499
1503
1500 "dotencode"
1504 "dotencode"
1501
1505
1502 "usefncache"
1506 "usefncache"
1503
1507
1504 "usestore"
1508 "usestore"
1505
1509
1506 "sparse-revlog"
1510 "sparse-revlog"
1507
1511
1508 "profiling"
1512 "profiling"
1509 -----------
1513 -----------
1510
1514
1511 "format"
1515 "format"
1512
1516
1513 "progress"
1517 "progress"
1514 ----------
1518 ----------
1515
1519
1516 "format"
1520 "format"
1517
1521
1518
1522
1519 Last item in help config.*:
1523 Last item in help config.*:
1520
1524
1521 $ hg help config.`hg help config|grep '^ "'| \
1525 $ hg help config.`hg help config|grep '^ "'| \
1522 > tail -1|sed 's![ "]*!!g'`| \
1526 > tail -1|sed 's![ "]*!!g'`| \
1523 > grep 'hg help -c config' > /dev/null
1527 > grep 'hg help -c config' > /dev/null
1524 [1]
1528 [1]
1525
1529
1526 note to use help -c for general hg help config:
1530 note to use help -c for general hg help config:
1527
1531
1528 $ hg help config |grep 'hg help -c config' > /dev/null
1532 $ hg help config |grep 'hg help -c config' > /dev/null
1529
1533
1530 Test templating help
1534 Test templating help
1531
1535
1532 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1536 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1533 desc String. The text of the changeset description.
1537 desc String. The text of the changeset description.
1534 diffstat String. Statistics of changes with the following format:
1538 diffstat String. Statistics of changes with the following format:
1535 firstline Any text. Returns the first line of text.
1539 firstline Any text. Returns the first line of text.
1536 nonempty Any text. Returns '(none)' if the string is empty.
1540 nonempty Any text. Returns '(none)' if the string is empty.
1537
1541
1538 Test deprecated items
1542 Test deprecated items
1539
1543
1540 $ hg help -v templating | grep currentbookmark
1544 $ hg help -v templating | grep currentbookmark
1541 currentbookmark
1545 currentbookmark
1542 $ hg help templating | (grep currentbookmark || true)
1546 $ hg help templating | (grep currentbookmark || true)
1543
1547
1544 Test help hooks
1548 Test help hooks
1545
1549
1546 $ cat > helphook1.py <<EOF
1550 $ cat > helphook1.py <<EOF
1547 > from mercurial import help
1551 > from mercurial import help
1548 >
1552 >
1549 > def rewrite(ui, topic, doc):
1553 > def rewrite(ui, topic, doc):
1550 > return doc + b'\nhelphook1\n'
1554 > return doc + b'\nhelphook1\n'
1551 >
1555 >
1552 > def extsetup(ui):
1556 > def extsetup(ui):
1553 > help.addtopichook(b'revisions', rewrite)
1557 > help.addtopichook(b'revisions', rewrite)
1554 > EOF
1558 > EOF
1555 $ cat > helphook2.py <<EOF
1559 $ cat > helphook2.py <<EOF
1556 > from mercurial import help
1560 > from mercurial import help
1557 >
1561 >
1558 > def rewrite(ui, topic, doc):
1562 > def rewrite(ui, topic, doc):
1559 > return doc + b'\nhelphook2\n'
1563 > return doc + b'\nhelphook2\n'
1560 >
1564 >
1561 > def extsetup(ui):
1565 > def extsetup(ui):
1562 > help.addtopichook(b'revisions', rewrite)
1566 > help.addtopichook(b'revisions', rewrite)
1563 > EOF
1567 > EOF
1564 $ echo '[extensions]' >> $HGRCPATH
1568 $ echo '[extensions]' >> $HGRCPATH
1565 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1569 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1566 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1570 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1567 $ hg help revsets | grep helphook
1571 $ hg help revsets | grep helphook
1568 helphook1
1572 helphook1
1569 helphook2
1573 helphook2
1570
1574
1571 help -c should only show debug --debug
1575 help -c should only show debug --debug
1572
1576
1573 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1577 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1574 [1]
1578 [1]
1575
1579
1576 help -c should only show deprecated for -v
1580 help -c should only show deprecated for -v
1577
1581
1578 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1582 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1579 [1]
1583 [1]
1580
1584
1581 Test -s / --system
1585 Test -s / --system
1582
1586
1583 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1587 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1584 > wc -l | sed -e 's/ //g'
1588 > wc -l | sed -e 's/ //g'
1585 0
1589 0
1586 $ hg help config.files --system unix | grep 'USER' | \
1590 $ hg help config.files --system unix | grep 'USER' | \
1587 > wc -l | sed -e 's/ //g'
1591 > wc -l | sed -e 's/ //g'
1588 0
1592 0
1589
1593
1590 Test -e / -c / -k combinations
1594 Test -e / -c / -k combinations
1591
1595
1592 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1596 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1593 Commands:
1597 Commands:
1594 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1598 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1595 Extensions:
1599 Extensions:
1596 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1600 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1597 Topics:
1601 Topics:
1598 Commands:
1602 Commands:
1599 Extensions:
1603 Extensions:
1600 Extension Commands:
1604 Extension Commands:
1601 $ hg help -c schemes
1605 $ hg help -c schemes
1602 abort: no such help topic: schemes
1606 abort: no such help topic: schemes
1603 (try 'hg help --keyword schemes')
1607 (try 'hg help --keyword schemes')
1604 [255]
1608 [255]
1605 $ hg help -e schemes |head -1
1609 $ hg help -e schemes |head -1
1606 schemes extension - extend schemes with shortcuts to repository swarms
1610 schemes extension - extend schemes with shortcuts to repository swarms
1607 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1611 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1608 Commands:
1612 Commands:
1609 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1613 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1610 Extensions:
1614 Extensions:
1611 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1615 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1612 Extensions:
1616 Extensions:
1613 Commands:
1617 Commands:
1614 $ hg help -c commit > /dev/null
1618 $ hg help -c commit > /dev/null
1615 $ hg help -e -c commit > /dev/null
1619 $ hg help -e -c commit > /dev/null
1616 $ hg help -e commit
1620 $ hg help -e commit
1617 abort: no such help topic: commit
1621 abort: no such help topic: commit
1618 (try 'hg help --keyword commit')
1622 (try 'hg help --keyword commit')
1619 [255]
1623 [255]
1620
1624
1621 Test keyword search help
1625 Test keyword search help
1622
1626
1623 $ cat > prefixedname.py <<EOF
1627 $ cat > prefixedname.py <<EOF
1624 > '''matched against word "clone"
1628 > '''matched against word "clone"
1625 > '''
1629 > '''
1626 > EOF
1630 > EOF
1627 $ echo '[extensions]' >> $HGRCPATH
1631 $ echo '[extensions]' >> $HGRCPATH
1628 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1632 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1629 $ hg help -k clone
1633 $ hg help -k clone
1630 Topics:
1634 Topics:
1631
1635
1632 config Configuration Files
1636 config Configuration Files
1633 extensions Using Additional Features
1637 extensions Using Additional Features
1634 glossary Glossary
1638 glossary Glossary
1635 phases Working with Phases
1639 phases Working with Phases
1636 subrepos Subrepositories
1640 subrepos Subrepositories
1637 urls URL Paths
1641 urls URL Paths
1638
1642
1639 Commands:
1643 Commands:
1640
1644
1641 bookmarks create a new bookmark or list existing bookmarks
1645 bookmarks create a new bookmark or list existing bookmarks
1642 clone make a copy of an existing repository
1646 clone make a copy of an existing repository
1643 paths show aliases for remote repositories
1647 paths show aliases for remote repositories
1644 pull pull changes from the specified source
1648 pull pull changes from the specified source
1645 update update working directory (or switch revisions)
1649 update update working directory (or switch revisions)
1646
1650
1647 Extensions:
1651 Extensions:
1648
1652
1649 clonebundles advertise pre-generated bundles to seed clones
1653 clonebundles advertise pre-generated bundles to seed clones
1650 narrow create clones which fetch history data for subset of files
1654 narrow create clones which fetch history data for subset of files
1651 (EXPERIMENTAL)
1655 (EXPERIMENTAL)
1652 prefixedname matched against word "clone"
1656 prefixedname matched against word "clone"
1653 relink recreates hardlinks between repository clones
1657 relink recreates hardlinks between repository clones
1654
1658
1655 Extension Commands:
1659 Extension Commands:
1656
1660
1657 qclone clone main and patch repository at same time
1661 qclone clone main and patch repository at same time
1658
1662
1659 Test unfound topic
1663 Test unfound topic
1660
1664
1661 $ hg help nonexistingtopicthatwillneverexisteverever
1665 $ hg help nonexistingtopicthatwillneverexisteverever
1662 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1666 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1663 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1667 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1664 [255]
1668 [255]
1665
1669
1666 Test unfound keyword
1670 Test unfound keyword
1667
1671
1668 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1672 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1669 abort: no matches
1673 abort: no matches
1670 (try 'hg help' for a list of topics)
1674 (try 'hg help' for a list of topics)
1671 [255]
1675 [255]
1672
1676
1673 Test omit indicating for help
1677 Test omit indicating for help
1674
1678
1675 $ cat > addverboseitems.py <<EOF
1679 $ cat > addverboseitems.py <<EOF
1676 > r'''extension to test omit indicating.
1680 > r'''extension to test omit indicating.
1677 >
1681 >
1678 > This paragraph is never omitted (for extension)
1682 > This paragraph is never omitted (for extension)
1679 >
1683 >
1680 > .. container:: verbose
1684 > .. container:: verbose
1681 >
1685 >
1682 > This paragraph is omitted,
1686 > This paragraph is omitted,
1683 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1687 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1684 >
1688 >
1685 > This paragraph is never omitted, too (for extension)
1689 > This paragraph is never omitted, too (for extension)
1686 > '''
1690 > '''
1687 > from __future__ import absolute_import
1691 > from __future__ import absolute_import
1688 > from mercurial import commands, help
1692 > from mercurial import commands, help
1689 > testtopic = br"""This paragraph is never omitted (for topic).
1693 > testtopic = br"""This paragraph is never omitted (for topic).
1690 >
1694 >
1691 > .. container:: verbose
1695 > .. container:: verbose
1692 >
1696 >
1693 > This paragraph is omitted,
1697 > This paragraph is omitted,
1694 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1698 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1695 >
1699 >
1696 > This paragraph is never omitted, too (for topic)
1700 > This paragraph is never omitted, too (for topic)
1697 > """
1701 > """
1698 > def extsetup(ui):
1702 > def extsetup(ui):
1699 > help.helptable.append(([b"topic-containing-verbose"],
1703 > help.helptable.append(([b"topic-containing-verbose"],
1700 > b"This is the topic to test omit indicating.",
1704 > b"This is the topic to test omit indicating.",
1701 > lambda ui: testtopic))
1705 > lambda ui: testtopic))
1702 > EOF
1706 > EOF
1703 $ echo '[extensions]' >> $HGRCPATH
1707 $ echo '[extensions]' >> $HGRCPATH
1704 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1708 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1705 $ hg help addverboseitems
1709 $ hg help addverboseitems
1706 addverboseitems extension - extension to test omit indicating.
1710 addverboseitems extension - extension to test omit indicating.
1707
1711
1708 This paragraph is never omitted (for extension)
1712 This paragraph is never omitted (for extension)
1709
1713
1710 This paragraph is never omitted, too (for extension)
1714 This paragraph is never omitted, too (for extension)
1711
1715
1712 (some details hidden, use --verbose to show complete help)
1716 (some details hidden, use --verbose to show complete help)
1713
1717
1714 no commands defined
1718 no commands defined
1715 $ hg help -v addverboseitems
1719 $ hg help -v addverboseitems
1716 addverboseitems extension - extension to test omit indicating.
1720 addverboseitems extension - extension to test omit indicating.
1717
1721
1718 This paragraph is never omitted (for extension)
1722 This paragraph is never omitted (for extension)
1719
1723
1720 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1724 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1721 extension)
1725 extension)
1722
1726
1723 This paragraph is never omitted, too (for extension)
1727 This paragraph is never omitted, too (for extension)
1724
1728
1725 no commands defined
1729 no commands defined
1726 $ hg help topic-containing-verbose
1730 $ hg help topic-containing-verbose
1727 This is the topic to test omit indicating.
1731 This is the topic to test omit indicating.
1728 """"""""""""""""""""""""""""""""""""""""""
1732 """"""""""""""""""""""""""""""""""""""""""
1729
1733
1730 This paragraph is never omitted (for topic).
1734 This paragraph is never omitted (for topic).
1731
1735
1732 This paragraph is never omitted, too (for topic)
1736 This paragraph is never omitted, too (for topic)
1733
1737
1734 (some details hidden, use --verbose to show complete help)
1738 (some details hidden, use --verbose to show complete help)
1735 $ hg help -v topic-containing-verbose
1739 $ hg help -v topic-containing-verbose
1736 This is the topic to test omit indicating.
1740 This is the topic to test omit indicating.
1737 """"""""""""""""""""""""""""""""""""""""""
1741 """"""""""""""""""""""""""""""""""""""""""
1738
1742
1739 This paragraph is never omitted (for topic).
1743 This paragraph is never omitted (for topic).
1740
1744
1741 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1745 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1742 topic)
1746 topic)
1743
1747
1744 This paragraph is never omitted, too (for topic)
1748 This paragraph is never omitted, too (for topic)
1745
1749
1746 Test section lookup
1750 Test section lookup
1747
1751
1748 $ hg help revset.merge
1752 $ hg help revset.merge
1749 "merge()"
1753 "merge()"
1750 Changeset is a merge changeset.
1754 Changeset is a merge changeset.
1751
1755
1752 $ hg help glossary.dag
1756 $ hg help glossary.dag
1753 DAG
1757 DAG
1754 The repository of changesets of a distributed version control system
1758 The repository of changesets of a distributed version control system
1755 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1759 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1756 of nodes and edges, where nodes correspond to changesets and edges
1760 of nodes and edges, where nodes correspond to changesets and edges
1757 imply a parent -> child relation. This graph can be visualized by
1761 imply a parent -> child relation. This graph can be visualized by
1758 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1762 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1759 limited by the requirement for children to have at most two parents.
1763 limited by the requirement for children to have at most two parents.
1760
1764
1761
1765
1762 $ hg help hgrc.paths
1766 $ hg help hgrc.paths
1763 "paths"
1767 "paths"
1764 -------
1768 -------
1765
1769
1766 Assigns symbolic names and behavior to repositories.
1770 Assigns symbolic names and behavior to repositories.
1767
1771
1768 Options are symbolic names defining the URL or directory that is the
1772 Options are symbolic names defining the URL or directory that is the
1769 location of the repository. Example:
1773 location of the repository. Example:
1770
1774
1771 [paths]
1775 [paths]
1772 my_server = https://example.com/my_repo
1776 my_server = https://example.com/my_repo
1773 local_path = /home/me/repo
1777 local_path = /home/me/repo
1774
1778
1775 These symbolic names can be used from the command line. To pull from
1779 These symbolic names can be used from the command line. To pull from
1776 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1780 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1777 local_path'.
1781 local_path'.
1778
1782
1779 Options containing colons (":") denote sub-options that can influence
1783 Options containing colons (":") denote sub-options that can influence
1780 behavior for that specific path. Example:
1784 behavior for that specific path. Example:
1781
1785
1782 [paths]
1786 [paths]
1783 my_server = https://example.com/my_path
1787 my_server = https://example.com/my_path
1784 my_server:pushurl = ssh://example.com/my_path
1788 my_server:pushurl = ssh://example.com/my_path
1785
1789
1786 The following sub-options can be defined:
1790 The following sub-options can be defined:
1787
1791
1788 "pushurl"
1792 "pushurl"
1789 The URL to use for push operations. If not defined, the location
1793 The URL to use for push operations. If not defined, the location
1790 defined by the path's main entry is used.
1794 defined by the path's main entry is used.
1791
1795
1792 "pushrev"
1796 "pushrev"
1793 A revset defining which revisions to push by default.
1797 A revset defining which revisions to push by default.
1794
1798
1795 When 'hg push' is executed without a "-r" argument, the revset defined
1799 When 'hg push' is executed without a "-r" argument, the revset defined
1796 by this sub-option is evaluated to determine what to push.
1800 by this sub-option is evaluated to determine what to push.
1797
1801
1798 For example, a value of "." will push the working directory's revision
1802 For example, a value of "." will push the working directory's revision
1799 by default.
1803 by default.
1800
1804
1801 Revsets specifying bookmarks will not result in the bookmark being
1805 Revsets specifying bookmarks will not result in the bookmark being
1802 pushed.
1806 pushed.
1803
1807
1804 The following special named paths exist:
1808 The following special named paths exist:
1805
1809
1806 "default"
1810 "default"
1807 The URL or directory to use when no source or remote is specified.
1811 The URL or directory to use when no source or remote is specified.
1808
1812
1809 'hg clone' will automatically define this path to the location the
1813 'hg clone' will automatically define this path to the location the
1810 repository was cloned from.
1814 repository was cloned from.
1811
1815
1812 "default-push"
1816 "default-push"
1813 (deprecated) The URL or directory for the default 'hg push' location.
1817 (deprecated) The URL or directory for the default 'hg push' location.
1814 "default:pushurl" should be used instead.
1818 "default:pushurl" should be used instead.
1815
1819
1816 $ hg help glossary.mcguffin
1820 $ hg help glossary.mcguffin
1817 abort: help section not found: glossary.mcguffin
1821 abort: help section not found: glossary.mcguffin
1818 [255]
1822 [255]
1819
1823
1820 $ hg help glossary.mc.guffin
1824 $ hg help glossary.mc.guffin
1821 abort: help section not found: glossary.mc.guffin
1825 abort: help section not found: glossary.mc.guffin
1822 [255]
1826 [255]
1823
1827
1824 $ hg help template.files
1828 $ hg help template.files
1825 files List of strings. All files modified, added, or removed by
1829 files List of strings. All files modified, added, or removed by
1826 this changeset.
1830 this changeset.
1827 files(pattern)
1831 files(pattern)
1828 All files of the current changeset matching the pattern. See
1832 All files of the current changeset matching the pattern. See
1829 'hg help patterns'.
1833 'hg help patterns'.
1830
1834
1831 Test section lookup by translated message
1835 Test section lookup by translated message
1832
1836
1833 str.lower() instead of encoding.lower(str) on translated message might
1837 str.lower() instead of encoding.lower(str) on translated message might
1834 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1838 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1835 as the second or later byte of multi-byte character.
1839 as the second or later byte of multi-byte character.
1836
1840
1837 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1841 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1838 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1842 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1839 replacement makes message meaningless.
1843 replacement makes message meaningless.
1840
1844
1841 This tests that section lookup by translated string isn't broken by
1845 This tests that section lookup by translated string isn't broken by
1842 such str.lower().
1846 such str.lower().
1843
1847
1844 $ "$PYTHON" <<EOF
1848 $ "$PYTHON" <<EOF
1845 > def escape(s):
1849 > def escape(s):
1846 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1850 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1847 > # translation of "record" in ja_JP.cp932
1851 > # translation of "record" in ja_JP.cp932
1848 > upper = b"\x8bL\x98^"
1852 > upper = b"\x8bL\x98^"
1849 > # str.lower()-ed section name should be treated as different one
1853 > # str.lower()-ed section name should be treated as different one
1850 > lower = b"\x8bl\x98^"
1854 > lower = b"\x8bl\x98^"
1851 > with open('ambiguous.py', 'wb') as fp:
1855 > with open('ambiguous.py', 'wb') as fp:
1852 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1856 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1853 > u'''summary of extension
1857 > u'''summary of extension
1854 >
1858 >
1855 > %s
1859 > %s
1856 > ----
1860 > ----
1857 >
1861 >
1858 > Upper name should show only this message
1862 > Upper name should show only this message
1859 >
1863 >
1860 > %s
1864 > %s
1861 > ----
1865 > ----
1862 >
1866 >
1863 > Lower name should show only this message
1867 > Lower name should show only this message
1864 >
1868 >
1865 > subsequent section
1869 > subsequent section
1866 > ------------------
1870 > ------------------
1867 >
1871 >
1868 > This should be hidden at 'hg help ambiguous' with section name.
1872 > This should be hidden at 'hg help ambiguous' with section name.
1869 > '''
1873 > '''
1870 > """ % (escape(upper), escape(lower)))
1874 > """ % (escape(upper), escape(lower)))
1871 > EOF
1875 > EOF
1872
1876
1873 $ cat >> $HGRCPATH <<EOF
1877 $ cat >> $HGRCPATH <<EOF
1874 > [extensions]
1878 > [extensions]
1875 > ambiguous = ./ambiguous.py
1879 > ambiguous = ./ambiguous.py
1876 > EOF
1880 > EOF
1877
1881
1878 $ "$PYTHON" <<EOF | sh
1882 $ "$PYTHON" <<EOF | sh
1879 > from mercurial import pycompat
1883 > from mercurial import pycompat
1880 > upper = b"\x8bL\x98^"
1884 > upper = b"\x8bL\x98^"
1881 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
1885 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
1882 > EOF
1886 > EOF
1883 \x8bL\x98^ (esc)
1887 \x8bL\x98^ (esc)
1884 ----
1888 ----
1885
1889
1886 Upper name should show only this message
1890 Upper name should show only this message
1887
1891
1888
1892
1889 $ "$PYTHON" <<EOF | sh
1893 $ "$PYTHON" <<EOF | sh
1890 > from mercurial import pycompat
1894 > from mercurial import pycompat
1891 > lower = b"\x8bl\x98^"
1895 > lower = b"\x8bl\x98^"
1892 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
1896 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
1893 > EOF
1897 > EOF
1894 \x8bl\x98^ (esc)
1898 \x8bl\x98^ (esc)
1895 ----
1899 ----
1896
1900
1897 Lower name should show only this message
1901 Lower name should show only this message
1898
1902
1899
1903
1900 $ cat >> $HGRCPATH <<EOF
1904 $ cat >> $HGRCPATH <<EOF
1901 > [extensions]
1905 > [extensions]
1902 > ambiguous = !
1906 > ambiguous = !
1903 > EOF
1907 > EOF
1904
1908
1905 Show help content of disabled extensions
1909 Show help content of disabled extensions
1906
1910
1907 $ cat >> $HGRCPATH <<EOF
1911 $ cat >> $HGRCPATH <<EOF
1908 > [extensions]
1912 > [extensions]
1909 > ambiguous = !./ambiguous.py
1913 > ambiguous = !./ambiguous.py
1910 > EOF
1914 > EOF
1911 $ hg help -e ambiguous
1915 $ hg help -e ambiguous
1912 ambiguous extension - (no help text available)
1916 ambiguous extension - (no help text available)
1913
1917
1914 (use 'hg help extensions' for information on enabling extensions)
1918 (use 'hg help extensions' for information on enabling extensions)
1915
1919
1916 Test dynamic list of merge tools only shows up once
1920 Test dynamic list of merge tools only shows up once
1917 $ hg help merge-tools
1921 $ hg help merge-tools
1918 Merge Tools
1922 Merge Tools
1919 """""""""""
1923 """""""""""
1920
1924
1921 To merge files Mercurial uses merge tools.
1925 To merge files Mercurial uses merge tools.
1922
1926
1923 A merge tool combines two different versions of a file into a merged file.
1927 A merge tool combines two different versions of a file into a merged file.
1924 Merge tools are given the two files and the greatest common ancestor of
1928 Merge tools are given the two files and the greatest common ancestor of
1925 the two file versions, so they can determine the changes made on both
1929 the two file versions, so they can determine the changes made on both
1926 branches.
1930 branches.
1927
1931
1928 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1932 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1929 backout' and in several extensions.
1933 backout' and in several extensions.
1930
1934
1931 Usually, the merge tool tries to automatically reconcile the files by
1935 Usually, the merge tool tries to automatically reconcile the files by
1932 combining all non-overlapping changes that occurred separately in the two
1936 combining all non-overlapping changes that occurred separately in the two
1933 different evolutions of the same initial base file. Furthermore, some
1937 different evolutions of the same initial base file. Furthermore, some
1934 interactive merge programs make it easier to manually resolve conflicting
1938 interactive merge programs make it easier to manually resolve conflicting
1935 merges, either in a graphical way, or by inserting some conflict markers.
1939 merges, either in a graphical way, or by inserting some conflict markers.
1936 Mercurial does not include any interactive merge programs but relies on
1940 Mercurial does not include any interactive merge programs but relies on
1937 external tools for that.
1941 external tools for that.
1938
1942
1939 Available merge tools
1943 Available merge tools
1940 =====================
1944 =====================
1941
1945
1942 External merge tools and their properties are configured in the merge-
1946 External merge tools and their properties are configured in the merge-
1943 tools configuration section - see hgrc(5) - but they can often just be
1947 tools configuration section - see hgrc(5) - but they can often just be
1944 named by their executable.
1948 named by their executable.
1945
1949
1946 A merge tool is generally usable if its executable can be found on the
1950 A merge tool is generally usable if its executable can be found on the
1947 system and if it can handle the merge. The executable is found if it is an
1951 system and if it can handle the merge. The executable is found if it is an
1948 absolute or relative executable path or the name of an application in the
1952 absolute or relative executable path or the name of an application in the
1949 executable search path. The tool is assumed to be able to handle the merge
1953 executable search path. The tool is assumed to be able to handle the merge
1950 if it can handle symlinks if the file is a symlink, if it can handle
1954 if it can handle symlinks if the file is a symlink, if it can handle
1951 binary files if the file is binary, and if a GUI is available if the tool
1955 binary files if the file is binary, and if a GUI is available if the tool
1952 requires a GUI.
1956 requires a GUI.
1953
1957
1954 There are some internal merge tools which can be used. The internal merge
1958 There are some internal merge tools which can be used. The internal merge
1955 tools are:
1959 tools are:
1956
1960
1957 ":dump"
1961 ":dump"
1958 Creates three versions of the files to merge, containing the contents of
1962 Creates three versions of the files to merge, containing the contents of
1959 local, other and base. These files can then be used to perform a merge
1963 local, other and base. These files can then be used to perform a merge
1960 manually. If the file to be merged is named "a.txt", these files will
1964 manually. If the file to be merged is named "a.txt", these files will
1961 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1965 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1962 they will be placed in the same directory as "a.txt".
1966 they will be placed in the same directory as "a.txt".
1963
1967
1964 This implies premerge. Therefore, files aren't dumped, if premerge runs
1968 This implies premerge. Therefore, files aren't dumped, if premerge runs
1965 successfully. Use :forcedump to forcibly write files out.
1969 successfully. Use :forcedump to forcibly write files out.
1966
1970
1967 (actual capabilities: binary, symlink)
1971 (actual capabilities: binary, symlink)
1968
1972
1969 ":fail"
1973 ":fail"
1970 Rather than attempting to merge files that were modified on both
1974 Rather than attempting to merge files that were modified on both
1971 branches, it marks them as unresolved. The resolve command must be used
1975 branches, it marks them as unresolved. The resolve command must be used
1972 to resolve these conflicts.
1976 to resolve these conflicts.
1973
1977
1974 (actual capabilities: binary, symlink)
1978 (actual capabilities: binary, symlink)
1975
1979
1976 ":forcedump"
1980 ":forcedump"
1977 Creates three versions of the files as same as :dump, but omits
1981 Creates three versions of the files as same as :dump, but omits
1978 premerge.
1982 premerge.
1979
1983
1980 (actual capabilities: binary, symlink)
1984 (actual capabilities: binary, symlink)
1981
1985
1982 ":local"
1986 ":local"
1983 Uses the local 'p1()' version of files as the merged version.
1987 Uses the local 'p1()' version of files as the merged version.
1984
1988
1985 (actual capabilities: binary, symlink)
1989 (actual capabilities: binary, symlink)
1986
1990
1987 ":merge"
1991 ":merge"
1988 Uses the internal non-interactive simple merge algorithm for merging
1992 Uses the internal non-interactive simple merge algorithm for merging
1989 files. It will fail if there are any conflicts and leave markers in the
1993 files. It will fail if there are any conflicts and leave markers in the
1990 partially merged file. Markers will have two sections, one for each side
1994 partially merged file. Markers will have two sections, one for each side
1991 of merge.
1995 of merge.
1992
1996
1993 ":merge-local"
1997 ":merge-local"
1994 Like :merge, but resolve all conflicts non-interactively in favor of the
1998 Like :merge, but resolve all conflicts non-interactively in favor of the
1995 local 'p1()' changes.
1999 local 'p1()' changes.
1996
2000
1997 ":merge-other"
2001 ":merge-other"
1998 Like :merge, but resolve all conflicts non-interactively in favor of the
2002 Like :merge, but resolve all conflicts non-interactively in favor of the
1999 other 'p2()' changes.
2003 other 'p2()' changes.
2000
2004
2001 ":merge3"
2005 ":merge3"
2002 Uses the internal non-interactive simple merge algorithm for merging
2006 Uses the internal non-interactive simple merge algorithm for merging
2003 files. It will fail if there are any conflicts and leave markers in the
2007 files. It will fail if there are any conflicts and leave markers in the
2004 partially merged file. Marker will have three sections, one from each
2008 partially merged file. Marker will have three sections, one from each
2005 side of the merge and one for the base content.
2009 side of the merge and one for the base content.
2006
2010
2007 ":other"
2011 ":other"
2008 Uses the other 'p2()' version of files as the merged version.
2012 Uses the other 'p2()' version of files as the merged version.
2009
2013
2010 (actual capabilities: binary, symlink)
2014 (actual capabilities: binary, symlink)
2011
2015
2012 ":prompt"
2016 ":prompt"
2013 Asks the user which of the local 'p1()' or the other 'p2()' version to
2017 Asks the user which of the local 'p1()' or the other 'p2()' version to
2014 keep as the merged version.
2018 keep as the merged version.
2015
2019
2016 (actual capabilities: binary, symlink)
2020 (actual capabilities: binary, symlink)
2017
2021
2018 ":tagmerge"
2022 ":tagmerge"
2019 Uses the internal tag merge algorithm (experimental).
2023 Uses the internal tag merge algorithm (experimental).
2020
2024
2021 ":union"
2025 ":union"
2022 Uses the internal non-interactive simple merge algorithm for merging
2026 Uses the internal non-interactive simple merge algorithm for merging
2023 files. It will use both left and right sides for conflict regions. No
2027 files. It will use both left and right sides for conflict regions. No
2024 markers are inserted.
2028 markers are inserted.
2025
2029
2026 Internal tools are always available and do not require a GUI but will by
2030 Internal tools are always available and do not require a GUI but will by
2027 default not handle symlinks or binary files. See next section for detail
2031 default not handle symlinks or binary files. See next section for detail
2028 about "actual capabilities" described above.
2032 about "actual capabilities" described above.
2029
2033
2030 Choosing a merge tool
2034 Choosing a merge tool
2031 =====================
2035 =====================
2032
2036
2033 Mercurial uses these rules when deciding which merge tool to use:
2037 Mercurial uses these rules when deciding which merge tool to use:
2034
2038
2035 1. If a tool has been specified with the --tool option to merge or
2039 1. If a tool has been specified with the --tool option to merge or
2036 resolve, it is used. If it is the name of a tool in the merge-tools
2040 resolve, it is used. If it is the name of a tool in the merge-tools
2037 configuration, its configuration is used. Otherwise the specified tool
2041 configuration, its configuration is used. Otherwise the specified tool
2038 must be executable by the shell.
2042 must be executable by the shell.
2039 2. If the "HGMERGE" environment variable is present, its value is used and
2043 2. If the "HGMERGE" environment variable is present, its value is used and
2040 must be executable by the shell.
2044 must be executable by the shell.
2041 3. If the filename of the file to be merged matches any of the patterns in
2045 3. If the filename of the file to be merged matches any of the patterns in
2042 the merge-patterns configuration section, the first usable merge tool
2046 the merge-patterns configuration section, the first usable merge tool
2043 corresponding to a matching pattern is used.
2047 corresponding to a matching pattern is used.
2044 4. If ui.merge is set it will be considered next. If the value is not the
2048 4. If ui.merge is set it will be considered next. If the value is not the
2045 name of a configured tool, the specified value is used and must be
2049 name of a configured tool, the specified value is used and must be
2046 executable by the shell. Otherwise the named tool is used if it is
2050 executable by the shell. Otherwise the named tool is used if it is
2047 usable.
2051 usable.
2048 5. If any usable merge tools are present in the merge-tools configuration
2052 5. If any usable merge tools are present in the merge-tools configuration
2049 section, the one with the highest priority is used.
2053 section, the one with the highest priority is used.
2050 6. If a program named "hgmerge" can be found on the system, it is used -
2054 6. If a program named "hgmerge" can be found on the system, it is used -
2051 but it will by default not be used for symlinks and binary files.
2055 but it will by default not be used for symlinks and binary files.
2052 7. If the file to be merged is not binary and is not a symlink, then
2056 7. If the file to be merged is not binary and is not a symlink, then
2053 internal ":merge" is used.
2057 internal ":merge" is used.
2054 8. Otherwise, ":prompt" is used.
2058 8. Otherwise, ":prompt" is used.
2055
2059
2056 For historical reason, Mercurial treats merge tools as below while
2060 For historical reason, Mercurial treats merge tools as below while
2057 examining rules above.
2061 examining rules above.
2058
2062
2059 step specified via binary symlink
2063 step specified via binary symlink
2060 ----------------------------------
2064 ----------------------------------
2061 1. --tool o/o o/o
2065 1. --tool o/o o/o
2062 2. HGMERGE o/o o/o
2066 2. HGMERGE o/o o/o
2063 3. merge-patterns o/o(*) x/?(*)
2067 3. merge-patterns o/o(*) x/?(*)
2064 4. ui.merge x/?(*) x/?(*)
2068 4. ui.merge x/?(*) x/?(*)
2065
2069
2066 Each capability column indicates Mercurial behavior for internal/external
2070 Each capability column indicates Mercurial behavior for internal/external
2067 merge tools at examining each rule.
2071 merge tools at examining each rule.
2068
2072
2069 - "o": "assume that a tool has capability"
2073 - "o": "assume that a tool has capability"
2070 - "x": "assume that a tool does not have capability"
2074 - "x": "assume that a tool does not have capability"
2071 - "?": "check actual capability of a tool"
2075 - "?": "check actual capability of a tool"
2072
2076
2073 If "merge.strict-capability-check" configuration is true, Mercurial checks
2077 If "merge.strict-capability-check" configuration is true, Mercurial checks
2074 capabilities of merge tools strictly in (*) cases above (= each capability
2078 capabilities of merge tools strictly in (*) cases above (= each capability
2075 column becomes "?/?"). It is false by default for backward compatibility.
2079 column becomes "?/?"). It is false by default for backward compatibility.
2076
2080
2077 Note:
2081 Note:
2078 After selecting a merge program, Mercurial will by default attempt to
2082 After selecting a merge program, Mercurial will by default attempt to
2079 merge the files using a simple merge algorithm first. Only if it
2083 merge the files using a simple merge algorithm first. Only if it
2080 doesn't succeed because of conflicting changes will Mercurial actually
2084 doesn't succeed because of conflicting changes will Mercurial actually
2081 execute the merge program. Whether to use the simple merge algorithm
2085 execute the merge program. Whether to use the simple merge algorithm
2082 first can be controlled by the premerge setting of the merge tool.
2086 first can be controlled by the premerge setting of the merge tool.
2083 Premerge is enabled by default unless the file is binary or a symlink.
2087 Premerge is enabled by default unless the file is binary or a symlink.
2084
2088
2085 See the merge-tools and ui sections of hgrc(5) for details on the
2089 See the merge-tools and ui sections of hgrc(5) for details on the
2086 configuration of merge tools.
2090 configuration of merge tools.
2087
2091
2088 Compression engines listed in `hg help bundlespec`
2092 Compression engines listed in `hg help bundlespec`
2089
2093
2090 $ hg help bundlespec | grep gzip
2094 $ hg help bundlespec | grep gzip
2091 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2095 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2092 An algorithm that produces smaller bundles than "gzip".
2096 An algorithm that produces smaller bundles than "gzip".
2093 This engine will likely produce smaller bundles than "gzip" but will be
2097 This engine will likely produce smaller bundles than "gzip" but will be
2094 "gzip"
2098 "gzip"
2095 better compression than "gzip". It also frequently yields better (?)
2099 better compression than "gzip". It also frequently yields better (?)
2096
2100
2097 Test usage of section marks in help documents
2101 Test usage of section marks in help documents
2098
2102
2099 $ cd "$TESTDIR"/../doc
2103 $ cd "$TESTDIR"/../doc
2100 $ "$PYTHON" check-seclevel.py
2104 $ "$PYTHON" check-seclevel.py
2101 $ cd $TESTTMP
2105 $ cd $TESTTMP
2102
2106
2103 #if serve
2107 #if serve
2104
2108
2105 Test the help pages in hgweb.
2109 Test the help pages in hgweb.
2106
2110
2107 Dish up an empty repo; serve it cold.
2111 Dish up an empty repo; serve it cold.
2108
2112
2109 $ hg init "$TESTTMP/test"
2113 $ hg init "$TESTTMP/test"
2110 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2114 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2111 $ cat hg.pid >> $DAEMON_PIDS
2115 $ cat hg.pid >> $DAEMON_PIDS
2112
2116
2113 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2117 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2114 200 Script output follows
2118 200 Script output follows
2115
2119
2116 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2120 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2117 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2121 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2118 <head>
2122 <head>
2119 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2123 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2120 <meta name="robots" content="index, nofollow" />
2124 <meta name="robots" content="index, nofollow" />
2121 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2125 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2122 <script type="text/javascript" src="/static/mercurial.js"></script>
2126 <script type="text/javascript" src="/static/mercurial.js"></script>
2123
2127
2124 <title>Help: Index</title>
2128 <title>Help: Index</title>
2125 </head>
2129 </head>
2126 <body>
2130 <body>
2127
2131
2128 <div class="container">
2132 <div class="container">
2129 <div class="menu">
2133 <div class="menu">
2130 <div class="logo">
2134 <div class="logo">
2131 <a href="https://mercurial-scm.org/">
2135 <a href="https://mercurial-scm.org/">
2132 <img src="/static/hglogo.png" alt="mercurial" /></a>
2136 <img src="/static/hglogo.png" alt="mercurial" /></a>
2133 </div>
2137 </div>
2134 <ul>
2138 <ul>
2135 <li><a href="/shortlog">log</a></li>
2139 <li><a href="/shortlog">log</a></li>
2136 <li><a href="/graph">graph</a></li>
2140 <li><a href="/graph">graph</a></li>
2137 <li><a href="/tags">tags</a></li>
2141 <li><a href="/tags">tags</a></li>
2138 <li><a href="/bookmarks">bookmarks</a></li>
2142 <li><a href="/bookmarks">bookmarks</a></li>
2139 <li><a href="/branches">branches</a></li>
2143 <li><a href="/branches">branches</a></li>
2140 </ul>
2144 </ul>
2141 <ul>
2145 <ul>
2142 <li class="active">help</li>
2146 <li class="active">help</li>
2143 </ul>
2147 </ul>
2144 </div>
2148 </div>
2145
2149
2146 <div class="main">
2150 <div class="main">
2147 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2151 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2148
2152
2149 <form class="search" action="/log">
2153 <form class="search" action="/log">
2150
2154
2151 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2155 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2152 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2156 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2153 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2157 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2154 </form>
2158 </form>
2155 <table class="bigtable">
2159 <table class="bigtable">
2156 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2160 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2157
2161
2158 <tr><td>
2162 <tr><td>
2159 <a href="/help/bundlespec">
2163 <a href="/help/bundlespec">
2160 bundlespec
2164 bundlespec
2161 </a>
2165 </a>
2162 </td><td>
2166 </td><td>
2163 Bundle File Formats
2167 Bundle File Formats
2164 </td></tr>
2168 </td></tr>
2165 <tr><td>
2169 <tr><td>
2166 <a href="/help/color">
2170 <a href="/help/color">
2167 color
2171 color
2168 </a>
2172 </a>
2169 </td><td>
2173 </td><td>
2170 Colorizing Outputs
2174 Colorizing Outputs
2171 </td></tr>
2175 </td></tr>
2172 <tr><td>
2176 <tr><td>
2173 <a href="/help/config">
2177 <a href="/help/config">
2174 config
2178 config
2175 </a>
2179 </a>
2176 </td><td>
2180 </td><td>
2177 Configuration Files
2181 Configuration Files
2178 </td></tr>
2182 </td></tr>
2179 <tr><td>
2183 <tr><td>
2180 <a href="/help/dates">
2184 <a href="/help/dates">
2181 dates
2185 dates
2182 </a>
2186 </a>
2183 </td><td>
2187 </td><td>
2184 Date Formats
2188 Date Formats
2185 </td></tr>
2189 </td></tr>
2186 <tr><td>
2190 <tr><td>
2187 <a href="/help/deprecated">
2191 <a href="/help/deprecated">
2188 deprecated
2192 deprecated
2189 </a>
2193 </a>
2190 </td><td>
2194 </td><td>
2191 Deprecated Features
2195 Deprecated Features
2192 </td></tr>
2196 </td></tr>
2193 <tr><td>
2197 <tr><td>
2194 <a href="/help/diffs">
2198 <a href="/help/diffs">
2195 diffs
2199 diffs
2196 </a>
2200 </a>
2197 </td><td>
2201 </td><td>
2198 Diff Formats
2202 Diff Formats
2199 </td></tr>
2203 </td></tr>
2200 <tr><td>
2204 <tr><td>
2201 <a href="/help/environment">
2205 <a href="/help/environment">
2202 environment
2206 environment
2203 </a>
2207 </a>
2204 </td><td>
2208 </td><td>
2205 Environment Variables
2209 Environment Variables
2206 </td></tr>
2210 </td></tr>
2207 <tr><td>
2211 <tr><td>
2208 <a href="/help/extensions">
2212 <a href="/help/extensions">
2209 extensions
2213 extensions
2210 </a>
2214 </a>
2211 </td><td>
2215 </td><td>
2212 Using Additional Features
2216 Using Additional Features
2213 </td></tr>
2217 </td></tr>
2214 <tr><td>
2218 <tr><td>
2215 <a href="/help/filesets">
2219 <a href="/help/filesets">
2216 filesets
2220 filesets
2217 </a>
2221 </a>
2218 </td><td>
2222 </td><td>
2219 Specifying File Sets
2223 Specifying File Sets
2220 </td></tr>
2224 </td></tr>
2221 <tr><td>
2225 <tr><td>
2222 <a href="/help/flags">
2226 <a href="/help/flags">
2223 flags
2227 flags
2224 </a>
2228 </a>
2225 </td><td>
2229 </td><td>
2226 Command-line flags
2230 Command-line flags
2227 </td></tr>
2231 </td></tr>
2228 <tr><td>
2232 <tr><td>
2229 <a href="/help/glossary">
2233 <a href="/help/glossary">
2230 glossary
2234 glossary
2231 </a>
2235 </a>
2232 </td><td>
2236 </td><td>
2233 Glossary
2237 Glossary
2234 </td></tr>
2238 </td></tr>
2235 <tr><td>
2239 <tr><td>
2236 <a href="/help/hgignore">
2240 <a href="/help/hgignore">
2237 hgignore
2241 hgignore
2238 </a>
2242 </a>
2239 </td><td>
2243 </td><td>
2240 Syntax for Mercurial Ignore Files
2244 Syntax for Mercurial Ignore Files
2241 </td></tr>
2245 </td></tr>
2242 <tr><td>
2246 <tr><td>
2243 <a href="/help/hgweb">
2247 <a href="/help/hgweb">
2244 hgweb
2248 hgweb
2245 </a>
2249 </a>
2246 </td><td>
2250 </td><td>
2247 Configuring hgweb
2251 Configuring hgweb
2248 </td></tr>
2252 </td></tr>
2249 <tr><td>
2253 <tr><td>
2250 <a href="/help/internals">
2254 <a href="/help/internals">
2251 internals
2255 internals
2252 </a>
2256 </a>
2253 </td><td>
2257 </td><td>
2254 Technical implementation topics
2258 Technical implementation topics
2255 </td></tr>
2259 </td></tr>
2256 <tr><td>
2260 <tr><td>
2257 <a href="/help/merge-tools">
2261 <a href="/help/merge-tools">
2258 merge-tools
2262 merge-tools
2259 </a>
2263 </a>
2260 </td><td>
2264 </td><td>
2261 Merge Tools
2265 Merge Tools
2262 </td></tr>
2266 </td></tr>
2263 <tr><td>
2267 <tr><td>
2264 <a href="/help/pager">
2268 <a href="/help/pager">
2265 pager
2269 pager
2266 </a>
2270 </a>
2267 </td><td>
2271 </td><td>
2268 Pager Support
2272 Pager Support
2269 </td></tr>
2273 </td></tr>
2270 <tr><td>
2274 <tr><td>
2271 <a href="/help/patterns">
2275 <a href="/help/patterns">
2272 patterns
2276 patterns
2273 </a>
2277 </a>
2274 </td><td>
2278 </td><td>
2275 File Name Patterns
2279 File Name Patterns
2276 </td></tr>
2280 </td></tr>
2277 <tr><td>
2281 <tr><td>
2278 <a href="/help/phases">
2282 <a href="/help/phases">
2279 phases
2283 phases
2280 </a>
2284 </a>
2281 </td><td>
2285 </td><td>
2282 Working with Phases
2286 Working with Phases
2283 </td></tr>
2287 </td></tr>
2284 <tr><td>
2288 <tr><td>
2285 <a href="/help/revisions">
2289 <a href="/help/revisions">
2286 revisions
2290 revisions
2287 </a>
2291 </a>
2288 </td><td>
2292 </td><td>
2289 Specifying Revisions
2293 Specifying Revisions
2290 </td></tr>
2294 </td></tr>
2291 <tr><td>
2295 <tr><td>
2292 <a href="/help/scripting">
2296 <a href="/help/scripting">
2293 scripting
2297 scripting
2294 </a>
2298 </a>
2295 </td><td>
2299 </td><td>
2296 Using Mercurial from scripts and automation
2300 Using Mercurial from scripts and automation
2297 </td></tr>
2301 </td></tr>
2298 <tr><td>
2302 <tr><td>
2299 <a href="/help/subrepos">
2303 <a href="/help/subrepos">
2300 subrepos
2304 subrepos
2301 </a>
2305 </a>
2302 </td><td>
2306 </td><td>
2303 Subrepositories
2307 Subrepositories
2304 </td></tr>
2308 </td></tr>
2305 <tr><td>
2309 <tr><td>
2306 <a href="/help/templating">
2310 <a href="/help/templating">
2307 templating
2311 templating
2308 </a>
2312 </a>
2309 </td><td>
2313 </td><td>
2310 Template Usage
2314 Template Usage
2311 </td></tr>
2315 </td></tr>
2312 <tr><td>
2316 <tr><td>
2313 <a href="/help/urls">
2317 <a href="/help/urls">
2314 urls
2318 urls
2315 </a>
2319 </a>
2316 </td><td>
2320 </td><td>
2317 URL Paths
2321 URL Paths
2318 </td></tr>
2322 </td></tr>
2319 <tr><td>
2323 <tr><td>
2320 <a href="/help/topic-containing-verbose">
2324 <a href="/help/topic-containing-verbose">
2321 topic-containing-verbose
2325 topic-containing-verbose
2322 </a>
2326 </a>
2323 </td><td>
2327 </td><td>
2324 This is the topic to test omit indicating.
2328 This is the topic to test omit indicating.
2325 </td></tr>
2329 </td></tr>
2326
2330
2327
2331
2328 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2332 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2329
2333
2330 <tr><td>
2334 <tr><td>
2331 <a href="/help/add">
2335 <a href="/help/add">
2332 add
2336 add
2333 </a>
2337 </a>
2334 </td><td>
2338 </td><td>
2335 add the specified files on the next commit
2339 add the specified files on the next commit
2336 </td></tr>
2340 </td></tr>
2337 <tr><td>
2341 <tr><td>
2338 <a href="/help/annotate">
2342 <a href="/help/annotate">
2339 annotate
2343 annotate
2340 </a>
2344 </a>
2341 </td><td>
2345 </td><td>
2342 show changeset information by line for each file
2346 show changeset information by line for each file
2343 </td></tr>
2347 </td></tr>
2344 <tr><td>
2348 <tr><td>
2345 <a href="/help/clone">
2349 <a href="/help/clone">
2346 clone
2350 clone
2347 </a>
2351 </a>
2348 </td><td>
2352 </td><td>
2349 make a copy of an existing repository
2353 make a copy of an existing repository
2350 </td></tr>
2354 </td></tr>
2351 <tr><td>
2355 <tr><td>
2352 <a href="/help/commit">
2356 <a href="/help/commit">
2353 commit
2357 commit
2354 </a>
2358 </a>
2355 </td><td>
2359 </td><td>
2356 commit the specified files or all outstanding changes
2360 commit the specified files or all outstanding changes
2357 </td></tr>
2361 </td></tr>
2358 <tr><td>
2362 <tr><td>
2359 <a href="/help/diff">
2363 <a href="/help/diff">
2360 diff
2364 diff
2361 </a>
2365 </a>
2362 </td><td>
2366 </td><td>
2363 diff repository (or selected files)
2367 diff repository (or selected files)
2364 </td></tr>
2368 </td></tr>
2365 <tr><td>
2369 <tr><td>
2366 <a href="/help/export">
2370 <a href="/help/export">
2367 export
2371 export
2368 </a>
2372 </a>
2369 </td><td>
2373 </td><td>
2370 dump the header and diffs for one or more changesets
2374 dump the header and diffs for one or more changesets
2371 </td></tr>
2375 </td></tr>
2372 <tr><td>
2376 <tr><td>
2373 <a href="/help/forget">
2377 <a href="/help/forget">
2374 forget
2378 forget
2375 </a>
2379 </a>
2376 </td><td>
2380 </td><td>
2377 forget the specified files on the next commit
2381 forget the specified files on the next commit
2378 </td></tr>
2382 </td></tr>
2379 <tr><td>
2383 <tr><td>
2380 <a href="/help/init">
2384 <a href="/help/init">
2381 init
2385 init
2382 </a>
2386 </a>
2383 </td><td>
2387 </td><td>
2384 create a new repository in the given directory
2388 create a new repository in the given directory
2385 </td></tr>
2389 </td></tr>
2386 <tr><td>
2390 <tr><td>
2387 <a href="/help/log">
2391 <a href="/help/log">
2388 log
2392 log
2389 </a>
2393 </a>
2390 </td><td>
2394 </td><td>
2391 show revision history of entire repository or files
2395 show revision history of entire repository or files
2392 </td></tr>
2396 </td></tr>
2393 <tr><td>
2397 <tr><td>
2394 <a href="/help/merge">
2398 <a href="/help/merge">
2395 merge
2399 merge
2396 </a>
2400 </a>
2397 </td><td>
2401 </td><td>
2398 merge another revision into working directory
2402 merge another revision into working directory
2399 </td></tr>
2403 </td></tr>
2400 <tr><td>
2404 <tr><td>
2401 <a href="/help/pull">
2405 <a href="/help/pull">
2402 pull
2406 pull
2403 </a>
2407 </a>
2404 </td><td>
2408 </td><td>
2405 pull changes from the specified source
2409 pull changes from the specified source
2406 </td></tr>
2410 </td></tr>
2407 <tr><td>
2411 <tr><td>
2408 <a href="/help/push">
2412 <a href="/help/push">
2409 push
2413 push
2410 </a>
2414 </a>
2411 </td><td>
2415 </td><td>
2412 push changes to the specified destination
2416 push changes to the specified destination
2413 </td></tr>
2417 </td></tr>
2414 <tr><td>
2418 <tr><td>
2415 <a href="/help/remove">
2419 <a href="/help/remove">
2416 remove
2420 remove
2417 </a>
2421 </a>
2418 </td><td>
2422 </td><td>
2419 remove the specified files on the next commit
2423 remove the specified files on the next commit
2420 </td></tr>
2424 </td></tr>
2421 <tr><td>
2425 <tr><td>
2422 <a href="/help/serve">
2426 <a href="/help/serve">
2423 serve
2427 serve
2424 </a>
2428 </a>
2425 </td><td>
2429 </td><td>
2426 start stand-alone webserver
2430 start stand-alone webserver
2427 </td></tr>
2431 </td></tr>
2428 <tr><td>
2432 <tr><td>
2429 <a href="/help/status">
2433 <a href="/help/status">
2430 status
2434 status
2431 </a>
2435 </a>
2432 </td><td>
2436 </td><td>
2433 show changed files in the working directory
2437 show changed files in the working directory
2434 </td></tr>
2438 </td></tr>
2435 <tr><td>
2439 <tr><td>
2436 <a href="/help/summary">
2440 <a href="/help/summary">
2437 summary
2441 summary
2438 </a>
2442 </a>
2439 </td><td>
2443 </td><td>
2440 summarize working directory state
2444 summarize working directory state
2441 </td></tr>
2445 </td></tr>
2442 <tr><td>
2446 <tr><td>
2443 <a href="/help/update">
2447 <a href="/help/update">
2444 update
2448 update
2445 </a>
2449 </a>
2446 </td><td>
2450 </td><td>
2447 update working directory (or switch revisions)
2451 update working directory (or switch revisions)
2448 </td></tr>
2452 </td></tr>
2449
2453
2450
2454
2451
2455
2452 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2456 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2453
2457
2454 <tr><td>
2458 <tr><td>
2455 <a href="/help/addremove">
2459 <a href="/help/addremove">
2456 addremove
2460 addremove
2457 </a>
2461 </a>
2458 </td><td>
2462 </td><td>
2459 add all new files, delete all missing files
2463 add all new files, delete all missing files
2460 </td></tr>
2464 </td></tr>
2461 <tr><td>
2465 <tr><td>
2462 <a href="/help/archive">
2466 <a href="/help/archive">
2463 archive
2467 archive
2464 </a>
2468 </a>
2465 </td><td>
2469 </td><td>
2466 create an unversioned archive of a repository revision
2470 create an unversioned archive of a repository revision
2467 </td></tr>
2471 </td></tr>
2468 <tr><td>
2472 <tr><td>
2469 <a href="/help/backout">
2473 <a href="/help/backout">
2470 backout
2474 backout
2471 </a>
2475 </a>
2472 </td><td>
2476 </td><td>
2473 reverse effect of earlier changeset
2477 reverse effect of earlier changeset
2474 </td></tr>
2478 </td></tr>
2475 <tr><td>
2479 <tr><td>
2476 <a href="/help/bisect">
2480 <a href="/help/bisect">
2477 bisect
2481 bisect
2478 </a>
2482 </a>
2479 </td><td>
2483 </td><td>
2480 subdivision search of changesets
2484 subdivision search of changesets
2481 </td></tr>
2485 </td></tr>
2482 <tr><td>
2486 <tr><td>
2483 <a href="/help/bookmarks">
2487 <a href="/help/bookmarks">
2484 bookmarks
2488 bookmarks
2485 </a>
2489 </a>
2486 </td><td>
2490 </td><td>
2487 create a new bookmark or list existing bookmarks
2491 create a new bookmark or list existing bookmarks
2488 </td></tr>
2492 </td></tr>
2489 <tr><td>
2493 <tr><td>
2490 <a href="/help/branch">
2494 <a href="/help/branch">
2491 branch
2495 branch
2492 </a>
2496 </a>
2493 </td><td>
2497 </td><td>
2494 set or show the current branch name
2498 set or show the current branch name
2495 </td></tr>
2499 </td></tr>
2496 <tr><td>
2500 <tr><td>
2497 <a href="/help/branches">
2501 <a href="/help/branches">
2498 branches
2502 branches
2499 </a>
2503 </a>
2500 </td><td>
2504 </td><td>
2501 list repository named branches
2505 list repository named branches
2502 </td></tr>
2506 </td></tr>
2503 <tr><td>
2507 <tr><td>
2504 <a href="/help/bundle">
2508 <a href="/help/bundle">
2505 bundle
2509 bundle
2506 </a>
2510 </a>
2507 </td><td>
2511 </td><td>
2508 create a bundle file
2512 create a bundle file
2509 </td></tr>
2513 </td></tr>
2510 <tr><td>
2514 <tr><td>
2511 <a href="/help/cat">
2515 <a href="/help/cat">
2512 cat
2516 cat
2513 </a>
2517 </a>
2514 </td><td>
2518 </td><td>
2515 output the current or given revision of files
2519 output the current or given revision of files
2516 </td></tr>
2520 </td></tr>
2517 <tr><td>
2521 <tr><td>
2518 <a href="/help/config">
2522 <a href="/help/config">
2519 config
2523 config
2520 </a>
2524 </a>
2521 </td><td>
2525 </td><td>
2522 show combined config settings from all hgrc files
2526 show combined config settings from all hgrc files
2523 </td></tr>
2527 </td></tr>
2524 <tr><td>
2528 <tr><td>
2525 <a href="/help/copy">
2529 <a href="/help/copy">
2526 copy
2530 copy
2527 </a>
2531 </a>
2528 </td><td>
2532 </td><td>
2529 mark files as copied for the next commit
2533 mark files as copied for the next commit
2530 </td></tr>
2534 </td></tr>
2531 <tr><td>
2535 <tr><td>
2532 <a href="/help/files">
2536 <a href="/help/files">
2533 files
2537 files
2534 </a>
2538 </a>
2535 </td><td>
2539 </td><td>
2536 list tracked files
2540 list tracked files
2537 </td></tr>
2541 </td></tr>
2538 <tr><td>
2542 <tr><td>
2539 <a href="/help/graft">
2543 <a href="/help/graft">
2540 graft
2544 graft
2541 </a>
2545 </a>
2542 </td><td>
2546 </td><td>
2543 copy changes from other branches onto the current branch
2547 copy changes from other branches onto the current branch
2544 </td></tr>
2548 </td></tr>
2545 <tr><td>
2549 <tr><td>
2546 <a href="/help/grep">
2550 <a href="/help/grep">
2547 grep
2551 grep
2548 </a>
2552 </a>
2549 </td><td>
2553 </td><td>
2550 search revision history for a pattern in specified files
2554 search revision history for a pattern in specified files
2551 </td></tr>
2555 </td></tr>
2552 <tr><td>
2556 <tr><td>
2553 <a href="/help/hashelp">
2557 <a href="/help/hashelp">
2554 hashelp
2558 hashelp
2555 </a>
2559 </a>
2556 </td><td>
2560 </td><td>
2557 Extension command's help
2561 Extension command's help
2558 </td></tr>
2562 </td></tr>
2559 <tr><td>
2563 <tr><td>
2560 <a href="/help/heads">
2564 <a href="/help/heads">
2561 heads
2565 heads
2562 </a>
2566 </a>
2563 </td><td>
2567 </td><td>
2564 show branch heads
2568 show branch heads
2565 </td></tr>
2569 </td></tr>
2566 <tr><td>
2570 <tr><td>
2567 <a href="/help/help">
2571 <a href="/help/help">
2568 help
2572 help
2569 </a>
2573 </a>
2570 </td><td>
2574 </td><td>
2571 show help for a given topic or a help overview
2575 show help for a given topic or a help overview
2572 </td></tr>
2576 </td></tr>
2573 <tr><td>
2577 <tr><td>
2574 <a href="/help/hgalias">
2578 <a href="/help/hgalias">
2575 hgalias
2579 hgalias
2576 </a>
2580 </a>
2577 </td><td>
2581 </td><td>
2578 My doc
2582 My doc
2579 </td></tr>
2583 </td></tr>
2580 <tr><td>
2584 <tr><td>
2581 <a href="/help/hgaliasnodoc">
2585 <a href="/help/hgaliasnodoc">
2582 hgaliasnodoc
2586 hgaliasnodoc
2583 </a>
2587 </a>
2584 </td><td>
2588 </td><td>
2585 summarize working directory state
2589 summarize working directory state
2586 </td></tr>
2590 </td></tr>
2587 <tr><td>
2591 <tr><td>
2588 <a href="/help/identify">
2592 <a href="/help/identify">
2589 identify
2593 identify
2590 </a>
2594 </a>
2591 </td><td>
2595 </td><td>
2592 identify the working directory or specified revision
2596 identify the working directory or specified revision
2593 </td></tr>
2597 </td></tr>
2594 <tr><td>
2598 <tr><td>
2595 <a href="/help/import">
2599 <a href="/help/import">
2596 import
2600 import
2597 </a>
2601 </a>
2598 </td><td>
2602 </td><td>
2599 import an ordered set of patches
2603 import an ordered set of patches
2600 </td></tr>
2604 </td></tr>
2601 <tr><td>
2605 <tr><td>
2602 <a href="/help/incoming">
2606 <a href="/help/incoming">
2603 incoming
2607 incoming
2604 </a>
2608 </a>
2605 </td><td>
2609 </td><td>
2606 show new changesets found in source
2610 show new changesets found in source
2607 </td></tr>
2611 </td></tr>
2608 <tr><td>
2612 <tr><td>
2609 <a href="/help/manifest">
2613 <a href="/help/manifest">
2610 manifest
2614 manifest
2611 </a>
2615 </a>
2612 </td><td>
2616 </td><td>
2613 output the current or given revision of the project manifest
2617 output the current or given revision of the project manifest
2614 </td></tr>
2618 </td></tr>
2615 <tr><td>
2619 <tr><td>
2616 <a href="/help/nohelp">
2620 <a href="/help/nohelp">
2617 nohelp
2621 nohelp
2618 </a>
2622 </a>
2619 </td><td>
2623 </td><td>
2620 (no help text available)
2624 (no help text available)
2621 </td></tr>
2625 </td></tr>
2622 <tr><td>
2626 <tr><td>
2623 <a href="/help/outgoing">
2627 <a href="/help/outgoing">
2624 outgoing
2628 outgoing
2625 </a>
2629 </a>
2626 </td><td>
2630 </td><td>
2627 show changesets not found in the destination
2631 show changesets not found in the destination
2628 </td></tr>
2632 </td></tr>
2629 <tr><td>
2633 <tr><td>
2630 <a href="/help/paths">
2634 <a href="/help/paths">
2631 paths
2635 paths
2632 </a>
2636 </a>
2633 </td><td>
2637 </td><td>
2634 show aliases for remote repositories
2638 show aliases for remote repositories
2635 </td></tr>
2639 </td></tr>
2636 <tr><td>
2640 <tr><td>
2637 <a href="/help/phase">
2641 <a href="/help/phase">
2638 phase
2642 phase
2639 </a>
2643 </a>
2640 </td><td>
2644 </td><td>
2641 set or show the current phase name
2645 set or show the current phase name
2642 </td></tr>
2646 </td></tr>
2643 <tr><td>
2647 <tr><td>
2644 <a href="/help/recover">
2648 <a href="/help/recover">
2645 recover
2649 recover
2646 </a>
2650 </a>
2647 </td><td>
2651 </td><td>
2648 roll back an interrupted transaction
2652 roll back an interrupted transaction
2649 </td></tr>
2653 </td></tr>
2650 <tr><td>
2654 <tr><td>
2651 <a href="/help/rename">
2655 <a href="/help/rename">
2652 rename
2656 rename
2653 </a>
2657 </a>
2654 </td><td>
2658 </td><td>
2655 rename files; equivalent of copy + remove
2659 rename files; equivalent of copy + remove
2656 </td></tr>
2660 </td></tr>
2657 <tr><td>
2661 <tr><td>
2658 <a href="/help/resolve">
2662 <a href="/help/resolve">
2659 resolve
2663 resolve
2660 </a>
2664 </a>
2661 </td><td>
2665 </td><td>
2662 redo merges or set/view the merge status of files
2666 redo merges or set/view the merge status of files
2663 </td></tr>
2667 </td></tr>
2664 <tr><td>
2668 <tr><td>
2665 <a href="/help/revert">
2669 <a href="/help/revert">
2666 revert
2670 revert
2667 </a>
2671 </a>
2668 </td><td>
2672 </td><td>
2669 restore files to their checkout state
2673 restore files to their checkout state
2670 </td></tr>
2674 </td></tr>
2671 <tr><td>
2675 <tr><td>
2672 <a href="/help/root">
2676 <a href="/help/root">
2673 root
2677 root
2674 </a>
2678 </a>
2675 </td><td>
2679 </td><td>
2676 print the root (top) of the current working directory
2680 print the root (top) of the current working directory
2677 </td></tr>
2681 </td></tr>
2678 <tr><td>
2682 <tr><td>
2679 <a href="/help/shellalias">
2683 <a href="/help/shellalias">
2680 shellalias
2684 shellalias
2681 </a>
2685 </a>
2682 </td><td>
2686 </td><td>
2683 (no help text available)
2687 (no help text available)
2684 </td></tr>
2688 </td></tr>
2685 <tr><td>
2689 <tr><td>
2686 <a href="/help/tag">
2690 <a href="/help/tag">
2687 tag
2691 tag
2688 </a>
2692 </a>
2689 </td><td>
2693 </td><td>
2690 add one or more tags for the current or given revision
2694 add one or more tags for the current or given revision
2691 </td></tr>
2695 </td></tr>
2692 <tr><td>
2696 <tr><td>
2693 <a href="/help/tags">
2697 <a href="/help/tags">
2694 tags
2698 tags
2695 </a>
2699 </a>
2696 </td><td>
2700 </td><td>
2697 list repository tags
2701 list repository tags
2698 </td></tr>
2702 </td></tr>
2699 <tr><td>
2703 <tr><td>
2700 <a href="/help/unbundle">
2704 <a href="/help/unbundle">
2701 unbundle
2705 unbundle
2702 </a>
2706 </a>
2703 </td><td>
2707 </td><td>
2704 apply one or more bundle files
2708 apply one or more bundle files
2705 </td></tr>
2709 </td></tr>
2706 <tr><td>
2710 <tr><td>
2707 <a href="/help/verify">
2711 <a href="/help/verify">
2708 verify
2712 verify
2709 </a>
2713 </a>
2710 </td><td>
2714 </td><td>
2711 verify the integrity of the repository
2715 verify the integrity of the repository
2712 </td></tr>
2716 </td></tr>
2713 <tr><td>
2717 <tr><td>
2714 <a href="/help/version">
2718 <a href="/help/version">
2715 version
2719 version
2716 </a>
2720 </a>
2717 </td><td>
2721 </td><td>
2718 output version and copyright information
2722 output version and copyright information
2719 </td></tr>
2723 </td></tr>
2720
2724
2721
2725
2722 </table>
2726 </table>
2723 </div>
2727 </div>
2724 </div>
2728 </div>
2725
2729
2726
2730
2727
2731
2728 </body>
2732 </body>
2729 </html>
2733 </html>
2730
2734
2731
2735
2732 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2736 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2733 200 Script output follows
2737 200 Script output follows
2734
2738
2735 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2739 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2736 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2740 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2737 <head>
2741 <head>
2738 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2742 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2739 <meta name="robots" content="index, nofollow" />
2743 <meta name="robots" content="index, nofollow" />
2740 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2744 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2741 <script type="text/javascript" src="/static/mercurial.js"></script>
2745 <script type="text/javascript" src="/static/mercurial.js"></script>
2742
2746
2743 <title>Help: add</title>
2747 <title>Help: add</title>
2744 </head>
2748 </head>
2745 <body>
2749 <body>
2746
2750
2747 <div class="container">
2751 <div class="container">
2748 <div class="menu">
2752 <div class="menu">
2749 <div class="logo">
2753 <div class="logo">
2750 <a href="https://mercurial-scm.org/">
2754 <a href="https://mercurial-scm.org/">
2751 <img src="/static/hglogo.png" alt="mercurial" /></a>
2755 <img src="/static/hglogo.png" alt="mercurial" /></a>
2752 </div>
2756 </div>
2753 <ul>
2757 <ul>
2754 <li><a href="/shortlog">log</a></li>
2758 <li><a href="/shortlog">log</a></li>
2755 <li><a href="/graph">graph</a></li>
2759 <li><a href="/graph">graph</a></li>
2756 <li><a href="/tags">tags</a></li>
2760 <li><a href="/tags">tags</a></li>
2757 <li><a href="/bookmarks">bookmarks</a></li>
2761 <li><a href="/bookmarks">bookmarks</a></li>
2758 <li><a href="/branches">branches</a></li>
2762 <li><a href="/branches">branches</a></li>
2759 </ul>
2763 </ul>
2760 <ul>
2764 <ul>
2761 <li class="active"><a href="/help">help</a></li>
2765 <li class="active"><a href="/help">help</a></li>
2762 </ul>
2766 </ul>
2763 </div>
2767 </div>
2764
2768
2765 <div class="main">
2769 <div class="main">
2766 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2770 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2767 <h3>Help: add</h3>
2771 <h3>Help: add</h3>
2768
2772
2769 <form class="search" action="/log">
2773 <form class="search" action="/log">
2770
2774
2771 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2775 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2772 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2776 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2773 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2777 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2774 </form>
2778 </form>
2775 <div id="doc">
2779 <div id="doc">
2776 <p>
2780 <p>
2777 hg add [OPTION]... [FILE]...
2781 hg add [OPTION]... [FILE]...
2778 </p>
2782 </p>
2779 <p>
2783 <p>
2780 add the specified files on the next commit
2784 add the specified files on the next commit
2781 </p>
2785 </p>
2782 <p>
2786 <p>
2783 Schedule files to be version controlled and added to the
2787 Schedule files to be version controlled and added to the
2784 repository.
2788 repository.
2785 </p>
2789 </p>
2786 <p>
2790 <p>
2787 The files will be added to the repository at the next commit. To
2791 The files will be added to the repository at the next commit. To
2788 undo an add before that, see 'hg forget'.
2792 undo an add before that, see 'hg forget'.
2789 </p>
2793 </p>
2790 <p>
2794 <p>
2791 If no names are given, add all files to the repository (except
2795 If no names are given, add all files to the repository (except
2792 files matching &quot;.hgignore&quot;).
2796 files matching &quot;.hgignore&quot;).
2793 </p>
2797 </p>
2794 <p>
2798 <p>
2795 Examples:
2799 Examples:
2796 </p>
2800 </p>
2797 <ul>
2801 <ul>
2798 <li> New (unknown) files are added automatically by 'hg add':
2802 <li> New (unknown) files are added automatically by 'hg add':
2799 <pre>
2803 <pre>
2800 \$ ls (re)
2804 \$ ls (re)
2801 foo.c
2805 foo.c
2802 \$ hg status (re)
2806 \$ hg status (re)
2803 ? foo.c
2807 ? foo.c
2804 \$ hg add (re)
2808 \$ hg add (re)
2805 adding foo.c
2809 adding foo.c
2806 \$ hg status (re)
2810 \$ hg status (re)
2807 A foo.c
2811 A foo.c
2808 </pre>
2812 </pre>
2809 <li> Specific files to be added can be specified:
2813 <li> Specific files to be added can be specified:
2810 <pre>
2814 <pre>
2811 \$ ls (re)
2815 \$ ls (re)
2812 bar.c foo.c
2816 bar.c foo.c
2813 \$ hg status (re)
2817 \$ hg status (re)
2814 ? bar.c
2818 ? bar.c
2815 ? foo.c
2819 ? foo.c
2816 \$ hg add bar.c (re)
2820 \$ hg add bar.c (re)
2817 \$ hg status (re)
2821 \$ hg status (re)
2818 A bar.c
2822 A bar.c
2819 ? foo.c
2823 ? foo.c
2820 </pre>
2824 </pre>
2821 </ul>
2825 </ul>
2822 <p>
2826 <p>
2823 Returns 0 if all files are successfully added.
2827 Returns 0 if all files are successfully added.
2824 </p>
2828 </p>
2825 <p>
2829 <p>
2826 options ([+] can be repeated):
2830 options ([+] can be repeated):
2827 </p>
2831 </p>
2828 <table>
2832 <table>
2829 <tr><td>-I</td>
2833 <tr><td>-I</td>
2830 <td>--include PATTERN [+]</td>
2834 <td>--include PATTERN [+]</td>
2831 <td>include names matching the given patterns</td></tr>
2835 <td>include names matching the given patterns</td></tr>
2832 <tr><td>-X</td>
2836 <tr><td>-X</td>
2833 <td>--exclude PATTERN [+]</td>
2837 <td>--exclude PATTERN [+]</td>
2834 <td>exclude names matching the given patterns</td></tr>
2838 <td>exclude names matching the given patterns</td></tr>
2835 <tr><td>-S</td>
2839 <tr><td>-S</td>
2836 <td>--subrepos</td>
2840 <td>--subrepos</td>
2837 <td>recurse into subrepositories</td></tr>
2841 <td>recurse into subrepositories</td></tr>
2838 <tr><td>-n</td>
2842 <tr><td>-n</td>
2839 <td>--dry-run</td>
2843 <td>--dry-run</td>
2840 <td>do not perform actions, just print output</td></tr>
2844 <td>do not perform actions, just print output</td></tr>
2841 </table>
2845 </table>
2842 <p>
2846 <p>
2843 global options ([+] can be repeated):
2847 global options ([+] can be repeated):
2844 </p>
2848 </p>
2845 <table>
2849 <table>
2846 <tr><td>-R</td>
2850 <tr><td>-R</td>
2847 <td>--repository REPO</td>
2851 <td>--repository REPO</td>
2848 <td>repository root directory or name of overlay bundle file</td></tr>
2852 <td>repository root directory or name of overlay bundle file</td></tr>
2849 <tr><td></td>
2853 <tr><td></td>
2850 <td>--cwd DIR</td>
2854 <td>--cwd DIR</td>
2851 <td>change working directory</td></tr>
2855 <td>change working directory</td></tr>
2852 <tr><td>-y</td>
2856 <tr><td>-y</td>
2853 <td>--noninteractive</td>
2857 <td>--noninteractive</td>
2854 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2858 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2855 <tr><td>-q</td>
2859 <tr><td>-q</td>
2856 <td>--quiet</td>
2860 <td>--quiet</td>
2857 <td>suppress output</td></tr>
2861 <td>suppress output</td></tr>
2858 <tr><td>-v</td>
2862 <tr><td>-v</td>
2859 <td>--verbose</td>
2863 <td>--verbose</td>
2860 <td>enable additional output</td></tr>
2864 <td>enable additional output</td></tr>
2861 <tr><td></td>
2865 <tr><td></td>
2862 <td>--color TYPE</td>
2866 <td>--color TYPE</td>
2863 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2867 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2864 <tr><td></td>
2868 <tr><td></td>
2865 <td>--config CONFIG [+]</td>
2869 <td>--config CONFIG [+]</td>
2866 <td>set/override config option (use 'section.name=value')</td></tr>
2870 <td>set/override config option (use 'section.name=value')</td></tr>
2867 <tr><td></td>
2871 <tr><td></td>
2868 <td>--debug</td>
2872 <td>--debug</td>
2869 <td>enable debugging output</td></tr>
2873 <td>enable debugging output</td></tr>
2870 <tr><td></td>
2874 <tr><td></td>
2871 <td>--debugger</td>
2875 <td>--debugger</td>
2872 <td>start debugger</td></tr>
2876 <td>start debugger</td></tr>
2873 <tr><td></td>
2877 <tr><td></td>
2874 <td>--encoding ENCODE</td>
2878 <td>--encoding ENCODE</td>
2875 <td>set the charset encoding (default: ascii)</td></tr>
2879 <td>set the charset encoding (default: ascii)</td></tr>
2876 <tr><td></td>
2880 <tr><td></td>
2877 <td>--encodingmode MODE</td>
2881 <td>--encodingmode MODE</td>
2878 <td>set the charset encoding mode (default: strict)</td></tr>
2882 <td>set the charset encoding mode (default: strict)</td></tr>
2879 <tr><td></td>
2883 <tr><td></td>
2880 <td>--traceback</td>
2884 <td>--traceback</td>
2881 <td>always print a traceback on exception</td></tr>
2885 <td>always print a traceback on exception</td></tr>
2882 <tr><td></td>
2886 <tr><td></td>
2883 <td>--time</td>
2887 <td>--time</td>
2884 <td>time how long the command takes</td></tr>
2888 <td>time how long the command takes</td></tr>
2885 <tr><td></td>
2889 <tr><td></td>
2886 <td>--profile</td>
2890 <td>--profile</td>
2887 <td>print command execution profile</td></tr>
2891 <td>print command execution profile</td></tr>
2888 <tr><td></td>
2892 <tr><td></td>
2889 <td>--version</td>
2893 <td>--version</td>
2890 <td>output version information and exit</td></tr>
2894 <td>output version information and exit</td></tr>
2891 <tr><td>-h</td>
2895 <tr><td>-h</td>
2892 <td>--help</td>
2896 <td>--help</td>
2893 <td>display help and exit</td></tr>
2897 <td>display help and exit</td></tr>
2894 <tr><td></td>
2898 <tr><td></td>
2895 <td>--hidden</td>
2899 <td>--hidden</td>
2896 <td>consider hidden changesets</td></tr>
2900 <td>consider hidden changesets</td></tr>
2897 <tr><td></td>
2901 <tr><td></td>
2898 <td>--pager TYPE</td>
2902 <td>--pager TYPE</td>
2899 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2903 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2900 </table>
2904 </table>
2901
2905
2902 </div>
2906 </div>
2903 </div>
2907 </div>
2904 </div>
2908 </div>
2905
2909
2906
2910
2907
2911
2908 </body>
2912 </body>
2909 </html>
2913 </html>
2910
2914
2911
2915
2912 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2916 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2913 200 Script output follows
2917 200 Script output follows
2914
2918
2915 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2919 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2916 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2920 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2917 <head>
2921 <head>
2918 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2922 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2919 <meta name="robots" content="index, nofollow" />
2923 <meta name="robots" content="index, nofollow" />
2920 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2924 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2921 <script type="text/javascript" src="/static/mercurial.js"></script>
2925 <script type="text/javascript" src="/static/mercurial.js"></script>
2922
2926
2923 <title>Help: remove</title>
2927 <title>Help: remove</title>
2924 </head>
2928 </head>
2925 <body>
2929 <body>
2926
2930
2927 <div class="container">
2931 <div class="container">
2928 <div class="menu">
2932 <div class="menu">
2929 <div class="logo">
2933 <div class="logo">
2930 <a href="https://mercurial-scm.org/">
2934 <a href="https://mercurial-scm.org/">
2931 <img src="/static/hglogo.png" alt="mercurial" /></a>
2935 <img src="/static/hglogo.png" alt="mercurial" /></a>
2932 </div>
2936 </div>
2933 <ul>
2937 <ul>
2934 <li><a href="/shortlog">log</a></li>
2938 <li><a href="/shortlog">log</a></li>
2935 <li><a href="/graph">graph</a></li>
2939 <li><a href="/graph">graph</a></li>
2936 <li><a href="/tags">tags</a></li>
2940 <li><a href="/tags">tags</a></li>
2937 <li><a href="/bookmarks">bookmarks</a></li>
2941 <li><a href="/bookmarks">bookmarks</a></li>
2938 <li><a href="/branches">branches</a></li>
2942 <li><a href="/branches">branches</a></li>
2939 </ul>
2943 </ul>
2940 <ul>
2944 <ul>
2941 <li class="active"><a href="/help">help</a></li>
2945 <li class="active"><a href="/help">help</a></li>
2942 </ul>
2946 </ul>
2943 </div>
2947 </div>
2944
2948
2945 <div class="main">
2949 <div class="main">
2946 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2950 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2947 <h3>Help: remove</h3>
2951 <h3>Help: remove</h3>
2948
2952
2949 <form class="search" action="/log">
2953 <form class="search" action="/log">
2950
2954
2951 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2955 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2952 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2956 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2953 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2957 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2954 </form>
2958 </form>
2955 <div id="doc">
2959 <div id="doc">
2956 <p>
2960 <p>
2957 hg remove [OPTION]... FILE...
2961 hg remove [OPTION]... FILE...
2958 </p>
2962 </p>
2959 <p>
2963 <p>
2960 aliases: rm
2964 aliases: rm
2961 </p>
2965 </p>
2962 <p>
2966 <p>
2963 remove the specified files on the next commit
2967 remove the specified files on the next commit
2964 </p>
2968 </p>
2965 <p>
2969 <p>
2966 Schedule the indicated files for removal from the current branch.
2970 Schedule the indicated files for removal from the current branch.
2967 </p>
2971 </p>
2968 <p>
2972 <p>
2969 This command schedules the files to be removed at the next commit.
2973 This command schedules the files to be removed at the next commit.
2970 To undo a remove before that, see 'hg revert'. To undo added
2974 To undo a remove before that, see 'hg revert'. To undo added
2971 files, see 'hg forget'.
2975 files, see 'hg forget'.
2972 </p>
2976 </p>
2973 <p>
2977 <p>
2974 -A/--after can be used to remove only files that have already
2978 -A/--after can be used to remove only files that have already
2975 been deleted, -f/--force can be used to force deletion, and -Af
2979 been deleted, -f/--force can be used to force deletion, and -Af
2976 can be used to remove files from the next revision without
2980 can be used to remove files from the next revision without
2977 deleting them from the working directory.
2981 deleting them from the working directory.
2978 </p>
2982 </p>
2979 <p>
2983 <p>
2980 The following table details the behavior of remove for different
2984 The following table details the behavior of remove for different
2981 file states (columns) and option combinations (rows). The file
2985 file states (columns) and option combinations (rows). The file
2982 states are Added [A], Clean [C], Modified [M] and Missing [!]
2986 states are Added [A], Clean [C], Modified [M] and Missing [!]
2983 (as reported by 'hg status'). The actions are Warn, Remove
2987 (as reported by 'hg status'). The actions are Warn, Remove
2984 (from branch) and Delete (from disk):
2988 (from branch) and Delete (from disk):
2985 </p>
2989 </p>
2986 <table>
2990 <table>
2987 <tr><td>opt/state</td>
2991 <tr><td>opt/state</td>
2988 <td>A</td>
2992 <td>A</td>
2989 <td>C</td>
2993 <td>C</td>
2990 <td>M</td>
2994 <td>M</td>
2991 <td>!</td></tr>
2995 <td>!</td></tr>
2992 <tr><td>none</td>
2996 <tr><td>none</td>
2993 <td>W</td>
2997 <td>W</td>
2994 <td>RD</td>
2998 <td>RD</td>
2995 <td>W</td>
2999 <td>W</td>
2996 <td>R</td></tr>
3000 <td>R</td></tr>
2997 <tr><td>-f</td>
3001 <tr><td>-f</td>
2998 <td>R</td>
3002 <td>R</td>
2999 <td>RD</td>
3003 <td>RD</td>
3000 <td>RD</td>
3004 <td>RD</td>
3001 <td>R</td></tr>
3005 <td>R</td></tr>
3002 <tr><td>-A</td>
3006 <tr><td>-A</td>
3003 <td>W</td>
3007 <td>W</td>
3004 <td>W</td>
3008 <td>W</td>
3005 <td>W</td>
3009 <td>W</td>
3006 <td>R</td></tr>
3010 <td>R</td></tr>
3007 <tr><td>-Af</td>
3011 <tr><td>-Af</td>
3008 <td>R</td>
3012 <td>R</td>
3009 <td>R</td>
3013 <td>R</td>
3010 <td>R</td>
3014 <td>R</td>
3011 <td>R</td></tr>
3015 <td>R</td></tr>
3012 </table>
3016 </table>
3013 <p>
3017 <p>
3014 <b>Note:</b>
3018 <b>Note:</b>
3015 </p>
3019 </p>
3016 <p>
3020 <p>
3017 'hg remove' never deletes files in Added [A] state from the
3021 'hg remove' never deletes files in Added [A] state from the
3018 working directory, not even if &quot;--force&quot; is specified.
3022 working directory, not even if &quot;--force&quot; is specified.
3019 </p>
3023 </p>
3020 <p>
3024 <p>
3021 Returns 0 on success, 1 if any warnings encountered.
3025 Returns 0 on success, 1 if any warnings encountered.
3022 </p>
3026 </p>
3023 <p>
3027 <p>
3024 options ([+] can be repeated):
3028 options ([+] can be repeated):
3025 </p>
3029 </p>
3026 <table>
3030 <table>
3027 <tr><td>-A</td>
3031 <tr><td>-A</td>
3028 <td>--after</td>
3032 <td>--after</td>
3029 <td>record delete for missing files</td></tr>
3033 <td>record delete for missing files</td></tr>
3030 <tr><td>-f</td>
3034 <tr><td>-f</td>
3031 <td>--force</td>
3035 <td>--force</td>
3032 <td>forget added files, delete modified files</td></tr>
3036 <td>forget added files, delete modified files</td></tr>
3033 <tr><td>-S</td>
3037 <tr><td>-S</td>
3034 <td>--subrepos</td>
3038 <td>--subrepos</td>
3035 <td>recurse into subrepositories</td></tr>
3039 <td>recurse into subrepositories</td></tr>
3036 <tr><td>-I</td>
3040 <tr><td>-I</td>
3037 <td>--include PATTERN [+]</td>
3041 <td>--include PATTERN [+]</td>
3038 <td>include names matching the given patterns</td></tr>
3042 <td>include names matching the given patterns</td></tr>
3039 <tr><td>-X</td>
3043 <tr><td>-X</td>
3040 <td>--exclude PATTERN [+]</td>
3044 <td>--exclude PATTERN [+]</td>
3041 <td>exclude names matching the given patterns</td></tr>
3045 <td>exclude names matching the given patterns</td></tr>
3042 <tr><td>-n</td>
3046 <tr><td>-n</td>
3043 <td>--dry-run</td>
3047 <td>--dry-run</td>
3044 <td>do not perform actions, just print output</td></tr>
3048 <td>do not perform actions, just print output</td></tr>
3045 </table>
3049 </table>
3046 <p>
3050 <p>
3047 global options ([+] can be repeated):
3051 global options ([+] can be repeated):
3048 </p>
3052 </p>
3049 <table>
3053 <table>
3050 <tr><td>-R</td>
3054 <tr><td>-R</td>
3051 <td>--repository REPO</td>
3055 <td>--repository REPO</td>
3052 <td>repository root directory or name of overlay bundle file</td></tr>
3056 <td>repository root directory or name of overlay bundle file</td></tr>
3053 <tr><td></td>
3057 <tr><td></td>
3054 <td>--cwd DIR</td>
3058 <td>--cwd DIR</td>
3055 <td>change working directory</td></tr>
3059 <td>change working directory</td></tr>
3056 <tr><td>-y</td>
3060 <tr><td>-y</td>
3057 <td>--noninteractive</td>
3061 <td>--noninteractive</td>
3058 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3062 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3059 <tr><td>-q</td>
3063 <tr><td>-q</td>
3060 <td>--quiet</td>
3064 <td>--quiet</td>
3061 <td>suppress output</td></tr>
3065 <td>suppress output</td></tr>
3062 <tr><td>-v</td>
3066 <tr><td>-v</td>
3063 <td>--verbose</td>
3067 <td>--verbose</td>
3064 <td>enable additional output</td></tr>
3068 <td>enable additional output</td></tr>
3065 <tr><td></td>
3069 <tr><td></td>
3066 <td>--color TYPE</td>
3070 <td>--color TYPE</td>
3067 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3071 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3068 <tr><td></td>
3072 <tr><td></td>
3069 <td>--config CONFIG [+]</td>
3073 <td>--config CONFIG [+]</td>
3070 <td>set/override config option (use 'section.name=value')</td></tr>
3074 <td>set/override config option (use 'section.name=value')</td></tr>
3071 <tr><td></td>
3075 <tr><td></td>
3072 <td>--debug</td>
3076 <td>--debug</td>
3073 <td>enable debugging output</td></tr>
3077 <td>enable debugging output</td></tr>
3074 <tr><td></td>
3078 <tr><td></td>
3075 <td>--debugger</td>
3079 <td>--debugger</td>
3076 <td>start debugger</td></tr>
3080 <td>start debugger</td></tr>
3077 <tr><td></td>
3081 <tr><td></td>
3078 <td>--encoding ENCODE</td>
3082 <td>--encoding ENCODE</td>
3079 <td>set the charset encoding (default: ascii)</td></tr>
3083 <td>set the charset encoding (default: ascii)</td></tr>
3080 <tr><td></td>
3084 <tr><td></td>
3081 <td>--encodingmode MODE</td>
3085 <td>--encodingmode MODE</td>
3082 <td>set the charset encoding mode (default: strict)</td></tr>
3086 <td>set the charset encoding mode (default: strict)</td></tr>
3083 <tr><td></td>
3087 <tr><td></td>
3084 <td>--traceback</td>
3088 <td>--traceback</td>
3085 <td>always print a traceback on exception</td></tr>
3089 <td>always print a traceback on exception</td></tr>
3086 <tr><td></td>
3090 <tr><td></td>
3087 <td>--time</td>
3091 <td>--time</td>
3088 <td>time how long the command takes</td></tr>
3092 <td>time how long the command takes</td></tr>
3089 <tr><td></td>
3093 <tr><td></td>
3090 <td>--profile</td>
3094 <td>--profile</td>
3091 <td>print command execution profile</td></tr>
3095 <td>print command execution profile</td></tr>
3092 <tr><td></td>
3096 <tr><td></td>
3093 <td>--version</td>
3097 <td>--version</td>
3094 <td>output version information and exit</td></tr>
3098 <td>output version information and exit</td></tr>
3095 <tr><td>-h</td>
3099 <tr><td>-h</td>
3096 <td>--help</td>
3100 <td>--help</td>
3097 <td>display help and exit</td></tr>
3101 <td>display help and exit</td></tr>
3098 <tr><td></td>
3102 <tr><td></td>
3099 <td>--hidden</td>
3103 <td>--hidden</td>
3100 <td>consider hidden changesets</td></tr>
3104 <td>consider hidden changesets</td></tr>
3101 <tr><td></td>
3105 <tr><td></td>
3102 <td>--pager TYPE</td>
3106 <td>--pager TYPE</td>
3103 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3107 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3104 </table>
3108 </table>
3105
3109
3106 </div>
3110 </div>
3107 </div>
3111 </div>
3108 </div>
3112 </div>
3109
3113
3110
3114
3111
3115
3112 </body>
3116 </body>
3113 </html>
3117 </html>
3114
3118
3115
3119
3116 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3120 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3117 200 Script output follows
3121 200 Script output follows
3118
3122
3119 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3123 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3120 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3124 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3121 <head>
3125 <head>
3122 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3126 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3123 <meta name="robots" content="index, nofollow" />
3127 <meta name="robots" content="index, nofollow" />
3124 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3128 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3125 <script type="text/javascript" src="/static/mercurial.js"></script>
3129 <script type="text/javascript" src="/static/mercurial.js"></script>
3126
3130
3127 <title>Help: dates</title>
3131 <title>Help: dates</title>
3128 </head>
3132 </head>
3129 <body>
3133 <body>
3130
3134
3131 <div class="container">
3135 <div class="container">
3132 <div class="menu">
3136 <div class="menu">
3133 <div class="logo">
3137 <div class="logo">
3134 <a href="https://mercurial-scm.org/">
3138 <a href="https://mercurial-scm.org/">
3135 <img src="/static/hglogo.png" alt="mercurial" /></a>
3139 <img src="/static/hglogo.png" alt="mercurial" /></a>
3136 </div>
3140 </div>
3137 <ul>
3141 <ul>
3138 <li><a href="/shortlog">log</a></li>
3142 <li><a href="/shortlog">log</a></li>
3139 <li><a href="/graph">graph</a></li>
3143 <li><a href="/graph">graph</a></li>
3140 <li><a href="/tags">tags</a></li>
3144 <li><a href="/tags">tags</a></li>
3141 <li><a href="/bookmarks">bookmarks</a></li>
3145 <li><a href="/bookmarks">bookmarks</a></li>
3142 <li><a href="/branches">branches</a></li>
3146 <li><a href="/branches">branches</a></li>
3143 </ul>
3147 </ul>
3144 <ul>
3148 <ul>
3145 <li class="active"><a href="/help">help</a></li>
3149 <li class="active"><a href="/help">help</a></li>
3146 </ul>
3150 </ul>
3147 </div>
3151 </div>
3148
3152
3149 <div class="main">
3153 <div class="main">
3150 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3154 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3151 <h3>Help: dates</h3>
3155 <h3>Help: dates</h3>
3152
3156
3153 <form class="search" action="/log">
3157 <form class="search" action="/log">
3154
3158
3155 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3159 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3156 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3160 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3157 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3161 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3158 </form>
3162 </form>
3159 <div id="doc">
3163 <div id="doc">
3160 <h1>Date Formats</h1>
3164 <h1>Date Formats</h1>
3161 <p>
3165 <p>
3162 Some commands allow the user to specify a date, e.g.:
3166 Some commands allow the user to specify a date, e.g.:
3163 </p>
3167 </p>
3164 <ul>
3168 <ul>
3165 <li> backout, commit, import, tag: Specify the commit date.
3169 <li> backout, commit, import, tag: Specify the commit date.
3166 <li> log, revert, update: Select revision(s) by date.
3170 <li> log, revert, update: Select revision(s) by date.
3167 </ul>
3171 </ul>
3168 <p>
3172 <p>
3169 Many date formats are valid. Here are some examples:
3173 Many date formats are valid. Here are some examples:
3170 </p>
3174 </p>
3171 <ul>
3175 <ul>
3172 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3176 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3173 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3177 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3174 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3178 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3175 <li> &quot;Dec 6&quot; (midnight)
3179 <li> &quot;Dec 6&quot; (midnight)
3176 <li> &quot;13:18&quot; (today assumed)
3180 <li> &quot;13:18&quot; (today assumed)
3177 <li> &quot;3:39&quot; (3:39AM assumed)
3181 <li> &quot;3:39&quot; (3:39AM assumed)
3178 <li> &quot;3:39pm&quot; (15:39)
3182 <li> &quot;3:39pm&quot; (15:39)
3179 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3183 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3180 <li> &quot;2006-12-6 13:18&quot;
3184 <li> &quot;2006-12-6 13:18&quot;
3181 <li> &quot;2006-12-6&quot;
3185 <li> &quot;2006-12-6&quot;
3182 <li> &quot;12-6&quot;
3186 <li> &quot;12-6&quot;
3183 <li> &quot;12/6&quot;
3187 <li> &quot;12/6&quot;
3184 <li> &quot;12/6/6&quot; (Dec 6 2006)
3188 <li> &quot;12/6/6&quot; (Dec 6 2006)
3185 <li> &quot;today&quot; (midnight)
3189 <li> &quot;today&quot; (midnight)
3186 <li> &quot;yesterday&quot; (midnight)
3190 <li> &quot;yesterday&quot; (midnight)
3187 <li> &quot;now&quot; - right now
3191 <li> &quot;now&quot; - right now
3188 </ul>
3192 </ul>
3189 <p>
3193 <p>
3190 Lastly, there is Mercurial's internal format:
3194 Lastly, there is Mercurial's internal format:
3191 </p>
3195 </p>
3192 <ul>
3196 <ul>
3193 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3197 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3194 </ul>
3198 </ul>
3195 <p>
3199 <p>
3196 This is the internal representation format for dates. The first number
3200 This is the internal representation format for dates. The first number
3197 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3201 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3198 second is the offset of the local timezone, in seconds west of UTC
3202 second is the offset of the local timezone, in seconds west of UTC
3199 (negative if the timezone is east of UTC).
3203 (negative if the timezone is east of UTC).
3200 </p>
3204 </p>
3201 <p>
3205 <p>
3202 The log command also accepts date ranges:
3206 The log command also accepts date ranges:
3203 </p>
3207 </p>
3204 <ul>
3208 <ul>
3205 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3209 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3206 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3210 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3207 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3211 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3208 <li> &quot;-DAYS&quot; - within a given number of days of today
3212 <li> &quot;-DAYS&quot; - within a given number of days of today
3209 </ul>
3213 </ul>
3210
3214
3211 </div>
3215 </div>
3212 </div>
3216 </div>
3213 </div>
3217 </div>
3214
3218
3215
3219
3216
3220
3217 </body>
3221 </body>
3218 </html>
3222 </html>
3219
3223
3220
3224
3221 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3225 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3222 200 Script output follows
3226 200 Script output follows
3223
3227
3224 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3228 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3225 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3229 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3226 <head>
3230 <head>
3227 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3231 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3228 <meta name="robots" content="index, nofollow" />
3232 <meta name="robots" content="index, nofollow" />
3229 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3233 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3230 <script type="text/javascript" src="/static/mercurial.js"></script>
3234 <script type="text/javascript" src="/static/mercurial.js"></script>
3231
3235
3232 <title>Help: pager</title>
3236 <title>Help: pager</title>
3233 </head>
3237 </head>
3234 <body>
3238 <body>
3235
3239
3236 <div class="container">
3240 <div class="container">
3237 <div class="menu">
3241 <div class="menu">
3238 <div class="logo">
3242 <div class="logo">
3239 <a href="https://mercurial-scm.org/">
3243 <a href="https://mercurial-scm.org/">
3240 <img src="/static/hglogo.png" alt="mercurial" /></a>
3244 <img src="/static/hglogo.png" alt="mercurial" /></a>
3241 </div>
3245 </div>
3242 <ul>
3246 <ul>
3243 <li><a href="/shortlog">log</a></li>
3247 <li><a href="/shortlog">log</a></li>
3244 <li><a href="/graph">graph</a></li>
3248 <li><a href="/graph">graph</a></li>
3245 <li><a href="/tags">tags</a></li>
3249 <li><a href="/tags">tags</a></li>
3246 <li><a href="/bookmarks">bookmarks</a></li>
3250 <li><a href="/bookmarks">bookmarks</a></li>
3247 <li><a href="/branches">branches</a></li>
3251 <li><a href="/branches">branches</a></li>
3248 </ul>
3252 </ul>
3249 <ul>
3253 <ul>
3250 <li class="active"><a href="/help">help</a></li>
3254 <li class="active"><a href="/help">help</a></li>
3251 </ul>
3255 </ul>
3252 </div>
3256 </div>
3253
3257
3254 <div class="main">
3258 <div class="main">
3255 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3259 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3256 <h3>Help: pager</h3>
3260 <h3>Help: pager</h3>
3257
3261
3258 <form class="search" action="/log">
3262 <form class="search" action="/log">
3259
3263
3260 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3264 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3261 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3265 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3262 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3266 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3263 </form>
3267 </form>
3264 <div id="doc">
3268 <div id="doc">
3265 <h1>Pager Support</h1>
3269 <h1>Pager Support</h1>
3266 <p>
3270 <p>
3267 Some Mercurial commands can produce a lot of output, and Mercurial will
3271 Some Mercurial commands can produce a lot of output, and Mercurial will
3268 attempt to use a pager to make those commands more pleasant.
3272 attempt to use a pager to make those commands more pleasant.
3269 </p>
3273 </p>
3270 <p>
3274 <p>
3271 To set the pager that should be used, set the application variable:
3275 To set the pager that should be used, set the application variable:
3272 </p>
3276 </p>
3273 <pre>
3277 <pre>
3274 [pager]
3278 [pager]
3275 pager = less -FRX
3279 pager = less -FRX
3276 </pre>
3280 </pre>
3277 <p>
3281 <p>
3278 If no pager is set in the user or repository configuration, Mercurial uses the
3282 If no pager is set in the user or repository configuration, Mercurial uses the
3279 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3283 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3280 or system configuration is used. If none of these are set, a default pager will
3284 or system configuration is used. If none of these are set, a default pager will
3281 be used, typically 'less' on Unix and 'more' on Windows.
3285 be used, typically 'less' on Unix and 'more' on Windows.
3282 </p>
3286 </p>
3283 <p>
3287 <p>
3284 You can disable the pager for certain commands by adding them to the
3288 You can disable the pager for certain commands by adding them to the
3285 pager.ignore list:
3289 pager.ignore list:
3286 </p>
3290 </p>
3287 <pre>
3291 <pre>
3288 [pager]
3292 [pager]
3289 ignore = version, help, update
3293 ignore = version, help, update
3290 </pre>
3294 </pre>
3291 <p>
3295 <p>
3292 To ignore global commands like 'hg version' or 'hg help', you have
3296 To ignore global commands like 'hg version' or 'hg help', you have
3293 to specify them in your user configuration file.
3297 to specify them in your user configuration file.
3294 </p>
3298 </p>
3295 <p>
3299 <p>
3296 To control whether the pager is used at all for an individual command,
3300 To control whether the pager is used at all for an individual command,
3297 you can use --pager=&lt;value&gt;:
3301 you can use --pager=&lt;value&gt;:
3298 </p>
3302 </p>
3299 <ul>
3303 <ul>
3300 <li> use as needed: 'auto'.
3304 <li> use as needed: 'auto'.
3301 <li> require the pager: 'yes' or 'on'.
3305 <li> require the pager: 'yes' or 'on'.
3302 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3306 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3303 </ul>
3307 </ul>
3304 <p>
3308 <p>
3305 To globally turn off all attempts to use a pager, set:
3309 To globally turn off all attempts to use a pager, set:
3306 </p>
3310 </p>
3307 <pre>
3311 <pre>
3308 [ui]
3312 [ui]
3309 paginate = never
3313 paginate = never
3310 </pre>
3314 </pre>
3311 <p>
3315 <p>
3312 which will prevent the pager from running.
3316 which will prevent the pager from running.
3313 </p>
3317 </p>
3314
3318
3315 </div>
3319 </div>
3316 </div>
3320 </div>
3317 </div>
3321 </div>
3318
3322
3319
3323
3320
3324
3321 </body>
3325 </body>
3322 </html>
3326 </html>
3323
3327
3324
3328
3325 Sub-topic indexes rendered properly
3329 Sub-topic indexes rendered properly
3326
3330
3327 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3331 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3328 200 Script output follows
3332 200 Script output follows
3329
3333
3330 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3334 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3331 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3335 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3332 <head>
3336 <head>
3333 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3337 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3334 <meta name="robots" content="index, nofollow" />
3338 <meta name="robots" content="index, nofollow" />
3335 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3339 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3336 <script type="text/javascript" src="/static/mercurial.js"></script>
3340 <script type="text/javascript" src="/static/mercurial.js"></script>
3337
3341
3338 <title>Help: internals</title>
3342 <title>Help: internals</title>
3339 </head>
3343 </head>
3340 <body>
3344 <body>
3341
3345
3342 <div class="container">
3346 <div class="container">
3343 <div class="menu">
3347 <div class="menu">
3344 <div class="logo">
3348 <div class="logo">
3345 <a href="https://mercurial-scm.org/">
3349 <a href="https://mercurial-scm.org/">
3346 <img src="/static/hglogo.png" alt="mercurial" /></a>
3350 <img src="/static/hglogo.png" alt="mercurial" /></a>
3347 </div>
3351 </div>
3348 <ul>
3352 <ul>
3349 <li><a href="/shortlog">log</a></li>
3353 <li><a href="/shortlog">log</a></li>
3350 <li><a href="/graph">graph</a></li>
3354 <li><a href="/graph">graph</a></li>
3351 <li><a href="/tags">tags</a></li>
3355 <li><a href="/tags">tags</a></li>
3352 <li><a href="/bookmarks">bookmarks</a></li>
3356 <li><a href="/bookmarks">bookmarks</a></li>
3353 <li><a href="/branches">branches</a></li>
3357 <li><a href="/branches">branches</a></li>
3354 </ul>
3358 </ul>
3355 <ul>
3359 <ul>
3356 <li><a href="/help">help</a></li>
3360 <li><a href="/help">help</a></li>
3357 </ul>
3361 </ul>
3358 </div>
3362 </div>
3359
3363
3360 <div class="main">
3364 <div class="main">
3361 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3365 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3362
3366
3363 <form class="search" action="/log">
3367 <form class="search" action="/log">
3364
3368
3365 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3369 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3366 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3370 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3367 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3371 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3368 </form>
3372 </form>
3369 <table class="bigtable">
3373 <table class="bigtable">
3370 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3374 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3371
3375
3372 <tr><td>
3376 <tr><td>
3373 <a href="/help/internals.bundle2">
3377 <a href="/help/internals.bundle2">
3374 bundle2
3378 bundle2
3375 </a>
3379 </a>
3376 </td><td>
3380 </td><td>
3377 Bundle2
3381 Bundle2
3378 </td></tr>
3382 </td></tr>
3379 <tr><td>
3383 <tr><td>
3380 <a href="/help/internals.bundles">
3384 <a href="/help/internals.bundles">
3381 bundles
3385 bundles
3382 </a>
3386 </a>
3383 </td><td>
3387 </td><td>
3384 Bundles
3388 Bundles
3385 </td></tr>
3389 </td></tr>
3386 <tr><td>
3390 <tr><td>
3387 <a href="/help/internals.cbor">
3391 <a href="/help/internals.cbor">
3388 cbor
3392 cbor
3389 </a>
3393 </a>
3390 </td><td>
3394 </td><td>
3391 CBOR
3395 CBOR
3392 </td></tr>
3396 </td></tr>
3393 <tr><td>
3397 <tr><td>
3394 <a href="/help/internals.censor">
3398 <a href="/help/internals.censor">
3395 censor
3399 censor
3396 </a>
3400 </a>
3397 </td><td>
3401 </td><td>
3398 Censor
3402 Censor
3399 </td></tr>
3403 </td></tr>
3400 <tr><td>
3404 <tr><td>
3401 <a href="/help/internals.changegroups">
3405 <a href="/help/internals.changegroups">
3402 changegroups
3406 changegroups
3403 </a>
3407 </a>
3404 </td><td>
3408 </td><td>
3405 Changegroups
3409 Changegroups
3406 </td></tr>
3410 </td></tr>
3407 <tr><td>
3411 <tr><td>
3408 <a href="/help/internals.config">
3412 <a href="/help/internals.config">
3409 config
3413 config
3410 </a>
3414 </a>
3411 </td><td>
3415 </td><td>
3412 Config Registrar
3416 Config Registrar
3413 </td></tr>
3417 </td></tr>
3414 <tr><td>
3418 <tr><td>
3415 <a href="/help/internals.extensions">
3419 <a href="/help/internals.extensions">
3416 extensions
3420 extensions
3417 </a>
3421 </a>
3418 </td><td>
3422 </td><td>
3419 Extension API
3423 Extension API
3420 </td></tr>
3424 </td></tr>
3421 <tr><td>
3425 <tr><td>
3422 <a href="/help/internals.requirements">
3426 <a href="/help/internals.requirements">
3423 requirements
3427 requirements
3424 </a>
3428 </a>
3425 </td><td>
3429 </td><td>
3426 Repository Requirements
3430 Repository Requirements
3427 </td></tr>
3431 </td></tr>
3428 <tr><td>
3432 <tr><td>
3429 <a href="/help/internals.revlogs">
3433 <a href="/help/internals.revlogs">
3430 revlogs
3434 revlogs
3431 </a>
3435 </a>
3432 </td><td>
3436 </td><td>
3433 Revision Logs
3437 Revision Logs
3434 </td></tr>
3438 </td></tr>
3435 <tr><td>
3439 <tr><td>
3436 <a href="/help/internals.wireprotocol">
3440 <a href="/help/internals.wireprotocol">
3437 wireprotocol
3441 wireprotocol
3438 </a>
3442 </a>
3439 </td><td>
3443 </td><td>
3440 Wire Protocol
3444 Wire Protocol
3441 </td></tr>
3445 </td></tr>
3442 <tr><td>
3446 <tr><td>
3443 <a href="/help/internals.wireprotocolrpc">
3447 <a href="/help/internals.wireprotocolrpc">
3444 wireprotocolrpc
3448 wireprotocolrpc
3445 </a>
3449 </a>
3446 </td><td>
3450 </td><td>
3447 Wire Protocol RPC
3451 Wire Protocol RPC
3448 </td></tr>
3452 </td></tr>
3449 <tr><td>
3453 <tr><td>
3450 <a href="/help/internals.wireprotocolv2">
3454 <a href="/help/internals.wireprotocolv2">
3451 wireprotocolv2
3455 wireprotocolv2
3452 </a>
3456 </a>
3453 </td><td>
3457 </td><td>
3454 Wire Protocol Version 2
3458 Wire Protocol Version 2
3455 </td></tr>
3459 </td></tr>
3456
3460
3457
3461
3458
3462
3459
3463
3460
3464
3461 </table>
3465 </table>
3462 </div>
3466 </div>
3463 </div>
3467 </div>
3464
3468
3465
3469
3466
3470
3467 </body>
3471 </body>
3468 </html>
3472 </html>
3469
3473
3470
3474
3471 Sub-topic topics rendered properly
3475 Sub-topic topics rendered properly
3472
3476
3473 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3477 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3474 200 Script output follows
3478 200 Script output follows
3475
3479
3476 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3480 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3477 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3481 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3478 <head>
3482 <head>
3479 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3483 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3480 <meta name="robots" content="index, nofollow" />
3484 <meta name="robots" content="index, nofollow" />
3481 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3485 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3482 <script type="text/javascript" src="/static/mercurial.js"></script>
3486 <script type="text/javascript" src="/static/mercurial.js"></script>
3483
3487
3484 <title>Help: internals.changegroups</title>
3488 <title>Help: internals.changegroups</title>
3485 </head>
3489 </head>
3486 <body>
3490 <body>
3487
3491
3488 <div class="container">
3492 <div class="container">
3489 <div class="menu">
3493 <div class="menu">
3490 <div class="logo">
3494 <div class="logo">
3491 <a href="https://mercurial-scm.org/">
3495 <a href="https://mercurial-scm.org/">
3492 <img src="/static/hglogo.png" alt="mercurial" /></a>
3496 <img src="/static/hglogo.png" alt="mercurial" /></a>
3493 </div>
3497 </div>
3494 <ul>
3498 <ul>
3495 <li><a href="/shortlog">log</a></li>
3499 <li><a href="/shortlog">log</a></li>
3496 <li><a href="/graph">graph</a></li>
3500 <li><a href="/graph">graph</a></li>
3497 <li><a href="/tags">tags</a></li>
3501 <li><a href="/tags">tags</a></li>
3498 <li><a href="/bookmarks">bookmarks</a></li>
3502 <li><a href="/bookmarks">bookmarks</a></li>
3499 <li><a href="/branches">branches</a></li>
3503 <li><a href="/branches">branches</a></li>
3500 </ul>
3504 </ul>
3501 <ul>
3505 <ul>
3502 <li class="active"><a href="/help">help</a></li>
3506 <li class="active"><a href="/help">help</a></li>
3503 </ul>
3507 </ul>
3504 </div>
3508 </div>
3505
3509
3506 <div class="main">
3510 <div class="main">
3507 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3511 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3508 <h3>Help: internals.changegroups</h3>
3512 <h3>Help: internals.changegroups</h3>
3509
3513
3510 <form class="search" action="/log">
3514 <form class="search" action="/log">
3511
3515
3512 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3516 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3513 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3517 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3514 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3518 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3515 </form>
3519 </form>
3516 <div id="doc">
3520 <div id="doc">
3517 <h1>Changegroups</h1>
3521 <h1>Changegroups</h1>
3518 <p>
3522 <p>
3519 Changegroups are representations of repository revlog data, specifically
3523 Changegroups are representations of repository revlog data, specifically
3520 the changelog data, root/flat manifest data, treemanifest data, and
3524 the changelog data, root/flat manifest data, treemanifest data, and
3521 filelogs.
3525 filelogs.
3522 </p>
3526 </p>
3523 <p>
3527 <p>
3524 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3528 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3525 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3529 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3526 only difference being an additional item in the *delta header*. Version
3530 only difference being an additional item in the *delta header*. Version
3527 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3531 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3528 exchanging treemanifests (enabled by setting an option on the
3532 exchanging treemanifests (enabled by setting an option on the
3529 &quot;changegroup&quot; part in the bundle2).
3533 &quot;changegroup&quot; part in the bundle2).
3530 </p>
3534 </p>
3531 <p>
3535 <p>
3532 Changegroups when not exchanging treemanifests consist of 3 logical
3536 Changegroups when not exchanging treemanifests consist of 3 logical
3533 segments:
3537 segments:
3534 </p>
3538 </p>
3535 <pre>
3539 <pre>
3536 +---------------------------------+
3540 +---------------------------------+
3537 | | | |
3541 | | | |
3538 | changeset | manifest | filelogs |
3542 | changeset | manifest | filelogs |
3539 | | | |
3543 | | | |
3540 | | | |
3544 | | | |
3541 +---------------------------------+
3545 +---------------------------------+
3542 </pre>
3546 </pre>
3543 <p>
3547 <p>
3544 When exchanging treemanifests, there are 4 logical segments:
3548 When exchanging treemanifests, there are 4 logical segments:
3545 </p>
3549 </p>
3546 <pre>
3550 <pre>
3547 +-------------------------------------------------+
3551 +-------------------------------------------------+
3548 | | | | |
3552 | | | | |
3549 | changeset | root | treemanifests | filelogs |
3553 | changeset | root | treemanifests | filelogs |
3550 | | manifest | | |
3554 | | manifest | | |
3551 | | | | |
3555 | | | | |
3552 +-------------------------------------------------+
3556 +-------------------------------------------------+
3553 </pre>
3557 </pre>
3554 <p>
3558 <p>
3555 The principle building block of each segment is a *chunk*. A *chunk*
3559 The principle building block of each segment is a *chunk*. A *chunk*
3556 is a framed piece of data:
3560 is a framed piece of data:
3557 </p>
3561 </p>
3558 <pre>
3562 <pre>
3559 +---------------------------------------+
3563 +---------------------------------------+
3560 | | |
3564 | | |
3561 | length | data |
3565 | length | data |
3562 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3566 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3563 | | |
3567 | | |
3564 +---------------------------------------+
3568 +---------------------------------------+
3565 </pre>
3569 </pre>
3566 <p>
3570 <p>
3567 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3571 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3568 integer indicating the length of the entire chunk (including the length field
3572 integer indicating the length of the entire chunk (including the length field
3569 itself).
3573 itself).
3570 </p>
3574 </p>
3571 <p>
3575 <p>
3572 There is a special case chunk that has a value of 0 for the length
3576 There is a special case chunk that has a value of 0 for the length
3573 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3577 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3574 </p>
3578 </p>
3575 <h2>Delta Groups</h2>
3579 <h2>Delta Groups</h2>
3576 <p>
3580 <p>
3577 A *delta group* expresses the content of a revlog as a series of deltas,
3581 A *delta group* expresses the content of a revlog as a series of deltas,
3578 or patches against previous revisions.
3582 or patches against previous revisions.
3579 </p>
3583 </p>
3580 <p>
3584 <p>
3581 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3585 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3582 to signal the end of the delta group:
3586 to signal the end of the delta group:
3583 </p>
3587 </p>
3584 <pre>
3588 <pre>
3585 +------------------------------------------------------------------------+
3589 +------------------------------------------------------------------------+
3586 | | | | | |
3590 | | | | | |
3587 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3591 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3588 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3592 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3589 | | | | | |
3593 | | | | | |
3590 +------------------------------------------------------------------------+
3594 +------------------------------------------------------------------------+
3591 </pre>
3595 </pre>
3592 <p>
3596 <p>
3593 Each *chunk*'s data consists of the following:
3597 Each *chunk*'s data consists of the following:
3594 </p>
3598 </p>
3595 <pre>
3599 <pre>
3596 +---------------------------------------+
3600 +---------------------------------------+
3597 | | |
3601 | | |
3598 | delta header | delta data |
3602 | delta header | delta data |
3599 | (various by version) | (various) |
3603 | (various by version) | (various) |
3600 | | |
3604 | | |
3601 +---------------------------------------+
3605 +---------------------------------------+
3602 </pre>
3606 </pre>
3603 <p>
3607 <p>
3604 The *delta data* is a series of *delta*s that describe a diff from an existing
3608 The *delta data* is a series of *delta*s that describe a diff from an existing
3605 entry (either that the recipient already has, or previously specified in the
3609 entry (either that the recipient already has, or previously specified in the
3606 bundle/changegroup).
3610 bundle/changegroup).
3607 </p>
3611 </p>
3608 <p>
3612 <p>
3609 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3613 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3610 &quot;3&quot; of the changegroup format.
3614 &quot;3&quot; of the changegroup format.
3611 </p>
3615 </p>
3612 <p>
3616 <p>
3613 Version 1 (headerlen=80):
3617 Version 1 (headerlen=80):
3614 </p>
3618 </p>
3615 <pre>
3619 <pre>
3616 +------------------------------------------------------+
3620 +------------------------------------------------------+
3617 | | | | |
3621 | | | | |
3618 | node | p1 node | p2 node | link node |
3622 | node | p1 node | p2 node | link node |
3619 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3623 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3620 | | | | |
3624 | | | | |
3621 +------------------------------------------------------+
3625 +------------------------------------------------------+
3622 </pre>
3626 </pre>
3623 <p>
3627 <p>
3624 Version 2 (headerlen=100):
3628 Version 2 (headerlen=100):
3625 </p>
3629 </p>
3626 <pre>
3630 <pre>
3627 +------------------------------------------------------------------+
3631 +------------------------------------------------------------------+
3628 | | | | | |
3632 | | | | | |
3629 | node | p1 node | p2 node | base node | link node |
3633 | node | p1 node | p2 node | base node | link node |
3630 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3634 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3631 | | | | | |
3635 | | | | | |
3632 +------------------------------------------------------------------+
3636 +------------------------------------------------------------------+
3633 </pre>
3637 </pre>
3634 <p>
3638 <p>
3635 Version 3 (headerlen=102):
3639 Version 3 (headerlen=102):
3636 </p>
3640 </p>
3637 <pre>
3641 <pre>
3638 +------------------------------------------------------------------------------+
3642 +------------------------------------------------------------------------------+
3639 | | | | | | |
3643 | | | | | | |
3640 | node | p1 node | p2 node | base node | link node | flags |
3644 | node | p1 node | p2 node | base node | link node | flags |
3641 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3645 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3642 | | | | | | |
3646 | | | | | | |
3643 +------------------------------------------------------------------------------+
3647 +------------------------------------------------------------------------------+
3644 </pre>
3648 </pre>
3645 <p>
3649 <p>
3646 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3650 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3647 series of *delta*s, densely packed (no separators). These deltas describe a diff
3651 series of *delta*s, densely packed (no separators). These deltas describe a diff
3648 from an existing entry (either that the recipient already has, or previously
3652 from an existing entry (either that the recipient already has, or previously
3649 specified in the bundle/changegroup). The format is described more fully in
3653 specified in the bundle/changegroup). The format is described more fully in
3650 &quot;hg help internals.bdiff&quot;, but briefly:
3654 &quot;hg help internals.bdiff&quot;, but briefly:
3651 </p>
3655 </p>
3652 <pre>
3656 <pre>
3653 +---------------------------------------------------------------+
3657 +---------------------------------------------------------------+
3654 | | | | |
3658 | | | | |
3655 | start offset | end offset | new length | content |
3659 | start offset | end offset | new length | content |
3656 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3660 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3657 | | | | |
3661 | | | | |
3658 +---------------------------------------------------------------+
3662 +---------------------------------------------------------------+
3659 </pre>
3663 </pre>
3660 <p>
3664 <p>
3661 Please note that the length field in the delta data does *not* include itself.
3665 Please note that the length field in the delta data does *not* include itself.
3662 </p>
3666 </p>
3663 <p>
3667 <p>
3664 In version 1, the delta is always applied against the previous node from
3668 In version 1, the delta is always applied against the previous node from
3665 the changegroup or the first parent if this is the first entry in the
3669 the changegroup or the first parent if this is the first entry in the
3666 changegroup.
3670 changegroup.
3667 </p>
3671 </p>
3668 <p>
3672 <p>
3669 In version 2 and up, the delta base node is encoded in the entry in the
3673 In version 2 and up, the delta base node is encoded in the entry in the
3670 changegroup. This allows the delta to be expressed against any parent,
3674 changegroup. This allows the delta to be expressed against any parent,
3671 which can result in smaller deltas and more efficient encoding of data.
3675 which can result in smaller deltas and more efficient encoding of data.
3672 </p>
3676 </p>
3673 <p>
3677 <p>
3674 The *flags* field holds bitwise flags affecting the processing of revision
3678 The *flags* field holds bitwise flags affecting the processing of revision
3675 data. The following flags are defined:
3679 data. The following flags are defined:
3676 </p>
3680 </p>
3677 <dl>
3681 <dl>
3678 <dt>32768
3682 <dt>32768
3679 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3683 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3680 <dt>16384
3684 <dt>16384
3681 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3685 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3682 <dt>8192
3686 <dt>8192
3683 <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.
3687 <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.
3684 </dl>
3688 </dl>
3685 <p>
3689 <p>
3686 For historical reasons, the integer values are identical to revlog version 1
3690 For historical reasons, the integer values are identical to revlog version 1
3687 per-revision storage flags and correspond to bits being set in this 2-byte
3691 per-revision storage flags and correspond to bits being set in this 2-byte
3688 field. Bits were allocated starting from the most-significant bit, hence the
3692 field. Bits were allocated starting from the most-significant bit, hence the
3689 reverse ordering and allocation of these flags.
3693 reverse ordering and allocation of these flags.
3690 </p>
3694 </p>
3691 <h2>Changeset Segment</h2>
3695 <h2>Changeset Segment</h2>
3692 <p>
3696 <p>
3693 The *changeset segment* consists of a single *delta group* holding
3697 The *changeset segment* consists of a single *delta group* holding
3694 changelog data. The *empty chunk* at the end of the *delta group* denotes
3698 changelog data. The *empty chunk* at the end of the *delta group* denotes
3695 the boundary to the *manifest segment*.
3699 the boundary to the *manifest segment*.
3696 </p>
3700 </p>
3697 <h2>Manifest Segment</h2>
3701 <h2>Manifest Segment</h2>
3698 <p>
3702 <p>
3699 The *manifest segment* consists of a single *delta group* holding manifest
3703 The *manifest segment* consists of a single *delta group* holding manifest
3700 data. If treemanifests are in use, it contains only the manifest for the
3704 data. If treemanifests are in use, it contains only the manifest for the
3701 root directory of the repository. Otherwise, it contains the entire
3705 root directory of the repository. Otherwise, it contains the entire
3702 manifest data. The *empty chunk* at the end of the *delta group* denotes
3706 manifest data. The *empty chunk* at the end of the *delta group* denotes
3703 the boundary to the next segment (either the *treemanifests segment* or the
3707 the boundary to the next segment (either the *treemanifests segment* or the
3704 *filelogs segment*, depending on version and the request options).
3708 *filelogs segment*, depending on version and the request options).
3705 </p>
3709 </p>
3706 <h3>Treemanifests Segment</h3>
3710 <h3>Treemanifests Segment</h3>
3707 <p>
3711 <p>
3708 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3712 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3709 only if the 'treemanifest' param is part of the bundle2 changegroup part
3713 only if the 'treemanifest' param is part of the bundle2 changegroup part
3710 (it is not possible to use changegroup version 3 outside of bundle2).
3714 (it is not possible to use changegroup version 3 outside of bundle2).
3711 Aside from the filenames in the *treemanifests segment* containing a
3715 Aside from the filenames in the *treemanifests segment* containing a
3712 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3716 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3713 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3717 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3714 a sub-segment with filename size 0). This denotes the boundary to the
3718 a sub-segment with filename size 0). This denotes the boundary to the
3715 *filelogs segment*.
3719 *filelogs segment*.
3716 </p>
3720 </p>
3717 <h2>Filelogs Segment</h2>
3721 <h2>Filelogs Segment</h2>
3718 <p>
3722 <p>
3719 The *filelogs segment* consists of multiple sub-segments, each
3723 The *filelogs segment* consists of multiple sub-segments, each
3720 corresponding to an individual file whose data is being described:
3724 corresponding to an individual file whose data is being described:
3721 </p>
3725 </p>
3722 <pre>
3726 <pre>
3723 +--------------------------------------------------+
3727 +--------------------------------------------------+
3724 | | | | | |
3728 | | | | | |
3725 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3729 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3726 | | | | | (4 bytes) |
3730 | | | | | (4 bytes) |
3727 | | | | | |
3731 | | | | | |
3728 +--------------------------------------------------+
3732 +--------------------------------------------------+
3729 </pre>
3733 </pre>
3730 <p>
3734 <p>
3731 The final filelog sub-segment is followed by an *empty chunk* (logically,
3735 The final filelog sub-segment is followed by an *empty chunk* (logically,
3732 a sub-segment with filename size 0). This denotes the end of the segment
3736 a sub-segment with filename size 0). This denotes the end of the segment
3733 and of the overall changegroup.
3737 and of the overall changegroup.
3734 </p>
3738 </p>
3735 <p>
3739 <p>
3736 Each filelog sub-segment consists of the following:
3740 Each filelog sub-segment consists of the following:
3737 </p>
3741 </p>
3738 <pre>
3742 <pre>
3739 +------------------------------------------------------+
3743 +------------------------------------------------------+
3740 | | | |
3744 | | | |
3741 | filename length | filename | delta group |
3745 | filename length | filename | delta group |
3742 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3746 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3743 | | | |
3747 | | | |
3744 +------------------------------------------------------+
3748 +------------------------------------------------------+
3745 </pre>
3749 </pre>
3746 <p>
3750 <p>
3747 That is, a *chunk* consisting of the filename (not terminated or padded)
3751 That is, a *chunk* consisting of the filename (not terminated or padded)
3748 followed by N chunks constituting the *delta group* for this file. The
3752 followed by N chunks constituting the *delta group* for this file. The
3749 *empty chunk* at the end of each *delta group* denotes the boundary to the
3753 *empty chunk* at the end of each *delta group* denotes the boundary to the
3750 next filelog sub-segment.
3754 next filelog sub-segment.
3751 </p>
3755 </p>
3752
3756
3753 </div>
3757 </div>
3754 </div>
3758 </div>
3755 </div>
3759 </div>
3756
3760
3757
3761
3758
3762
3759 </body>
3763 </body>
3760 </html>
3764 </html>
3761
3765
3762
3766
3763 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3767 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3764 404 Not Found
3768 404 Not Found
3765
3769
3766 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3770 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3767 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3771 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3768 <head>
3772 <head>
3769 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3773 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3770 <meta name="robots" content="index, nofollow" />
3774 <meta name="robots" content="index, nofollow" />
3771 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3775 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3772 <script type="text/javascript" src="/static/mercurial.js"></script>
3776 <script type="text/javascript" src="/static/mercurial.js"></script>
3773
3777
3774 <title>test: error</title>
3778 <title>test: error</title>
3775 </head>
3779 </head>
3776 <body>
3780 <body>
3777
3781
3778 <div class="container">
3782 <div class="container">
3779 <div class="menu">
3783 <div class="menu">
3780 <div class="logo">
3784 <div class="logo">
3781 <a href="https://mercurial-scm.org/">
3785 <a href="https://mercurial-scm.org/">
3782 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3786 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3783 </div>
3787 </div>
3784 <ul>
3788 <ul>
3785 <li><a href="/shortlog">log</a></li>
3789 <li><a href="/shortlog">log</a></li>
3786 <li><a href="/graph">graph</a></li>
3790 <li><a href="/graph">graph</a></li>
3787 <li><a href="/tags">tags</a></li>
3791 <li><a href="/tags">tags</a></li>
3788 <li><a href="/bookmarks">bookmarks</a></li>
3792 <li><a href="/bookmarks">bookmarks</a></li>
3789 <li><a href="/branches">branches</a></li>
3793 <li><a href="/branches">branches</a></li>
3790 </ul>
3794 </ul>
3791 <ul>
3795 <ul>
3792 <li><a href="/help">help</a></li>
3796 <li><a href="/help">help</a></li>
3793 </ul>
3797 </ul>
3794 </div>
3798 </div>
3795
3799
3796 <div class="main">
3800 <div class="main">
3797
3801
3798 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3802 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3799 <h3>error</h3>
3803 <h3>error</h3>
3800
3804
3801
3805
3802 <form class="search" action="/log">
3806 <form class="search" action="/log">
3803
3807
3804 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3808 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3805 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3809 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3806 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3810 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3807 </form>
3811 </form>
3808
3812
3809 <div class="description">
3813 <div class="description">
3810 <p>
3814 <p>
3811 An error occurred while processing your request:
3815 An error occurred while processing your request:
3812 </p>
3816 </p>
3813 <p>
3817 <p>
3814 Not Found
3818 Not Found
3815 </p>
3819 </p>
3816 </div>
3820 </div>
3817 </div>
3821 </div>
3818 </div>
3822 </div>
3819
3823
3820
3824
3821
3825
3822 </body>
3826 </body>
3823 </html>
3827 </html>
3824
3828
3825 [1]
3829 [1]
3826
3830
3827 $ killdaemons.py
3831 $ killdaemons.py
3828
3832
3829 #endif
3833 #endif
General Comments 0
You need to be logged in to leave comments. Login now