##// END OF EJS Templates
bookmarks: keep bookmarks in .hg/store if new config set...
Martin von Zweigbergk -
r42897:526750cd default
parent child Browse files
Show More
@@ -1,181 +1,185 b''
1 1 # Copyright 2006, 2007 Matt Mackall <mpm@selenic.com>
2 2 #
3 3 # This software may be used and distributed according to the terms of the
4 4 # GNU General Public License version 2 or any later version.
5 5
6 6 '''share a common history between several working directories
7 7
8 8 Automatic Pooled Storage for Clones
9 9 -----------------------------------
10 10
11 11 When this extension is active, :hg:`clone` can be configured to
12 12 automatically share/pool storage across multiple clones. This
13 13 mode effectively converts :hg:`clone` to :hg:`clone` + :hg:`share`.
14 14 The benefit of using this mode is the automatic management of
15 15 store paths and intelligent pooling of related repositories.
16 16
17 17 The following ``share.`` config options influence this feature:
18 18
19 19 ``share.pool``
20 20 Filesystem path where shared repository data will be stored. When
21 21 defined, :hg:`clone` will automatically use shared repository
22 22 storage instead of creating a store inside each clone.
23 23
24 24 ``share.poolnaming``
25 25 How directory names in ``share.pool`` are constructed.
26 26
27 27 "identity" means the name is derived from the first changeset in the
28 28 repository. In this mode, different remotes share storage if their
29 29 root/initial changeset is identical. In this mode, the local shared
30 30 repository is an aggregate of all encountered remote repositories.
31 31
32 32 "remote" means the name is derived from the source repository's
33 33 path or URL. In this mode, storage is only shared if the path or URL
34 34 requested in the :hg:`clone` command matches exactly to a repository
35 35 that was cloned before.
36 36
37 37 The default naming mode is "identity".
38 38 '''
39 39
40 40 from __future__ import absolute_import
41 41
42 42 import errno
43 43 from mercurial.i18n import _
44 44 from mercurial import (
45 45 bookmarks,
46 46 commands,
47 47 error,
48 48 extensions,
49 49 hg,
50 50 registrar,
51 51 txnutil,
52 52 util,
53 53 )
54 54
55 55 cmdtable = {}
56 56 command = registrar.command(cmdtable)
57 57 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
58 58 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
59 59 # be specifying the version(s) of Mercurial they are tested with, or
60 60 # leave the attribute unspecified.
61 61 testedwith = 'ships-with-hg-core'
62 62
63 63 @command('share',
64 64 [('U', 'noupdate', None, _('do not create a working directory')),
65 65 ('B', 'bookmarks', None, _('also share bookmarks')),
66 66 ('', 'relative', None, _('point to source using a relative path '
67 67 '(EXPERIMENTAL)')),
68 68 ],
69 69 _('[-U] [-B] SOURCE [DEST]'),
70 70 helpcategory=command.CATEGORY_REPO_CREATION,
71 71 norepo=True)
72 72 def share(ui, source, dest=None, noupdate=False, bookmarks=False,
73 73 relative=False):
74 74 """create a new shared repository
75 75
76 76 Initialize a new repository and working directory that shares its
77 77 history (and optionally bookmarks) with another repository.
78 78
79 79 .. note::
80 80
81 81 using rollback or extensions that destroy/modify history (mq,
82 82 rebase, etc.) can cause considerable confusion with shared
83 83 clones. In particular, if two shared clones are both updated to
84 84 the same changeset, and one of them destroys that changeset
85 85 with rollback, the other clone will suddenly stop working: all
86 86 operations will fail with "abort: working directory has unknown
87 87 parent". The only known workaround is to use debugsetparents on
88 88 the broken clone to reset it to a changeset that still exists.
89 89 """
90 90
91 91 hg.share(ui, source, dest=dest, update=not noupdate,
92 92 bookmarks=bookmarks, relative=relative)
93 93 return 0
94 94
95 95 @command('unshare', [], '', helpcategory=command.CATEGORY_MAINTENANCE)
96 96 def unshare(ui, repo):
97 97 """convert a shared repository to a normal one
98 98
99 99 Copy the store data to the repo and remove the sharedpath data.
100 100 """
101 101
102 102 if not repo.shared():
103 103 raise error.Abort(_("this is not a shared repo"))
104 104
105 105 hg.unshare(ui, repo)
106 106
107 107 # Wrap clone command to pass auto share options.
108 108 def clone(orig, ui, source, *args, **opts):
109 109 pool = ui.config('share', 'pool')
110 110 if pool:
111 111 pool = util.expandpath(pool)
112 112
113 113 opts[r'shareopts'] = {
114 114 'pool': pool,
115 115 'mode': ui.config('share', 'poolnaming'),
116 116 }
117 117
118 118 return orig(ui, source, *args, **opts)
119 119
120 120 def extsetup(ui):
121 121 extensions.wrapfunction(bookmarks, '_getbkfile', getbkfile)
122 122 extensions.wrapfunction(bookmarks.bmstore, '_recordchange', recordchange)
123 123 extensions.wrapfunction(bookmarks.bmstore, '_writerepo', writerepo)
124 124 extensions.wrapcommand(commands.table, 'clone', clone)
125 125
126 126 def _hassharedbookmarks(repo):
127 127 """Returns whether this repo has shared bookmarks"""
128 if bookmarks.bookmarksinstore(repo):
129 # Kind of a lie, but it means that we skip our custom reads and writes
130 # from/to the source repo.
131 return False
128 132 try:
129 133 shared = repo.vfs.read('shared').splitlines()
130 134 except IOError as inst:
131 135 if inst.errno != errno.ENOENT:
132 136 raise
133 137 return False
134 138 return hg.sharedbookmarks in shared
135 139
136 140 def getbkfile(orig, repo):
137 141 if _hassharedbookmarks(repo):
138 142 srcrepo = hg.sharedreposource(repo)
139 143 if srcrepo is not None:
140 144 # just orig(srcrepo) doesn't work as expected, because
141 145 # HG_PENDING refers repo.root.
142 146 try:
143 147 fp, pending = txnutil.trypending(repo.root, repo.vfs,
144 148 'bookmarks')
145 149 if pending:
146 150 # only in this case, bookmark information in repo
147 151 # is up-to-date.
148 152 return fp
149 153 fp.close()
150 154 except IOError as inst:
151 155 if inst.errno != errno.ENOENT:
152 156 raise
153 157
154 158 # otherwise, we should read bookmarks from srcrepo,
155 159 # because .hg/bookmarks in srcrepo might be already
156 160 # changed via another sharing repo
157 161 repo = srcrepo
158 162
159 163 # TODO: Pending changes in repo are still invisible in
160 164 # srcrepo, because bookmarks.pending is written only into repo.
161 165 # See also https://www.mercurial-scm.org/wiki/SharedRepository
162 166 return orig(repo)
163 167
164 168 def recordchange(orig, self, tr):
165 169 # Continue with write to local bookmarks file as usual
166 170 orig(self, tr)
167 171
168 172 if _hassharedbookmarks(self._repo):
169 173 srcrepo = hg.sharedreposource(self._repo)
170 174 if srcrepo is not None:
171 175 category = 'share-bookmarks'
172 176 tr.addpostclose(category, lambda tr: self._writerepo(srcrepo))
173 177
174 178 def writerepo(orig, self, repo):
175 179 # First write local bookmarks file in case we ever unshare
176 180 orig(self, repo)
177 181
178 182 if _hassharedbookmarks(self._repo):
179 183 srcrepo = hg.sharedreposource(self._repo)
180 184 if srcrepo is not None:
181 185 orig(self, srcrepo)
@@ -1,939 +1,960 b''
1 1 # Mercurial bookmark support code
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import struct
12 12
13 13 from .i18n import _
14 14 from .node import (
15 15 bin,
16 16 hex,
17 17 short,
18 18 wdirid,
19 19 )
20 20 from . import (
21 21 encoding,
22 22 error,
23 23 obsutil,
24 24 pycompat,
25 25 scmutil,
26 26 txnutil,
27 27 util,
28 28 )
29 29
30 30 # label constants
31 31 # until 3.5, bookmarks.current was the advertised name, not
32 32 # bookmarks.active, so we must use both to avoid breaking old
33 33 # custom styles
34 34 activebookmarklabel = 'bookmarks.active bookmarks.current'
35 35
36 BOOKMARKS_IN_STORE_REQUIREMENT = 'bookmarksinstore'
37
38 def bookmarksinstore(repo):
39 return BOOKMARKS_IN_STORE_REQUIREMENT in repo.requirements
40
41 def bookmarksvfs(repo):
42 return repo.svfs if bookmarksinstore(repo) else repo.vfs
43
36 44 def _getbkfile(repo):
37 45 """Hook so that extensions that mess with the store can hook bm storage.
38 46
39 47 For core, this just handles wether we should see pending
40 48 bookmarks or the committed ones. Other extensions (like share)
41 49 may need to tweak this behavior further.
42 50 """
43 fp, pending = txnutil.trypending(repo.root, repo.vfs, 'bookmarks')
51 fp, pending = txnutil.trypending(repo.root, bookmarksvfs(repo), 'bookmarks')
44 52 return fp
45 53
46 54 class bmstore(object):
47 55 r"""Storage for bookmarks.
48 56
49 57 This object should do all bookmark-related reads and writes, so
50 58 that it's fairly simple to replace the storage underlying
51 59 bookmarks without having to clone the logic surrounding
52 60 bookmarks. This type also should manage the active bookmark, if
53 61 any.
54 62
55 63 This particular bmstore implementation stores bookmarks as
56 64 {hash}\s{name}\n (the same format as localtags) in
57 65 .hg/bookmarks. The mapping is stored as {name: nodeid}.
58 66 """
59 67
60 68 def __init__(self, repo):
61 69 self._repo = repo
62 70 self._refmap = refmap = {} # refspec: node
63 71 self._nodemap = nodemap = {} # node: sorted([refspec, ...])
64 72 self._clean = True
65 73 self._aclean = True
66 74 nm = repo.changelog.nodemap
67 75 tonode = bin # force local lookup
68 76 try:
69 77 with _getbkfile(repo) as bkfile:
70 78 for line in bkfile:
71 79 line = line.strip()
72 80 if not line:
73 81 continue
74 82 try:
75 83 sha, refspec = line.split(' ', 1)
76 84 node = tonode(sha)
77 85 if node in nm:
78 86 refspec = encoding.tolocal(refspec)
79 87 refmap[refspec] = node
80 88 nrefs = nodemap.get(node)
81 89 if nrefs is None:
82 90 nodemap[node] = [refspec]
83 91 else:
84 92 nrefs.append(refspec)
85 93 if nrefs[-2] > refspec:
86 94 # bookmarks weren't sorted before 4.5
87 95 nrefs.sort()
88 96 except (TypeError, ValueError):
89 97 # TypeError:
90 98 # - bin(...)
91 99 # ValueError:
92 100 # - node in nm, for non-20-bytes entry
93 101 # - split(...), for string without ' '
94 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
95 % pycompat.bytestr(line))
102 bookmarkspath = '.hg/bookmarks'
103 if bookmarksinstore(repo):
104 bookmarkspath = '.hg/store/bookmarks'
105 repo.ui.warn(_('malformed line in %s: %r\n')
106 % (bookmarkspath, pycompat.bytestr(line)))
96 107 except IOError as inst:
97 108 if inst.errno != errno.ENOENT:
98 109 raise
99 110 self._active = _readactive(repo, self)
100 111
101 112 @property
102 113 def active(self):
103 114 return self._active
104 115
105 116 @active.setter
106 117 def active(self, mark):
107 118 if mark is not None and mark not in self._refmap:
108 119 raise AssertionError('bookmark %s does not exist!' % mark)
109 120
110 121 self._active = mark
111 122 self._aclean = False
112 123
113 124 def __len__(self):
114 125 return len(self._refmap)
115 126
116 127 def __iter__(self):
117 128 return iter(self._refmap)
118 129
119 130 def iteritems(self):
120 131 return self._refmap.iteritems()
121 132
122 133 def items(self):
123 134 return self._refmap.items()
124 135
125 136 # TODO: maybe rename to allnames()?
126 137 def keys(self):
127 138 return self._refmap.keys()
128 139
129 140 # TODO: maybe rename to allnodes()? but nodes would have to be deduplicated
130 141 # could be self._nodemap.keys()
131 142 def values(self):
132 143 return self._refmap.values()
133 144
134 145 def __contains__(self, mark):
135 146 return mark in self._refmap
136 147
137 148 def __getitem__(self, mark):
138 149 return self._refmap[mark]
139 150
140 151 def get(self, mark, default=None):
141 152 return self._refmap.get(mark, default)
142 153
143 154 def _set(self, mark, node):
144 155 self._clean = False
145 156 if mark in self._refmap:
146 157 self._del(mark)
147 158 self._refmap[mark] = node
148 159 nrefs = self._nodemap.get(node)
149 160 if nrefs is None:
150 161 self._nodemap[node] = [mark]
151 162 else:
152 163 nrefs.append(mark)
153 164 nrefs.sort()
154 165
155 166 def _del(self, mark):
156 167 self._clean = False
157 168 node = self._refmap.pop(mark)
158 169 nrefs = self._nodemap[node]
159 170 if len(nrefs) == 1:
160 171 assert nrefs[0] == mark
161 172 del self._nodemap[node]
162 173 else:
163 174 nrefs.remove(mark)
164 175
165 176 def names(self, node):
166 177 """Return a sorted list of bookmarks pointing to the specified node"""
167 178 return self._nodemap.get(node, [])
168 179
169 180 def changectx(self, mark):
170 181 node = self._refmap[mark]
171 182 return self._repo[node]
172 183
173 184 def applychanges(self, repo, tr, changes):
174 185 """Apply a list of changes to bookmarks
175 186 """
176 187 bmchanges = tr.changes.get('bookmarks')
177 188 for name, node in changes:
178 189 old = self._refmap.get(name)
179 190 if node is None:
180 191 self._del(name)
181 192 else:
182 193 self._set(name, node)
183 194 if bmchanges is not None:
184 195 # if a previous value exist preserve the "initial" value
185 196 previous = bmchanges.get(name)
186 197 if previous is not None:
187 198 old = previous[0]
188 199 bmchanges[name] = (old, node)
189 200 self._recordchange(tr)
190 201
191 202 def _recordchange(self, tr):
192 203 """record that bookmarks have been changed in a transaction
193 204
194 205 The transaction is then responsible for updating the file content."""
206 location = '' if bookmarksinstore(self._repo) else 'plain'
195 207 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
196 location='plain')
208 location=location)
197 209 tr.hookargs['bookmark_moved'] = '1'
198 210
199 211 def _writerepo(self, repo):
200 212 """Factored out for extensibility"""
201 213 rbm = repo._bookmarks
202 214 if rbm.active not in self._refmap:
203 215 rbm.active = None
204 216 rbm._writeactive()
205 217
206 with repo.wlock():
207 with repo.vfs('bookmarks', 'w', atomictemp=True,
208 checkambig=True) as f:
218 if bookmarksinstore(repo):
219 vfs = repo.svfs
220 lock = repo.lock()
221 else:
222 vfs = repo.vfs
223 lock = repo.wlock()
224 with lock:
225 with vfs('bookmarks', 'w', atomictemp=True, checkambig=True) as f:
209 226 self._write(f)
210 227
211 228 def _writeactive(self):
212 229 if self._aclean:
213 230 return
214 231 with self._repo.wlock():
215 232 if self._active is not None:
216 233 with self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
217 234 checkambig=True) as f:
218 235 f.write(encoding.fromlocal(self._active))
219 236 else:
220 237 self._repo.vfs.tryunlink('bookmarks.current')
221 238 self._aclean = True
222 239
223 240 def _write(self, fp):
224 241 for name, node in sorted(self._refmap.iteritems()):
225 242 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
226 243 self._clean = True
227 244 self._repo.invalidatevolatilesets()
228 245
229 246 def expandname(self, bname):
230 247 if bname == '.':
231 248 if self.active:
232 249 return self.active
233 250 else:
234 251 raise error.RepoLookupError(_("no active bookmark"))
235 252 return bname
236 253
237 254 def checkconflict(self, mark, force=False, target=None):
238 255 """check repo for a potential clash of mark with an existing bookmark,
239 256 branch, or hash
240 257
241 258 If target is supplied, then check that we are moving the bookmark
242 259 forward.
243 260
244 261 If force is supplied, then forcibly move the bookmark to a new commit
245 262 regardless if it is a move forward.
246 263
247 264 If divergent bookmark are to be deleted, they will be returned as list.
248 265 """
249 266 cur = self._repo['.'].node()
250 267 if mark in self._refmap and not force:
251 268 if target:
252 269 if self._refmap[mark] == target and target == cur:
253 270 # re-activating a bookmark
254 271 return []
255 272 rev = self._repo[target].rev()
256 273 anc = self._repo.changelog.ancestors([rev])
257 274 bmctx = self.changectx(mark)
258 275 divs = [self._refmap[b] for b in self._refmap
259 276 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
260 277
261 278 # allow resolving a single divergent bookmark even if moving
262 279 # the bookmark across branches when a revision is specified
263 280 # that contains a divergent bookmark
264 281 if bmctx.rev() not in anc and target in divs:
265 282 return divergent2delete(self._repo, [target], mark)
266 283
267 284 deletefrom = [b for b in divs
268 285 if self._repo[b].rev() in anc or b == target]
269 286 delbms = divergent2delete(self._repo, deletefrom, mark)
270 287 if validdest(self._repo, bmctx, self._repo[target]):
271 288 self._repo.ui.status(
272 289 _("moving bookmark '%s' forward from %s\n") %
273 290 (mark, short(bmctx.node())))
274 291 return delbms
275 292 raise error.Abort(_("bookmark '%s' already exists "
276 293 "(use -f to force)") % mark)
277 294 if ((mark in self._repo.branchmap() or
278 295 mark == self._repo.dirstate.branch()) and not force):
279 296 raise error.Abort(
280 297 _("a bookmark cannot have the name of an existing branch"))
281 298 if len(mark) > 3 and not force:
282 299 try:
283 300 shadowhash = scmutil.isrevsymbol(self._repo, mark)
284 301 except error.LookupError: # ambiguous identifier
285 302 shadowhash = False
286 303 if shadowhash:
287 304 self._repo.ui.warn(
288 305 _("bookmark %s matches a changeset hash\n"
289 306 "(did you leave a -r out of an 'hg bookmark' "
290 307 "command?)\n")
291 308 % mark)
292 309 return []
293 310
294 311 def _readactive(repo, marks):
295 312 """
296 313 Get the active bookmark. We can have an active bookmark that updates
297 314 itself as we commit. This function returns the name of that bookmark.
298 315 It is stored in .hg/bookmarks.current
299 316 """
300 317 # No readline() in osutil.posixfile, reading everything is
301 318 # cheap.
302 319 content = repo.vfs.tryread('bookmarks.current')
303 320 mark = encoding.tolocal((content.splitlines() or [''])[0])
304 321 if mark == '' or mark not in marks:
305 322 mark = None
306 323 return mark
307 324
308 325 def activate(repo, mark):
309 326 """
310 327 Set the given bookmark to be 'active', meaning that this bookmark will
311 328 follow new commits that are made.
312 329 The name is recorded in .hg/bookmarks.current
313 330 """
314 331 repo._bookmarks.active = mark
315 332 repo._bookmarks._writeactive()
316 333
317 334 def deactivate(repo):
318 335 """
319 336 Unset the active bookmark in this repository.
320 337 """
321 338 repo._bookmarks.active = None
322 339 repo._bookmarks._writeactive()
323 340
324 341 def isactivewdirparent(repo):
325 342 """
326 343 Tell whether the 'active' bookmark (the one that follows new commits)
327 344 points to one of the parents of the current working directory (wdir).
328 345
329 346 While this is normally the case, it can on occasion be false; for example,
330 347 immediately after a pull, the active bookmark can be moved to point
331 348 to a place different than the wdir. This is solved by running `hg update`.
332 349 """
333 350 mark = repo._activebookmark
334 351 marks = repo._bookmarks
335 352 parents = [p.node() for p in repo[None].parents()]
336 353 return (mark in marks and marks[mark] in parents)
337 354
338 355 def divergent2delete(repo, deletefrom, bm):
339 356 """find divergent versions of bm on nodes in deletefrom.
340 357
341 358 the list of bookmark to delete."""
342 359 todelete = []
343 360 marks = repo._bookmarks
344 361 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
345 362 for mark in divergent:
346 363 if mark == '@' or '@' not in mark:
347 364 # can't be divergent by definition
348 365 continue
349 366 if mark and marks[mark] in deletefrom:
350 367 if mark != bm:
351 368 todelete.append(mark)
352 369 return todelete
353 370
354 371 def headsforactive(repo):
355 372 """Given a repo with an active bookmark, return divergent bookmark nodes.
356 373
357 374 Args:
358 375 repo: A repository with an active bookmark.
359 376
360 377 Returns:
361 378 A list of binary node ids that is the full list of other
362 379 revisions with bookmarks divergent from the active bookmark. If
363 380 there were no divergent bookmarks, then this list will contain
364 381 only one entry.
365 382 """
366 383 if not repo._activebookmark:
367 384 raise ValueError(
368 385 'headsforactive() only makes sense with an active bookmark')
369 386 name = repo._activebookmark.split('@', 1)[0]
370 387 heads = []
371 388 for mark, n in repo._bookmarks.iteritems():
372 389 if mark.split('@', 1)[0] == name:
373 390 heads.append(n)
374 391 return heads
375 392
376 393 def calculateupdate(ui, repo):
377 394 '''Return a tuple (activemark, movemarkfrom) indicating the active bookmark
378 395 and where to move the active bookmark from, if needed.'''
379 396 checkout, movemarkfrom = None, None
380 397 activemark = repo._activebookmark
381 398 if isactivewdirparent(repo):
382 399 movemarkfrom = repo['.'].node()
383 400 elif activemark:
384 401 ui.status(_("updating to active bookmark %s\n") % activemark)
385 402 checkout = activemark
386 403 return (checkout, movemarkfrom)
387 404
388 405 def update(repo, parents, node):
389 406 deletefrom = parents
390 407 marks = repo._bookmarks
391 408 active = marks.active
392 409 if not active:
393 410 return False
394 411
395 412 bmchanges = []
396 413 if marks[active] in parents:
397 414 new = repo[node]
398 415 divs = [marks.changectx(b) for b in marks
399 416 if b.split('@', 1)[0] == active.split('@', 1)[0]]
400 417 anc = repo.changelog.ancestors([new.rev()])
401 418 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
402 419 if validdest(repo, marks.changectx(active), new):
403 420 bmchanges.append((active, new.node()))
404 421
405 422 for bm in divergent2delete(repo, deletefrom, active):
406 423 bmchanges.append((bm, None))
407 424
408 425 if bmchanges:
409 426 with repo.lock(), repo.transaction('bookmark') as tr:
410 427 marks.applychanges(repo, tr, bmchanges)
411 428 return bool(bmchanges)
412 429
413 430 def listbinbookmarks(repo):
414 431 # We may try to list bookmarks on a repo type that does not
415 432 # support it (e.g., statichttprepository).
416 433 marks = getattr(repo, '_bookmarks', {})
417 434
418 435 hasnode = repo.changelog.hasnode
419 436 for k, v in marks.iteritems():
420 437 # don't expose local divergent bookmarks
421 438 if hasnode(v) and ('@' not in k or k.endswith('@')):
422 439 yield k, v
423 440
424 441 def listbookmarks(repo):
425 442 d = {}
426 443 for book, node in listbinbookmarks(repo):
427 444 d[book] = hex(node)
428 445 return d
429 446
430 447 def pushbookmark(repo, key, old, new):
431 with repo.wlock(), repo.lock(), repo.transaction('bookmarks') as tr:
448 if bookmarksinstore(repo):
449 wlock = util.nullcontextmanager()
450 else:
451 wlock = repo.wlock()
452 with wlock, repo.lock(), repo.transaction('bookmarks') as tr:
432 453 marks = repo._bookmarks
433 454 existing = hex(marks.get(key, ''))
434 455 if existing != old and existing != new:
435 456 return False
436 457 if new == '':
437 458 changes = [(key, None)]
438 459 else:
439 460 if new not in repo:
440 461 return False
441 462 changes = [(key, repo[new].node())]
442 463 marks.applychanges(repo, tr, changes)
443 464 return True
444 465
445 466 def comparebookmarks(repo, srcmarks, dstmarks, targets=None):
446 467 '''Compare bookmarks between srcmarks and dstmarks
447 468
448 469 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
449 470 differ, invalid)", each are list of bookmarks below:
450 471
451 472 :addsrc: added on src side (removed on dst side, perhaps)
452 473 :adddst: added on dst side (removed on src side, perhaps)
453 474 :advsrc: advanced on src side
454 475 :advdst: advanced on dst side
455 476 :diverge: diverge
456 477 :differ: changed, but changeset referred on src is unknown on dst
457 478 :invalid: unknown on both side
458 479 :same: same on both side
459 480
460 481 Each elements of lists in result tuple is tuple "(bookmark name,
461 482 changeset ID on source side, changeset ID on destination
462 483 side)". Each changeset IDs are 40 hexadecimal digit string or
463 484 None.
464 485
465 486 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
466 487 "invalid" list may be unknown for repo.
467 488
468 489 If "targets" is specified, only bookmarks listed in it are
469 490 examined.
470 491 '''
471 492
472 493 if targets:
473 494 bset = set(targets)
474 495 else:
475 496 srcmarkset = set(srcmarks)
476 497 dstmarkset = set(dstmarks)
477 498 bset = srcmarkset | dstmarkset
478 499
479 500 results = ([], [], [], [], [], [], [], [])
480 501 addsrc = results[0].append
481 502 adddst = results[1].append
482 503 advsrc = results[2].append
483 504 advdst = results[3].append
484 505 diverge = results[4].append
485 506 differ = results[5].append
486 507 invalid = results[6].append
487 508 same = results[7].append
488 509
489 510 for b in sorted(bset):
490 511 if b not in srcmarks:
491 512 if b in dstmarks:
492 513 adddst((b, None, dstmarks[b]))
493 514 else:
494 515 invalid((b, None, None))
495 516 elif b not in dstmarks:
496 517 addsrc((b, srcmarks[b], None))
497 518 else:
498 519 scid = srcmarks[b]
499 520 dcid = dstmarks[b]
500 521 if scid == dcid:
501 522 same((b, scid, dcid))
502 523 elif scid in repo and dcid in repo:
503 524 sctx = repo[scid]
504 525 dctx = repo[dcid]
505 526 if sctx.rev() < dctx.rev():
506 527 if validdest(repo, sctx, dctx):
507 528 advdst((b, scid, dcid))
508 529 else:
509 530 diverge((b, scid, dcid))
510 531 else:
511 532 if validdest(repo, dctx, sctx):
512 533 advsrc((b, scid, dcid))
513 534 else:
514 535 diverge((b, scid, dcid))
515 536 else:
516 537 # it is too expensive to examine in detail, in this case
517 538 differ((b, scid, dcid))
518 539
519 540 return results
520 541
521 542 def _diverge(ui, b, path, localmarks, remotenode):
522 543 '''Return appropriate diverged bookmark for specified ``path``
523 544
524 545 This returns None, if it is failed to assign any divergent
525 546 bookmark name.
526 547
527 548 This reuses already existing one with "@number" suffix, if it
528 549 refers ``remotenode``.
529 550 '''
530 551 if b == '@':
531 552 b = ''
532 553 # try to use an @pathalias suffix
533 554 # if an @pathalias already exists, we overwrite (update) it
534 555 if path.startswith("file:"):
535 556 path = util.url(path).path
536 557 for p, u in ui.configitems("paths"):
537 558 if u.startswith("file:"):
538 559 u = util.url(u).path
539 560 if path == u:
540 561 return '%s@%s' % (b, p)
541 562
542 563 # assign a unique "@number" suffix newly
543 564 for x in range(1, 100):
544 565 n = '%s@%d' % (b, x)
545 566 if n not in localmarks or localmarks[n] == remotenode:
546 567 return n
547 568
548 569 return None
549 570
550 571 def unhexlifybookmarks(marks):
551 572 binremotemarks = {}
552 573 for name, node in marks.items():
553 574 binremotemarks[name] = bin(node)
554 575 return binremotemarks
555 576
556 577 _binaryentry = struct.Struct('>20sH')
557 578
558 579 def binaryencode(bookmarks):
559 580 """encode a '(bookmark, node)' iterable into a binary stream
560 581
561 582 the binary format is:
562 583
563 584 <node><bookmark-length><bookmark-name>
564 585
565 586 :node: is a 20 bytes binary node,
566 587 :bookmark-length: an unsigned short,
567 588 :bookmark-name: the name of the bookmark (of length <bookmark-length>)
568 589
569 590 wdirid (all bits set) will be used as a special value for "missing"
570 591 """
571 592 binarydata = []
572 593 for book, node in bookmarks:
573 594 if not node: # None or ''
574 595 node = wdirid
575 596 binarydata.append(_binaryentry.pack(node, len(book)))
576 597 binarydata.append(book)
577 598 return ''.join(binarydata)
578 599
579 600 def binarydecode(stream):
580 601 """decode a binary stream into an '(bookmark, node)' iterable
581 602
582 603 the binary format is:
583 604
584 605 <node><bookmark-length><bookmark-name>
585 606
586 607 :node: is a 20 bytes binary node,
587 608 :bookmark-length: an unsigned short,
588 609 :bookmark-name: the name of the bookmark (of length <bookmark-length>))
589 610
590 611 wdirid (all bits set) will be used as a special value for "missing"
591 612 """
592 613 entrysize = _binaryentry.size
593 614 books = []
594 615 while True:
595 616 entry = stream.read(entrysize)
596 617 if len(entry) < entrysize:
597 618 if entry:
598 619 raise error.Abort(_('bad bookmark stream'))
599 620 break
600 621 node, length = _binaryentry.unpack(entry)
601 622 bookmark = stream.read(length)
602 623 if len(bookmark) < length:
603 624 if entry:
604 625 raise error.Abort(_('bad bookmark stream'))
605 626 if node == wdirid:
606 627 node = None
607 628 books.append((bookmark, node))
608 629 return books
609 630
610 631 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
611 632 ui.debug("checking for updated bookmarks\n")
612 633 localmarks = repo._bookmarks
613 634 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
614 635 ) = comparebookmarks(repo, remotemarks, localmarks)
615 636
616 637 status = ui.status
617 638 warn = ui.warn
618 639 if ui.configbool('ui', 'quietbookmarkmove'):
619 640 status = warn = ui.debug
620 641
621 642 explicit = set(explicit)
622 643 changed = []
623 644 for b, scid, dcid in addsrc:
624 645 if scid in repo: # add remote bookmarks for changes we already have
625 646 changed.append((b, scid, status,
626 647 _("adding remote bookmark %s\n") % (b)))
627 648 elif b in explicit:
628 649 explicit.remove(b)
629 650 ui.warn(_("remote bookmark %s points to locally missing %s\n")
630 651 % (b, hex(scid)[:12]))
631 652
632 653 for b, scid, dcid in advsrc:
633 654 changed.append((b, scid, status,
634 655 _("updating bookmark %s\n") % (b)))
635 656 # remove normal movement from explicit set
636 657 explicit.difference_update(d[0] for d in changed)
637 658
638 659 for b, scid, dcid in diverge:
639 660 if b in explicit:
640 661 explicit.discard(b)
641 662 changed.append((b, scid, status,
642 663 _("importing bookmark %s\n") % (b)))
643 664 else:
644 665 db = _diverge(ui, b, path, localmarks, scid)
645 666 if db:
646 667 changed.append((db, scid, warn,
647 668 _("divergent bookmark %s stored as %s\n") %
648 669 (b, db)))
649 670 else:
650 671 warn(_("warning: failed to assign numbered name "
651 672 "to divergent bookmark %s\n") % (b))
652 673 for b, scid, dcid in adddst + advdst:
653 674 if b in explicit:
654 675 explicit.discard(b)
655 676 changed.append((b, scid, status,
656 677 _("importing bookmark %s\n") % (b)))
657 678 for b, scid, dcid in differ:
658 679 if b in explicit:
659 680 explicit.remove(b)
660 681 ui.warn(_("remote bookmark %s points to locally missing %s\n")
661 682 % (b, hex(scid)[:12]))
662 683
663 684 if changed:
664 685 tr = trfunc()
665 686 changes = []
666 687 for b, node, writer, msg in sorted(changed):
667 688 changes.append((b, node))
668 689 writer(msg)
669 690 localmarks.applychanges(repo, tr, changes)
670 691
671 692 def incoming(ui, repo, peer):
672 693 '''Show bookmarks incoming from other to repo
673 694 '''
674 695 ui.status(_("searching for changed bookmarks\n"))
675 696
676 697 with peer.commandexecutor() as e:
677 698 remotemarks = unhexlifybookmarks(e.callcommand('listkeys', {
678 699 'namespace': 'bookmarks',
679 700 }).result())
680 701
681 702 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
682 703 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
683 704
684 705 incomings = []
685 706 if ui.debugflag:
686 707 getid = lambda id: id
687 708 else:
688 709 getid = lambda id: id[:12]
689 710 if ui.verbose:
690 711 def add(b, id, st):
691 712 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
692 713 else:
693 714 def add(b, id, st):
694 715 incomings.append(" %-25s %s\n" % (b, getid(id)))
695 716 for b, scid, dcid in addsrc:
696 717 # i18n: "added" refers to a bookmark
697 718 add(b, hex(scid), _('added'))
698 719 for b, scid, dcid in advsrc:
699 720 # i18n: "advanced" refers to a bookmark
700 721 add(b, hex(scid), _('advanced'))
701 722 for b, scid, dcid in diverge:
702 723 # i18n: "diverged" refers to a bookmark
703 724 add(b, hex(scid), _('diverged'))
704 725 for b, scid, dcid in differ:
705 726 # i18n: "changed" refers to a bookmark
706 727 add(b, hex(scid), _('changed'))
707 728
708 729 if not incomings:
709 730 ui.status(_("no changed bookmarks found\n"))
710 731 return 1
711 732
712 733 for s in sorted(incomings):
713 734 ui.write(s)
714 735
715 736 return 0
716 737
717 738 def outgoing(ui, repo, other):
718 739 '''Show bookmarks outgoing from repo to other
719 740 '''
720 741 ui.status(_("searching for changed bookmarks\n"))
721 742
722 743 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
723 744 r = comparebookmarks(repo, repo._bookmarks, remotemarks)
724 745 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
725 746
726 747 outgoings = []
727 748 if ui.debugflag:
728 749 getid = lambda id: id
729 750 else:
730 751 getid = lambda id: id[:12]
731 752 if ui.verbose:
732 753 def add(b, id, st):
733 754 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
734 755 else:
735 756 def add(b, id, st):
736 757 outgoings.append(" %-25s %s\n" % (b, getid(id)))
737 758 for b, scid, dcid in addsrc:
738 759 # i18n: "added refers to a bookmark
739 760 add(b, hex(scid), _('added'))
740 761 for b, scid, dcid in adddst:
741 762 # i18n: "deleted" refers to a bookmark
742 763 add(b, ' ' * 40, _('deleted'))
743 764 for b, scid, dcid in advsrc:
744 765 # i18n: "advanced" refers to a bookmark
745 766 add(b, hex(scid), _('advanced'))
746 767 for b, scid, dcid in diverge:
747 768 # i18n: "diverged" refers to a bookmark
748 769 add(b, hex(scid), _('diverged'))
749 770 for b, scid, dcid in differ:
750 771 # i18n: "changed" refers to a bookmark
751 772 add(b, hex(scid), _('changed'))
752 773
753 774 if not outgoings:
754 775 ui.status(_("no changed bookmarks found\n"))
755 776 return 1
756 777
757 778 for s in sorted(outgoings):
758 779 ui.write(s)
759 780
760 781 return 0
761 782
762 783 def summary(repo, peer):
763 784 '''Compare bookmarks between repo and other for "hg summary" output
764 785
765 786 This returns "(# of incoming, # of outgoing)" tuple.
766 787 '''
767 788 with peer.commandexecutor() as e:
768 789 remotemarks = unhexlifybookmarks(e.callcommand('listkeys', {
769 790 'namespace': 'bookmarks',
770 791 }).result())
771 792
772 793 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
773 794 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
774 795 return (len(addsrc), len(adddst))
775 796
776 797 def validdest(repo, old, new):
777 798 """Is the new bookmark destination a valid update from the old one"""
778 799 repo = repo.unfiltered()
779 800 if old == new:
780 801 # Old == new -> nothing to update.
781 802 return False
782 803 elif not old:
783 804 # old is nullrev, anything is valid.
784 805 # (new != nullrev has been excluded by the previous check)
785 806 return True
786 807 elif repo.obsstore:
787 808 return new.node() in obsutil.foreground(repo, [old.node()])
788 809 else:
789 810 # still an independent clause as it is lazier (and therefore faster)
790 811 return old.isancestorof(new)
791 812
792 813 def checkformat(repo, mark):
793 814 """return a valid version of a potential bookmark name
794 815
795 816 Raises an abort error if the bookmark name is not valid.
796 817 """
797 818 mark = mark.strip()
798 819 if not mark:
799 820 raise error.Abort(_("bookmark names cannot consist entirely of "
800 821 "whitespace"))
801 822 scmutil.checknewlabel(repo, mark, 'bookmark')
802 823 return mark
803 824
804 825 def delete(repo, tr, names):
805 826 """remove a mark from the bookmark store
806 827
807 828 Raises an abort error if mark does not exist.
808 829 """
809 830 marks = repo._bookmarks
810 831 changes = []
811 832 for mark in names:
812 833 if mark not in marks:
813 834 raise error.Abort(_("bookmark '%s' does not exist") % mark)
814 835 if mark == repo._activebookmark:
815 836 deactivate(repo)
816 837 changes.append((mark, None))
817 838 marks.applychanges(repo, tr, changes)
818 839
819 840 def rename(repo, tr, old, new, force=False, inactive=False):
820 841 """rename a bookmark from old to new
821 842
822 843 If force is specified, then the new name can overwrite an existing
823 844 bookmark.
824 845
825 846 If inactive is specified, then do not activate the new bookmark.
826 847
827 848 Raises an abort error if old is not in the bookmark store.
828 849 """
829 850 marks = repo._bookmarks
830 851 mark = checkformat(repo, new)
831 852 if old not in marks:
832 853 raise error.Abort(_("bookmark '%s' does not exist") % old)
833 854 changes = []
834 855 for bm in marks.checkconflict(mark, force):
835 856 changes.append((bm, None))
836 857 changes.extend([(mark, marks[old]), (old, None)])
837 858 marks.applychanges(repo, tr, changes)
838 859 if repo._activebookmark == old and not inactive:
839 860 activate(repo, mark)
840 861
841 862 def addbookmarks(repo, tr, names, rev=None, force=False, inactive=False):
842 863 """add a list of bookmarks
843 864
844 865 If force is specified, then the new name can overwrite an existing
845 866 bookmark.
846 867
847 868 If inactive is specified, then do not activate any bookmark. Otherwise, the
848 869 first bookmark is activated.
849 870
850 871 Raises an abort error if old is not in the bookmark store.
851 872 """
852 873 marks = repo._bookmarks
853 874 cur = repo['.'].node()
854 875 newact = None
855 876 changes = []
856 877 hiddenrev = None
857 878
858 879 # unhide revs if any
859 880 if rev:
860 881 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
861 882
862 883 for mark in names:
863 884 mark = checkformat(repo, mark)
864 885 if newact is None:
865 886 newact = mark
866 887 if inactive and mark == repo._activebookmark:
867 888 deactivate(repo)
868 889 return
869 890 tgt = cur
870 891 if rev:
871 892 ctx = scmutil.revsingle(repo, rev)
872 893 if ctx.hidden():
873 894 hiddenrev = ctx.hex()[:12]
874 895 tgt = ctx.node()
875 896 for bm in marks.checkconflict(mark, force, tgt):
876 897 changes.append((bm, None))
877 898 changes.append((mark, tgt))
878 899
879 900 if hiddenrev:
880 901 repo.ui.warn(_("bookmarking hidden changeset %s\n") % hiddenrev)
881 902
882 903 if ctx.obsolete():
883 904 msg = obsutil._getfilteredreason(repo, "%s" % hiddenrev, ctx)
884 905 repo.ui.warn("(%s)\n" % msg)
885 906
886 907 marks.applychanges(repo, tr, changes)
887 908 if not inactive and cur == marks[newact] and not rev:
888 909 activate(repo, newact)
889 910 elif cur != tgt and newact == repo._activebookmark:
890 911 deactivate(repo)
891 912
892 913 def _printbookmarks(ui, repo, fm, bmarks):
893 914 """private method to print bookmarks
894 915
895 916 Provides a way for extensions to control how bookmarks are printed (e.g.
896 917 prepend or postpend names)
897 918 """
898 919 hexfn = fm.hexfunc
899 920 if len(bmarks) == 0 and fm.isplain():
900 921 ui.status(_("no bookmarks set\n"))
901 922 for bmark, (n, prefix, label) in sorted(bmarks.iteritems()):
902 923 fm.startitem()
903 924 fm.context(repo=repo)
904 925 if not ui.quiet:
905 926 fm.plain(' %s ' % prefix, label=label)
906 927 fm.write('bookmark', '%s', bmark, label=label)
907 928 pad = " " * (25 - encoding.colwidth(bmark))
908 929 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
909 930 repo.changelog.rev(n), hexfn(n), label=label)
910 931 fm.data(active=(activebookmarklabel in label))
911 932 fm.plain('\n')
912 933
913 934 def printbookmarks(ui, repo, fm, names=None):
914 935 """print bookmarks by the given formatter
915 936
916 937 Provides a way for extensions to control how bookmarks are printed.
917 938 """
918 939 marks = repo._bookmarks
919 940 bmarks = {}
920 941 for bmark in (names or marks):
921 942 if bmark not in marks:
922 943 raise error.Abort(_("bookmark '%s' does not exist") % bmark)
923 944 active = repo._activebookmark
924 945 if bmark == active:
925 946 prefix, label = '*', activebookmarklabel
926 947 else:
927 948 prefix, label = ' ', ''
928 949
929 950 bmarks[bmark] = (marks[bmark], prefix, label)
930 951 _printbookmarks(ui, repo, fm, bmarks)
931 952
932 953 def preparehookargs(name, old, new):
933 954 if new is None:
934 955 new = ''
935 956 if old is None:
936 957 old = ''
937 958 return {'bookmark': name,
938 959 'node': hex(new),
939 960 'oldnode': hex(old)}
@@ -1,1490 +1,1493 b''
1 1 # configitems.py - centralized declaration of configuration option
2 2 #
3 3 # Copyright 2017 Pierre-Yves David <pierre-yves.david@octobus.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import functools
11 11 import re
12 12
13 13 from . import (
14 14 encoding,
15 15 error,
16 16 )
17 17
18 18 def loadconfigtable(ui, extname, configtable):
19 19 """update config item known to the ui with the extension ones"""
20 20 for section, items in sorted(configtable.items()):
21 21 knownitems = ui._knownconfig.setdefault(section, itemregister())
22 22 knownkeys = set(knownitems)
23 23 newkeys = set(items)
24 24 for key in sorted(knownkeys & newkeys):
25 25 msg = "extension '%s' overwrite config item '%s.%s'"
26 26 msg %= (extname, section, key)
27 27 ui.develwarn(msg, config='warn-config')
28 28
29 29 knownitems.update(items)
30 30
31 31 class configitem(object):
32 32 """represent a known config item
33 33
34 34 :section: the official config section where to find this item,
35 35 :name: the official name within the section,
36 36 :default: default value for this item,
37 37 :alias: optional list of tuples as alternatives,
38 38 :generic: this is a generic definition, match name using regular expression.
39 39 """
40 40
41 41 def __init__(self, section, name, default=None, alias=(),
42 42 generic=False, priority=0):
43 43 self.section = section
44 44 self.name = name
45 45 self.default = default
46 46 self.alias = list(alias)
47 47 self.generic = generic
48 48 self.priority = priority
49 49 self._re = None
50 50 if generic:
51 51 self._re = re.compile(self.name)
52 52
53 53 class itemregister(dict):
54 54 """A specialized dictionary that can handle wild-card selection"""
55 55
56 56 def __init__(self):
57 57 super(itemregister, self).__init__()
58 58 self._generics = set()
59 59
60 60 def update(self, other):
61 61 super(itemregister, self).update(other)
62 62 self._generics.update(other._generics)
63 63
64 64 def __setitem__(self, key, item):
65 65 super(itemregister, self).__setitem__(key, item)
66 66 if item.generic:
67 67 self._generics.add(item)
68 68
69 69 def get(self, key):
70 70 baseitem = super(itemregister, self).get(key)
71 71 if baseitem is not None and not baseitem.generic:
72 72 return baseitem
73 73
74 74 # search for a matching generic item
75 75 generics = sorted(self._generics, key=(lambda x: (x.priority, x.name)))
76 76 for item in generics:
77 77 # we use 'match' instead of 'search' to make the matching simpler
78 78 # for people unfamiliar with regular expression. Having the match
79 79 # rooted to the start of the string will produce less surprising
80 80 # result for user writing simple regex for sub-attribute.
81 81 #
82 82 # For example using "color\..*" match produces an unsurprising
83 83 # result, while using search could suddenly match apparently
84 84 # unrelated configuration that happens to contains "color."
85 85 # anywhere. This is a tradeoff where we favor requiring ".*" on
86 86 # some match to avoid the need to prefix most pattern with "^".
87 87 # The "^" seems more error prone.
88 88 if item._re.match(key):
89 89 return item
90 90
91 91 return None
92 92
93 93 coreitems = {}
94 94
95 95 def _register(configtable, *args, **kwargs):
96 96 item = configitem(*args, **kwargs)
97 97 section = configtable.setdefault(item.section, itemregister())
98 98 if item.name in section:
99 99 msg = "duplicated config item registration for '%s.%s'"
100 100 raise error.ProgrammingError(msg % (item.section, item.name))
101 101 section[item.name] = item
102 102
103 103 # special value for case where the default is derived from other values
104 104 dynamicdefault = object()
105 105
106 106 # Registering actual config items
107 107
108 108 def getitemregister(configtable):
109 109 f = functools.partial(_register, configtable)
110 110 # export pseudo enum as configitem.*
111 111 f.dynamicdefault = dynamicdefault
112 112 return f
113 113
114 114 coreconfigitem = getitemregister(coreitems)
115 115
116 116 def _registerdiffopts(section, configprefix=''):
117 117 coreconfigitem(section, configprefix + 'nodates',
118 118 default=False,
119 119 )
120 120 coreconfigitem(section, configprefix + 'showfunc',
121 121 default=False,
122 122 )
123 123 coreconfigitem(section, configprefix + 'unified',
124 124 default=None,
125 125 )
126 126 coreconfigitem(section, configprefix + 'git',
127 127 default=False,
128 128 )
129 129 coreconfigitem(section, configprefix + 'ignorews',
130 130 default=False,
131 131 )
132 132 coreconfigitem(section, configprefix + 'ignorewsamount',
133 133 default=False,
134 134 )
135 135 coreconfigitem(section, configprefix + 'ignoreblanklines',
136 136 default=False,
137 137 )
138 138 coreconfigitem(section, configprefix + 'ignorewseol',
139 139 default=False,
140 140 )
141 141 coreconfigitem(section, configprefix + 'nobinary',
142 142 default=False,
143 143 )
144 144 coreconfigitem(section, configprefix + 'noprefix',
145 145 default=False,
146 146 )
147 147 coreconfigitem(section, configprefix + 'word-diff',
148 148 default=False,
149 149 )
150 150
151 151 coreconfigitem('alias', '.*',
152 152 default=dynamicdefault,
153 153 generic=True,
154 154 )
155 155 coreconfigitem('auth', 'cookiefile',
156 156 default=None,
157 157 )
158 158 _registerdiffopts(section='annotate')
159 159 # bookmarks.pushing: internal hack for discovery
160 160 coreconfigitem('bookmarks', 'pushing',
161 161 default=list,
162 162 )
163 163 # bundle.mainreporoot: internal hack for bundlerepo
164 164 coreconfigitem('bundle', 'mainreporoot',
165 165 default='',
166 166 )
167 167 coreconfigitem('censor', 'policy',
168 168 default='abort',
169 169 )
170 170 coreconfigitem('chgserver', 'idletimeout',
171 171 default=3600,
172 172 )
173 173 coreconfigitem('chgserver', 'skiphash',
174 174 default=False,
175 175 )
176 176 coreconfigitem('cmdserver', 'log',
177 177 default=None,
178 178 )
179 179 coreconfigitem('cmdserver', 'max-log-files',
180 180 default=7,
181 181 )
182 182 coreconfigitem('cmdserver', 'max-log-size',
183 183 default='1 MB',
184 184 )
185 185 coreconfigitem('cmdserver', 'max-repo-cache',
186 186 default=0,
187 187 )
188 188 coreconfigitem('cmdserver', 'message-encodings',
189 189 default=list,
190 190 )
191 191 coreconfigitem('cmdserver', 'track-log',
192 192 default=lambda: ['chgserver', 'cmdserver', 'repocache'],
193 193 )
194 194 coreconfigitem('color', '.*',
195 195 default=None,
196 196 generic=True,
197 197 )
198 198 coreconfigitem('color', 'mode',
199 199 default='auto',
200 200 )
201 201 coreconfigitem('color', 'pagermode',
202 202 default=dynamicdefault,
203 203 )
204 204 _registerdiffopts(section='commands', configprefix='commit.interactive.')
205 205 coreconfigitem('commands', 'commit.post-status',
206 206 default=False,
207 207 )
208 208 coreconfigitem('commands', 'grep.all-files',
209 209 default=False,
210 210 )
211 211 coreconfigitem('commands', 'resolve.confirm',
212 212 default=False,
213 213 )
214 214 coreconfigitem('commands', 'resolve.explicit-re-merge',
215 215 default=False,
216 216 )
217 217 coreconfigitem('commands', 'resolve.mark-check',
218 218 default='none',
219 219 )
220 220 _registerdiffopts(section='commands', configprefix='revert.interactive.')
221 221 coreconfigitem('commands', 'show.aliasprefix',
222 222 default=list,
223 223 )
224 224 coreconfigitem('commands', 'status.relative',
225 225 default=False,
226 226 )
227 227 coreconfigitem('commands', 'status.skipstates',
228 228 default=[],
229 229 )
230 230 coreconfigitem('commands', 'status.terse',
231 231 default='',
232 232 )
233 233 coreconfigitem('commands', 'status.verbose',
234 234 default=False,
235 235 )
236 236 coreconfigitem('commands', 'update.check',
237 237 default=None,
238 238 )
239 239 coreconfigitem('commands', 'update.requiredest',
240 240 default=False,
241 241 )
242 242 coreconfigitem('committemplate', '.*',
243 243 default=None,
244 244 generic=True,
245 245 )
246 246 coreconfigitem('convert', 'bzr.saverev',
247 247 default=True,
248 248 )
249 249 coreconfigitem('convert', 'cvsps.cache',
250 250 default=True,
251 251 )
252 252 coreconfigitem('convert', 'cvsps.fuzz',
253 253 default=60,
254 254 )
255 255 coreconfigitem('convert', 'cvsps.logencoding',
256 256 default=None,
257 257 )
258 258 coreconfigitem('convert', 'cvsps.mergefrom',
259 259 default=None,
260 260 )
261 261 coreconfigitem('convert', 'cvsps.mergeto',
262 262 default=None,
263 263 )
264 264 coreconfigitem('convert', 'git.committeractions',
265 265 default=lambda: ['messagedifferent'],
266 266 )
267 267 coreconfigitem('convert', 'git.extrakeys',
268 268 default=list,
269 269 )
270 270 coreconfigitem('convert', 'git.findcopiesharder',
271 271 default=False,
272 272 )
273 273 coreconfigitem('convert', 'git.remoteprefix',
274 274 default='remote',
275 275 )
276 276 coreconfigitem('convert', 'git.renamelimit',
277 277 default=400,
278 278 )
279 279 coreconfigitem('convert', 'git.saverev',
280 280 default=True,
281 281 )
282 282 coreconfigitem('convert', 'git.similarity',
283 283 default=50,
284 284 )
285 285 coreconfigitem('convert', 'git.skipsubmodules',
286 286 default=False,
287 287 )
288 288 coreconfigitem('convert', 'hg.clonebranches',
289 289 default=False,
290 290 )
291 291 coreconfigitem('convert', 'hg.ignoreerrors',
292 292 default=False,
293 293 )
294 294 coreconfigitem('convert', 'hg.revs',
295 295 default=None,
296 296 )
297 297 coreconfigitem('convert', 'hg.saverev',
298 298 default=False,
299 299 )
300 300 coreconfigitem('convert', 'hg.sourcename',
301 301 default=None,
302 302 )
303 303 coreconfigitem('convert', 'hg.startrev',
304 304 default=None,
305 305 )
306 306 coreconfigitem('convert', 'hg.tagsbranch',
307 307 default='default',
308 308 )
309 309 coreconfigitem('convert', 'hg.usebranchnames',
310 310 default=True,
311 311 )
312 312 coreconfigitem('convert', 'ignoreancestorcheck',
313 313 default=False,
314 314 )
315 315 coreconfigitem('convert', 'localtimezone',
316 316 default=False,
317 317 )
318 318 coreconfigitem('convert', 'p4.encoding',
319 319 default=dynamicdefault,
320 320 )
321 321 coreconfigitem('convert', 'p4.startrev',
322 322 default=0,
323 323 )
324 324 coreconfigitem('convert', 'skiptags',
325 325 default=False,
326 326 )
327 327 coreconfigitem('convert', 'svn.debugsvnlog',
328 328 default=True,
329 329 )
330 330 coreconfigitem('convert', 'svn.trunk',
331 331 default=None,
332 332 )
333 333 coreconfigitem('convert', 'svn.tags',
334 334 default=None,
335 335 )
336 336 coreconfigitem('convert', 'svn.branches',
337 337 default=None,
338 338 )
339 339 coreconfigitem('convert', 'svn.startrev',
340 340 default=0,
341 341 )
342 342 coreconfigitem('debug', 'dirstate.delaywrite',
343 343 default=0,
344 344 )
345 345 coreconfigitem('defaults', '.*',
346 346 default=None,
347 347 generic=True,
348 348 )
349 349 coreconfigitem('devel', 'all-warnings',
350 350 default=False,
351 351 )
352 352 coreconfigitem('devel', 'bundle2.debug',
353 353 default=False,
354 354 )
355 355 coreconfigitem('devel', 'bundle.delta',
356 356 default='',
357 357 )
358 358 coreconfigitem('devel', 'cache-vfs',
359 359 default=None,
360 360 )
361 361 coreconfigitem('devel', 'check-locks',
362 362 default=False,
363 363 )
364 364 coreconfigitem('devel', 'check-relroot',
365 365 default=False,
366 366 )
367 367 coreconfigitem('devel', 'default-date',
368 368 default=None,
369 369 )
370 370 coreconfigitem('devel', 'deprec-warn',
371 371 default=False,
372 372 )
373 373 coreconfigitem('devel', 'disableloaddefaultcerts',
374 374 default=False,
375 375 )
376 376 coreconfigitem('devel', 'warn-empty-changegroup',
377 377 default=False,
378 378 )
379 379 coreconfigitem('devel', 'legacy.exchange',
380 380 default=list,
381 381 )
382 382 coreconfigitem('devel', 'servercafile',
383 383 default='',
384 384 )
385 385 coreconfigitem('devel', 'serverexactprotocol',
386 386 default='',
387 387 )
388 388 coreconfigitem('devel', 'serverrequirecert',
389 389 default=False,
390 390 )
391 391 coreconfigitem('devel', 'strip-obsmarkers',
392 392 default=True,
393 393 )
394 394 coreconfigitem('devel', 'warn-config',
395 395 default=None,
396 396 )
397 397 coreconfigitem('devel', 'warn-config-default',
398 398 default=None,
399 399 )
400 400 coreconfigitem('devel', 'user.obsmarker',
401 401 default=None,
402 402 )
403 403 coreconfigitem('devel', 'warn-config-unknown',
404 404 default=None,
405 405 )
406 406 coreconfigitem('devel', 'debug.copies',
407 407 default=False,
408 408 )
409 409 coreconfigitem('devel', 'debug.extensions',
410 410 default=False,
411 411 )
412 412 coreconfigitem('devel', 'debug.peer-request',
413 413 default=False,
414 414 )
415 415 _registerdiffopts(section='diff')
416 416 coreconfigitem('email', 'bcc',
417 417 default=None,
418 418 )
419 419 coreconfigitem('email', 'cc',
420 420 default=None,
421 421 )
422 422 coreconfigitem('email', 'charsets',
423 423 default=list,
424 424 )
425 425 coreconfigitem('email', 'from',
426 426 default=None,
427 427 )
428 428 coreconfigitem('email', 'method',
429 429 default='smtp',
430 430 )
431 431 coreconfigitem('email', 'reply-to',
432 432 default=None,
433 433 )
434 434 coreconfigitem('email', 'to',
435 435 default=None,
436 436 )
437 437 coreconfigitem('experimental', 'archivemetatemplate',
438 438 default=dynamicdefault,
439 439 )
440 440 coreconfigitem('experimental', 'auto-publish',
441 441 default='publish',
442 442 )
443 443 coreconfigitem('experimental', 'bundle-phases',
444 444 default=False,
445 445 )
446 446 coreconfigitem('experimental', 'bundle2-advertise',
447 447 default=True,
448 448 )
449 449 coreconfigitem('experimental', 'bundle2-output-capture',
450 450 default=False,
451 451 )
452 452 coreconfigitem('experimental', 'bundle2.pushback',
453 453 default=False,
454 454 )
455 455 coreconfigitem('experimental', 'bundle2lazylocking',
456 456 default=False,
457 457 )
458 458 coreconfigitem('experimental', 'bundlecomplevel',
459 459 default=None,
460 460 )
461 461 coreconfigitem('experimental', 'bundlecomplevel.bzip2',
462 462 default=None,
463 463 )
464 464 coreconfigitem('experimental', 'bundlecomplevel.gzip',
465 465 default=None,
466 466 )
467 467 coreconfigitem('experimental', 'bundlecomplevel.none',
468 468 default=None,
469 469 )
470 470 coreconfigitem('experimental', 'bundlecomplevel.zstd',
471 471 default=None,
472 472 )
473 473 coreconfigitem('experimental', 'changegroup3',
474 474 default=False,
475 475 )
476 476 coreconfigitem('experimental', 'cleanup-as-archived',
477 477 default=False,
478 478 )
479 479 coreconfigitem('experimental', 'clientcompressionengines',
480 480 default=list,
481 481 )
482 482 coreconfigitem('experimental', 'copytrace',
483 483 default='on',
484 484 )
485 485 coreconfigitem('experimental', 'copytrace.movecandidateslimit',
486 486 default=100,
487 487 )
488 488 coreconfigitem('experimental', 'copytrace.sourcecommitlimit',
489 489 default=100,
490 490 )
491 491 coreconfigitem('experimental', 'copies.read-from',
492 492 default="filelog-only",
493 493 )
494 494 coreconfigitem('experimental', 'copies.write-to',
495 495 default='filelog-only',
496 496 )
497 497 coreconfigitem('experimental', 'crecordtest',
498 498 default=None,
499 499 )
500 500 coreconfigitem('experimental', 'directaccess',
501 501 default=False,
502 502 )
503 503 coreconfigitem('experimental', 'directaccess.revnums',
504 504 default=False,
505 505 )
506 506 coreconfigitem('experimental', 'editortmpinhg',
507 507 default=False,
508 508 )
509 509 coreconfigitem('experimental', 'evolution',
510 510 default=list,
511 511 )
512 512 coreconfigitem('experimental', 'evolution.allowdivergence',
513 513 default=False,
514 514 alias=[('experimental', 'allowdivergence')]
515 515 )
516 516 coreconfigitem('experimental', 'evolution.allowunstable',
517 517 default=None,
518 518 )
519 519 coreconfigitem('experimental', 'evolution.createmarkers',
520 520 default=None,
521 521 )
522 522 coreconfigitem('experimental', 'evolution.effect-flags',
523 523 default=True,
524 524 alias=[('experimental', 'effect-flags')]
525 525 )
526 526 coreconfigitem('experimental', 'evolution.exchange',
527 527 default=None,
528 528 )
529 529 coreconfigitem('experimental', 'evolution.bundle-obsmarker',
530 530 default=False,
531 531 )
532 532 coreconfigitem('experimental', 'log.topo',
533 533 default=False,
534 534 )
535 535 coreconfigitem('experimental', 'evolution.report-instabilities',
536 536 default=True,
537 537 )
538 538 coreconfigitem('experimental', 'evolution.track-operation',
539 539 default=True,
540 540 )
541 541 # repo-level config to exclude a revset visibility
542 542 #
543 543 # The target use case is to use `share` to expose different subset of the same
544 544 # repository, especially server side. See also `server.view`.
545 545 coreconfigitem('experimental', 'extra-filter-revs',
546 546 default=None,
547 547 )
548 548 coreconfigitem('experimental', 'maxdeltachainspan',
549 549 default=-1,
550 550 )
551 551 coreconfigitem('experimental', 'mergetempdirprefix',
552 552 default=None,
553 553 )
554 554 coreconfigitem('experimental', 'mmapindexthreshold',
555 555 default=None,
556 556 )
557 557 coreconfigitem('experimental', 'narrow',
558 558 default=False,
559 559 )
560 560 coreconfigitem('experimental', 'nonnormalparanoidcheck',
561 561 default=False,
562 562 )
563 563 coreconfigitem('experimental', 'exportableenviron',
564 564 default=list,
565 565 )
566 566 coreconfigitem('experimental', 'extendedheader.index',
567 567 default=None,
568 568 )
569 569 coreconfigitem('experimental', 'extendedheader.similarity',
570 570 default=False,
571 571 )
572 572 coreconfigitem('experimental', 'graphshorten',
573 573 default=False,
574 574 )
575 575 coreconfigitem('experimental', 'graphstyle.parent',
576 576 default=dynamicdefault,
577 577 )
578 578 coreconfigitem('experimental', 'graphstyle.missing',
579 579 default=dynamicdefault,
580 580 )
581 581 coreconfigitem('experimental', 'graphstyle.grandparent',
582 582 default=dynamicdefault,
583 583 )
584 584 coreconfigitem('experimental', 'hook-track-tags',
585 585 default=False,
586 586 )
587 587 coreconfigitem('experimental', 'httppeer.advertise-v2',
588 588 default=False,
589 589 )
590 590 coreconfigitem('experimental', 'httppeer.v2-encoder-order',
591 591 default=None,
592 592 )
593 593 coreconfigitem('experimental', 'httppostargs',
594 594 default=False,
595 595 )
596 596 coreconfigitem('experimental', 'mergedriver',
597 597 default=None,
598 598 )
599 599 coreconfigitem('experimental', 'nointerrupt', default=False)
600 600 coreconfigitem('experimental', 'nointerrupt-interactiveonly', default=True)
601 601
602 602 coreconfigitem('experimental', 'obsmarkers-exchange-debug',
603 603 default=False,
604 604 )
605 605 coreconfigitem('experimental', 'remotenames',
606 606 default=False,
607 607 )
608 608 coreconfigitem('experimental', 'removeemptydirs',
609 609 default=True,
610 610 )
611 611 coreconfigitem('experimental', 'revert.interactive.select-to-keep',
612 612 default=False,
613 613 )
614 614 coreconfigitem('experimental', 'revisions.prefixhexnode',
615 615 default=False,
616 616 )
617 617 coreconfigitem('experimental', 'revlogv2',
618 618 default=None,
619 619 )
620 620 coreconfigitem('experimental', 'revisions.disambiguatewithin',
621 621 default=None,
622 622 )
623 623 coreconfigitem('experimental', 'server.filesdata.recommended-batch-size',
624 624 default=50000,
625 625 )
626 626 coreconfigitem('experimental', 'server.manifestdata.recommended-batch-size',
627 627 default=100000,
628 628 )
629 629 coreconfigitem('experimental', 'server.stream-narrow-clones',
630 630 default=False,
631 631 )
632 632 coreconfigitem('experimental', 'single-head-per-branch',
633 633 default=False,
634 634 )
635 635 coreconfigitem('experimental', 'sshserver.support-v2',
636 636 default=False,
637 637 )
638 638 coreconfigitem('experimental', 'sparse-read',
639 639 default=False,
640 640 )
641 641 coreconfigitem('experimental', 'sparse-read.density-threshold',
642 642 default=0.50,
643 643 )
644 644 coreconfigitem('experimental', 'sparse-read.min-gap-size',
645 645 default='65K',
646 646 )
647 647 coreconfigitem('experimental', 'treemanifest',
648 648 default=False,
649 649 )
650 650 coreconfigitem('experimental', 'update.atomic-file',
651 651 default=False,
652 652 )
653 653 coreconfigitem('experimental', 'sshpeer.advertise-v2',
654 654 default=False,
655 655 )
656 656 coreconfigitem('experimental', 'web.apiserver',
657 657 default=False,
658 658 )
659 659 coreconfigitem('experimental', 'web.api.http-v2',
660 660 default=False,
661 661 )
662 662 coreconfigitem('experimental', 'web.api.debugreflect',
663 663 default=False,
664 664 )
665 665 coreconfigitem('experimental', 'worker.wdir-get-thread-safe',
666 666 default=False,
667 667 )
668 668 coreconfigitem('experimental', 'xdiff',
669 669 default=False,
670 670 )
671 671 coreconfigitem('extensions', '.*',
672 672 default=None,
673 673 generic=True,
674 674 )
675 675 coreconfigitem('extdata', '.*',
676 676 default=None,
677 677 generic=True,
678 678 )
679 coreconfigitem('format', 'bookmarks-in-store',
680 default=False,
681 )
679 682 coreconfigitem('format', 'chunkcachesize',
680 683 default=None,
681 684 )
682 685 coreconfigitem('format', 'dotencode',
683 686 default=True,
684 687 )
685 688 coreconfigitem('format', 'generaldelta',
686 689 default=False,
687 690 )
688 691 coreconfigitem('format', 'manifestcachesize',
689 692 default=None,
690 693 )
691 694 coreconfigitem('format', 'maxchainlen',
692 695 default=dynamicdefault,
693 696 )
694 697 coreconfigitem('format', 'obsstore-version',
695 698 default=None,
696 699 )
697 700 coreconfigitem('format', 'sparse-revlog',
698 701 default=True,
699 702 )
700 703 coreconfigitem('format', 'revlog-compression',
701 704 default='zlib',
702 705 alias=[('experimental', 'format.compression')]
703 706 )
704 707 coreconfigitem('format', 'usefncache',
705 708 default=True,
706 709 )
707 710 coreconfigitem('format', 'usegeneraldelta',
708 711 default=True,
709 712 )
710 713 coreconfigitem('format', 'usestore',
711 714 default=True,
712 715 )
713 716 coreconfigitem('format', 'internal-phase',
714 717 default=False,
715 718 )
716 719 coreconfigitem('fsmonitor', 'warn_when_unused',
717 720 default=True,
718 721 )
719 722 coreconfigitem('fsmonitor', 'warn_update_file_count',
720 723 default=50000,
721 724 )
722 725 coreconfigitem('help', br'hidden-command\..*',
723 726 default=False,
724 727 generic=True,
725 728 )
726 729 coreconfigitem('help', br'hidden-topic\..*',
727 730 default=False,
728 731 generic=True,
729 732 )
730 733 coreconfigitem('hooks', '.*',
731 734 default=dynamicdefault,
732 735 generic=True,
733 736 )
734 737 coreconfigitem('hgweb-paths', '.*',
735 738 default=list,
736 739 generic=True,
737 740 )
738 741 coreconfigitem('hostfingerprints', '.*',
739 742 default=list,
740 743 generic=True,
741 744 )
742 745 coreconfigitem('hostsecurity', 'ciphers',
743 746 default=None,
744 747 )
745 748 coreconfigitem('hostsecurity', 'disabletls10warning',
746 749 default=False,
747 750 )
748 751 coreconfigitem('hostsecurity', 'minimumprotocol',
749 752 default=dynamicdefault,
750 753 )
751 754 coreconfigitem('hostsecurity', '.*:minimumprotocol$',
752 755 default=dynamicdefault,
753 756 generic=True,
754 757 )
755 758 coreconfigitem('hostsecurity', '.*:ciphers$',
756 759 default=dynamicdefault,
757 760 generic=True,
758 761 )
759 762 coreconfigitem('hostsecurity', '.*:fingerprints$',
760 763 default=list,
761 764 generic=True,
762 765 )
763 766 coreconfigitem('hostsecurity', '.*:verifycertsfile$',
764 767 default=None,
765 768 generic=True,
766 769 )
767 770
768 771 coreconfigitem('http_proxy', 'always',
769 772 default=False,
770 773 )
771 774 coreconfigitem('http_proxy', 'host',
772 775 default=None,
773 776 )
774 777 coreconfigitem('http_proxy', 'no',
775 778 default=list,
776 779 )
777 780 coreconfigitem('http_proxy', 'passwd',
778 781 default=None,
779 782 )
780 783 coreconfigitem('http_proxy', 'user',
781 784 default=None,
782 785 )
783 786
784 787 coreconfigitem('http', 'timeout',
785 788 default=None,
786 789 )
787 790
788 791 coreconfigitem('logtoprocess', 'commandexception',
789 792 default=None,
790 793 )
791 794 coreconfigitem('logtoprocess', 'commandfinish',
792 795 default=None,
793 796 )
794 797 coreconfigitem('logtoprocess', 'command',
795 798 default=None,
796 799 )
797 800 coreconfigitem('logtoprocess', 'develwarn',
798 801 default=None,
799 802 )
800 803 coreconfigitem('logtoprocess', 'uiblocked',
801 804 default=None,
802 805 )
803 806 coreconfigitem('merge', 'checkunknown',
804 807 default='abort',
805 808 )
806 809 coreconfigitem('merge', 'checkignored',
807 810 default='abort',
808 811 )
809 812 coreconfigitem('experimental', 'merge.checkpathconflicts',
810 813 default=False,
811 814 )
812 815 coreconfigitem('merge', 'followcopies',
813 816 default=True,
814 817 )
815 818 coreconfigitem('merge', 'on-failure',
816 819 default='continue',
817 820 )
818 821 coreconfigitem('merge', 'preferancestor',
819 822 default=lambda: ['*'],
820 823 )
821 824 coreconfigitem('merge', 'strict-capability-check',
822 825 default=False,
823 826 )
824 827 coreconfigitem('merge-tools', '.*',
825 828 default=None,
826 829 generic=True,
827 830 )
828 831 coreconfigitem('merge-tools', br'.*\.args$',
829 832 default="$local $base $other",
830 833 generic=True,
831 834 priority=-1,
832 835 )
833 836 coreconfigitem('merge-tools', br'.*\.binary$',
834 837 default=False,
835 838 generic=True,
836 839 priority=-1,
837 840 )
838 841 coreconfigitem('merge-tools', br'.*\.check$',
839 842 default=list,
840 843 generic=True,
841 844 priority=-1,
842 845 )
843 846 coreconfigitem('merge-tools', br'.*\.checkchanged$',
844 847 default=False,
845 848 generic=True,
846 849 priority=-1,
847 850 )
848 851 coreconfigitem('merge-tools', br'.*\.executable$',
849 852 default=dynamicdefault,
850 853 generic=True,
851 854 priority=-1,
852 855 )
853 856 coreconfigitem('merge-tools', br'.*\.fixeol$',
854 857 default=False,
855 858 generic=True,
856 859 priority=-1,
857 860 )
858 861 coreconfigitem('merge-tools', br'.*\.gui$',
859 862 default=False,
860 863 generic=True,
861 864 priority=-1,
862 865 )
863 866 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
864 867 default='basic',
865 868 generic=True,
866 869 priority=-1,
867 870 )
868 871 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
869 872 default=dynamicdefault, # take from ui.mergemarkertemplate
870 873 generic=True,
871 874 priority=-1,
872 875 )
873 876 coreconfigitem('merge-tools', br'.*\.priority$',
874 877 default=0,
875 878 generic=True,
876 879 priority=-1,
877 880 )
878 881 coreconfigitem('merge-tools', br'.*\.premerge$',
879 882 default=dynamicdefault,
880 883 generic=True,
881 884 priority=-1,
882 885 )
883 886 coreconfigitem('merge-tools', br'.*\.symlink$',
884 887 default=False,
885 888 generic=True,
886 889 priority=-1,
887 890 )
888 891 coreconfigitem('pager', 'attend-.*',
889 892 default=dynamicdefault,
890 893 generic=True,
891 894 )
892 895 coreconfigitem('pager', 'ignore',
893 896 default=list,
894 897 )
895 898 coreconfigitem('pager', 'pager',
896 899 default=dynamicdefault,
897 900 )
898 901 coreconfigitem('patch', 'eol',
899 902 default='strict',
900 903 )
901 904 coreconfigitem('patch', 'fuzz',
902 905 default=2,
903 906 )
904 907 coreconfigitem('paths', 'default',
905 908 default=None,
906 909 )
907 910 coreconfigitem('paths', 'default-push',
908 911 default=None,
909 912 )
910 913 coreconfigitem('paths', '.*',
911 914 default=None,
912 915 generic=True,
913 916 )
914 917 coreconfigitem('phases', 'checksubrepos',
915 918 default='follow',
916 919 )
917 920 coreconfigitem('phases', 'new-commit',
918 921 default='draft',
919 922 )
920 923 coreconfigitem('phases', 'publish',
921 924 default=True,
922 925 )
923 926 coreconfigitem('profiling', 'enabled',
924 927 default=False,
925 928 )
926 929 coreconfigitem('profiling', 'format',
927 930 default='text',
928 931 )
929 932 coreconfigitem('profiling', 'freq',
930 933 default=1000,
931 934 )
932 935 coreconfigitem('profiling', 'limit',
933 936 default=30,
934 937 )
935 938 coreconfigitem('profiling', 'nested',
936 939 default=0,
937 940 )
938 941 coreconfigitem('profiling', 'output',
939 942 default=None,
940 943 )
941 944 coreconfigitem('profiling', 'showmax',
942 945 default=0.999,
943 946 )
944 947 coreconfigitem('profiling', 'showmin',
945 948 default=dynamicdefault,
946 949 )
947 950 coreconfigitem('profiling', 'sort',
948 951 default='inlinetime',
949 952 )
950 953 coreconfigitem('profiling', 'statformat',
951 954 default='hotpath',
952 955 )
953 956 coreconfigitem('profiling', 'time-track',
954 957 default=dynamicdefault,
955 958 )
956 959 coreconfigitem('profiling', 'type',
957 960 default='stat',
958 961 )
959 962 coreconfigitem('progress', 'assume-tty',
960 963 default=False,
961 964 )
962 965 coreconfigitem('progress', 'changedelay',
963 966 default=1,
964 967 )
965 968 coreconfigitem('progress', 'clear-complete',
966 969 default=True,
967 970 )
968 971 coreconfigitem('progress', 'debug',
969 972 default=False,
970 973 )
971 974 coreconfigitem('progress', 'delay',
972 975 default=3,
973 976 )
974 977 coreconfigitem('progress', 'disable',
975 978 default=False,
976 979 )
977 980 coreconfigitem('progress', 'estimateinterval',
978 981 default=60.0,
979 982 )
980 983 coreconfigitem('progress', 'format',
981 984 default=lambda: ['topic', 'bar', 'number', 'estimate'],
982 985 )
983 986 coreconfigitem('progress', 'refresh',
984 987 default=0.1,
985 988 )
986 989 coreconfigitem('progress', 'width',
987 990 default=dynamicdefault,
988 991 )
989 992 coreconfigitem('push', 'pushvars.server',
990 993 default=False,
991 994 )
992 995 coreconfigitem('rewrite', 'backup-bundle',
993 996 default=True,
994 997 alias=[('ui', 'history-editing-backup')],
995 998 )
996 999 coreconfigitem('rewrite', 'update-timestamp',
997 1000 default=False,
998 1001 )
999 1002 coreconfigitem('storage', 'new-repo-backend',
1000 1003 default='revlogv1',
1001 1004 )
1002 1005 coreconfigitem('storage', 'revlog.optimize-delta-parent-choice',
1003 1006 default=True,
1004 1007 alias=[('format', 'aggressivemergedeltas')],
1005 1008 )
1006 1009 coreconfigitem('storage', 'revlog.reuse-external-delta',
1007 1010 default=True,
1008 1011 )
1009 1012 coreconfigitem('storage', 'revlog.reuse-external-delta-parent',
1010 1013 default=None,
1011 1014 )
1012 1015 coreconfigitem('storage', 'revlog.zlib.level',
1013 1016 default=None,
1014 1017 )
1015 1018 coreconfigitem('storage', 'revlog.zstd.level',
1016 1019 default=None,
1017 1020 )
1018 1021 coreconfigitem('server', 'bookmarks-pushkey-compat',
1019 1022 default=True,
1020 1023 )
1021 1024 coreconfigitem('server', 'bundle1',
1022 1025 default=True,
1023 1026 )
1024 1027 coreconfigitem('server', 'bundle1gd',
1025 1028 default=None,
1026 1029 )
1027 1030 coreconfigitem('server', 'bundle1.pull',
1028 1031 default=None,
1029 1032 )
1030 1033 coreconfigitem('server', 'bundle1gd.pull',
1031 1034 default=None,
1032 1035 )
1033 1036 coreconfigitem('server', 'bundle1.push',
1034 1037 default=None,
1035 1038 )
1036 1039 coreconfigitem('server', 'bundle1gd.push',
1037 1040 default=None,
1038 1041 )
1039 1042 coreconfigitem('server', 'bundle2.stream',
1040 1043 default=True,
1041 1044 alias=[('experimental', 'bundle2.stream')]
1042 1045 )
1043 1046 coreconfigitem('server', 'compressionengines',
1044 1047 default=list,
1045 1048 )
1046 1049 coreconfigitem('server', 'concurrent-push-mode',
1047 1050 default='strict',
1048 1051 )
1049 1052 coreconfigitem('server', 'disablefullbundle',
1050 1053 default=False,
1051 1054 )
1052 1055 coreconfigitem('server', 'maxhttpheaderlen',
1053 1056 default=1024,
1054 1057 )
1055 1058 coreconfigitem('server', 'pullbundle',
1056 1059 default=False,
1057 1060 )
1058 1061 coreconfigitem('server', 'preferuncompressed',
1059 1062 default=False,
1060 1063 )
1061 1064 coreconfigitem('server', 'streamunbundle',
1062 1065 default=False,
1063 1066 )
1064 1067 coreconfigitem('server', 'uncompressed',
1065 1068 default=True,
1066 1069 )
1067 1070 coreconfigitem('server', 'uncompressedallowsecret',
1068 1071 default=False,
1069 1072 )
1070 1073 coreconfigitem('server', 'view',
1071 1074 default='served',
1072 1075 )
1073 1076 coreconfigitem('server', 'validate',
1074 1077 default=False,
1075 1078 )
1076 1079 coreconfigitem('server', 'zliblevel',
1077 1080 default=-1,
1078 1081 )
1079 1082 coreconfigitem('server', 'zstdlevel',
1080 1083 default=3,
1081 1084 )
1082 1085 coreconfigitem('share', 'pool',
1083 1086 default=None,
1084 1087 )
1085 1088 coreconfigitem('share', 'poolnaming',
1086 1089 default='identity',
1087 1090 )
1088 1091 coreconfigitem('smtp', 'host',
1089 1092 default=None,
1090 1093 )
1091 1094 coreconfigitem('smtp', 'local_hostname',
1092 1095 default=None,
1093 1096 )
1094 1097 coreconfigitem('smtp', 'password',
1095 1098 default=None,
1096 1099 )
1097 1100 coreconfigitem('smtp', 'port',
1098 1101 default=dynamicdefault,
1099 1102 )
1100 1103 coreconfigitem('smtp', 'tls',
1101 1104 default='none',
1102 1105 )
1103 1106 coreconfigitem('smtp', 'username',
1104 1107 default=None,
1105 1108 )
1106 1109 coreconfigitem('sparse', 'missingwarning',
1107 1110 default=True,
1108 1111 )
1109 1112 coreconfigitem('subrepos', 'allowed',
1110 1113 default=dynamicdefault, # to make backporting simpler
1111 1114 )
1112 1115 coreconfigitem('subrepos', 'hg:allowed',
1113 1116 default=dynamicdefault,
1114 1117 )
1115 1118 coreconfigitem('subrepos', 'git:allowed',
1116 1119 default=dynamicdefault,
1117 1120 )
1118 1121 coreconfigitem('subrepos', 'svn:allowed',
1119 1122 default=dynamicdefault,
1120 1123 )
1121 1124 coreconfigitem('templates', '.*',
1122 1125 default=None,
1123 1126 generic=True,
1124 1127 )
1125 1128 coreconfigitem('templateconfig', '.*',
1126 1129 default=dynamicdefault,
1127 1130 generic=True,
1128 1131 )
1129 1132 coreconfigitem('trusted', 'groups',
1130 1133 default=list,
1131 1134 )
1132 1135 coreconfigitem('trusted', 'users',
1133 1136 default=list,
1134 1137 )
1135 1138 coreconfigitem('ui', '_usedassubrepo',
1136 1139 default=False,
1137 1140 )
1138 1141 coreconfigitem('ui', 'allowemptycommit',
1139 1142 default=False,
1140 1143 )
1141 1144 coreconfigitem('ui', 'archivemeta',
1142 1145 default=True,
1143 1146 )
1144 1147 coreconfigitem('ui', 'askusername',
1145 1148 default=False,
1146 1149 )
1147 1150 coreconfigitem('ui', 'clonebundlefallback',
1148 1151 default=False,
1149 1152 )
1150 1153 coreconfigitem('ui', 'clonebundleprefers',
1151 1154 default=list,
1152 1155 )
1153 1156 coreconfigitem('ui', 'clonebundles',
1154 1157 default=True,
1155 1158 )
1156 1159 coreconfigitem('ui', 'color',
1157 1160 default='auto',
1158 1161 )
1159 1162 coreconfigitem('ui', 'commitsubrepos',
1160 1163 default=False,
1161 1164 )
1162 1165 coreconfigitem('ui', 'debug',
1163 1166 default=False,
1164 1167 )
1165 1168 coreconfigitem('ui', 'debugger',
1166 1169 default=None,
1167 1170 )
1168 1171 coreconfigitem('ui', 'editor',
1169 1172 default=dynamicdefault,
1170 1173 )
1171 1174 coreconfigitem('ui', 'fallbackencoding',
1172 1175 default=None,
1173 1176 )
1174 1177 coreconfigitem('ui', 'forcecwd',
1175 1178 default=None,
1176 1179 )
1177 1180 coreconfigitem('ui', 'forcemerge',
1178 1181 default=None,
1179 1182 )
1180 1183 coreconfigitem('ui', 'formatdebug',
1181 1184 default=False,
1182 1185 )
1183 1186 coreconfigitem('ui', 'formatjson',
1184 1187 default=False,
1185 1188 )
1186 1189 coreconfigitem('ui', 'formatted',
1187 1190 default=None,
1188 1191 )
1189 1192 coreconfigitem('ui', 'graphnodetemplate',
1190 1193 default=None,
1191 1194 )
1192 1195 coreconfigitem('ui', 'interactive',
1193 1196 default=None,
1194 1197 )
1195 1198 coreconfigitem('ui', 'interface',
1196 1199 default=None,
1197 1200 )
1198 1201 coreconfigitem('ui', 'interface.chunkselector',
1199 1202 default=None,
1200 1203 )
1201 1204 coreconfigitem('ui', 'large-file-limit',
1202 1205 default=10000000,
1203 1206 )
1204 1207 coreconfigitem('ui', 'logblockedtimes',
1205 1208 default=False,
1206 1209 )
1207 1210 coreconfigitem('ui', 'logtemplate',
1208 1211 default=None,
1209 1212 )
1210 1213 coreconfigitem('ui', 'merge',
1211 1214 default=None,
1212 1215 )
1213 1216 coreconfigitem('ui', 'mergemarkers',
1214 1217 default='basic',
1215 1218 )
1216 1219 coreconfigitem('ui', 'mergemarkertemplate',
1217 1220 default=('{node|short} '
1218 1221 '{ifeq(tags, "tip", "", '
1219 1222 'ifeq(tags, "", "", "{tags} "))}'
1220 1223 '{if(bookmarks, "{bookmarks} ")}'
1221 1224 '{ifeq(branch, "default", "", "{branch} ")}'
1222 1225 '- {author|user}: {desc|firstline}')
1223 1226 )
1224 1227 coreconfigitem('ui', 'message-output',
1225 1228 default='stdio',
1226 1229 )
1227 1230 coreconfigitem('ui', 'nontty',
1228 1231 default=False,
1229 1232 )
1230 1233 coreconfigitem('ui', 'origbackuppath',
1231 1234 default=None,
1232 1235 )
1233 1236 coreconfigitem('ui', 'paginate',
1234 1237 default=True,
1235 1238 )
1236 1239 coreconfigitem('ui', 'patch',
1237 1240 default=None,
1238 1241 )
1239 1242 coreconfigitem('ui', 'pre-merge-tool-output-template',
1240 1243 default=None,
1241 1244 )
1242 1245 coreconfigitem('ui', 'portablefilenames',
1243 1246 default='warn',
1244 1247 )
1245 1248 coreconfigitem('ui', 'promptecho',
1246 1249 default=False,
1247 1250 )
1248 1251 coreconfigitem('ui', 'quiet',
1249 1252 default=False,
1250 1253 )
1251 1254 coreconfigitem('ui', 'quietbookmarkmove',
1252 1255 default=False,
1253 1256 )
1254 1257 coreconfigitem('ui', 'relative-paths',
1255 1258 default='legacy',
1256 1259 )
1257 1260 coreconfigitem('ui', 'remotecmd',
1258 1261 default='hg',
1259 1262 )
1260 1263 coreconfigitem('ui', 'report_untrusted',
1261 1264 default=True,
1262 1265 )
1263 1266 coreconfigitem('ui', 'rollback',
1264 1267 default=True,
1265 1268 )
1266 1269 coreconfigitem('ui', 'signal-safe-lock',
1267 1270 default=True,
1268 1271 )
1269 1272 coreconfigitem('ui', 'slash',
1270 1273 default=False,
1271 1274 )
1272 1275 coreconfigitem('ui', 'ssh',
1273 1276 default='ssh',
1274 1277 )
1275 1278 coreconfigitem('ui', 'ssherrorhint',
1276 1279 default=None,
1277 1280 )
1278 1281 coreconfigitem('ui', 'statuscopies',
1279 1282 default=False,
1280 1283 )
1281 1284 coreconfigitem('ui', 'strict',
1282 1285 default=False,
1283 1286 )
1284 1287 coreconfigitem('ui', 'style',
1285 1288 default='',
1286 1289 )
1287 1290 coreconfigitem('ui', 'supportcontact',
1288 1291 default=None,
1289 1292 )
1290 1293 coreconfigitem('ui', 'textwidth',
1291 1294 default=78,
1292 1295 )
1293 1296 coreconfigitem('ui', 'timeout',
1294 1297 default='600',
1295 1298 )
1296 1299 coreconfigitem('ui', 'timeout.warn',
1297 1300 default=0,
1298 1301 )
1299 1302 coreconfigitem('ui', 'traceback',
1300 1303 default=False,
1301 1304 )
1302 1305 coreconfigitem('ui', 'tweakdefaults',
1303 1306 default=False,
1304 1307 )
1305 1308 coreconfigitem('ui', 'username',
1306 1309 alias=[('ui', 'user')]
1307 1310 )
1308 1311 coreconfigitem('ui', 'verbose',
1309 1312 default=False,
1310 1313 )
1311 1314 coreconfigitem('verify', 'skipflags',
1312 1315 default=None,
1313 1316 )
1314 1317 coreconfigitem('web', 'allowbz2',
1315 1318 default=False,
1316 1319 )
1317 1320 coreconfigitem('web', 'allowgz',
1318 1321 default=False,
1319 1322 )
1320 1323 coreconfigitem('web', 'allow-pull',
1321 1324 alias=[('web', 'allowpull')],
1322 1325 default=True,
1323 1326 )
1324 1327 coreconfigitem('web', 'allow-push',
1325 1328 alias=[('web', 'allow_push')],
1326 1329 default=list,
1327 1330 )
1328 1331 coreconfigitem('web', 'allowzip',
1329 1332 default=False,
1330 1333 )
1331 1334 coreconfigitem('web', 'archivesubrepos',
1332 1335 default=False,
1333 1336 )
1334 1337 coreconfigitem('web', 'cache',
1335 1338 default=True,
1336 1339 )
1337 1340 coreconfigitem('web', 'comparisoncontext',
1338 1341 default=5,
1339 1342 )
1340 1343 coreconfigitem('web', 'contact',
1341 1344 default=None,
1342 1345 )
1343 1346 coreconfigitem('web', 'deny_push',
1344 1347 default=list,
1345 1348 )
1346 1349 coreconfigitem('web', 'guessmime',
1347 1350 default=False,
1348 1351 )
1349 1352 coreconfigitem('web', 'hidden',
1350 1353 default=False,
1351 1354 )
1352 1355 coreconfigitem('web', 'labels',
1353 1356 default=list,
1354 1357 )
1355 1358 coreconfigitem('web', 'logoimg',
1356 1359 default='hglogo.png',
1357 1360 )
1358 1361 coreconfigitem('web', 'logourl',
1359 1362 default='https://mercurial-scm.org/',
1360 1363 )
1361 1364 coreconfigitem('web', 'accesslog',
1362 1365 default='-',
1363 1366 )
1364 1367 coreconfigitem('web', 'address',
1365 1368 default='',
1366 1369 )
1367 1370 coreconfigitem('web', 'allow-archive',
1368 1371 alias=[('web', 'allow_archive')],
1369 1372 default=list,
1370 1373 )
1371 1374 coreconfigitem('web', 'allow_read',
1372 1375 default=list,
1373 1376 )
1374 1377 coreconfigitem('web', 'baseurl',
1375 1378 default=None,
1376 1379 )
1377 1380 coreconfigitem('web', 'cacerts',
1378 1381 default=None,
1379 1382 )
1380 1383 coreconfigitem('web', 'certificate',
1381 1384 default=None,
1382 1385 )
1383 1386 coreconfigitem('web', 'collapse',
1384 1387 default=False,
1385 1388 )
1386 1389 coreconfigitem('web', 'csp',
1387 1390 default=None,
1388 1391 )
1389 1392 coreconfigitem('web', 'deny_read',
1390 1393 default=list,
1391 1394 )
1392 1395 coreconfigitem('web', 'descend',
1393 1396 default=True,
1394 1397 )
1395 1398 coreconfigitem('web', 'description',
1396 1399 default="",
1397 1400 )
1398 1401 coreconfigitem('web', 'encoding',
1399 1402 default=lambda: encoding.encoding,
1400 1403 )
1401 1404 coreconfigitem('web', 'errorlog',
1402 1405 default='-',
1403 1406 )
1404 1407 coreconfigitem('web', 'ipv6',
1405 1408 default=False,
1406 1409 )
1407 1410 coreconfigitem('web', 'maxchanges',
1408 1411 default=10,
1409 1412 )
1410 1413 coreconfigitem('web', 'maxfiles',
1411 1414 default=10,
1412 1415 )
1413 1416 coreconfigitem('web', 'maxshortchanges',
1414 1417 default=60,
1415 1418 )
1416 1419 coreconfigitem('web', 'motd',
1417 1420 default='',
1418 1421 )
1419 1422 coreconfigitem('web', 'name',
1420 1423 default=dynamicdefault,
1421 1424 )
1422 1425 coreconfigitem('web', 'port',
1423 1426 default=8000,
1424 1427 )
1425 1428 coreconfigitem('web', 'prefix',
1426 1429 default='',
1427 1430 )
1428 1431 coreconfigitem('web', 'push_ssl',
1429 1432 default=True,
1430 1433 )
1431 1434 coreconfigitem('web', 'refreshinterval',
1432 1435 default=20,
1433 1436 )
1434 1437 coreconfigitem('web', 'server-header',
1435 1438 default=None,
1436 1439 )
1437 1440 coreconfigitem('web', 'static',
1438 1441 default=None,
1439 1442 )
1440 1443 coreconfigitem('web', 'staticurl',
1441 1444 default=None,
1442 1445 )
1443 1446 coreconfigitem('web', 'stripes',
1444 1447 default=1,
1445 1448 )
1446 1449 coreconfigitem('web', 'style',
1447 1450 default='paper',
1448 1451 )
1449 1452 coreconfigitem('web', 'templates',
1450 1453 default=None,
1451 1454 )
1452 1455 coreconfigitem('web', 'view',
1453 1456 default='served',
1454 1457 )
1455 1458 coreconfigitem('worker', 'backgroundclose',
1456 1459 default=dynamicdefault,
1457 1460 )
1458 1461 # Windows defaults to a limit of 512 open files. A buffer of 128
1459 1462 # should give us enough headway.
1460 1463 coreconfigitem('worker', 'backgroundclosemaxqueue',
1461 1464 default=384,
1462 1465 )
1463 1466 coreconfigitem('worker', 'backgroundcloseminfilecount',
1464 1467 default=2048,
1465 1468 )
1466 1469 coreconfigitem('worker', 'backgroundclosethreadcount',
1467 1470 default=4,
1468 1471 )
1469 1472 coreconfigitem('worker', 'enabled',
1470 1473 default=True,
1471 1474 )
1472 1475 coreconfigitem('worker', 'numcpus',
1473 1476 default=None,
1474 1477 )
1475 1478
1476 1479 # Rebase related configuration moved to core because other extension are doing
1477 1480 # strange things. For example, shelve import the extensions to reuse some bit
1478 1481 # without formally loading it.
1479 1482 coreconfigitem('commands', 'rebase.requiredest',
1480 1483 default=False,
1481 1484 )
1482 1485 coreconfigitem('experimental', 'rebaseskipobsolete',
1483 1486 default=True,
1484 1487 )
1485 1488 coreconfigitem('rebase', 'singletransaction',
1486 1489 default=False,
1487 1490 )
1488 1491 coreconfigitem('rebase', 'experimental.inmemory',
1489 1492 default=False,
1490 1493 )
@@ -1,2847 +1,2856 b''
1 1 The Mercurial system uses a set of configuration files to control
2 2 aspects of its behavior.
3 3
4 4 Troubleshooting
5 5 ===============
6 6
7 7 If you're having problems with your configuration,
8 8 :hg:`config --debug` can help you understand what is introducing
9 9 a setting into your environment.
10 10
11 11 See :hg:`help config.syntax` and :hg:`help config.files`
12 12 for information about how and where to override things.
13 13
14 14 Structure
15 15 =========
16 16
17 17 The configuration files use a simple ini-file format. A configuration
18 18 file consists of sections, led by a ``[section]`` header and followed
19 19 by ``name = value`` entries::
20 20
21 21 [ui]
22 22 username = Firstname Lastname <firstname.lastname@example.net>
23 23 verbose = True
24 24
25 25 The above entries will be referred to as ``ui.username`` and
26 26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
27 27
28 28 Files
29 29 =====
30 30
31 31 Mercurial reads configuration data from several files, if they exist.
32 32 These files do not exist by default and you will have to create the
33 33 appropriate configuration files yourself:
34 34
35 35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
36 36
37 37 Global configuration like the username setting is typically put into:
38 38
39 39 .. container:: windows
40 40
41 41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
42 42
43 43 .. container:: unix.plan9
44 44
45 45 - ``$HOME/.hgrc`` (on Unix, Plan9)
46 46
47 47 The names of these files depend on the system on which Mercurial is
48 48 installed. ``*.rc`` files from a single directory are read in
49 49 alphabetical order, later ones overriding earlier ones. Where multiple
50 50 paths are given below, settings from earlier paths override later
51 51 ones.
52 52
53 53 .. container:: verbose.unix
54 54
55 55 On Unix, the following files are consulted:
56 56
57 57 - ``<repo>/.hg/hgrc`` (per-repository)
58 58 - ``$HOME/.hgrc`` (per-user)
59 59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
60 60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
61 61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
62 62 - ``/etc/mercurial/hgrc`` (per-system)
63 63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
64 64 - ``<internal>/default.d/*.rc`` (defaults)
65 65
66 66 .. container:: verbose.windows
67 67
68 68 On Windows, the following files are consulted:
69 69
70 70 - ``<repo>/.hg/hgrc`` (per-repository)
71 71 - ``%USERPROFILE%\.hgrc`` (per-user)
72 72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
73 73 - ``%HOME%\.hgrc`` (per-user)
74 74 - ``%HOME%\Mercurial.ini`` (per-user)
75 75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
76 76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
77 77 - ``<install-dir>\Mercurial.ini`` (per-installation)
78 78 - ``<internal>/default.d/*.rc`` (defaults)
79 79
80 80 .. note::
81 81
82 82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
83 83 is used when running 32-bit Python on 64-bit Windows.
84 84
85 85 .. container:: windows
86 86
87 87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
88 88
89 89 .. container:: verbose.plan9
90 90
91 91 On Plan9, the following files are consulted:
92 92
93 93 - ``<repo>/.hg/hgrc`` (per-repository)
94 94 - ``$home/lib/hgrc`` (per-user)
95 95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
96 96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
97 97 - ``/lib/mercurial/hgrc`` (per-system)
98 98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
99 99 - ``<internal>/default.d/*.rc`` (defaults)
100 100
101 101 Per-repository configuration options only apply in a
102 102 particular repository. This file is not version-controlled, and
103 103 will not get transferred during a "clone" operation. Options in
104 104 this file override options in all other configuration files.
105 105
106 106 .. container:: unix.plan9
107 107
108 108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
109 109 belong to a trusted user or to a trusted group. See
110 110 :hg:`help config.trusted` for more details.
111 111
112 112 Per-user configuration file(s) are for the user running Mercurial. Options
113 113 in these files apply to all Mercurial commands executed by this user in any
114 114 directory. Options in these files override per-system and per-installation
115 115 options.
116 116
117 117 Per-installation configuration files are searched for in the
118 118 directory where Mercurial is installed. ``<install-root>`` is the
119 119 parent directory of the **hg** executable (or symlink) being run.
120 120
121 121 .. container:: unix.plan9
122 122
123 123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
124 124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
125 125 files apply to all Mercurial commands executed by any user in any
126 126 directory.
127 127
128 128 Per-installation configuration files are for the system on
129 129 which Mercurial is running. Options in these files apply to all
130 130 Mercurial commands executed by any user in any directory. Registry
131 131 keys contain PATH-like strings, every part of which must reference
132 132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
133 133 be read. Mercurial checks each of these locations in the specified
134 134 order until one or more configuration files are detected.
135 135
136 136 Per-system configuration files are for the system on which Mercurial
137 137 is running. Options in these files apply to all Mercurial commands
138 138 executed by any user in any directory. Options in these files
139 139 override per-installation options.
140 140
141 141 Mercurial comes with some default configuration. The default configuration
142 142 files are installed with Mercurial and will be overwritten on upgrades. Default
143 143 configuration files should never be edited by users or administrators but can
144 144 be overridden in other configuration files. So far the directory only contains
145 145 merge tool configuration but packagers can also put other default configuration
146 146 there.
147 147
148 148 Syntax
149 149 ======
150 150
151 151 A configuration file consists of sections, led by a ``[section]`` header
152 152 and followed by ``name = value`` entries (sometimes called
153 153 ``configuration keys``)::
154 154
155 155 [spam]
156 156 eggs=ham
157 157 green=
158 158 eggs
159 159
160 160 Each line contains one entry. If the lines that follow are indented,
161 161 they are treated as continuations of that entry. Leading whitespace is
162 162 removed from values. Empty lines are skipped. Lines beginning with
163 163 ``#`` or ``;`` are ignored and may be used to provide comments.
164 164
165 165 Configuration keys can be set multiple times, in which case Mercurial
166 166 will use the value that was configured last. As an example::
167 167
168 168 [spam]
169 169 eggs=large
170 170 ham=serrano
171 171 eggs=small
172 172
173 173 This would set the configuration key named ``eggs`` to ``small``.
174 174
175 175 It is also possible to define a section multiple times. A section can
176 176 be redefined on the same and/or on different configuration files. For
177 177 example::
178 178
179 179 [foo]
180 180 eggs=large
181 181 ham=serrano
182 182 eggs=small
183 183
184 184 [bar]
185 185 eggs=ham
186 186 green=
187 187 eggs
188 188
189 189 [foo]
190 190 ham=prosciutto
191 191 eggs=medium
192 192 bread=toasted
193 193
194 194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
195 195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
196 196 respectively. As you can see there only thing that matters is the last
197 197 value that was set for each of the configuration keys.
198 198
199 199 If a configuration key is set multiple times in different
200 200 configuration files the final value will depend on the order in which
201 201 the different configuration files are read, with settings from earlier
202 202 paths overriding later ones as described on the ``Files`` section
203 203 above.
204 204
205 205 A line of the form ``%include file`` will include ``file`` into the
206 206 current configuration file. The inclusion is recursive, which means
207 207 that included files can include other files. Filenames are relative to
208 208 the configuration file in which the ``%include`` directive is found.
209 209 Environment variables and ``~user`` constructs are expanded in
210 210 ``file``. This lets you do something like::
211 211
212 212 %include ~/.hgrc.d/$HOST.rc
213 213
214 214 to include a different configuration file on each computer you use.
215 215
216 216 A line with ``%unset name`` will remove ``name`` from the current
217 217 section, if it has been set previously.
218 218
219 219 The values are either free-form text strings, lists of text strings,
220 220 or Boolean values. Boolean values can be set to true using any of "1",
221 221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
222 222 (all case insensitive).
223 223
224 224 List values are separated by whitespace or comma, except when values are
225 225 placed in double quotation marks::
226 226
227 227 allow_read = "John Doe, PhD", brian, betty
228 228
229 229 Quotation marks can be escaped by prefixing them with a backslash. Only
230 230 quotation marks at the beginning of a word is counted as a quotation
231 231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
232 232
233 233 Sections
234 234 ========
235 235
236 236 This section describes the different sections that may appear in a
237 237 Mercurial configuration file, the purpose of each section, its possible
238 238 keys, and their possible values.
239 239
240 240 ``alias``
241 241 ---------
242 242
243 243 Defines command aliases.
244 244
245 245 Aliases allow you to define your own commands in terms of other
246 246 commands (or aliases), optionally including arguments. Positional
247 247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
248 248 are expanded by Mercurial before execution. Positional arguments not
249 249 already used by ``$N`` in the definition are put at the end of the
250 250 command to be executed.
251 251
252 252 Alias definitions consist of lines of the form::
253 253
254 254 <alias> = <command> [<argument>]...
255 255
256 256 For example, this definition::
257 257
258 258 latest = log --limit 5
259 259
260 260 creates a new command ``latest`` that shows only the five most recent
261 261 changesets. You can define subsequent aliases using earlier ones::
262 262
263 263 stable5 = latest -b stable
264 264
265 265 .. note::
266 266
267 267 It is possible to create aliases with the same names as
268 268 existing commands, which will then override the original
269 269 definitions. This is almost always a bad idea!
270 270
271 271 An alias can start with an exclamation point (``!``) to make it a
272 272 shell alias. A shell alias is executed with the shell and will let you
273 273 run arbitrary commands. As an example, ::
274 274
275 275 echo = !echo $@
276 276
277 277 will let you do ``hg echo foo`` to have ``foo`` printed in your
278 278 terminal. A better example might be::
279 279
280 280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
281 281
282 282 which will make ``hg purge`` delete all unknown files in the
283 283 repository in the same manner as the purge extension.
284 284
285 285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
286 286 expand to the command arguments. Unmatched arguments are
287 287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
288 288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
289 289 arguments quoted individually and separated by a space. These expansions
290 290 happen before the command is passed to the shell.
291 291
292 292 Shell aliases are executed in an environment where ``$HG`` expands to
293 293 the path of the Mercurial that was used to execute the alias. This is
294 294 useful when you want to call further Mercurial commands in a shell
295 295 alias, as was done above for the purge alias. In addition,
296 296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
297 297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
298 298
299 299 .. note::
300 300
301 301 Some global configuration options such as ``-R`` are
302 302 processed before shell aliases and will thus not be passed to
303 303 aliases.
304 304
305 305
306 306 ``annotate``
307 307 ------------
308 308
309 309 Settings used when displaying file annotations. All values are
310 310 Booleans and default to False. See :hg:`help config.diff` for
311 311 related options for the diff command.
312 312
313 313 ``ignorews``
314 314 Ignore white space when comparing lines.
315 315
316 316 ``ignorewseol``
317 317 Ignore white space at the end of a line when comparing lines.
318 318
319 319 ``ignorewsamount``
320 320 Ignore changes in the amount of white space.
321 321
322 322 ``ignoreblanklines``
323 323 Ignore changes whose lines are all blank.
324 324
325 325
326 326 ``auth``
327 327 --------
328 328
329 329 Authentication credentials and other authentication-like configuration
330 330 for HTTP connections. This section allows you to store usernames and
331 331 passwords for use when logging *into* HTTP servers. See
332 332 :hg:`help config.web` if you want to configure *who* can login to
333 333 your HTTP server.
334 334
335 335 The following options apply to all hosts.
336 336
337 337 ``cookiefile``
338 338 Path to a file containing HTTP cookie lines. Cookies matching a
339 339 host will be sent automatically.
340 340
341 341 The file format uses the Mozilla cookies.txt format, which defines cookies
342 342 on their own lines. Each line contains 7 fields delimited by the tab
343 343 character (domain, is_domain_cookie, path, is_secure, expires, name,
344 344 value). For more info, do an Internet search for "Netscape cookies.txt
345 345 format."
346 346
347 347 Note: the cookies parser does not handle port numbers on domains. You
348 348 will need to remove ports from the domain for the cookie to be recognized.
349 349 This could result in a cookie being disclosed to an unwanted server.
350 350
351 351 The cookies file is read-only.
352 352
353 353 Other options in this section are grouped by name and have the following
354 354 format::
355 355
356 356 <name>.<argument> = <value>
357 357
358 358 where ``<name>`` is used to group arguments into authentication
359 359 entries. Example::
360 360
361 361 foo.prefix = hg.intevation.de/mercurial
362 362 foo.username = foo
363 363 foo.password = bar
364 364 foo.schemes = http https
365 365
366 366 bar.prefix = secure.example.org
367 367 bar.key = path/to/file.key
368 368 bar.cert = path/to/file.cert
369 369 bar.schemes = https
370 370
371 371 Supported arguments:
372 372
373 373 ``prefix``
374 374 Either ``*`` or a URI prefix with or without the scheme part.
375 375 The authentication entry with the longest matching prefix is used
376 376 (where ``*`` matches everything and counts as a match of length
377 377 1). If the prefix doesn't include a scheme, the match is performed
378 378 against the URI with its scheme stripped as well, and the schemes
379 379 argument, q.v., is then subsequently consulted.
380 380
381 381 ``username``
382 382 Optional. Username to authenticate with. If not given, and the
383 383 remote site requires basic or digest authentication, the user will
384 384 be prompted for it. Environment variables are expanded in the
385 385 username letting you do ``foo.username = $USER``. If the URI
386 386 includes a username, only ``[auth]`` entries with a matching
387 387 username or without a username will be considered.
388 388
389 389 ``password``
390 390 Optional. Password to authenticate with. If not given, and the
391 391 remote site requires basic or digest authentication, the user
392 392 will be prompted for it.
393 393
394 394 ``key``
395 395 Optional. PEM encoded client certificate key file. Environment
396 396 variables are expanded in the filename.
397 397
398 398 ``cert``
399 399 Optional. PEM encoded client certificate chain file. Environment
400 400 variables are expanded in the filename.
401 401
402 402 ``schemes``
403 403 Optional. Space separated list of URI schemes to use this
404 404 authentication entry with. Only used if the prefix doesn't include
405 405 a scheme. Supported schemes are http and https. They will match
406 406 static-http and static-https respectively, as well.
407 407 (default: https)
408 408
409 409 If no suitable authentication entry is found, the user is prompted
410 410 for credentials as usual if required by the remote.
411 411
412 412 ``color``
413 413 ---------
414 414
415 415 Configure the Mercurial color mode. For details about how to define your custom
416 416 effect and style see :hg:`help color`.
417 417
418 418 ``mode``
419 419 String: control the method used to output color. One of ``auto``, ``ansi``,
420 420 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
421 421 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
422 422 terminal. Any invalid value will disable color.
423 423
424 424 ``pagermode``
425 425 String: optional override of ``color.mode`` used with pager.
426 426
427 427 On some systems, terminfo mode may cause problems when using
428 428 color with ``less -R`` as a pager program. less with the -R option
429 429 will only display ECMA-48 color codes, and terminfo mode may sometimes
430 430 emit codes that less doesn't understand. You can work around this by
431 431 either using ansi mode (or auto mode), or by using less -r (which will
432 432 pass through all terminal control codes, not just color control
433 433 codes).
434 434
435 435 On some systems (such as MSYS in Windows), the terminal may support
436 436 a different color mode than the pager program.
437 437
438 438 ``commands``
439 439 ------------
440 440
441 441 ``commit.post-status``
442 442 Show status of files in the working directory after successful commit.
443 443 (default: False)
444 444
445 445 ``resolve.confirm``
446 446 Confirm before performing action if no filename is passed.
447 447 (default: False)
448 448
449 449 ``resolve.explicit-re-merge``
450 450 Require uses of ``hg resolve`` to specify which action it should perform,
451 451 instead of re-merging files by default.
452 452 (default: False)
453 453
454 454 ``resolve.mark-check``
455 455 Determines what level of checking :hg:`resolve --mark` will perform before
456 456 marking files as resolved. Valid values are ``none`, ``warn``, and
457 457 ``abort``. ``warn`` will output a warning listing the file(s) that still
458 458 have conflict markers in them, but will still mark everything resolved.
459 459 ``abort`` will output the same warning but will not mark things as resolved.
460 460 If --all is passed and this is set to ``abort``, only a warning will be
461 461 shown (an error will not be raised).
462 462 (default: ``none``)
463 463
464 464 ``status.relative``
465 465 Make paths in :hg:`status` output relative to the current directory.
466 466 (default: False)
467 467
468 468 ``status.terse``
469 469 Default value for the --terse flag, which condenses status output.
470 470 (default: empty)
471 471
472 472 ``update.check``
473 473 Determines what level of checking :hg:`update` will perform before moving
474 474 to a destination revision. Valid values are ``abort``, ``none``,
475 475 ``linear``, and ``noconflict``. ``abort`` always fails if the working
476 476 directory has uncommitted changes. ``none`` performs no checking, and may
477 477 result in a merge with uncommitted changes. ``linear`` allows any update
478 478 as long as it follows a straight line in the revision history, and may
479 479 trigger a merge with uncommitted changes. ``noconflict`` will allow any
480 480 update which would not trigger a merge with uncommitted changes, if any
481 481 are present.
482 482 (default: ``linear``)
483 483
484 484 ``update.requiredest``
485 485 Require that the user pass a destination when running :hg:`update`.
486 486 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
487 487 will be disallowed.
488 488 (default: False)
489 489
490 490 ``committemplate``
491 491 ------------------
492 492
493 493 ``changeset``
494 494 String: configuration in this section is used as the template to
495 495 customize the text shown in the editor when committing.
496 496
497 497 In addition to pre-defined template keywords, commit log specific one
498 498 below can be used for customization:
499 499
500 500 ``extramsg``
501 501 String: Extra message (typically 'Leave message empty to abort
502 502 commit.'). This may be changed by some commands or extensions.
503 503
504 504 For example, the template configuration below shows as same text as
505 505 one shown by default::
506 506
507 507 [committemplate]
508 508 changeset = {desc}\n\n
509 509 HG: Enter commit message. Lines beginning with 'HG:' are removed.
510 510 HG: {extramsg}
511 511 HG: --
512 512 HG: user: {author}\n{ifeq(p2rev, "-1", "",
513 513 "HG: branch merge\n")
514 514 }HG: branch '{branch}'\n{if(activebookmark,
515 515 "HG: bookmark '{activebookmark}'\n") }{subrepos %
516 516 "HG: subrepo {subrepo}\n" }{file_adds %
517 517 "HG: added {file}\n" }{file_mods %
518 518 "HG: changed {file}\n" }{file_dels %
519 519 "HG: removed {file}\n" }{if(files, "",
520 520 "HG: no files changed\n")}
521 521
522 522 ``diff()``
523 523 String: show the diff (see :hg:`help templates` for detail)
524 524
525 525 Sometimes it is helpful to show the diff of the changeset in the editor without
526 526 having to prefix 'HG: ' to each line so that highlighting works correctly. For
527 527 this, Mercurial provides a special string which will ignore everything below
528 528 it::
529 529
530 530 HG: ------------------------ >8 ------------------------
531 531
532 532 For example, the template configuration below will show the diff below the
533 533 extra message::
534 534
535 535 [committemplate]
536 536 changeset = {desc}\n\n
537 537 HG: Enter commit message. Lines beginning with 'HG:' are removed.
538 538 HG: {extramsg}
539 539 HG: ------------------------ >8 ------------------------
540 540 HG: Do not touch the line above.
541 541 HG: Everything below will be removed.
542 542 {diff()}
543 543
544 544 .. note::
545 545
546 546 For some problematic encodings (see :hg:`help win32mbcs` for
547 547 detail), this customization should be configured carefully, to
548 548 avoid showing broken characters.
549 549
550 550 For example, if a multibyte character ending with backslash (0x5c) is
551 551 followed by the ASCII character 'n' in the customized template,
552 552 the sequence of backslash and 'n' is treated as line-feed unexpectedly
553 553 (and the multibyte character is broken, too).
554 554
555 555 Customized template is used for commands below (``--edit`` may be
556 556 required):
557 557
558 558 - :hg:`backout`
559 559 - :hg:`commit`
560 560 - :hg:`fetch` (for merge commit only)
561 561 - :hg:`graft`
562 562 - :hg:`histedit`
563 563 - :hg:`import`
564 564 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
565 565 - :hg:`rebase`
566 566 - :hg:`shelve`
567 567 - :hg:`sign`
568 568 - :hg:`tag`
569 569 - :hg:`transplant`
570 570
571 571 Configuring items below instead of ``changeset`` allows showing
572 572 customized message only for specific actions, or showing different
573 573 messages for each action.
574 574
575 575 - ``changeset.backout`` for :hg:`backout`
576 576 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
577 577 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
578 578 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
579 579 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
580 580 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
581 581 - ``changeset.gpg.sign`` for :hg:`sign`
582 582 - ``changeset.graft`` for :hg:`graft`
583 583 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
584 584 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
585 585 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
586 586 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
587 587 - ``changeset.import.bypass`` for :hg:`import --bypass`
588 588 - ``changeset.import.normal.merge`` for :hg:`import` on merges
589 589 - ``changeset.import.normal.normal`` for :hg:`import` on other
590 590 - ``changeset.mq.qnew`` for :hg:`qnew`
591 591 - ``changeset.mq.qfold`` for :hg:`qfold`
592 592 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
593 593 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
594 594 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
595 595 - ``changeset.rebase.normal`` for :hg:`rebase` on other
596 596 - ``changeset.shelve.shelve`` for :hg:`shelve`
597 597 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
598 598 - ``changeset.tag.remove`` for :hg:`tag --remove`
599 599 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
600 600 - ``changeset.transplant.normal`` for :hg:`transplant` on other
601 601
602 602 These dot-separated lists of names are treated as hierarchical ones.
603 603 For example, ``changeset.tag.remove`` customizes the commit message
604 604 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
605 605 commit message for :hg:`tag` regardless of ``--remove`` option.
606 606
607 607 When the external editor is invoked for a commit, the corresponding
608 608 dot-separated list of names without the ``changeset.`` prefix
609 609 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
610 610 variable.
611 611
612 612 In this section, items other than ``changeset`` can be referred from
613 613 others. For example, the configuration to list committed files up
614 614 below can be referred as ``{listupfiles}``::
615 615
616 616 [committemplate]
617 617 listupfiles = {file_adds %
618 618 "HG: added {file}\n" }{file_mods %
619 619 "HG: changed {file}\n" }{file_dels %
620 620 "HG: removed {file}\n" }{if(files, "",
621 621 "HG: no files changed\n")}
622 622
623 623 ``decode/encode``
624 624 -----------------
625 625
626 626 Filters for transforming files on checkout/checkin. This would
627 627 typically be used for newline processing or other
628 628 localization/canonicalization of files.
629 629
630 630 Filters consist of a filter pattern followed by a filter command.
631 631 Filter patterns are globs by default, rooted at the repository root.
632 632 For example, to match any file ending in ``.txt`` in the root
633 633 directory only, use the pattern ``*.txt``. To match any file ending
634 634 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
635 635 For each file only the first matching filter applies.
636 636
637 637 The filter command can start with a specifier, either ``pipe:`` or
638 638 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
639 639
640 640 A ``pipe:`` command must accept data on stdin and return the transformed
641 641 data on stdout.
642 642
643 643 Pipe example::
644 644
645 645 [encode]
646 646 # uncompress gzip files on checkin to improve delta compression
647 647 # note: not necessarily a good idea, just an example
648 648 *.gz = pipe: gunzip
649 649
650 650 [decode]
651 651 # recompress gzip files when writing them to the working dir (we
652 652 # can safely omit "pipe:", because it's the default)
653 653 *.gz = gzip
654 654
655 655 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
656 656 with the name of a temporary file that contains the data to be
657 657 filtered by the command. The string ``OUTFILE`` is replaced with the name
658 658 of an empty temporary file, where the filtered data must be written by
659 659 the command.
660 660
661 661 .. container:: windows
662 662
663 663 .. note::
664 664
665 665 The tempfile mechanism is recommended for Windows systems,
666 666 where the standard shell I/O redirection operators often have
667 667 strange effects and may corrupt the contents of your files.
668 668
669 669 This filter mechanism is used internally by the ``eol`` extension to
670 670 translate line ending characters between Windows (CRLF) and Unix (LF)
671 671 format. We suggest you use the ``eol`` extension for convenience.
672 672
673 673
674 674 ``defaults``
675 675 ------------
676 676
677 677 (defaults are deprecated. Don't use them. Use aliases instead.)
678 678
679 679 Use the ``[defaults]`` section to define command defaults, i.e. the
680 680 default options/arguments to pass to the specified commands.
681 681
682 682 The following example makes :hg:`log` run in verbose mode, and
683 683 :hg:`status` show only the modified files, by default::
684 684
685 685 [defaults]
686 686 log = -v
687 687 status = -m
688 688
689 689 The actual commands, instead of their aliases, must be used when
690 690 defining command defaults. The command defaults will also be applied
691 691 to the aliases of the commands defined.
692 692
693 693
694 694 ``diff``
695 695 --------
696 696
697 697 Settings used when displaying diffs. Everything except for ``unified``
698 698 is a Boolean and defaults to False. See :hg:`help config.annotate`
699 699 for related options for the annotate command.
700 700
701 701 ``git``
702 702 Use git extended diff format.
703 703
704 704 ``nobinary``
705 705 Omit git binary patches.
706 706
707 707 ``nodates``
708 708 Don't include dates in diff headers.
709 709
710 710 ``noprefix``
711 711 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
712 712
713 713 ``showfunc``
714 714 Show which function each change is in.
715 715
716 716 ``ignorews``
717 717 Ignore white space when comparing lines.
718 718
719 719 ``ignorewsamount``
720 720 Ignore changes in the amount of white space.
721 721
722 722 ``ignoreblanklines``
723 723 Ignore changes whose lines are all blank.
724 724
725 725 ``unified``
726 726 Number of lines of context to show.
727 727
728 728 ``word-diff``
729 729 Highlight changed words.
730 730
731 731 ``email``
732 732 ---------
733 733
734 734 Settings for extensions that send email messages.
735 735
736 736 ``from``
737 737 Optional. Email address to use in "From" header and SMTP envelope
738 738 of outgoing messages.
739 739
740 740 ``to``
741 741 Optional. Comma-separated list of recipients' email addresses.
742 742
743 743 ``cc``
744 744 Optional. Comma-separated list of carbon copy recipients'
745 745 email addresses.
746 746
747 747 ``bcc``
748 748 Optional. Comma-separated list of blind carbon copy recipients'
749 749 email addresses.
750 750
751 751 ``method``
752 752 Optional. Method to use to send email messages. If value is ``smtp``
753 753 (default), use SMTP (see the ``[smtp]`` section for configuration).
754 754 Otherwise, use as name of program to run that acts like sendmail
755 755 (takes ``-f`` option for sender, list of recipients on command line,
756 756 message on stdin). Normally, setting this to ``sendmail`` or
757 757 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
758 758
759 759 ``charsets``
760 760 Optional. Comma-separated list of character sets considered
761 761 convenient for recipients. Addresses, headers, and parts not
762 762 containing patches of outgoing messages will be encoded in the
763 763 first character set to which conversion from local encoding
764 764 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
765 765 conversion fails, the text in question is sent as is.
766 766 (default: '')
767 767
768 768 Order of outgoing email character sets:
769 769
770 770 1. ``us-ascii``: always first, regardless of settings
771 771 2. ``email.charsets``: in order given by user
772 772 3. ``ui.fallbackencoding``: if not in email.charsets
773 773 4. ``$HGENCODING``: if not in email.charsets
774 774 5. ``utf-8``: always last, regardless of settings
775 775
776 776 Email example::
777 777
778 778 [email]
779 779 from = Joseph User <joe.user@example.com>
780 780 method = /usr/sbin/sendmail
781 781 # charsets for western Europeans
782 782 # us-ascii, utf-8 omitted, as they are tried first and last
783 783 charsets = iso-8859-1, iso-8859-15, windows-1252
784 784
785 785
786 786 ``extensions``
787 787 --------------
788 788
789 789 Mercurial has an extension mechanism for adding new features. To
790 790 enable an extension, create an entry for it in this section.
791 791
792 792 If you know that the extension is already in Python's search path,
793 793 you can give the name of the module, followed by ``=``, with nothing
794 794 after the ``=``.
795 795
796 796 Otherwise, give a name that you choose, followed by ``=``, followed by
797 797 the path to the ``.py`` file (including the file name extension) that
798 798 defines the extension.
799 799
800 800 To explicitly disable an extension that is enabled in an hgrc of
801 801 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
802 802 or ``foo = !`` when path is not supplied.
803 803
804 804 Example for ``~/.hgrc``::
805 805
806 806 [extensions]
807 807 # (the churn extension will get loaded from Mercurial's path)
808 808 churn =
809 809 # (this extension will get loaded from the file specified)
810 810 myfeature = ~/.hgext/myfeature.py
811 811
812 812
813 813 ``format``
814 814 ----------
815 815
816 816 Configuration that controls the repository format. Newer format options are more
817 817 powerful but incompatible with some older versions of Mercurial. Format options
818 818 are considered at repository initialization only. You need to make a new clone
819 819 for config change to be taken into account.
820 820
821 821 For more details about repository format and version compatibility, see
822 822 https://www.mercurial-scm.org/wiki/MissingRequirement
823 823
824 824 ``usegeneraldelta``
825 825 Enable or disable the "generaldelta" repository format which improves
826 826 repository compression by allowing "revlog" to store delta against arbitrary
827 827 revision instead of the previous stored one. This provides significant
828 828 improvement for repositories with branches.
829 829
830 830 Repositories with this on-disk format require Mercurial version 1.9.
831 831
832 832 Enabled by default.
833 833
834 834 ``dotencode``
835 835 Enable or disable the "dotencode" repository format which enhances
836 836 the "fncache" repository format (which has to be enabled to use
837 837 dotencode) to avoid issues with filenames starting with ._ on
838 838 Mac OS X and spaces on Windows.
839 839
840 840 Repositories with this on-disk format require Mercurial version 1.7.
841 841
842 842 Enabled by default.
843 843
844 844 ``usefncache``
845 845 Enable or disable the "fncache" repository format which enhances
846 846 the "store" repository format (which has to be enabled to use
847 847 fncache) to allow longer filenames and avoids using Windows
848 848 reserved names, e.g. "nul".
849 849
850 850 Repositories with this on-disk format require Mercurial version 1.1.
851 851
852 852 Enabled by default.
853 853
854 854 ``usestore``
855 855 Enable or disable the "store" repository format which improves
856 856 compatibility with systems that fold case or otherwise mangle
857 857 filenames. Disabling this option will allow you to store longer filenames
858 858 in some situations at the expense of compatibility.
859 859
860 860 Repositories with this on-disk format require Mercurial version 0.9.4.
861 861
862 862 Enabled by default.
863 863
864 864 ``sparse-revlog``
865 865 Enable or disable the ``sparse-revlog`` delta strategy. This format improves
866 866 delta re-use inside revlog. For very branchy repositories, it results in a
867 867 smaller store. For repositories with many revisions, it also helps
868 868 performance (by using shortened delta chains.)
869 869
870 870 Repositories with this on-disk format require Mercurial version 4.7
871 871
872 872 Enabled by default.
873 873
874 874 ``revlog-compression``
875 875 Compression algorithm used by revlog. Supported value are `zlib` and `zstd`.
876 876 The `zlib` engine is the historical default of Mercurial. `zstd` is a newer
877 877 format that is usually a net win over `zlib` operating faster at better
878 878 compression rate. Use `zstd` to reduce CPU usage.
879 879
880 880 On some system, Mercurial installation may lack `zstd` supports. Default is `zlib`.
881 881
882 ``bookmarks-in-store``
883 Store bookmarks in .hg/store/. This means that bookmarks are shared when
884 using `hg share` regardless of the `-B` option.
885
886 Repositories with this on-disk format require Mercurial version 5.1.
887
888 Disabled by default.
889
890
882 891 ``graph``
883 892 ---------
884 893
885 894 Web graph view configuration. This section let you change graph
886 895 elements display properties by branches, for instance to make the
887 896 ``default`` branch stand out.
888 897
889 898 Each line has the following format::
890 899
891 900 <branch>.<argument> = <value>
892 901
893 902 where ``<branch>`` is the name of the branch being
894 903 customized. Example::
895 904
896 905 [graph]
897 906 # 2px width
898 907 default.width = 2
899 908 # red color
900 909 default.color = FF0000
901 910
902 911 Supported arguments:
903 912
904 913 ``width``
905 914 Set branch edges width in pixels.
906 915
907 916 ``color``
908 917 Set branch edges color in hexadecimal RGB notation.
909 918
910 919 ``hooks``
911 920 ---------
912 921
913 922 Commands or Python functions that get automatically executed by
914 923 various actions such as starting or finishing a commit. Multiple
915 924 hooks can be run for the same action by appending a suffix to the
916 925 action. Overriding a site-wide hook can be done by changing its
917 926 value or setting it to an empty string. Hooks can be prioritized
918 927 by adding a prefix of ``priority.`` to the hook name on a new line
919 928 and setting the priority. The default priority is 0.
920 929
921 930 Example ``.hg/hgrc``::
922 931
923 932 [hooks]
924 933 # update working directory after adding changesets
925 934 changegroup.update = hg update
926 935 # do not use the site-wide hook
927 936 incoming =
928 937 incoming.email = /my/email/hook
929 938 incoming.autobuild = /my/build/hook
930 939 # force autobuild hook to run before other incoming hooks
931 940 priority.incoming.autobuild = 1
932 941
933 942 Most hooks are run with environment variables set that give useful
934 943 additional information. For each hook below, the environment variables
935 944 it is passed are listed with names in the form ``$HG_foo``. The
936 945 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
937 946 They contain the type of hook which triggered the run and the full name
938 947 of the hook in the config, respectively. In the example above, this will
939 948 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
940 949
941 950 .. container:: windows
942 951
943 952 Some basic Unix syntax can be enabled for portability, including ``$VAR``
944 953 and ``${VAR}`` style variables. A ``~`` followed by ``\`` or ``/`` will
945 954 be expanded to ``%USERPROFILE%`` to simulate a subset of tilde expansion
946 955 on Unix. To use a literal ``$`` or ``~``, it must be escaped with a back
947 956 slash or inside of a strong quote. Strong quotes will be replaced by
948 957 double quotes after processing.
949 958
950 959 This feature is enabled by adding a prefix of ``tonative.`` to the hook
951 960 name on a new line, and setting it to ``True``. For example::
952 961
953 962 [hooks]
954 963 incoming.autobuild = /my/build/hook
955 964 # enable translation to cmd.exe syntax for autobuild hook
956 965 tonative.incoming.autobuild = True
957 966
958 967 ``changegroup``
959 968 Run after a changegroup has been added via push, pull or unbundle. The ID of
960 969 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
961 970 The URL from which changes came is in ``$HG_URL``.
962 971
963 972 ``commit``
964 973 Run after a changeset has been created in the local repository. The ID
965 974 of the newly created changeset is in ``$HG_NODE``. Parent changeset
966 975 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
967 976
968 977 ``incoming``
969 978 Run after a changeset has been pulled, pushed, or unbundled into
970 979 the local repository. The ID of the newly arrived changeset is in
971 980 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
972 981
973 982 ``outgoing``
974 983 Run after sending changes from the local repository to another. The ID of
975 984 first changeset sent is in ``$HG_NODE``. The source of operation is in
976 985 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
977 986
978 987 ``post-<command>``
979 988 Run after successful invocations of the associated command. The
980 989 contents of the command line are passed as ``$HG_ARGS`` and the result
981 990 code in ``$HG_RESULT``. Parsed command line arguments are passed as
982 991 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
983 992 the python data internally passed to <command>. ``$HG_OPTS`` is a
984 993 dictionary of options (with unspecified options set to their defaults).
985 994 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
986 995
987 996 ``fail-<command>``
988 997 Run after a failed invocation of an associated command. The contents
989 998 of the command line are passed as ``$HG_ARGS``. Parsed command line
990 999 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
991 1000 string representations of the python data internally passed to
992 1001 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
993 1002 options set to their defaults). ``$HG_PATS`` is a list of arguments.
994 1003 Hook failure is ignored.
995 1004
996 1005 ``pre-<command>``
997 1006 Run before executing the associated command. The contents of the
998 1007 command line are passed as ``$HG_ARGS``. Parsed command line arguments
999 1008 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
1000 1009 representations of the data internally passed to <command>. ``$HG_OPTS``
1001 1010 is a dictionary of options (with unspecified options set to their
1002 1011 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
1003 1012 failure, the command doesn't execute and Mercurial returns the failure
1004 1013 code.
1005 1014
1006 1015 ``prechangegroup``
1007 1016 Run before a changegroup is added via push, pull or unbundle. Exit
1008 1017 status 0 allows the changegroup to proceed. A non-zero status will
1009 1018 cause the push, pull or unbundle to fail. The URL from which changes
1010 1019 will come is in ``$HG_URL``.
1011 1020
1012 1021 ``precommit``
1013 1022 Run before starting a local commit. Exit status 0 allows the
1014 1023 commit to proceed. A non-zero status will cause the commit to fail.
1015 1024 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1016 1025
1017 1026 ``prelistkeys``
1018 1027 Run before listing pushkeys (like bookmarks) in the
1019 1028 repository. A non-zero status will cause failure. The key namespace is
1020 1029 in ``$HG_NAMESPACE``.
1021 1030
1022 1031 ``preoutgoing``
1023 1032 Run before collecting changes to send from the local repository to
1024 1033 another. A non-zero status will cause failure. This lets you prevent
1025 1034 pull over HTTP or SSH. It can also prevent propagating commits (via
1026 1035 local pull, push (outbound) or bundle commands), but not completely,
1027 1036 since you can just copy files instead. The source of operation is in
1028 1037 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
1029 1038 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
1030 1039 is happening on behalf of a repository on same system.
1031 1040
1032 1041 ``prepushkey``
1033 1042 Run before a pushkey (like a bookmark) is added to the
1034 1043 repository. A non-zero status will cause the key to be rejected. The
1035 1044 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
1036 1045 the old value (if any) is in ``$HG_OLD``, and the new value is in
1037 1046 ``$HG_NEW``.
1038 1047
1039 1048 ``pretag``
1040 1049 Run before creating a tag. Exit status 0 allows the tag to be
1041 1050 created. A non-zero status will cause the tag to fail. The ID of the
1042 1051 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
1043 1052 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
1044 1053
1045 1054 ``pretxnopen``
1046 1055 Run before any new repository transaction is open. The reason for the
1047 1056 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
1048 1057 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
1049 1058 transaction from being opened.
1050 1059
1051 1060 ``pretxnclose``
1052 1061 Run right before the transaction is actually finalized. Any repository change
1053 1062 will be visible to the hook program. This lets you validate the transaction
1054 1063 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1055 1064 status will cause the transaction to be rolled back. The reason for the
1056 1065 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
1057 1066 the transaction will be in ``HG_TXNID``. The rest of the available data will
1058 1067 vary according the transaction type. New changesets will add ``$HG_NODE``
1059 1068 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
1060 1069 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
1061 1070 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
1062 1071 respectively, etc.
1063 1072
1064 1073 ``pretxnclose-bookmark``
1065 1074 Run right before a bookmark change is actually finalized. Any repository
1066 1075 change will be visible to the hook program. This lets you validate the
1067 1076 transaction content or change it. Exit status 0 allows the commit to
1068 1077 proceed. A non-zero status will cause the transaction to be rolled back.
1069 1078 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
1070 1079 bookmark location will be available in ``$HG_NODE`` while the previous
1071 1080 location will be available in ``$HG_OLDNODE``. In case of a bookmark
1072 1081 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
1073 1082 will be empty.
1074 1083 In addition, the reason for the transaction opening will be in
1075 1084 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1076 1085 ``HG_TXNID``.
1077 1086
1078 1087 ``pretxnclose-phase``
1079 1088 Run right before a phase change is actually finalized. Any repository change
1080 1089 will be visible to the hook program. This lets you validate the transaction
1081 1090 content or change it. Exit status 0 allows the commit to proceed. A non-zero
1082 1091 status will cause the transaction to be rolled back. The hook is called
1083 1092 multiple times, once for each revision affected by a phase change.
1084 1093 The affected node is available in ``$HG_NODE``, the phase in ``$HG_PHASE``
1085 1094 while the previous ``$HG_OLDPHASE``. In case of new node, ``$HG_OLDPHASE``
1086 1095 will be empty. In addition, the reason for the transaction opening will be in
1087 1096 ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1088 1097 ``HG_TXNID``. The hook is also run for newly added revisions. In this case
1089 1098 the ``$HG_OLDPHASE`` entry will be empty.
1090 1099
1091 1100 ``txnclose``
1092 1101 Run after any repository transaction has been committed. At this
1093 1102 point, the transaction can no longer be rolled back. The hook will run
1094 1103 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
1095 1104 details about available variables.
1096 1105
1097 1106 ``txnclose-bookmark``
1098 1107 Run after any bookmark change has been committed. At this point, the
1099 1108 transaction can no longer be rolled back. The hook will run after the lock
1100 1109 is released. See :hg:`help config.hooks.pretxnclose-bookmark` for details
1101 1110 about available variables.
1102 1111
1103 1112 ``txnclose-phase``
1104 1113 Run after any phase change has been committed. At this point, the
1105 1114 transaction can no longer be rolled back. The hook will run after the lock
1106 1115 is released. See :hg:`help config.hooks.pretxnclose-phase` for details about
1107 1116 available variables.
1108 1117
1109 1118 ``txnabort``
1110 1119 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1111 1120 for details about available variables.
1112 1121
1113 1122 ``pretxnchangegroup``
1114 1123 Run after a changegroup has been added via push, pull or unbundle, but before
1115 1124 the transaction has been committed. The changegroup is visible to the hook
1116 1125 program. This allows validation of incoming changes before accepting them.
1117 1126 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1118 1127 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1119 1128 status will cause the transaction to be rolled back, and the push, pull or
1120 1129 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1121 1130
1122 1131 ``pretxncommit``
1123 1132 Run after a changeset has been created, but before the transaction is
1124 1133 committed. The changeset is visible to the hook program. This allows
1125 1134 validation of the commit message and changes. Exit status 0 allows the
1126 1135 commit to proceed. A non-zero status will cause the transaction to
1127 1136 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1128 1137 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1129 1138
1130 1139 ``preupdate``
1131 1140 Run before updating the working directory. Exit status 0 allows
1132 1141 the update to proceed. A non-zero status will prevent the update.
1133 1142 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1134 1143 merge, the ID of second new parent is in ``$HG_PARENT2``.
1135 1144
1136 1145 ``listkeys``
1137 1146 Run after listing pushkeys (like bookmarks) in the repository. The
1138 1147 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1139 1148 dictionary containing the keys and values.
1140 1149
1141 1150 ``pushkey``
1142 1151 Run after a pushkey (like a bookmark) is added to the
1143 1152 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1144 1153 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1145 1154 value is in ``$HG_NEW``.
1146 1155
1147 1156 ``tag``
1148 1157 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1149 1158 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1150 1159 the repository if ``$HG_LOCAL=0``.
1151 1160
1152 1161 ``update``
1153 1162 Run after updating the working directory. The changeset ID of first
1154 1163 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1155 1164 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1156 1165 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1157 1166
1158 1167 .. note::
1159 1168
1160 1169 It is generally better to use standard hooks rather than the
1161 1170 generic pre- and post- command hooks, as they are guaranteed to be
1162 1171 called in the appropriate contexts for influencing transactions.
1163 1172 Also, hooks like "commit" will be called in all contexts that
1164 1173 generate a commit (e.g. tag) and not just the commit command.
1165 1174
1166 1175 .. note::
1167 1176
1168 1177 Environment variables with empty values may not be passed to
1169 1178 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1170 1179 will have an empty value under Unix-like platforms for non-merge
1171 1180 changesets, while it will not be available at all under Windows.
1172 1181
1173 1182 The syntax for Python hooks is as follows::
1174 1183
1175 1184 hookname = python:modulename.submodule.callable
1176 1185 hookname = python:/path/to/python/module.py:callable
1177 1186
1178 1187 Python hooks are run within the Mercurial process. Each hook is
1179 1188 called with at least three keyword arguments: a ui object (keyword
1180 1189 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1181 1190 keyword that tells what kind of hook is used. Arguments listed as
1182 1191 environment variables above are passed as keyword arguments, with no
1183 1192 ``HG_`` prefix, and names in lower case.
1184 1193
1185 1194 If a Python hook returns a "true" value or raises an exception, this
1186 1195 is treated as a failure.
1187 1196
1188 1197
1189 1198 ``hostfingerprints``
1190 1199 --------------------
1191 1200
1192 1201 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1193 1202
1194 1203 Fingerprints of the certificates of known HTTPS servers.
1195 1204
1196 1205 A HTTPS connection to a server with a fingerprint configured here will
1197 1206 only succeed if the servers certificate matches the fingerprint.
1198 1207 This is very similar to how ssh known hosts works.
1199 1208
1200 1209 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1201 1210 Multiple values can be specified (separated by spaces or commas). This can
1202 1211 be used to define both old and new fingerprints while a host transitions
1203 1212 to a new certificate.
1204 1213
1205 1214 The CA chain and web.cacerts is not used for servers with a fingerprint.
1206 1215
1207 1216 For example::
1208 1217
1209 1218 [hostfingerprints]
1210 1219 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1211 1220 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1212 1221
1213 1222 ``hostsecurity``
1214 1223 ----------------
1215 1224
1216 1225 Used to specify global and per-host security settings for connecting to
1217 1226 other machines.
1218 1227
1219 1228 The following options control default behavior for all hosts.
1220 1229
1221 1230 ``ciphers``
1222 1231 Defines the cryptographic ciphers to use for connections.
1223 1232
1224 1233 Value must be a valid OpenSSL Cipher List Format as documented at
1225 1234 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1226 1235
1227 1236 This setting is for advanced users only. Setting to incorrect values
1228 1237 can significantly lower connection security or decrease performance.
1229 1238 You have been warned.
1230 1239
1231 1240 This option requires Python 2.7.
1232 1241
1233 1242 ``minimumprotocol``
1234 1243 Defines the minimum channel encryption protocol to use.
1235 1244
1236 1245 By default, the highest version of TLS supported by both client and server
1237 1246 is used.
1238 1247
1239 1248 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1240 1249
1241 1250 When running on an old Python version, only ``tls1.0`` is allowed since
1242 1251 old versions of Python only support up to TLS 1.0.
1243 1252
1244 1253 When running a Python that supports modern TLS versions, the default is
1245 1254 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1246 1255 weakens security and should only be used as a feature of last resort if
1247 1256 a server does not support TLS 1.1+.
1248 1257
1249 1258 Options in the ``[hostsecurity]`` section can have the form
1250 1259 ``hostname``:``setting``. This allows multiple settings to be defined on a
1251 1260 per-host basis.
1252 1261
1253 1262 The following per-host settings can be defined.
1254 1263
1255 1264 ``ciphers``
1256 1265 This behaves like ``ciphers`` as described above except it only applies
1257 1266 to the host on which it is defined.
1258 1267
1259 1268 ``fingerprints``
1260 1269 A list of hashes of the DER encoded peer/remote certificate. Values have
1261 1270 the form ``algorithm``:``fingerprint``. e.g.
1262 1271 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1263 1272 In addition, colons (``:``) can appear in the fingerprint part.
1264 1273
1265 1274 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1266 1275 ``sha512``.
1267 1276
1268 1277 Use of ``sha256`` or ``sha512`` is preferred.
1269 1278
1270 1279 If a fingerprint is specified, the CA chain is not validated for this
1271 1280 host and Mercurial will require the remote certificate to match one
1272 1281 of the fingerprints specified. This means if the server updates its
1273 1282 certificate, Mercurial will abort until a new fingerprint is defined.
1274 1283 This can provide stronger security than traditional CA-based validation
1275 1284 at the expense of convenience.
1276 1285
1277 1286 This option takes precedence over ``verifycertsfile``.
1278 1287
1279 1288 ``minimumprotocol``
1280 1289 This behaves like ``minimumprotocol`` as described above except it
1281 1290 only applies to the host on which it is defined.
1282 1291
1283 1292 ``verifycertsfile``
1284 1293 Path to file a containing a list of PEM encoded certificates used to
1285 1294 verify the server certificate. Environment variables and ``~user``
1286 1295 constructs are expanded in the filename.
1287 1296
1288 1297 The server certificate or the certificate's certificate authority (CA)
1289 1298 must match a certificate from this file or certificate verification
1290 1299 will fail and connections to the server will be refused.
1291 1300
1292 1301 If defined, only certificates provided by this file will be used:
1293 1302 ``web.cacerts`` and any system/default certificates will not be
1294 1303 used.
1295 1304
1296 1305 This option has no effect if the per-host ``fingerprints`` option
1297 1306 is set.
1298 1307
1299 1308 The format of the file is as follows::
1300 1309
1301 1310 -----BEGIN CERTIFICATE-----
1302 1311 ... (certificate in base64 PEM encoding) ...
1303 1312 -----END CERTIFICATE-----
1304 1313 -----BEGIN CERTIFICATE-----
1305 1314 ... (certificate in base64 PEM encoding) ...
1306 1315 -----END CERTIFICATE-----
1307 1316
1308 1317 For example::
1309 1318
1310 1319 [hostsecurity]
1311 1320 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1312 1321 hg2.example.com:fingerprints = sha1:914f1aff87249c09b6859b88b1906d30756491ca, sha1:fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1313 1322 hg3.example.com:fingerprints = sha256:9a:b0:dc:e2:75:ad:8a:b7:84:58:e5:1f:07:32:f1:87:e6:bd:24:22:af:b7:ce:8e:9c:b4:10:cf:b9:f4:0e:d2
1314 1323 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1315 1324
1316 1325 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1317 1326 when connecting to ``hg.example.com``::
1318 1327
1319 1328 [hostsecurity]
1320 1329 minimumprotocol = tls1.2
1321 1330 hg.example.com:minimumprotocol = tls1.1
1322 1331
1323 1332 ``http_proxy``
1324 1333 --------------
1325 1334
1326 1335 Used to access web-based Mercurial repositories through a HTTP
1327 1336 proxy.
1328 1337
1329 1338 ``host``
1330 1339 Host name and (optional) port of the proxy server, for example
1331 1340 "myproxy:8000".
1332 1341
1333 1342 ``no``
1334 1343 Optional. Comma-separated list of host names that should bypass
1335 1344 the proxy.
1336 1345
1337 1346 ``passwd``
1338 1347 Optional. Password to authenticate with at the proxy server.
1339 1348
1340 1349 ``user``
1341 1350 Optional. User name to authenticate with at the proxy server.
1342 1351
1343 1352 ``always``
1344 1353 Optional. Always use the proxy, even for localhost and any entries
1345 1354 in ``http_proxy.no``. (default: False)
1346 1355
1347 1356 ``http``
1348 1357 ----------
1349 1358
1350 1359 Used to configure access to Mercurial repositories via HTTP.
1351 1360
1352 1361 ``timeout``
1353 1362 If set, blocking operations will timeout after that many seconds.
1354 1363 (default: None)
1355 1364
1356 1365 ``merge``
1357 1366 ---------
1358 1367
1359 1368 This section specifies behavior during merges and updates.
1360 1369
1361 1370 ``checkignored``
1362 1371 Controls behavior when an ignored file on disk has the same name as a tracked
1363 1372 file in the changeset being merged or updated to, and has different
1364 1373 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1365 1374 abort on such files. With ``warn``, warn on such files and back them up as
1366 1375 ``.orig``. With ``ignore``, don't print a warning and back them up as
1367 1376 ``.orig``. (default: ``abort``)
1368 1377
1369 1378 ``checkunknown``
1370 1379 Controls behavior when an unknown file that isn't ignored has the same name
1371 1380 as a tracked file in the changeset being merged or updated to, and has
1372 1381 different contents. Similar to ``merge.checkignored``, except for files that
1373 1382 are not ignored. (default: ``abort``)
1374 1383
1375 1384 ``on-failure``
1376 1385 When set to ``continue`` (the default), the merge process attempts to
1377 1386 merge all unresolved files using the merge chosen tool, regardless of
1378 1387 whether previous file merge attempts during the process succeeded or not.
1379 1388 Setting this to ``prompt`` will prompt after any merge failure continue
1380 1389 or halt the merge process. Setting this to ``halt`` will automatically
1381 1390 halt the merge process on any merge tool failure. The merge process
1382 1391 can be restarted by using the ``resolve`` command. When a merge is
1383 1392 halted, the repository is left in a normal ``unresolved`` merge state.
1384 1393 (default: ``continue``)
1385 1394
1386 1395 ``strict-capability-check``
1387 1396 Whether capabilities of internal merge tools are checked strictly
1388 1397 or not, while examining rules to decide merge tool to be used.
1389 1398 (default: False)
1390 1399
1391 1400 ``merge-patterns``
1392 1401 ------------------
1393 1402
1394 1403 This section specifies merge tools to associate with particular file
1395 1404 patterns. Tools matched here will take precedence over the default
1396 1405 merge tool. Patterns are globs by default, rooted at the repository
1397 1406 root.
1398 1407
1399 1408 Example::
1400 1409
1401 1410 [merge-patterns]
1402 1411 **.c = kdiff3
1403 1412 **.jpg = myimgmerge
1404 1413
1405 1414 ``merge-tools``
1406 1415 ---------------
1407 1416
1408 1417 This section configures external merge tools to use for file-level
1409 1418 merges. This section has likely been preconfigured at install time.
1410 1419 Use :hg:`config merge-tools` to check the existing configuration.
1411 1420 Also see :hg:`help merge-tools` for more details.
1412 1421
1413 1422 Example ``~/.hgrc``::
1414 1423
1415 1424 [merge-tools]
1416 1425 # Override stock tool location
1417 1426 kdiff3.executable = ~/bin/kdiff3
1418 1427 # Specify command line
1419 1428 kdiff3.args = $base $local $other -o $output
1420 1429 # Give higher priority
1421 1430 kdiff3.priority = 1
1422 1431
1423 1432 # Changing the priority of preconfigured tool
1424 1433 meld.priority = 0
1425 1434
1426 1435 # Disable a preconfigured tool
1427 1436 vimdiff.disabled = yes
1428 1437
1429 1438 # Define new tool
1430 1439 myHtmlTool.args = -m $local $other $base $output
1431 1440 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1432 1441 myHtmlTool.priority = 1
1433 1442
1434 1443 Supported arguments:
1435 1444
1436 1445 ``priority``
1437 1446 The priority in which to evaluate this tool.
1438 1447 (default: 0)
1439 1448
1440 1449 ``executable``
1441 1450 Either just the name of the executable or its pathname.
1442 1451
1443 1452 .. container:: windows
1444 1453
1445 1454 On Windows, the path can use environment variables with ${ProgramFiles}
1446 1455 syntax.
1447 1456
1448 1457 (default: the tool name)
1449 1458
1450 1459 ``args``
1451 1460 The arguments to pass to the tool executable. You can refer to the
1452 1461 files being merged as well as the output file through these
1453 1462 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1454 1463
1455 1464 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1456 1465 being performed. During an update or merge, ``$local`` represents the original
1457 1466 state of the file, while ``$other`` represents the commit you are updating to or
1458 1467 the commit you are merging with. During a rebase, ``$local`` represents the
1459 1468 destination of the rebase, and ``$other`` represents the commit being rebased.
1460 1469
1461 1470 Some operations define custom labels to assist with identifying the revisions,
1462 1471 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1463 1472 labels are not available, these will be ``local``, ``other``, and ``base``,
1464 1473 respectively.
1465 1474 (default: ``$local $base $other``)
1466 1475
1467 1476 ``premerge``
1468 1477 Attempt to run internal non-interactive 3-way merge tool before
1469 1478 launching external tool. Options are ``true``, ``false``, ``keep`` or
1470 1479 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1471 1480 premerge fails. The ``keep-merge3`` will do the same but include information
1472 1481 about the base of the merge in the marker (see internal :merge3 in
1473 1482 :hg:`help merge-tools`).
1474 1483 (default: True)
1475 1484
1476 1485 ``binary``
1477 1486 This tool can merge binary files. (default: False, unless tool
1478 1487 was selected by file pattern match)
1479 1488
1480 1489 ``symlink``
1481 1490 This tool can merge symlinks. (default: False)
1482 1491
1483 1492 ``check``
1484 1493 A list of merge success-checking options:
1485 1494
1486 1495 ``changed``
1487 1496 Ask whether merge was successful when the merged file shows no changes.
1488 1497 ``conflicts``
1489 1498 Check whether there are conflicts even though the tool reported success.
1490 1499 ``prompt``
1491 1500 Always prompt for merge success, regardless of success reported by tool.
1492 1501
1493 1502 ``fixeol``
1494 1503 Attempt to fix up EOL changes caused by the merge tool.
1495 1504 (default: False)
1496 1505
1497 1506 ``gui``
1498 1507 This tool requires a graphical interface to run. (default: False)
1499 1508
1500 1509 ``mergemarkers``
1501 1510 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1502 1511 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1503 1512 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1504 1513 markers generated during premerge will be ``detailed`` if either this option or
1505 1514 the corresponding option in the ``[ui]`` section is ``detailed``.
1506 1515 (default: ``basic``)
1507 1516
1508 1517 ``mergemarkertemplate``
1509 1518 This setting can be used to override ``mergemarkertemplate`` from the ``[ui]``
1510 1519 section on a per-tool basis; this applies to the ``$label``-prefixed variables
1511 1520 and to the conflict markers that are generated if ``premerge`` is ``keep` or
1512 1521 ``keep-merge3``. See the corresponding variable in ``[ui]`` for more
1513 1522 information.
1514 1523
1515 1524 .. container:: windows
1516 1525
1517 1526 ``regkey``
1518 1527 Windows registry key which describes install location of this
1519 1528 tool. Mercurial will search for this key first under
1520 1529 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1521 1530 (default: None)
1522 1531
1523 1532 ``regkeyalt``
1524 1533 An alternate Windows registry key to try if the first key is not
1525 1534 found. The alternate key uses the same ``regname`` and ``regappend``
1526 1535 semantics of the primary key. The most common use for this key
1527 1536 is to search for 32bit applications on 64bit operating systems.
1528 1537 (default: None)
1529 1538
1530 1539 ``regname``
1531 1540 Name of value to read from specified registry key.
1532 1541 (default: the unnamed (default) value)
1533 1542
1534 1543 ``regappend``
1535 1544 String to append to the value read from the registry, typically
1536 1545 the executable name of the tool.
1537 1546 (default: None)
1538 1547
1539 1548 ``pager``
1540 1549 ---------
1541 1550
1542 1551 Setting used to control when to paginate and with what external tool. See
1543 1552 :hg:`help pager` for details.
1544 1553
1545 1554 ``pager``
1546 1555 Define the external tool used as pager.
1547 1556
1548 1557 If no pager is set, Mercurial uses the environment variable $PAGER.
1549 1558 If neither pager.pager, nor $PAGER is set, a default pager will be
1550 1559 used, typically `less` on Unix and `more` on Windows. Example::
1551 1560
1552 1561 [pager]
1553 1562 pager = less -FRX
1554 1563
1555 1564 ``ignore``
1556 1565 List of commands to disable the pager for. Example::
1557 1566
1558 1567 [pager]
1559 1568 ignore = version, help, update
1560 1569
1561 1570 ``patch``
1562 1571 ---------
1563 1572
1564 1573 Settings used when applying patches, for instance through the 'import'
1565 1574 command or with Mercurial Queues extension.
1566 1575
1567 1576 ``eol``
1568 1577 When set to 'strict' patch content and patched files end of lines
1569 1578 are preserved. When set to ``lf`` or ``crlf``, both files end of
1570 1579 lines are ignored when patching and the result line endings are
1571 1580 normalized to either LF (Unix) or CRLF (Windows). When set to
1572 1581 ``auto``, end of lines are again ignored while patching but line
1573 1582 endings in patched files are normalized to their original setting
1574 1583 on a per-file basis. If target file does not exist or has no end
1575 1584 of line, patch line endings are preserved.
1576 1585 (default: strict)
1577 1586
1578 1587 ``fuzz``
1579 1588 The number of lines of 'fuzz' to allow when applying patches. This
1580 1589 controls how much context the patcher is allowed to ignore when
1581 1590 trying to apply a patch.
1582 1591 (default: 2)
1583 1592
1584 1593 ``paths``
1585 1594 ---------
1586 1595
1587 1596 Assigns symbolic names and behavior to repositories.
1588 1597
1589 1598 Options are symbolic names defining the URL or directory that is the
1590 1599 location of the repository. Example::
1591 1600
1592 1601 [paths]
1593 1602 my_server = https://example.com/my_repo
1594 1603 local_path = /home/me/repo
1595 1604
1596 1605 These symbolic names can be used from the command line. To pull
1597 1606 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1598 1607 :hg:`push local_path`.
1599 1608
1600 1609 Options containing colons (``:``) denote sub-options that can influence
1601 1610 behavior for that specific path. Example::
1602 1611
1603 1612 [paths]
1604 1613 my_server = https://example.com/my_path
1605 1614 my_server:pushurl = ssh://example.com/my_path
1606 1615
1607 1616 The following sub-options can be defined:
1608 1617
1609 1618 ``pushurl``
1610 1619 The URL to use for push operations. If not defined, the location
1611 1620 defined by the path's main entry is used.
1612 1621
1613 1622 ``pushrev``
1614 1623 A revset defining which revisions to push by default.
1615 1624
1616 1625 When :hg:`push` is executed without a ``-r`` argument, the revset
1617 1626 defined by this sub-option is evaluated to determine what to push.
1618 1627
1619 1628 For example, a value of ``.`` will push the working directory's
1620 1629 revision by default.
1621 1630
1622 1631 Revsets specifying bookmarks will not result in the bookmark being
1623 1632 pushed.
1624 1633
1625 1634 The following special named paths exist:
1626 1635
1627 1636 ``default``
1628 1637 The URL or directory to use when no source or remote is specified.
1629 1638
1630 1639 :hg:`clone` will automatically define this path to the location the
1631 1640 repository was cloned from.
1632 1641
1633 1642 ``default-push``
1634 1643 (deprecated) The URL or directory for the default :hg:`push` location.
1635 1644 ``default:pushurl`` should be used instead.
1636 1645
1637 1646 ``phases``
1638 1647 ----------
1639 1648
1640 1649 Specifies default handling of phases. See :hg:`help phases` for more
1641 1650 information about working with phases.
1642 1651
1643 1652 ``publish``
1644 1653 Controls draft phase behavior when working as a server. When true,
1645 1654 pushed changesets are set to public in both client and server and
1646 1655 pulled or cloned changesets are set to public in the client.
1647 1656 (default: True)
1648 1657
1649 1658 ``new-commit``
1650 1659 Phase of newly-created commits.
1651 1660 (default: draft)
1652 1661
1653 1662 ``checksubrepos``
1654 1663 Check the phase of the current revision of each subrepository. Allowed
1655 1664 values are "ignore", "follow" and "abort". For settings other than
1656 1665 "ignore", the phase of the current revision of each subrepository is
1657 1666 checked before committing the parent repository. If any of those phases is
1658 1667 greater than the phase of the parent repository (e.g. if a subrepo is in a
1659 1668 "secret" phase while the parent repo is in "draft" phase), the commit is
1660 1669 either aborted (if checksubrepos is set to "abort") or the higher phase is
1661 1670 used for the parent repository commit (if set to "follow").
1662 1671 (default: follow)
1663 1672
1664 1673
1665 1674 ``profiling``
1666 1675 -------------
1667 1676
1668 1677 Specifies profiling type, format, and file output. Two profilers are
1669 1678 supported: an instrumenting profiler (named ``ls``), and a sampling
1670 1679 profiler (named ``stat``).
1671 1680
1672 1681 In this section description, 'profiling data' stands for the raw data
1673 1682 collected during profiling, while 'profiling report' stands for a
1674 1683 statistical text report generated from the profiling data.
1675 1684
1676 1685 ``enabled``
1677 1686 Enable the profiler.
1678 1687 (default: false)
1679 1688
1680 1689 This is equivalent to passing ``--profile`` on the command line.
1681 1690
1682 1691 ``type``
1683 1692 The type of profiler to use.
1684 1693 (default: stat)
1685 1694
1686 1695 ``ls``
1687 1696 Use Python's built-in instrumenting profiler. This profiler
1688 1697 works on all platforms, but each line number it reports is the
1689 1698 first line of a function. This restriction makes it difficult to
1690 1699 identify the expensive parts of a non-trivial function.
1691 1700 ``stat``
1692 1701 Use a statistical profiler, statprof. This profiler is most
1693 1702 useful for profiling commands that run for longer than about 0.1
1694 1703 seconds.
1695 1704
1696 1705 ``format``
1697 1706 Profiling format. Specific to the ``ls`` instrumenting profiler.
1698 1707 (default: text)
1699 1708
1700 1709 ``text``
1701 1710 Generate a profiling report. When saving to a file, it should be
1702 1711 noted that only the report is saved, and the profiling data is
1703 1712 not kept.
1704 1713 ``kcachegrind``
1705 1714 Format profiling data for kcachegrind use: when saving to a
1706 1715 file, the generated file can directly be loaded into
1707 1716 kcachegrind.
1708 1717
1709 1718 ``statformat``
1710 1719 Profiling format for the ``stat`` profiler.
1711 1720 (default: hotpath)
1712 1721
1713 1722 ``hotpath``
1714 1723 Show a tree-based display containing the hot path of execution (where
1715 1724 most time was spent).
1716 1725 ``bymethod``
1717 1726 Show a table of methods ordered by how frequently they are active.
1718 1727 ``byline``
1719 1728 Show a table of lines in files ordered by how frequently they are active.
1720 1729 ``json``
1721 1730 Render profiling data as JSON.
1722 1731
1723 1732 ``frequency``
1724 1733 Sampling frequency. Specific to the ``stat`` sampling profiler.
1725 1734 (default: 1000)
1726 1735
1727 1736 ``output``
1728 1737 File path where profiling data or report should be saved. If the
1729 1738 file exists, it is replaced. (default: None, data is printed on
1730 1739 stderr)
1731 1740
1732 1741 ``sort``
1733 1742 Sort field. Specific to the ``ls`` instrumenting profiler.
1734 1743 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1735 1744 ``inlinetime``.
1736 1745 (default: inlinetime)
1737 1746
1738 1747 ``time-track``
1739 1748 Control if the stat profiler track ``cpu`` or ``real`` time.
1740 1749 (default: ``cpu`` on Windows, otherwise ``real``)
1741 1750
1742 1751 ``limit``
1743 1752 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1744 1753 (default: 30)
1745 1754
1746 1755 ``nested``
1747 1756 Show at most this number of lines of drill-down info after each main entry.
1748 1757 This can help explain the difference between Total and Inline.
1749 1758 Specific to the ``ls`` instrumenting profiler.
1750 1759 (default: 0)
1751 1760
1752 1761 ``showmin``
1753 1762 Minimum fraction of samples an entry must have for it to be displayed.
1754 1763 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1755 1764 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1756 1765
1757 1766 Only used by the ``stat`` profiler.
1758 1767
1759 1768 For the ``hotpath`` format, default is ``0.05``.
1760 1769 For the ``chrome`` format, default is ``0.005``.
1761 1770
1762 1771 The option is unused on other formats.
1763 1772
1764 1773 ``showmax``
1765 1774 Maximum fraction of samples an entry can have before it is ignored in
1766 1775 display. Values format is the same as ``showmin``.
1767 1776
1768 1777 Only used by the ``stat`` profiler.
1769 1778
1770 1779 For the ``chrome`` format, default is ``0.999``.
1771 1780
1772 1781 The option is unused on other formats.
1773 1782
1774 1783 ``progress``
1775 1784 ------------
1776 1785
1777 1786 Mercurial commands can draw progress bars that are as informative as
1778 1787 possible. Some progress bars only offer indeterminate information, while others
1779 1788 have a definite end point.
1780 1789
1781 1790 ``debug``
1782 1791 Whether to print debug info when updating the progress bar. (default: False)
1783 1792
1784 1793 ``delay``
1785 1794 Number of seconds (float) before showing the progress bar. (default: 3)
1786 1795
1787 1796 ``changedelay``
1788 1797 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1789 1798 that value will be used instead. (default: 1)
1790 1799
1791 1800 ``estimateinterval``
1792 1801 Maximum sampling interval in seconds for speed and estimated time
1793 1802 calculation. (default: 60)
1794 1803
1795 1804 ``refresh``
1796 1805 Time in seconds between refreshes of the progress bar. (default: 0.1)
1797 1806
1798 1807 ``format``
1799 1808 Format of the progress bar.
1800 1809
1801 1810 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1802 1811 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1803 1812 last 20 characters of the item, but this can be changed by adding either
1804 1813 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1805 1814 first num characters.
1806 1815
1807 1816 (default: topic bar number estimate)
1808 1817
1809 1818 ``width``
1810 1819 If set, the maximum width of the progress information (that is, min(width,
1811 1820 term width) will be used).
1812 1821
1813 1822 ``clear-complete``
1814 1823 Clear the progress bar after it's done. (default: True)
1815 1824
1816 1825 ``disable``
1817 1826 If true, don't show a progress bar.
1818 1827
1819 1828 ``assume-tty``
1820 1829 If true, ALWAYS show a progress bar, unless disable is given.
1821 1830
1822 1831 ``rebase``
1823 1832 ----------
1824 1833
1825 1834 ``evolution.allowdivergence``
1826 1835 Default to False, when True allow creating divergence when performing
1827 1836 rebase of obsolete changesets.
1828 1837
1829 1838 ``revsetalias``
1830 1839 ---------------
1831 1840
1832 1841 Alias definitions for revsets. See :hg:`help revsets` for details.
1833 1842
1834 1843 ``rewrite``
1835 1844 -----------
1836 1845
1837 1846 ``backup-bundle``
1838 1847 Whether to save stripped changesets to a bundle file. (default: True)
1839 1848
1840 1849 ``update-timestamp``
1841 1850 If true, updates the date and time of the changeset to current. It is only
1842 1851 applicable for hg amend in current version.
1843 1852
1844 1853 ``storage``
1845 1854 -----------
1846 1855
1847 1856 Control the strategy Mercurial uses internally to store history. Options in this
1848 1857 category impact performance and repository size.
1849 1858
1850 1859 ``revlog.optimize-delta-parent-choice``
1851 1860 When storing a merge revision, both parents will be equally considered as
1852 1861 a possible delta base. This results in better delta selection and improved
1853 1862 revlog compression. This option is enabled by default.
1854 1863
1855 1864 Turning this option off can result in large increase of repository size for
1856 1865 repository with many merges.
1857 1866
1858 1867 ``revlog.reuse-external-delta-parent``
1859 1868 Control the order in which delta parents are considered when adding new
1860 1869 revisions from an external source.
1861 1870 (typically: apply bundle from `hg pull` or `hg push`).
1862 1871
1863 1872 New revisions are usually provided as a delta against other revisions. By
1864 1873 default, Mercurial will try to reuse this delta first, therefore using the
1865 1874 same "delta parent" as the source. Directly using delta's from the source
1866 1875 reduces CPU usage and usually speeds up operation. However, in some case,
1867 1876 the source might have sub-optimal delta bases and forcing their reevaluation
1868 1877 is useful. For example, pushes from an old client could have sub-optimal
1869 1878 delta's parent that the server want to optimize. (lack of general delta, bad
1870 1879 parents, choice, lack of sparse-revlog, etc).
1871 1880
1872 1881 This option is enabled by default. Turning it off will ensure bad delta
1873 1882 parent choices from older client do not propagate to this repository, at
1874 1883 the cost of a small increase in CPU consumption.
1875 1884
1876 1885 Note: this option only control the order in which delta parents are
1877 1886 considered. Even when disabled, the existing delta from the source will be
1878 1887 reused if the same delta parent is selected.
1879 1888
1880 1889 ``revlog.reuse-external-delta``
1881 1890 Control the reuse of delta from external source.
1882 1891 (typically: apply bundle from `hg pull` or `hg push`).
1883 1892
1884 1893 New revisions are usually provided as a delta against another revision. By
1885 1894 default, Mercurial will not recompute the same delta again, trusting
1886 1895 externally provided deltas. There have been rare cases of small adjustment
1887 1896 to the diffing algorithm in the past. So in some rare case, recomputing
1888 1897 delta provided by ancient clients can provides better results. Disabling
1889 1898 this option means going through a full delta recomputation for all incoming
1890 1899 revisions. It means a large increase in CPU usage and will slow operations
1891 1900 down.
1892 1901
1893 1902 This option is enabled by default. When disabled, it also disables the
1894 1903 related ``storage.revlog.reuse-external-delta-parent`` option.
1895 1904
1896 1905 ``revlog.zlib.level``
1897 1906 Zlib compression level used when storing data into the repository. Accepted
1898 1907 Value range from 1 (lowest compression) to 9 (highest compression). Zlib
1899 1908 default value is 6.
1900 1909
1901 1910
1902 1911 ``revlog.zstd.level``
1903 1912 zstd compression level used when storing data into the repository. Accepted
1904 1913 Value range from 1 (lowest compression) to 22 (highest compression).
1905 1914 (default 3)
1906 1915
1907 1916 ``server``
1908 1917 ----------
1909 1918
1910 1919 Controls generic server settings.
1911 1920
1912 1921 ``bookmarks-pushkey-compat``
1913 1922 Trigger pushkey hook when being pushed bookmark updates. This config exist
1914 1923 for compatibility purpose (default to True)
1915 1924
1916 1925 If you use ``pushkey`` and ``pre-pushkey`` hooks to control bookmark
1917 1926 movement we recommend you migrate them to ``txnclose-bookmark`` and
1918 1927 ``pretxnclose-bookmark``.
1919 1928
1920 1929 ``compressionengines``
1921 1930 List of compression engines and their relative priority to advertise
1922 1931 to clients.
1923 1932
1924 1933 The order of compression engines determines their priority, the first
1925 1934 having the highest priority. If a compression engine is not listed
1926 1935 here, it won't be advertised to clients.
1927 1936
1928 1937 If not set (the default), built-in defaults are used. Run
1929 1938 :hg:`debuginstall` to list available compression engines and their
1930 1939 default wire protocol priority.
1931 1940
1932 1941 Older Mercurial clients only support zlib compression and this setting
1933 1942 has no effect for legacy clients.
1934 1943
1935 1944 ``uncompressed``
1936 1945 Whether to allow clients to clone a repository using the
1937 1946 uncompressed streaming protocol. This transfers about 40% more
1938 1947 data than a regular clone, but uses less memory and CPU on both
1939 1948 server and client. Over a LAN (100 Mbps or better) or a very fast
1940 1949 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1941 1950 regular clone. Over most WAN connections (anything slower than
1942 1951 about 6 Mbps), uncompressed streaming is slower, because of the
1943 1952 extra data transfer overhead. This mode will also temporarily hold
1944 1953 the write lock while determining what data to transfer.
1945 1954 (default: True)
1946 1955
1947 1956 ``uncompressedallowsecret``
1948 1957 Whether to allow stream clones when the repository contains secret
1949 1958 changesets. (default: False)
1950 1959
1951 1960 ``preferuncompressed``
1952 1961 When set, clients will try to use the uncompressed streaming
1953 1962 protocol. (default: False)
1954 1963
1955 1964 ``disablefullbundle``
1956 1965 When set, servers will refuse attempts to do pull-based clones.
1957 1966 If this option is set, ``preferuncompressed`` and/or clone bundles
1958 1967 are highly recommended. Partial clones will still be allowed.
1959 1968 (default: False)
1960 1969
1961 1970 ``streamunbundle``
1962 1971 When set, servers will apply data sent from the client directly,
1963 1972 otherwise it will be written to a temporary file first. This option
1964 1973 effectively prevents concurrent pushes.
1965 1974
1966 1975 ``pullbundle``
1967 1976 When set, the server will check pullbundle.manifest for bundles
1968 1977 covering the requested heads and common nodes. The first matching
1969 1978 entry will be streamed to the client.
1970 1979
1971 1980 For HTTP transport, the stream will still use zlib compression
1972 1981 for older clients.
1973 1982
1974 1983 ``concurrent-push-mode``
1975 1984 Level of allowed race condition between two pushing clients.
1976 1985
1977 1986 - 'strict': push is abort if another client touched the repository
1978 1987 while the push was preparing. (default)
1979 1988 - 'check-related': push is only aborted if it affects head that got also
1980 1989 affected while the push was preparing.
1981 1990
1982 1991 This requires compatible client (version 4.3 and later). Old client will
1983 1992 use 'strict'.
1984 1993
1985 1994 ``validate``
1986 1995 Whether to validate the completeness of pushed changesets by
1987 1996 checking that all new file revisions specified in manifests are
1988 1997 present. (default: False)
1989 1998
1990 1999 ``maxhttpheaderlen``
1991 2000 Instruct HTTP clients not to send request headers longer than this
1992 2001 many bytes. (default: 1024)
1993 2002
1994 2003 ``bundle1``
1995 2004 Whether to allow clients to push and pull using the legacy bundle1
1996 2005 exchange format. (default: True)
1997 2006
1998 2007 ``bundle1gd``
1999 2008 Like ``bundle1`` but only used if the repository is using the
2000 2009 *generaldelta* storage format. (default: True)
2001 2010
2002 2011 ``bundle1.push``
2003 2012 Whether to allow clients to push using the legacy bundle1 exchange
2004 2013 format. (default: True)
2005 2014
2006 2015 ``bundle1gd.push``
2007 2016 Like ``bundle1.push`` but only used if the repository is using the
2008 2017 *generaldelta* storage format. (default: True)
2009 2018
2010 2019 ``bundle1.pull``
2011 2020 Whether to allow clients to pull using the legacy bundle1 exchange
2012 2021 format. (default: True)
2013 2022
2014 2023 ``bundle1gd.pull``
2015 2024 Like ``bundle1.pull`` but only used if the repository is using the
2016 2025 *generaldelta* storage format. (default: True)
2017 2026
2018 2027 Large repositories using the *generaldelta* storage format should
2019 2028 consider setting this option because converting *generaldelta*
2020 2029 repositories to the exchange format required by the bundle1 data
2021 2030 format can consume a lot of CPU.
2022 2031
2023 2032 ``bundle2.stream``
2024 2033 Whether to allow clients to pull using the bundle2 streaming protocol.
2025 2034 (default: True)
2026 2035
2027 2036 ``zliblevel``
2028 2037 Integer between ``-1`` and ``9`` that controls the zlib compression level
2029 2038 for wire protocol commands that send zlib compressed output (notably the
2030 2039 commands that send repository history data).
2031 2040
2032 2041 The default (``-1``) uses the default zlib compression level, which is
2033 2042 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
2034 2043 maximum compression.
2035 2044
2036 2045 Setting this option allows server operators to make trade-offs between
2037 2046 bandwidth and CPU used. Lowering the compression lowers CPU utilization
2038 2047 but sends more bytes to clients.
2039 2048
2040 2049 This option only impacts the HTTP server.
2041 2050
2042 2051 ``zstdlevel``
2043 2052 Integer between ``1`` and ``22`` that controls the zstd compression level
2044 2053 for wire protocol commands. ``1`` is the minimal amount of compression and
2045 2054 ``22`` is the highest amount of compression.
2046 2055
2047 2056 The default (``3``) should be significantly faster than zlib while likely
2048 2057 delivering better compression ratios.
2049 2058
2050 2059 This option only impacts the HTTP server.
2051 2060
2052 2061 See also ``server.zliblevel``.
2053 2062
2054 2063 ``view``
2055 2064 Repository filter used when exchanging revisions with the peer.
2056 2065
2057 2066 The default view (``served``) excludes secret and hidden changesets.
2058 2067 Another useful value is ``immutable`` (no draft, secret or hidden
2059 2068 changesets). (EXPERIMENTAL)
2060 2069
2061 2070 ``smtp``
2062 2071 --------
2063 2072
2064 2073 Configuration for extensions that need to send email messages.
2065 2074
2066 2075 ``host``
2067 2076 Host name of mail server, e.g. "mail.example.com".
2068 2077
2069 2078 ``port``
2070 2079 Optional. Port to connect to on mail server. (default: 465 if
2071 2080 ``tls`` is smtps; 25 otherwise)
2072 2081
2073 2082 ``tls``
2074 2083 Optional. Method to enable TLS when connecting to mail server: starttls,
2075 2084 smtps or none. (default: none)
2076 2085
2077 2086 ``username``
2078 2087 Optional. User name for authenticating with the SMTP server.
2079 2088 (default: None)
2080 2089
2081 2090 ``password``
2082 2091 Optional. Password for authenticating with the SMTP server. If not
2083 2092 specified, interactive sessions will prompt the user for a
2084 2093 password; non-interactive sessions will fail. (default: None)
2085 2094
2086 2095 ``local_hostname``
2087 2096 Optional. The hostname that the sender can use to identify
2088 2097 itself to the MTA.
2089 2098
2090 2099
2091 2100 ``subpaths``
2092 2101 ------------
2093 2102
2094 2103 Subrepository source URLs can go stale if a remote server changes name
2095 2104 or becomes temporarily unavailable. This section lets you define
2096 2105 rewrite rules of the form::
2097 2106
2098 2107 <pattern> = <replacement>
2099 2108
2100 2109 where ``pattern`` is a regular expression matching a subrepository
2101 2110 source URL and ``replacement`` is the replacement string used to
2102 2111 rewrite it. Groups can be matched in ``pattern`` and referenced in
2103 2112 ``replacements``. For instance::
2104 2113
2105 2114 http://server/(.*)-hg/ = http://hg.server/\1/
2106 2115
2107 2116 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
2108 2117
2109 2118 Relative subrepository paths are first made absolute, and the
2110 2119 rewrite rules are then applied on the full (absolute) path. If ``pattern``
2111 2120 doesn't match the full path, an attempt is made to apply it on the
2112 2121 relative path alone. The rules are applied in definition order.
2113 2122
2114 2123 ``subrepos``
2115 2124 ------------
2116 2125
2117 2126 This section contains options that control the behavior of the
2118 2127 subrepositories feature. See also :hg:`help subrepos`.
2119 2128
2120 2129 Security note: auditing in Mercurial is known to be insufficient to
2121 2130 prevent clone-time code execution with carefully constructed Git
2122 2131 subrepos. It is unknown if a similar detect is present in Subversion
2123 2132 subrepos. Both Git and Subversion subrepos are disabled by default
2124 2133 out of security concerns. These subrepo types can be enabled using
2125 2134 the respective options below.
2126 2135
2127 2136 ``allowed``
2128 2137 Whether subrepositories are allowed in the working directory.
2129 2138
2130 2139 When false, commands involving subrepositories (like :hg:`update`)
2131 2140 will fail for all subrepository types.
2132 2141 (default: true)
2133 2142
2134 2143 ``hg:allowed``
2135 2144 Whether Mercurial subrepositories are allowed in the working
2136 2145 directory. This option only has an effect if ``subrepos.allowed``
2137 2146 is true.
2138 2147 (default: true)
2139 2148
2140 2149 ``git:allowed``
2141 2150 Whether Git subrepositories are allowed in the working directory.
2142 2151 This option only has an effect if ``subrepos.allowed`` is true.
2143 2152
2144 2153 See the security note above before enabling Git subrepos.
2145 2154 (default: false)
2146 2155
2147 2156 ``svn:allowed``
2148 2157 Whether Subversion subrepositories are allowed in the working
2149 2158 directory. This option only has an effect if ``subrepos.allowed``
2150 2159 is true.
2151 2160
2152 2161 See the security note above before enabling Subversion subrepos.
2153 2162 (default: false)
2154 2163
2155 2164 ``templatealias``
2156 2165 -----------------
2157 2166
2158 2167 Alias definitions for templates. See :hg:`help templates` for details.
2159 2168
2160 2169 ``templates``
2161 2170 -------------
2162 2171
2163 2172 Use the ``[templates]`` section to define template strings.
2164 2173 See :hg:`help templates` for details.
2165 2174
2166 2175 ``trusted``
2167 2176 -----------
2168 2177
2169 2178 Mercurial will not use the settings in the
2170 2179 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
2171 2180 user or to a trusted group, as various hgrc features allow arbitrary
2172 2181 commands to be run. This issue is often encountered when configuring
2173 2182 hooks or extensions for shared repositories or servers. However,
2174 2183 the web interface will use some safe settings from the ``[web]``
2175 2184 section.
2176 2185
2177 2186 This section specifies what users and groups are trusted. The
2178 2187 current user is always trusted. To trust everybody, list a user or a
2179 2188 group with name ``*``. These settings must be placed in an
2180 2189 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
2181 2190 user or service running Mercurial.
2182 2191
2183 2192 ``users``
2184 2193 Comma-separated list of trusted users.
2185 2194
2186 2195 ``groups``
2187 2196 Comma-separated list of trusted groups.
2188 2197
2189 2198
2190 2199 ``ui``
2191 2200 ------
2192 2201
2193 2202 User interface controls.
2194 2203
2195 2204 ``archivemeta``
2196 2205 Whether to include the .hg_archival.txt file containing meta data
2197 2206 (hashes for the repository base and for tip) in archives created
2198 2207 by the :hg:`archive` command or downloaded via hgweb.
2199 2208 (default: True)
2200 2209
2201 2210 ``askusername``
2202 2211 Whether to prompt for a username when committing. If True, and
2203 2212 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
2204 2213 be prompted to enter a username. If no username is entered, the
2205 2214 default ``USER@HOST`` is used instead.
2206 2215 (default: False)
2207 2216
2208 2217 ``clonebundles``
2209 2218 Whether the "clone bundles" feature is enabled.
2210 2219
2211 2220 When enabled, :hg:`clone` may download and apply a server-advertised
2212 2221 bundle file from a URL instead of using the normal exchange mechanism.
2213 2222
2214 2223 This can likely result in faster and more reliable clones.
2215 2224
2216 2225 (default: True)
2217 2226
2218 2227 ``clonebundlefallback``
2219 2228 Whether failure to apply an advertised "clone bundle" from a server
2220 2229 should result in fallback to a regular clone.
2221 2230
2222 2231 This is disabled by default because servers advertising "clone
2223 2232 bundles" often do so to reduce server load. If advertised bundles
2224 2233 start mass failing and clients automatically fall back to a regular
2225 2234 clone, this would add significant and unexpected load to the server
2226 2235 since the server is expecting clone operations to be offloaded to
2227 2236 pre-generated bundles. Failing fast (the default behavior) ensures
2228 2237 clients don't overwhelm the server when "clone bundle" application
2229 2238 fails.
2230 2239
2231 2240 (default: False)
2232 2241
2233 2242 ``clonebundleprefers``
2234 2243 Defines preferences for which "clone bundles" to use.
2235 2244
2236 2245 Servers advertising "clone bundles" may advertise multiple available
2237 2246 bundles. Each bundle may have different attributes, such as the bundle
2238 2247 type and compression format. This option is used to prefer a particular
2239 2248 bundle over another.
2240 2249
2241 2250 The following keys are defined by Mercurial:
2242 2251
2243 2252 BUNDLESPEC
2244 2253 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
2245 2254 e.g. ``gzip-v2`` or ``bzip2-v1``.
2246 2255
2247 2256 COMPRESSION
2248 2257 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
2249 2258
2250 2259 Server operators may define custom keys.
2251 2260
2252 2261 Example values: ``COMPRESSION=bzip2``,
2253 2262 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
2254 2263
2255 2264 By default, the first bundle advertised by the server is used.
2256 2265
2257 2266 ``color``
2258 2267 When to colorize output. Possible value are Boolean ("yes" or "no"), or
2259 2268 "debug", or "always". (default: "yes"). "yes" will use color whenever it
2260 2269 seems possible. See :hg:`help color` for details.
2261 2270
2262 2271 ``commitsubrepos``
2263 2272 Whether to commit modified subrepositories when committing the
2264 2273 parent repository. If False and one subrepository has uncommitted
2265 2274 changes, abort the commit.
2266 2275 (default: False)
2267 2276
2268 2277 ``debug``
2269 2278 Print debugging information. (default: False)
2270 2279
2271 2280 ``editor``
2272 2281 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
2273 2282
2274 2283 ``fallbackencoding``
2275 2284 Encoding to try if it's not possible to decode the changelog using
2276 2285 UTF-8. (default: ISO-8859-1)
2277 2286
2278 2287 ``graphnodetemplate``
2279 2288 The template used to print changeset nodes in an ASCII revision graph.
2280 2289 (default: ``{graphnode}``)
2281 2290
2282 2291 ``ignore``
2283 2292 A file to read per-user ignore patterns from. This file should be
2284 2293 in the same format as a repository-wide .hgignore file. Filenames
2285 2294 are relative to the repository root. This option supports hook syntax,
2286 2295 so if you want to specify multiple ignore files, you can do so by
2287 2296 setting something like ``ignore.other = ~/.hgignore2``. For details
2288 2297 of the ignore file format, see the ``hgignore(5)`` man page.
2289 2298
2290 2299 ``interactive``
2291 2300 Allow to prompt the user. (default: True)
2292 2301
2293 2302 ``interface``
2294 2303 Select the default interface for interactive features (default: text).
2295 2304 Possible values are 'text' and 'curses'.
2296 2305
2297 2306 ``interface.chunkselector``
2298 2307 Select the interface for change recording (e.g. :hg:`commit -i`).
2299 2308 Possible values are 'text' and 'curses'.
2300 2309 This config overrides the interface specified by ui.interface.
2301 2310
2302 2311 ``large-file-limit``
2303 2312 Largest file size that gives no memory use warning.
2304 2313 Possible values are integers or 0 to disable the check.
2305 2314 (default: 10000000)
2306 2315
2307 2316 ``logtemplate``
2308 2317 Template string for commands that print changesets.
2309 2318
2310 2319 ``merge``
2311 2320 The conflict resolution program to use during a manual merge.
2312 2321 For more information on merge tools see :hg:`help merge-tools`.
2313 2322 For configuring merge tools see the ``[merge-tools]`` section.
2314 2323
2315 2324 ``mergemarkers``
2316 2325 Sets the merge conflict marker label styling. The ``detailed``
2317 2326 style uses the ``mergemarkertemplate`` setting to style the labels.
2318 2327 The ``basic`` style just uses 'local' and 'other' as the marker label.
2319 2328 One of ``basic`` or ``detailed``.
2320 2329 (default: ``basic``)
2321 2330
2322 2331 ``mergemarkertemplate``
2323 2332 The template used to print the commit description next to each conflict
2324 2333 marker during merge conflicts. See :hg:`help templates` for the template
2325 2334 format.
2326 2335
2327 2336 Defaults to showing the hash, tags, branches, bookmarks, author, and
2328 2337 the first line of the commit description.
2329 2338
2330 2339 If you use non-ASCII characters in names for tags, branches, bookmarks,
2331 2340 authors, and/or commit descriptions, you must pay attention to encodings of
2332 2341 managed files. At template expansion, non-ASCII characters use the encoding
2333 2342 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2334 2343 environment variables that govern your locale. If the encoding of the merge
2335 2344 markers is different from the encoding of the merged files,
2336 2345 serious problems may occur.
2337 2346
2338 2347 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2339 2348
2340 2349 ``message-output``
2341 2350 Where to write status and error messages. (default: ``stdio``)
2342 2351
2343 2352 ``stderr``
2344 2353 Everything to stderr.
2345 2354 ``stdio``
2346 2355 Status to stdout, and error to stderr.
2347 2356
2348 2357 ``origbackuppath``
2349 2358 The path to a directory used to store generated .orig files. If the path is
2350 2359 not a directory, one will be created. If set, files stored in this
2351 2360 directory have the same name as the original file and do not have a .orig
2352 2361 suffix.
2353 2362
2354 2363 ``paginate``
2355 2364 Control the pagination of command output (default: True). See :hg:`help pager`
2356 2365 for details.
2357 2366
2358 2367 ``patch``
2359 2368 An optional external tool that ``hg import`` and some extensions
2360 2369 will use for applying patches. By default Mercurial uses an
2361 2370 internal patch utility. The external tool must work as the common
2362 2371 Unix ``patch`` program. In particular, it must accept a ``-p``
2363 2372 argument to strip patch headers, a ``-d`` argument to specify the
2364 2373 current directory, a file name to patch, and a patch file to take
2365 2374 from stdin.
2366 2375
2367 2376 It is possible to specify a patch tool together with extra
2368 2377 arguments. For example, setting this option to ``patch --merge``
2369 2378 will use the ``patch`` program with its 2-way merge option.
2370 2379
2371 2380 ``portablefilenames``
2372 2381 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2373 2382 (default: ``warn``)
2374 2383
2375 2384 ``warn``
2376 2385 Print a warning message on POSIX platforms, if a file with a non-portable
2377 2386 filename is added (e.g. a file with a name that can't be created on
2378 2387 Windows because it contains reserved parts like ``AUX``, reserved
2379 2388 characters like ``:``, or would cause a case collision with an existing
2380 2389 file).
2381 2390
2382 2391 ``ignore``
2383 2392 Don't print a warning.
2384 2393
2385 2394 ``abort``
2386 2395 The command is aborted.
2387 2396
2388 2397 ``true``
2389 2398 Alias for ``warn``.
2390 2399
2391 2400 ``false``
2392 2401 Alias for ``ignore``.
2393 2402
2394 2403 .. container:: windows
2395 2404
2396 2405 On Windows, this configuration option is ignored and the command aborted.
2397 2406
2398 2407 ``pre-merge-tool-output-template``
2399 2408 A template that is printed before executing an external merge tool. This can
2400 2409 be used to print out additional context that might be useful to have during
2401 2410 the conflict resolution, such as the description of the various commits
2402 2411 involved or bookmarks/tags.
2403 2412
2404 2413 Additional information is available in the ``local`, ``base``, and ``other``
2405 2414 dicts. For example: ``{local.label}``, ``{base.name}``, or
2406 2415 ``{other.islink}``.
2407 2416
2408 2417 ``quiet``
2409 2418 Reduce the amount of output printed.
2410 2419 (default: False)
2411 2420
2412 2421 ``relative-paths``
2413 2422 Prefer relative paths in the UI.
2414 2423
2415 2424 ``remotecmd``
2416 2425 Remote command to use for clone/push/pull operations.
2417 2426 (default: ``hg``)
2418 2427
2419 2428 ``report_untrusted``
2420 2429 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2421 2430 trusted user or group.
2422 2431 (default: True)
2423 2432
2424 2433 ``slash``
2425 2434 (Deprecated. Use ``slashpath`` template filter instead.)
2426 2435
2427 2436 Display paths using a slash (``/``) as the path separator. This
2428 2437 only makes a difference on systems where the default path
2429 2438 separator is not the slash character (e.g. Windows uses the
2430 2439 backslash character (``\``)).
2431 2440 (default: False)
2432 2441
2433 2442 ``statuscopies``
2434 2443 Display copies in the status command.
2435 2444
2436 2445 ``ssh``
2437 2446 Command to use for SSH connections. (default: ``ssh``)
2438 2447
2439 2448 ``ssherrorhint``
2440 2449 A hint shown to the user in the case of SSH error (e.g.
2441 2450 ``Please see http://company/internalwiki/ssh.html``)
2442 2451
2443 2452 ``strict``
2444 2453 Require exact command names, instead of allowing unambiguous
2445 2454 abbreviations. (default: False)
2446 2455
2447 2456 ``style``
2448 2457 Name of style to use for command output.
2449 2458
2450 2459 ``supportcontact``
2451 2460 A URL where users should report a Mercurial traceback. Use this if you are a
2452 2461 large organisation with its own Mercurial deployment process and crash
2453 2462 reports should be addressed to your internal support.
2454 2463
2455 2464 ``textwidth``
2456 2465 Maximum width of help text. A longer line generated by ``hg help`` or
2457 2466 ``hg subcommand --help`` will be broken after white space to get this
2458 2467 width or the terminal width, whichever comes first.
2459 2468 A non-positive value will disable this and the terminal width will be
2460 2469 used. (default: 78)
2461 2470
2462 2471 ``timeout``
2463 2472 The timeout used when a lock is held (in seconds), a negative value
2464 2473 means no timeout. (default: 600)
2465 2474
2466 2475 ``timeout.warn``
2467 2476 Time (in seconds) before a warning is printed about held lock. A negative
2468 2477 value means no warning. (default: 0)
2469 2478
2470 2479 ``traceback``
2471 2480 Mercurial always prints a traceback when an unknown exception
2472 2481 occurs. Setting this to True will make Mercurial print a traceback
2473 2482 on all exceptions, even those recognized by Mercurial (such as
2474 2483 IOError or MemoryError). (default: False)
2475 2484
2476 2485 ``tweakdefaults``
2477 2486
2478 2487 By default Mercurial's behavior changes very little from release
2479 2488 to release, but over time the recommended config settings
2480 2489 shift. Enable this config to opt in to get automatic tweaks to
2481 2490 Mercurial's behavior over time. This config setting will have no
2482 2491 effect if ``HGPLAIN`` is set or ``HGPLAINEXCEPT`` is set and does
2483 2492 not include ``tweakdefaults``. (default: False)
2484 2493
2485 2494 It currently means::
2486 2495
2487 2496 .. tweakdefaultsmarker
2488 2497
2489 2498 ``username``
2490 2499 The committer of a changeset created when running "commit".
2491 2500 Typically a person's name and email address, e.g. ``Fred Widget
2492 2501 <fred@example.com>``. Environment variables in the
2493 2502 username are expanded.
2494 2503
2495 2504 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2496 2505 hgrc is empty, e.g. if the system admin set ``username =`` in the
2497 2506 system hgrc, it has to be specified manually or in a different
2498 2507 hgrc file)
2499 2508
2500 2509 ``verbose``
2501 2510 Increase the amount of output printed. (default: False)
2502 2511
2503 2512
2504 2513 ``web``
2505 2514 -------
2506 2515
2507 2516 Web interface configuration. The settings in this section apply to
2508 2517 both the builtin webserver (started by :hg:`serve`) and the script you
2509 2518 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2510 2519 and WSGI).
2511 2520
2512 2521 The Mercurial webserver does no authentication (it does not prompt for
2513 2522 usernames and passwords to validate *who* users are), but it does do
2514 2523 authorization (it grants or denies access for *authenticated users*
2515 2524 based on settings in this section). You must either configure your
2516 2525 webserver to do authentication for you, or disable the authorization
2517 2526 checks.
2518 2527
2519 2528 For a quick setup in a trusted environment, e.g., a private LAN, where
2520 2529 you want it to accept pushes from anybody, you can use the following
2521 2530 command line::
2522 2531
2523 2532 $ hg --config web.allow-push=* --config web.push_ssl=False serve
2524 2533
2525 2534 Note that this will allow anybody to push anything to the server and
2526 2535 that this should not be used for public servers.
2527 2536
2528 2537 The full set of options is:
2529 2538
2530 2539 ``accesslog``
2531 2540 Where to output the access log. (default: stdout)
2532 2541
2533 2542 ``address``
2534 2543 Interface address to bind to. (default: all)
2535 2544
2536 2545 ``allow-archive``
2537 2546 List of archive format (bz2, gz, zip) allowed for downloading.
2538 2547 (default: empty)
2539 2548
2540 2549 ``allowbz2``
2541 2550 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2542 2551 revisions.
2543 2552 (default: False)
2544 2553
2545 2554 ``allowgz``
2546 2555 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2547 2556 revisions.
2548 2557 (default: False)
2549 2558
2550 2559 ``allow-pull``
2551 2560 Whether to allow pulling from the repository. (default: True)
2552 2561
2553 2562 ``allow-push``
2554 2563 Whether to allow pushing to the repository. If empty or not set,
2555 2564 pushing is not allowed. If the special value ``*``, any remote
2556 2565 user can push, including unauthenticated users. Otherwise, the
2557 2566 remote user must have been authenticated, and the authenticated
2558 2567 user name must be present in this list. The contents of the
2559 2568 allow-push list are examined after the deny_push list.
2560 2569
2561 2570 ``allow_read``
2562 2571 If the user has not already been denied repository access due to
2563 2572 the contents of deny_read, this list determines whether to grant
2564 2573 repository access to the user. If this list is not empty, and the
2565 2574 user is unauthenticated or not present in the list, then access is
2566 2575 denied for the user. If the list is empty or not set, then access
2567 2576 is permitted to all users by default. Setting allow_read to the
2568 2577 special value ``*`` is equivalent to it not being set (i.e. access
2569 2578 is permitted to all users). The contents of the allow_read list are
2570 2579 examined after the deny_read list.
2571 2580
2572 2581 ``allowzip``
2573 2582 (DEPRECATED) Whether to allow .zip downloading of repository
2574 2583 revisions. This feature creates temporary files.
2575 2584 (default: False)
2576 2585
2577 2586 ``archivesubrepos``
2578 2587 Whether to recurse into subrepositories when archiving.
2579 2588 (default: False)
2580 2589
2581 2590 ``baseurl``
2582 2591 Base URL to use when publishing URLs in other locations, so
2583 2592 third-party tools like email notification hooks can construct
2584 2593 URLs. Example: ``http://hgserver/repos/``.
2585 2594
2586 2595 ``cacerts``
2587 2596 Path to file containing a list of PEM encoded certificate
2588 2597 authority certificates. Environment variables and ``~user``
2589 2598 constructs are expanded in the filename. If specified on the
2590 2599 client, then it will verify the identity of remote HTTPS servers
2591 2600 with these certificates.
2592 2601
2593 2602 To disable SSL verification temporarily, specify ``--insecure`` from
2594 2603 command line.
2595 2604
2596 2605 You can use OpenSSL's CA certificate file if your platform has
2597 2606 one. On most Linux systems this will be
2598 2607 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2599 2608 generate this file manually. The form must be as follows::
2600 2609
2601 2610 -----BEGIN CERTIFICATE-----
2602 2611 ... (certificate in base64 PEM encoding) ...
2603 2612 -----END CERTIFICATE-----
2604 2613 -----BEGIN CERTIFICATE-----
2605 2614 ... (certificate in base64 PEM encoding) ...
2606 2615 -----END CERTIFICATE-----
2607 2616
2608 2617 ``cache``
2609 2618 Whether to support caching in hgweb. (default: True)
2610 2619
2611 2620 ``certificate``
2612 2621 Certificate to use when running :hg:`serve`.
2613 2622
2614 2623 ``collapse``
2615 2624 With ``descend`` enabled, repositories in subdirectories are shown at
2616 2625 a single level alongside repositories in the current path. With
2617 2626 ``collapse`` also enabled, repositories residing at a deeper level than
2618 2627 the current path are grouped behind navigable directory entries that
2619 2628 lead to the locations of these repositories. In effect, this setting
2620 2629 collapses each collection of repositories found within a subdirectory
2621 2630 into a single entry for that subdirectory. (default: False)
2622 2631
2623 2632 ``comparisoncontext``
2624 2633 Number of lines of context to show in side-by-side file comparison. If
2625 2634 negative or the value ``full``, whole files are shown. (default: 5)
2626 2635
2627 2636 This setting can be overridden by a ``context`` request parameter to the
2628 2637 ``comparison`` command, taking the same values.
2629 2638
2630 2639 ``contact``
2631 2640 Name or email address of the person in charge of the repository.
2632 2641 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2633 2642
2634 2643 ``csp``
2635 2644 Send a ``Content-Security-Policy`` HTTP header with this value.
2636 2645
2637 2646 The value may contain a special string ``%nonce%``, which will be replaced
2638 2647 by a randomly-generated one-time use value. If the value contains
2639 2648 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2640 2649 one-time property of the nonce. This nonce will also be inserted into
2641 2650 ``<script>`` elements containing inline JavaScript.
2642 2651
2643 2652 Note: lots of HTML content sent by the server is derived from repository
2644 2653 data. Please consider the potential for malicious repository data to
2645 2654 "inject" itself into generated HTML content as part of your security
2646 2655 threat model.
2647 2656
2648 2657 ``deny_push``
2649 2658 Whether to deny pushing to the repository. If empty or not set,
2650 2659 push is not denied. If the special value ``*``, all remote users are
2651 2660 denied push. Otherwise, unauthenticated users are all denied, and
2652 2661 any authenticated user name present in this list is also denied. The
2653 2662 contents of the deny_push list are examined before the allow-push list.
2654 2663
2655 2664 ``deny_read``
2656 2665 Whether to deny reading/viewing of the repository. If this list is
2657 2666 not empty, unauthenticated users are all denied, and any
2658 2667 authenticated user name present in this list is also denied access to
2659 2668 the repository. If set to the special value ``*``, all remote users
2660 2669 are denied access (rarely needed ;). If deny_read is empty or not set,
2661 2670 the determination of repository access depends on the presence and
2662 2671 content of the allow_read list (see description). If both
2663 2672 deny_read and allow_read are empty or not set, then access is
2664 2673 permitted to all users by default. If the repository is being
2665 2674 served via hgwebdir, denied users will not be able to see it in
2666 2675 the list of repositories. The contents of the deny_read list have
2667 2676 priority over (are examined before) the contents of the allow_read
2668 2677 list.
2669 2678
2670 2679 ``descend``
2671 2680 hgwebdir indexes will not descend into subdirectories. Only repositories
2672 2681 directly in the current path will be shown (other repositories are still
2673 2682 available from the index corresponding to their containing path).
2674 2683
2675 2684 ``description``
2676 2685 Textual description of the repository's purpose or contents.
2677 2686 (default: "unknown")
2678 2687
2679 2688 ``encoding``
2680 2689 Character encoding name. (default: the current locale charset)
2681 2690 Example: "UTF-8".
2682 2691
2683 2692 ``errorlog``
2684 2693 Where to output the error log. (default: stderr)
2685 2694
2686 2695 ``guessmime``
2687 2696 Control MIME types for raw download of file content.
2688 2697 Set to True to let hgweb guess the content type from the file
2689 2698 extension. This will serve HTML files as ``text/html`` and might
2690 2699 allow cross-site scripting attacks when serving untrusted
2691 2700 repositories. (default: False)
2692 2701
2693 2702 ``hidden``
2694 2703 Whether to hide the repository in the hgwebdir index.
2695 2704 (default: False)
2696 2705
2697 2706 ``ipv6``
2698 2707 Whether to use IPv6. (default: False)
2699 2708
2700 2709 ``labels``
2701 2710 List of string *labels* associated with the repository.
2702 2711
2703 2712 Labels are exposed as a template keyword and can be used to customize
2704 2713 output. e.g. the ``index`` template can group or filter repositories
2705 2714 by labels and the ``summary`` template can display additional content
2706 2715 if a specific label is present.
2707 2716
2708 2717 ``logoimg``
2709 2718 File name of the logo image that some templates display on each page.
2710 2719 The file name is relative to ``staticurl``. That is, the full path to
2711 2720 the logo image is "staticurl/logoimg".
2712 2721 If unset, ``hglogo.png`` will be used.
2713 2722
2714 2723 ``logourl``
2715 2724 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2716 2725 will be used.
2717 2726
2718 2727 ``maxchanges``
2719 2728 Maximum number of changes to list on the changelog. (default: 10)
2720 2729
2721 2730 ``maxfiles``
2722 2731 Maximum number of files to list per changeset. (default: 10)
2723 2732
2724 2733 ``maxshortchanges``
2725 2734 Maximum number of changes to list on the shortlog, graph or filelog
2726 2735 pages. (default: 60)
2727 2736
2728 2737 ``name``
2729 2738 Repository name to use in the web interface.
2730 2739 (default: current working directory)
2731 2740
2732 2741 ``port``
2733 2742 Port to listen on. (default: 8000)
2734 2743
2735 2744 ``prefix``
2736 2745 Prefix path to serve from. (default: '' (server root))
2737 2746
2738 2747 ``push_ssl``
2739 2748 Whether to require that inbound pushes be transported over SSL to
2740 2749 prevent password sniffing. (default: True)
2741 2750
2742 2751 ``refreshinterval``
2743 2752 How frequently directory listings re-scan the filesystem for new
2744 2753 repositories, in seconds. This is relevant when wildcards are used
2745 2754 to define paths. Depending on how much filesystem traversal is
2746 2755 required, refreshing may negatively impact performance.
2747 2756
2748 2757 Values less than or equal to 0 always refresh.
2749 2758 (default: 20)
2750 2759
2751 2760 ``server-header``
2752 2761 Value for HTTP ``Server`` response header.
2753 2762
2754 2763 ``static``
2755 2764 Directory where static files are served from.
2756 2765
2757 2766 ``staticurl``
2758 2767 Base URL to use for static files. If unset, static files (e.g. the
2759 2768 hgicon.png favicon) will be served by the CGI script itself. Use
2760 2769 this setting to serve them directly with the HTTP server.
2761 2770 Example: ``http://hgserver/static/``.
2762 2771
2763 2772 ``stripes``
2764 2773 How many lines a "zebra stripe" should span in multi-line output.
2765 2774 Set to 0 to disable. (default: 1)
2766 2775
2767 2776 ``style``
2768 2777 Which template map style to use. The available options are the names of
2769 2778 subdirectories in the HTML templates path. (default: ``paper``)
2770 2779 Example: ``monoblue``.
2771 2780
2772 2781 ``templates``
2773 2782 Where to find the HTML templates. The default path to the HTML templates
2774 2783 can be obtained from ``hg debuginstall``.
2775 2784
2776 2785 ``websub``
2777 2786 ----------
2778 2787
2779 2788 Web substitution filter definition. You can use this section to
2780 2789 define a set of regular expression substitution patterns which
2781 2790 let you automatically modify the hgweb server output.
2782 2791
2783 2792 The default hgweb templates only apply these substitution patterns
2784 2793 on the revision description fields. You can apply them anywhere
2785 2794 you want when you create your own templates by adding calls to the
2786 2795 "websub" filter (usually after calling the "escape" filter).
2787 2796
2788 2797 This can be used, for example, to convert issue references to links
2789 2798 to your issue tracker, or to convert "markdown-like" syntax into
2790 2799 HTML (see the examples below).
2791 2800
2792 2801 Each entry in this section names a substitution filter.
2793 2802 The value of each entry defines the substitution expression itself.
2794 2803 The websub expressions follow the old interhg extension syntax,
2795 2804 which in turn imitates the Unix sed replacement syntax::
2796 2805
2797 2806 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2798 2807
2799 2808 You can use any separator other than "/". The final "i" is optional
2800 2809 and indicates that the search must be case insensitive.
2801 2810
2802 2811 Examples::
2803 2812
2804 2813 [websub]
2805 2814 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2806 2815 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2807 2816 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2808 2817
2809 2818 ``worker``
2810 2819 ----------
2811 2820
2812 2821 Parallel master/worker configuration. We currently perform working
2813 2822 directory updates in parallel on Unix-like systems, which greatly
2814 2823 helps performance.
2815 2824
2816 2825 ``enabled``
2817 2826 Whether to enable workers code to be used.
2818 2827 (default: true)
2819 2828
2820 2829 ``numcpus``
2821 2830 Number of CPUs to use for parallel operations. A zero or
2822 2831 negative value is treated as ``use the default``.
2823 2832 (default: 4 or the number of CPUs on the system, whichever is larger)
2824 2833
2825 2834 ``backgroundclose``
2826 2835 Whether to enable closing file handles on background threads during certain
2827 2836 operations. Some platforms aren't very efficient at closing file
2828 2837 handles that have been written or appended to. By performing file closing
2829 2838 on background threads, file write rate can increase substantially.
2830 2839 (default: true on Windows, false elsewhere)
2831 2840
2832 2841 ``backgroundcloseminfilecount``
2833 2842 Minimum number of files required to trigger background file closing.
2834 2843 Operations not writing this many files won't start background close
2835 2844 threads.
2836 2845 (default: 2048)
2837 2846
2838 2847 ``backgroundclosemaxqueue``
2839 2848 The maximum number of opened file handles waiting to be closed in the
2840 2849 background. This option only has an effect if ``backgroundclose`` is
2841 2850 enabled.
2842 2851 (default: 384)
2843 2852
2844 2853 ``backgroundclosethreadcount``
2845 2854 Number of threads to process background file closes. Only relevant if
2846 2855 ``backgroundclose`` is enabled.
2847 2856 (default: 4)
@@ -1,3151 +1,3177 b''
1 1 # localrepo.py - read/write repository class for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import hashlib
12 12 import os
13 13 import random
14 14 import sys
15 15 import time
16 16 import weakref
17 17
18 18 from .i18n import _
19 19 from .node import (
20 20 bin,
21 21 hex,
22 22 nullid,
23 23 nullrev,
24 24 short,
25 25 )
26 26 from . import (
27 27 bookmarks,
28 28 branchmap,
29 29 bundle2,
30 30 changegroup,
31 31 changelog,
32 32 color,
33 33 context,
34 34 dirstate,
35 35 dirstateguard,
36 36 discovery,
37 37 encoding,
38 38 error,
39 39 exchange,
40 40 extensions,
41 41 filelog,
42 42 hook,
43 43 lock as lockmod,
44 44 manifest,
45 45 match as matchmod,
46 46 merge as mergemod,
47 47 mergeutil,
48 48 namespaces,
49 49 narrowspec,
50 50 obsolete,
51 51 pathutil,
52 52 phases,
53 53 pushkey,
54 54 pycompat,
55 55 repository,
56 56 repoview,
57 57 revset,
58 58 revsetlang,
59 59 scmutil,
60 60 sparse,
61 61 store as storemod,
62 62 subrepoutil,
63 63 tags as tagsmod,
64 64 transaction,
65 65 txnutil,
66 66 util,
67 67 vfs as vfsmod,
68 68 )
69 69 from .utils import (
70 70 interfaceutil,
71 71 procutil,
72 72 stringutil,
73 73 )
74 74
75 75 from .revlogutils import (
76 76 constants as revlogconst,
77 77 )
78 78
79 79 release = lockmod.release
80 80 urlerr = util.urlerr
81 81 urlreq = util.urlreq
82 82
83 83 # set of (path, vfs-location) tuples. vfs-location is:
84 84 # - 'plain for vfs relative paths
85 85 # - '' for svfs relative paths
86 86 _cachedfiles = set()
87 87
88 88 class _basefilecache(scmutil.filecache):
89 89 """All filecache usage on repo are done for logic that should be unfiltered
90 90 """
91 91 def __get__(self, repo, type=None):
92 92 if repo is None:
93 93 return self
94 94 # proxy to unfiltered __dict__ since filtered repo has no entry
95 95 unfi = repo.unfiltered()
96 96 try:
97 97 return unfi.__dict__[self.sname]
98 98 except KeyError:
99 99 pass
100 100 return super(_basefilecache, self).__get__(unfi, type)
101 101
102 102 def set(self, repo, value):
103 103 return super(_basefilecache, self).set(repo.unfiltered(), value)
104 104
105 105 class repofilecache(_basefilecache):
106 106 """filecache for files in .hg but outside of .hg/store"""
107 107 def __init__(self, *paths):
108 108 super(repofilecache, self).__init__(*paths)
109 109 for path in paths:
110 110 _cachedfiles.add((path, 'plain'))
111 111
112 112 def join(self, obj, fname):
113 113 return obj.vfs.join(fname)
114 114
115 115 class storecache(_basefilecache):
116 116 """filecache for files in the store"""
117 117 def __init__(self, *paths):
118 118 super(storecache, self).__init__(*paths)
119 119 for path in paths:
120 120 _cachedfiles.add((path, ''))
121 121
122 122 def join(self, obj, fname):
123 123 return obj.sjoin(fname)
124 124
125 class mixedrepostorecache(_basefilecache):
126 """filecache for a mix files in .hg/store and outside"""
127 def __init__(self, *pathsandlocations):
128 # scmutil.filecache only uses the path for passing back into our
129 # join(), so we can safely pass a list of paths and locations
130 super(mixedrepostorecache, self).__init__(*pathsandlocations)
131 for path, location in pathsandlocations:
132 _cachedfiles.update(pathsandlocations)
133
134 def join(self, obj, fnameandlocation):
135 fname, location = fnameandlocation
136 if location == '':
137 return obj.vfs.join(fname)
138 else:
139 if location != 'store':
140 raise error.ProgrammingError('unexpected location: %s' %
141 location)
142 return obj.sjoin(fname)
143
125 144 def isfilecached(repo, name):
126 145 """check if a repo has already cached "name" filecache-ed property
127 146
128 147 This returns (cachedobj-or-None, iscached) tuple.
129 148 """
130 149 cacheentry = repo.unfiltered()._filecache.get(name, None)
131 150 if not cacheentry:
132 151 return None, False
133 152 return cacheentry.obj, True
134 153
135 154 class unfilteredpropertycache(util.propertycache):
136 155 """propertycache that apply to unfiltered repo only"""
137 156
138 157 def __get__(self, repo, type=None):
139 158 unfi = repo.unfiltered()
140 159 if unfi is repo:
141 160 return super(unfilteredpropertycache, self).__get__(unfi)
142 161 return getattr(unfi, self.name)
143 162
144 163 class filteredpropertycache(util.propertycache):
145 164 """propertycache that must take filtering in account"""
146 165
147 166 def cachevalue(self, obj, value):
148 167 object.__setattr__(obj, self.name, value)
149 168
150 169
151 170 def hasunfilteredcache(repo, name):
152 171 """check if a repo has an unfilteredpropertycache value for <name>"""
153 172 return name in vars(repo.unfiltered())
154 173
155 174 def unfilteredmethod(orig):
156 175 """decorate method that always need to be run on unfiltered version"""
157 176 def wrapper(repo, *args, **kwargs):
158 177 return orig(repo.unfiltered(), *args, **kwargs)
159 178 return wrapper
160 179
161 180 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
162 181 'unbundle'}
163 182 legacycaps = moderncaps.union({'changegroupsubset'})
164 183
165 184 @interfaceutil.implementer(repository.ipeercommandexecutor)
166 185 class localcommandexecutor(object):
167 186 def __init__(self, peer):
168 187 self._peer = peer
169 188 self._sent = False
170 189 self._closed = False
171 190
172 191 def __enter__(self):
173 192 return self
174 193
175 194 def __exit__(self, exctype, excvalue, exctb):
176 195 self.close()
177 196
178 197 def callcommand(self, command, args):
179 198 if self._sent:
180 199 raise error.ProgrammingError('callcommand() cannot be used after '
181 200 'sendcommands()')
182 201
183 202 if self._closed:
184 203 raise error.ProgrammingError('callcommand() cannot be used after '
185 204 'close()')
186 205
187 206 # We don't need to support anything fancy. Just call the named
188 207 # method on the peer and return a resolved future.
189 208 fn = getattr(self._peer, pycompat.sysstr(command))
190 209
191 210 f = pycompat.futures.Future()
192 211
193 212 try:
194 213 result = fn(**pycompat.strkwargs(args))
195 214 except Exception:
196 215 pycompat.future_set_exception_info(f, sys.exc_info()[1:])
197 216 else:
198 217 f.set_result(result)
199 218
200 219 return f
201 220
202 221 def sendcommands(self):
203 222 self._sent = True
204 223
205 224 def close(self):
206 225 self._closed = True
207 226
208 227 @interfaceutil.implementer(repository.ipeercommands)
209 228 class localpeer(repository.peer):
210 229 '''peer for a local repo; reflects only the most recent API'''
211 230
212 231 def __init__(self, repo, caps=None):
213 232 super(localpeer, self).__init__()
214 233
215 234 if caps is None:
216 235 caps = moderncaps.copy()
217 236 self._repo = repo.filtered('served')
218 237 self.ui = repo.ui
219 238 self._caps = repo._restrictcapabilities(caps)
220 239
221 240 # Begin of _basepeer interface.
222 241
223 242 def url(self):
224 243 return self._repo.url()
225 244
226 245 def local(self):
227 246 return self._repo
228 247
229 248 def peer(self):
230 249 return self
231 250
232 251 def canpush(self):
233 252 return True
234 253
235 254 def close(self):
236 255 self._repo.close()
237 256
238 257 # End of _basepeer interface.
239 258
240 259 # Begin of _basewirecommands interface.
241 260
242 261 def branchmap(self):
243 262 return self._repo.branchmap()
244 263
245 264 def capabilities(self):
246 265 return self._caps
247 266
248 267 def clonebundles(self):
249 268 return self._repo.tryread('clonebundles.manifest')
250 269
251 270 def debugwireargs(self, one, two, three=None, four=None, five=None):
252 271 """Used to test argument passing over the wire"""
253 272 return "%s %s %s %s %s" % (one, two, pycompat.bytestr(three),
254 273 pycompat.bytestr(four),
255 274 pycompat.bytestr(five))
256 275
257 276 def getbundle(self, source, heads=None, common=None, bundlecaps=None,
258 277 **kwargs):
259 278 chunks = exchange.getbundlechunks(self._repo, source, heads=heads,
260 279 common=common, bundlecaps=bundlecaps,
261 280 **kwargs)[1]
262 281 cb = util.chunkbuffer(chunks)
263 282
264 283 if exchange.bundle2requested(bundlecaps):
265 284 # When requesting a bundle2, getbundle returns a stream to make the
266 285 # wire level function happier. We need to build a proper object
267 286 # from it in local peer.
268 287 return bundle2.getunbundler(self.ui, cb)
269 288 else:
270 289 return changegroup.getunbundler('01', cb, None)
271 290
272 291 def heads(self):
273 292 return self._repo.heads()
274 293
275 294 def known(self, nodes):
276 295 return self._repo.known(nodes)
277 296
278 297 def listkeys(self, namespace):
279 298 return self._repo.listkeys(namespace)
280 299
281 300 def lookup(self, key):
282 301 return self._repo.lookup(key)
283 302
284 303 def pushkey(self, namespace, key, old, new):
285 304 return self._repo.pushkey(namespace, key, old, new)
286 305
287 306 def stream_out(self):
288 307 raise error.Abort(_('cannot perform stream clone against local '
289 308 'peer'))
290 309
291 310 def unbundle(self, bundle, heads, url):
292 311 """apply a bundle on a repo
293 312
294 313 This function handles the repo locking itself."""
295 314 try:
296 315 try:
297 316 bundle = exchange.readbundle(self.ui, bundle, None)
298 317 ret = exchange.unbundle(self._repo, bundle, heads, 'push', url)
299 318 if util.safehasattr(ret, 'getchunks'):
300 319 # This is a bundle20 object, turn it into an unbundler.
301 320 # This little dance should be dropped eventually when the
302 321 # API is finally improved.
303 322 stream = util.chunkbuffer(ret.getchunks())
304 323 ret = bundle2.getunbundler(self.ui, stream)
305 324 return ret
306 325 except Exception as exc:
307 326 # If the exception contains output salvaged from a bundle2
308 327 # reply, we need to make sure it is printed before continuing
309 328 # to fail. So we build a bundle2 with such output and consume
310 329 # it directly.
311 330 #
312 331 # This is not very elegant but allows a "simple" solution for
313 332 # issue4594
314 333 output = getattr(exc, '_bundle2salvagedoutput', ())
315 334 if output:
316 335 bundler = bundle2.bundle20(self._repo.ui)
317 336 for out in output:
318 337 bundler.addpart(out)
319 338 stream = util.chunkbuffer(bundler.getchunks())
320 339 b = bundle2.getunbundler(self.ui, stream)
321 340 bundle2.processbundle(self._repo, b)
322 341 raise
323 342 except error.PushRaced as exc:
324 343 raise error.ResponseError(_('push failed:'),
325 344 stringutil.forcebytestr(exc))
326 345
327 346 # End of _basewirecommands interface.
328 347
329 348 # Begin of peer interface.
330 349
331 350 def commandexecutor(self):
332 351 return localcommandexecutor(self)
333 352
334 353 # End of peer interface.
335 354
336 355 @interfaceutil.implementer(repository.ipeerlegacycommands)
337 356 class locallegacypeer(localpeer):
338 357 '''peer extension which implements legacy methods too; used for tests with
339 358 restricted capabilities'''
340 359
341 360 def __init__(self, repo):
342 361 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
343 362
344 363 # Begin of baselegacywirecommands interface.
345 364
346 365 def between(self, pairs):
347 366 return self._repo.between(pairs)
348 367
349 368 def branches(self, nodes):
350 369 return self._repo.branches(nodes)
351 370
352 371 def changegroup(self, nodes, source):
353 372 outgoing = discovery.outgoing(self._repo, missingroots=nodes,
354 373 missingheads=self._repo.heads())
355 374 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
356 375
357 376 def changegroupsubset(self, bases, heads, source):
358 377 outgoing = discovery.outgoing(self._repo, missingroots=bases,
359 378 missingheads=heads)
360 379 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
361 380
362 381 # End of baselegacywirecommands interface.
363 382
364 383 # Increment the sub-version when the revlog v2 format changes to lock out old
365 384 # clients.
366 385 REVLOGV2_REQUIREMENT = 'exp-revlogv2.1'
367 386
368 387 # A repository with the sparserevlog feature will have delta chains that
369 388 # can spread over a larger span. Sparse reading cuts these large spans into
370 389 # pieces, so that each piece isn't too big.
371 390 # Without the sparserevlog capability, reading from the repository could use
372 391 # huge amounts of memory, because the whole span would be read at once,
373 392 # including all the intermediate revisions that aren't pertinent for the chain.
374 393 # This is why once a repository has enabled sparse-read, it becomes required.
375 394 SPARSEREVLOG_REQUIREMENT = 'sparserevlog'
376 395
377 396 # Functions receiving (ui, features) that extensions can register to impact
378 397 # the ability to load repositories with custom requirements. Only
379 398 # functions defined in loaded extensions are called.
380 399 #
381 400 # The function receives a set of requirement strings that the repository
382 401 # is capable of opening. Functions will typically add elements to the
383 402 # set to reflect that the extension knows how to handle that requirements.
384 403 featuresetupfuncs = set()
385 404
386 405 def makelocalrepository(baseui, path, intents=None):
387 406 """Create a local repository object.
388 407
389 408 Given arguments needed to construct a local repository, this function
390 409 performs various early repository loading functionality (such as
391 410 reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
392 411 the repository can be opened, derives a type suitable for representing
393 412 that repository, and returns an instance of it.
394 413
395 414 The returned object conforms to the ``repository.completelocalrepository``
396 415 interface.
397 416
398 417 The repository type is derived by calling a series of factory functions
399 418 for each aspect/interface of the final repository. These are defined by
400 419 ``REPO_INTERFACES``.
401 420
402 421 Each factory function is called to produce a type implementing a specific
403 422 interface. The cumulative list of returned types will be combined into a
404 423 new type and that type will be instantiated to represent the local
405 424 repository.
406 425
407 426 The factory functions each receive various state that may be consulted
408 427 as part of deriving a type.
409 428
410 429 Extensions should wrap these factory functions to customize repository type
411 430 creation. Note that an extension's wrapped function may be called even if
412 431 that extension is not loaded for the repo being constructed. Extensions
413 432 should check if their ``__name__`` appears in the
414 433 ``extensionmodulenames`` set passed to the factory function and no-op if
415 434 not.
416 435 """
417 436 ui = baseui.copy()
418 437 # Prevent copying repo configuration.
419 438 ui.copy = baseui.copy
420 439
421 440 # Working directory VFS rooted at repository root.
422 441 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
423 442
424 443 # Main VFS for .hg/ directory.
425 444 hgpath = wdirvfs.join(b'.hg')
426 445 hgvfs = vfsmod.vfs(hgpath, cacheaudited=True)
427 446
428 447 # The .hg/ path should exist and should be a directory. All other
429 448 # cases are errors.
430 449 if not hgvfs.isdir():
431 450 try:
432 451 hgvfs.stat()
433 452 except OSError as e:
434 453 if e.errno != errno.ENOENT:
435 454 raise
436 455
437 456 raise error.RepoError(_(b'repository %s not found') % path)
438 457
439 458 # .hg/requires file contains a newline-delimited list of
440 459 # features/capabilities the opener (us) must have in order to use
441 460 # the repository. This file was introduced in Mercurial 0.9.2,
442 461 # which means very old repositories may not have one. We assume
443 462 # a missing file translates to no requirements.
444 463 try:
445 464 requirements = set(hgvfs.read(b'requires').splitlines())
446 465 except IOError as e:
447 466 if e.errno != errno.ENOENT:
448 467 raise
449 468 requirements = set()
450 469
451 470 # The .hg/hgrc file may load extensions or contain config options
452 471 # that influence repository construction. Attempt to load it and
453 472 # process any new extensions that it may have pulled in.
454 473 if loadhgrc(ui, wdirvfs, hgvfs, requirements):
455 474 afterhgrcload(ui, wdirvfs, hgvfs, requirements)
456 475 extensions.loadall(ui)
457 476 extensions.populateui(ui)
458 477
459 478 # Set of module names of extensions loaded for this repository.
460 479 extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
461 480
462 481 supportedrequirements = gathersupportedrequirements(ui)
463 482
464 483 # We first validate the requirements are known.
465 484 ensurerequirementsrecognized(requirements, supportedrequirements)
466 485
467 486 # Then we validate that the known set is reasonable to use together.
468 487 ensurerequirementscompatible(ui, requirements)
469 488
470 489 # TODO there are unhandled edge cases related to opening repositories with
471 490 # shared storage. If storage is shared, we should also test for requirements
472 491 # compatibility in the pointed-to repo. This entails loading the .hg/hgrc in
473 492 # that repo, as that repo may load extensions needed to open it. This is a
474 493 # bit complicated because we don't want the other hgrc to overwrite settings
475 494 # in this hgrc.
476 495 #
477 496 # This bug is somewhat mitigated by the fact that we copy the .hg/requires
478 497 # file when sharing repos. But if a requirement is added after the share is
479 498 # performed, thereby introducing a new requirement for the opener, we may
480 499 # will not see that and could encounter a run-time error interacting with
481 500 # that shared store since it has an unknown-to-us requirement.
482 501
483 502 # At this point, we know we should be capable of opening the repository.
484 503 # Now get on with doing that.
485 504
486 505 features = set()
487 506
488 507 # The "store" part of the repository holds versioned data. How it is
489 508 # accessed is determined by various requirements. The ``shared`` or
490 509 # ``relshared`` requirements indicate the store lives in the path contained
491 510 # in the ``.hg/sharedpath`` file. This is an absolute path for
492 511 # ``shared`` and relative to ``.hg/`` for ``relshared``.
493 512 if b'shared' in requirements or b'relshared' in requirements:
494 513 sharedpath = hgvfs.read(b'sharedpath').rstrip(b'\n')
495 514 if b'relshared' in requirements:
496 515 sharedpath = hgvfs.join(sharedpath)
497 516
498 517 sharedvfs = vfsmod.vfs(sharedpath, realpath=True)
499 518
500 519 if not sharedvfs.exists():
501 520 raise error.RepoError(_(b'.hg/sharedpath points to nonexistent '
502 521 b'directory %s') % sharedvfs.base)
503 522
504 523 features.add(repository.REPO_FEATURE_SHARED_STORAGE)
505 524
506 525 storebasepath = sharedvfs.base
507 526 cachepath = sharedvfs.join(b'cache')
508 527 else:
509 528 storebasepath = hgvfs.base
510 529 cachepath = hgvfs.join(b'cache')
511 530 wcachepath = hgvfs.join(b'wcache')
512 531
513 532
514 533 # The store has changed over time and the exact layout is dictated by
515 534 # requirements. The store interface abstracts differences across all
516 535 # of them.
517 536 store = makestore(requirements, storebasepath,
518 537 lambda base: vfsmod.vfs(base, cacheaudited=True))
519 538 hgvfs.createmode = store.createmode
520 539
521 540 storevfs = store.vfs
522 541 storevfs.options = resolvestorevfsoptions(ui, requirements, features)
523 542
524 543 # The cache vfs is used to manage cache files.
525 544 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
526 545 cachevfs.createmode = store.createmode
527 546 # The cache vfs is used to manage cache files related to the working copy
528 547 wcachevfs = vfsmod.vfs(wcachepath, cacheaudited=True)
529 548 wcachevfs.createmode = store.createmode
530 549
531 550 # Now resolve the type for the repository object. We do this by repeatedly
532 551 # calling a factory function to produces types for specific aspects of the
533 552 # repo's operation. The aggregate returned types are used as base classes
534 553 # for a dynamically-derived type, which will represent our new repository.
535 554
536 555 bases = []
537 556 extrastate = {}
538 557
539 558 for iface, fn in REPO_INTERFACES:
540 559 # We pass all potentially useful state to give extensions tons of
541 560 # flexibility.
542 561 typ = fn()(ui=ui,
543 562 intents=intents,
544 563 requirements=requirements,
545 564 features=features,
546 565 wdirvfs=wdirvfs,
547 566 hgvfs=hgvfs,
548 567 store=store,
549 568 storevfs=storevfs,
550 569 storeoptions=storevfs.options,
551 570 cachevfs=cachevfs,
552 571 wcachevfs=wcachevfs,
553 572 extensionmodulenames=extensionmodulenames,
554 573 extrastate=extrastate,
555 574 baseclasses=bases)
556 575
557 576 if not isinstance(typ, type):
558 577 raise error.ProgrammingError('unable to construct type for %s' %
559 578 iface)
560 579
561 580 bases.append(typ)
562 581
563 582 # type() allows you to use characters in type names that wouldn't be
564 583 # recognized as Python symbols in source code. We abuse that to add
565 584 # rich information about our constructed repo.
566 585 name = pycompat.sysstr(b'derivedrepo:%s<%s>' % (
567 586 wdirvfs.base,
568 587 b','.join(sorted(requirements))))
569 588
570 589 cls = type(name, tuple(bases), {})
571 590
572 591 return cls(
573 592 baseui=baseui,
574 593 ui=ui,
575 594 origroot=path,
576 595 wdirvfs=wdirvfs,
577 596 hgvfs=hgvfs,
578 597 requirements=requirements,
579 598 supportedrequirements=supportedrequirements,
580 599 sharedpath=storebasepath,
581 600 store=store,
582 601 cachevfs=cachevfs,
583 602 wcachevfs=wcachevfs,
584 603 features=features,
585 604 intents=intents)
586 605
587 606 def loadhgrc(ui, wdirvfs, hgvfs, requirements):
588 607 """Load hgrc files/content into a ui instance.
589 608
590 609 This is called during repository opening to load any additional
591 610 config files or settings relevant to the current repository.
592 611
593 612 Returns a bool indicating whether any additional configs were loaded.
594 613
595 614 Extensions should monkeypatch this function to modify how per-repo
596 615 configs are loaded. For example, an extension may wish to pull in
597 616 configs from alternate files or sources.
598 617 """
599 618 try:
600 619 ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
601 620 return True
602 621 except IOError:
603 622 return False
604 623
605 624 def afterhgrcload(ui, wdirvfs, hgvfs, requirements):
606 625 """Perform additional actions after .hg/hgrc is loaded.
607 626
608 627 This function is called during repository loading immediately after
609 628 the .hg/hgrc file is loaded and before per-repo extensions are loaded.
610 629
611 630 The function can be used to validate configs, automatically add
612 631 options (including extensions) based on requirements, etc.
613 632 """
614 633
615 634 # Map of requirements to list of extensions to load automatically when
616 635 # requirement is present.
617 636 autoextensions = {
618 637 b'largefiles': [b'largefiles'],
619 638 b'lfs': [b'lfs'],
620 639 }
621 640
622 641 for requirement, names in sorted(autoextensions.items()):
623 642 if requirement not in requirements:
624 643 continue
625 644
626 645 for name in names:
627 646 if not ui.hasconfig(b'extensions', name):
628 647 ui.setconfig(b'extensions', name, b'', source='autoload')
629 648
630 649 def gathersupportedrequirements(ui):
631 650 """Determine the complete set of recognized requirements."""
632 651 # Start with all requirements supported by this file.
633 652 supported = set(localrepository._basesupported)
634 653
635 654 # Execute ``featuresetupfuncs`` entries if they belong to an extension
636 655 # relevant to this ui instance.
637 656 modules = {m.__name__ for n, m in extensions.extensions(ui)}
638 657
639 658 for fn in featuresetupfuncs:
640 659 if fn.__module__ in modules:
641 660 fn(ui, supported)
642 661
643 662 # Add derived requirements from registered compression engines.
644 663 for name in util.compengines:
645 664 engine = util.compengines[name]
646 665 if engine.available() and engine.revlogheader():
647 666 supported.add(b'exp-compression-%s' % name)
648 667 if engine.name() == 'zstd':
649 668 supported.add(b'revlog-compression-zstd')
650 669
651 670 return supported
652 671
653 672 def ensurerequirementsrecognized(requirements, supported):
654 673 """Validate that a set of local requirements is recognized.
655 674
656 675 Receives a set of requirements. Raises an ``error.RepoError`` if there
657 676 exists any requirement in that set that currently loaded code doesn't
658 677 recognize.
659 678
660 679 Returns a set of supported requirements.
661 680 """
662 681 missing = set()
663 682
664 683 for requirement in requirements:
665 684 if requirement in supported:
666 685 continue
667 686
668 687 if not requirement or not requirement[0:1].isalnum():
669 688 raise error.RequirementError(_(b'.hg/requires file is corrupt'))
670 689
671 690 missing.add(requirement)
672 691
673 692 if missing:
674 693 raise error.RequirementError(
675 694 _(b'repository requires features unknown to this Mercurial: %s') %
676 695 b' '.join(sorted(missing)),
677 696 hint=_(b'see https://mercurial-scm.org/wiki/MissingRequirement '
678 697 b'for more information'))
679 698
680 699 def ensurerequirementscompatible(ui, requirements):
681 700 """Validates that a set of recognized requirements is mutually compatible.
682 701
683 702 Some requirements may not be compatible with others or require
684 703 config options that aren't enabled. This function is called during
685 704 repository opening to ensure that the set of requirements needed
686 705 to open a repository is sane and compatible with config options.
687 706
688 707 Extensions can monkeypatch this function to perform additional
689 708 checking.
690 709
691 710 ``error.RepoError`` should be raised on failure.
692 711 """
693 712 if b'exp-sparse' in requirements and not sparse.enabled:
694 713 raise error.RepoError(_(b'repository is using sparse feature but '
695 714 b'sparse is not enabled; enable the '
696 715 b'"sparse" extensions to access'))
697 716
698 717 def makestore(requirements, path, vfstype):
699 718 """Construct a storage object for a repository."""
700 719 if b'store' in requirements:
701 720 if b'fncache' in requirements:
702 721 return storemod.fncachestore(path, vfstype,
703 722 b'dotencode' in requirements)
704 723
705 724 return storemod.encodedstore(path, vfstype)
706 725
707 726 return storemod.basicstore(path, vfstype)
708 727
709 728 def resolvestorevfsoptions(ui, requirements, features):
710 729 """Resolve the options to pass to the store vfs opener.
711 730
712 731 The returned dict is used to influence behavior of the storage layer.
713 732 """
714 733 options = {}
715 734
716 735 if b'treemanifest' in requirements:
717 736 options[b'treemanifest'] = True
718 737
719 738 # experimental config: format.manifestcachesize
720 739 manifestcachesize = ui.configint(b'format', b'manifestcachesize')
721 740 if manifestcachesize is not None:
722 741 options[b'manifestcachesize'] = manifestcachesize
723 742
724 743 # In the absence of another requirement superseding a revlog-related
725 744 # requirement, we have to assume the repo is using revlog version 0.
726 745 # This revlog format is super old and we don't bother trying to parse
727 746 # opener options for it because those options wouldn't do anything
728 747 # meaningful on such old repos.
729 748 if b'revlogv1' in requirements or REVLOGV2_REQUIREMENT in requirements:
730 749 options.update(resolverevlogstorevfsoptions(ui, requirements, features))
731 750
732 751 return options
733 752
734 753 def resolverevlogstorevfsoptions(ui, requirements, features):
735 754 """Resolve opener options specific to revlogs."""
736 755
737 756 options = {}
738 757 options[b'flagprocessors'] = {}
739 758
740 759 if b'revlogv1' in requirements:
741 760 options[b'revlogv1'] = True
742 761 if REVLOGV2_REQUIREMENT in requirements:
743 762 options[b'revlogv2'] = True
744 763
745 764 if b'generaldelta' in requirements:
746 765 options[b'generaldelta'] = True
747 766
748 767 # experimental config: format.chunkcachesize
749 768 chunkcachesize = ui.configint(b'format', b'chunkcachesize')
750 769 if chunkcachesize is not None:
751 770 options[b'chunkcachesize'] = chunkcachesize
752 771
753 772 deltabothparents = ui.configbool(b'storage',
754 773 b'revlog.optimize-delta-parent-choice')
755 774 options[b'deltabothparents'] = deltabothparents
756 775
757 776 lazydelta = ui.configbool(b'storage', b'revlog.reuse-external-delta')
758 777 lazydeltabase = False
759 778 if lazydelta:
760 779 lazydeltabase = ui.configbool(b'storage',
761 780 b'revlog.reuse-external-delta-parent')
762 781 if lazydeltabase is None:
763 782 lazydeltabase = not scmutil.gddeltaconfig(ui)
764 783 options[b'lazydelta'] = lazydelta
765 784 options[b'lazydeltabase'] = lazydeltabase
766 785
767 786 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan')
768 787 if 0 <= chainspan:
769 788 options[b'maxdeltachainspan'] = chainspan
770 789
771 790 mmapindexthreshold = ui.configbytes(b'experimental',
772 791 b'mmapindexthreshold')
773 792 if mmapindexthreshold is not None:
774 793 options[b'mmapindexthreshold'] = mmapindexthreshold
775 794
776 795 withsparseread = ui.configbool(b'experimental', b'sparse-read')
777 796 srdensitythres = float(ui.config(b'experimental',
778 797 b'sparse-read.density-threshold'))
779 798 srmingapsize = ui.configbytes(b'experimental',
780 799 b'sparse-read.min-gap-size')
781 800 options[b'with-sparse-read'] = withsparseread
782 801 options[b'sparse-read-density-threshold'] = srdensitythres
783 802 options[b'sparse-read-min-gap-size'] = srmingapsize
784 803
785 804 sparserevlog = SPARSEREVLOG_REQUIREMENT in requirements
786 805 options[b'sparse-revlog'] = sparserevlog
787 806 if sparserevlog:
788 807 options[b'generaldelta'] = True
789 808
790 809 maxchainlen = None
791 810 if sparserevlog:
792 811 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH
793 812 # experimental config: format.maxchainlen
794 813 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen)
795 814 if maxchainlen is not None:
796 815 options[b'maxchainlen'] = maxchainlen
797 816
798 817 for r in requirements:
799 818 # we allow multiple compression engine requirement to co-exist because
800 819 # strickly speaking, revlog seems to support mixed compression style.
801 820 #
802 821 # The compression used for new entries will be "the last one"
803 822 prefix = r.startswith
804 823 if prefix('revlog-compression-') or prefix('exp-compression-'):
805 824 options[b'compengine'] = r.split('-', 2)[2]
806 825
807 826 options[b'zlib.level'] = ui.configint(b'storage', b'revlog.zlib.level')
808 827 if options[b'zlib.level'] is not None:
809 828 if not (0 <= options[b'zlib.level'] <= 9):
810 829 msg = _('invalid value for `storage.revlog.zlib.level` config: %d')
811 830 raise error.Abort(msg % options[b'zlib.level'])
812 831 options[b'zstd.level'] = ui.configint(b'storage', b'revlog.zstd.level')
813 832 if options[b'zstd.level'] is not None:
814 833 if not (0 <= options[b'zstd.level'] <= 22):
815 834 msg = _('invalid value for `storage.revlog.zstd.level` config: %d')
816 835 raise error.Abort(msg % options[b'zstd.level'])
817 836
818 837 if repository.NARROW_REQUIREMENT in requirements:
819 838 options[b'enableellipsis'] = True
820 839
821 840 return options
822 841
823 842 def makemain(**kwargs):
824 843 """Produce a type conforming to ``ilocalrepositorymain``."""
825 844 return localrepository
826 845
827 846 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
828 847 class revlogfilestorage(object):
829 848 """File storage when using revlogs."""
830 849
831 850 def file(self, path):
832 851 if path[0] == b'/':
833 852 path = path[1:]
834 853
835 854 return filelog.filelog(self.svfs, path)
836 855
837 856 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
838 857 class revlognarrowfilestorage(object):
839 858 """File storage when using revlogs and narrow files."""
840 859
841 860 def file(self, path):
842 861 if path[0] == b'/':
843 862 path = path[1:]
844 863
845 864 return filelog.narrowfilelog(self.svfs, path, self._storenarrowmatch)
846 865
847 866 def makefilestorage(requirements, features, **kwargs):
848 867 """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
849 868 features.add(repository.REPO_FEATURE_REVLOG_FILE_STORAGE)
850 869 features.add(repository.REPO_FEATURE_STREAM_CLONE)
851 870
852 871 if repository.NARROW_REQUIREMENT in requirements:
853 872 return revlognarrowfilestorage
854 873 else:
855 874 return revlogfilestorage
856 875
857 876 # List of repository interfaces and factory functions for them. Each
858 877 # will be called in order during ``makelocalrepository()`` to iteratively
859 878 # derive the final type for a local repository instance. We capture the
860 879 # function as a lambda so we don't hold a reference and the module-level
861 880 # functions can be wrapped.
862 881 REPO_INTERFACES = [
863 882 (repository.ilocalrepositorymain, lambda: makemain),
864 883 (repository.ilocalrepositoryfilestorage, lambda: makefilestorage),
865 884 ]
866 885
867 886 @interfaceutil.implementer(repository.ilocalrepositorymain)
868 887 class localrepository(object):
869 888 """Main class for representing local repositories.
870 889
871 890 All local repositories are instances of this class.
872 891
873 892 Constructed on its own, instances of this class are not usable as
874 893 repository objects. To obtain a usable repository object, call
875 894 ``hg.repository()``, ``localrepo.instance()``, or
876 895 ``localrepo.makelocalrepository()``. The latter is the lowest-level.
877 896 ``instance()`` adds support for creating new repositories.
878 897 ``hg.repository()`` adds more extension integration, including calling
879 898 ``reposetup()``. Generally speaking, ``hg.repository()`` should be
880 899 used.
881 900 """
882 901
883 902 # obsolete experimental requirements:
884 903 # - manifestv2: An experimental new manifest format that allowed
885 904 # for stem compression of long paths. Experiment ended up not
886 905 # being successful (repository sizes went up due to worse delta
887 906 # chains), and the code was deleted in 4.6.
888 907 supportedformats = {
889 908 'revlogv1',
890 909 'generaldelta',
891 910 'treemanifest',
892 911 REVLOGV2_REQUIREMENT,
893 912 SPARSEREVLOG_REQUIREMENT,
913 bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT,
894 914 }
895 915 _basesupported = supportedformats | {
896 916 'store',
897 917 'fncache',
898 918 'shared',
899 919 'relshared',
900 920 'dotencode',
901 921 'exp-sparse',
902 922 'internal-phase'
903 923 }
904 924
905 925 # list of prefix for file which can be written without 'wlock'
906 926 # Extensions should extend this list when needed
907 927 _wlockfreeprefix = {
908 928 # We migh consider requiring 'wlock' for the next
909 929 # two, but pretty much all the existing code assume
910 930 # wlock is not needed so we keep them excluded for
911 931 # now.
912 932 'hgrc',
913 933 'requires',
914 934 # XXX cache is a complicatged business someone
915 935 # should investigate this in depth at some point
916 936 'cache/',
917 937 # XXX shouldn't be dirstate covered by the wlock?
918 938 'dirstate',
919 939 # XXX bisect was still a bit too messy at the time
920 940 # this changeset was introduced. Someone should fix
921 941 # the remainig bit and drop this line
922 942 'bisect.state',
923 943 }
924 944
925 945 def __init__(self, baseui, ui, origroot, wdirvfs, hgvfs, requirements,
926 946 supportedrequirements, sharedpath, store, cachevfs, wcachevfs,
927 947 features, intents=None):
928 948 """Create a new local repository instance.
929 949
930 950 Most callers should use ``hg.repository()``, ``localrepo.instance()``,
931 951 or ``localrepo.makelocalrepository()`` for obtaining a new repository
932 952 object.
933 953
934 954 Arguments:
935 955
936 956 baseui
937 957 ``ui.ui`` instance that ``ui`` argument was based off of.
938 958
939 959 ui
940 960 ``ui.ui`` instance for use by the repository.
941 961
942 962 origroot
943 963 ``bytes`` path to working directory root of this repository.
944 964
945 965 wdirvfs
946 966 ``vfs.vfs`` rooted at the working directory.
947 967
948 968 hgvfs
949 969 ``vfs.vfs`` rooted at .hg/
950 970
951 971 requirements
952 972 ``set`` of bytestrings representing repository opening requirements.
953 973
954 974 supportedrequirements
955 975 ``set`` of bytestrings representing repository requirements that we
956 976 know how to open. May be a supetset of ``requirements``.
957 977
958 978 sharedpath
959 979 ``bytes`` Defining path to storage base directory. Points to a
960 980 ``.hg/`` directory somewhere.
961 981
962 982 store
963 983 ``store.basicstore`` (or derived) instance providing access to
964 984 versioned storage.
965 985
966 986 cachevfs
967 987 ``vfs.vfs`` used for cache files.
968 988
969 989 wcachevfs
970 990 ``vfs.vfs`` used for cache files related to the working copy.
971 991
972 992 features
973 993 ``set`` of bytestrings defining features/capabilities of this
974 994 instance.
975 995
976 996 intents
977 997 ``set`` of system strings indicating what this repo will be used
978 998 for.
979 999 """
980 1000 self.baseui = baseui
981 1001 self.ui = ui
982 1002 self.origroot = origroot
983 1003 # vfs rooted at working directory.
984 1004 self.wvfs = wdirvfs
985 1005 self.root = wdirvfs.base
986 1006 # vfs rooted at .hg/. Used to access most non-store paths.
987 1007 self.vfs = hgvfs
988 1008 self.path = hgvfs.base
989 1009 self.requirements = requirements
990 1010 self.supported = supportedrequirements
991 1011 self.sharedpath = sharedpath
992 1012 self.store = store
993 1013 self.cachevfs = cachevfs
994 1014 self.wcachevfs = wcachevfs
995 1015 self.features = features
996 1016
997 1017 self.filtername = None
998 1018
999 1019 if (self.ui.configbool('devel', 'all-warnings') or
1000 1020 self.ui.configbool('devel', 'check-locks')):
1001 1021 self.vfs.audit = self._getvfsward(self.vfs.audit)
1002 1022 # A list of callback to shape the phase if no data were found.
1003 1023 # Callback are in the form: func(repo, roots) --> processed root.
1004 1024 # This list it to be filled by extension during repo setup
1005 1025 self._phasedefaults = []
1006 1026
1007 1027 color.setup(self.ui)
1008 1028
1009 1029 self.spath = self.store.path
1010 1030 self.svfs = self.store.vfs
1011 1031 self.sjoin = self.store.join
1012 1032 if (self.ui.configbool('devel', 'all-warnings') or
1013 1033 self.ui.configbool('devel', 'check-locks')):
1014 1034 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs
1015 1035 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
1016 1036 else: # standard vfs
1017 1037 self.svfs.audit = self._getsvfsward(self.svfs.audit)
1018 1038
1019 1039 self._dirstatevalidatewarned = False
1020 1040
1021 1041 self._branchcaches = branchmap.BranchMapCache()
1022 1042 self._revbranchcache = None
1023 1043 self._filterpats = {}
1024 1044 self._datafilters = {}
1025 1045 self._transref = self._lockref = self._wlockref = None
1026 1046
1027 1047 # A cache for various files under .hg/ that tracks file changes,
1028 1048 # (used by the filecache decorator)
1029 1049 #
1030 1050 # Maps a property name to its util.filecacheentry
1031 1051 self._filecache = {}
1032 1052
1033 1053 # hold sets of revision to be filtered
1034 1054 # should be cleared when something might have changed the filter value:
1035 1055 # - new changesets,
1036 1056 # - phase change,
1037 1057 # - new obsolescence marker,
1038 1058 # - working directory parent change,
1039 1059 # - bookmark changes
1040 1060 self.filteredrevcache = {}
1041 1061
1042 1062 # post-dirstate-status hooks
1043 1063 self._postdsstatus = []
1044 1064
1045 1065 # generic mapping between names and nodes
1046 1066 self.names = namespaces.namespaces()
1047 1067
1048 1068 # Key to signature value.
1049 1069 self._sparsesignaturecache = {}
1050 1070 # Signature to cached matcher instance.
1051 1071 self._sparsematchercache = {}
1052 1072
1053 1073 self._extrafilterid = repoview.extrafilter(ui)
1054 1074
1055 1075 def _getvfsward(self, origfunc):
1056 1076 """build a ward for self.vfs"""
1057 1077 rref = weakref.ref(self)
1058 1078 def checkvfs(path, mode=None):
1059 1079 ret = origfunc(path, mode=mode)
1060 1080 repo = rref()
1061 1081 if (repo is None
1062 1082 or not util.safehasattr(repo, '_wlockref')
1063 1083 or not util.safehasattr(repo, '_lockref')):
1064 1084 return
1065 1085 if mode in (None, 'r', 'rb'):
1066 1086 return
1067 1087 if path.startswith(repo.path):
1068 1088 # truncate name relative to the repository (.hg)
1069 1089 path = path[len(repo.path) + 1:]
1070 1090 if path.startswith('cache/'):
1071 1091 msg = 'accessing cache with vfs instead of cachevfs: "%s"'
1072 1092 repo.ui.develwarn(msg % path, stacklevel=3, config="cache-vfs")
1073 1093 if path.startswith('journal.') or path.startswith('undo.'):
1074 1094 # journal is covered by 'lock'
1075 1095 if repo._currentlock(repo._lockref) is None:
1076 1096 repo.ui.develwarn('write with no lock: "%s"' % path,
1077 1097 stacklevel=3, config='check-locks')
1078 1098 elif repo._currentlock(repo._wlockref) is None:
1079 1099 # rest of vfs files are covered by 'wlock'
1080 1100 #
1081 1101 # exclude special files
1082 1102 for prefix in self._wlockfreeprefix:
1083 1103 if path.startswith(prefix):
1084 1104 return
1085 1105 repo.ui.develwarn('write with no wlock: "%s"' % path,
1086 1106 stacklevel=3, config='check-locks')
1087 1107 return ret
1088 1108 return checkvfs
1089 1109
1090 1110 def _getsvfsward(self, origfunc):
1091 1111 """build a ward for self.svfs"""
1092 1112 rref = weakref.ref(self)
1093 1113 def checksvfs(path, mode=None):
1094 1114 ret = origfunc(path, mode=mode)
1095 1115 repo = rref()
1096 1116 if repo is None or not util.safehasattr(repo, '_lockref'):
1097 1117 return
1098 1118 if mode in (None, 'r', 'rb'):
1099 1119 return
1100 1120 if path.startswith(repo.sharedpath):
1101 1121 # truncate name relative to the repository (.hg)
1102 1122 path = path[len(repo.sharedpath) + 1:]
1103 1123 if repo._currentlock(repo._lockref) is None:
1104 1124 repo.ui.develwarn('write with no lock: "%s"' % path,
1105 1125 stacklevel=4)
1106 1126 return ret
1107 1127 return checksvfs
1108 1128
1109 1129 def close(self):
1110 1130 self._writecaches()
1111 1131
1112 1132 def _writecaches(self):
1113 1133 if self._revbranchcache:
1114 1134 self._revbranchcache.write()
1115 1135
1116 1136 def _restrictcapabilities(self, caps):
1117 1137 if self.ui.configbool('experimental', 'bundle2-advertise'):
1118 1138 caps = set(caps)
1119 1139 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self,
1120 1140 role='client'))
1121 1141 caps.add('bundle2=' + urlreq.quote(capsblob))
1122 1142 return caps
1123 1143
1124 1144 def _writerequirements(self):
1125 1145 scmutil.writerequires(self.vfs, self.requirements)
1126 1146
1127 1147 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle:
1128 1148 # self -> auditor -> self._checknested -> self
1129 1149
1130 1150 @property
1131 1151 def auditor(self):
1132 1152 # This is only used by context.workingctx.match in order to
1133 1153 # detect files in subrepos.
1134 1154 return pathutil.pathauditor(self.root, callback=self._checknested)
1135 1155
1136 1156 @property
1137 1157 def nofsauditor(self):
1138 1158 # This is only used by context.basectx.match in order to detect
1139 1159 # files in subrepos.
1140 1160 return pathutil.pathauditor(self.root, callback=self._checknested,
1141 1161 realfs=False, cached=True)
1142 1162
1143 1163 def _checknested(self, path):
1144 1164 """Determine if path is a legal nested repository."""
1145 1165 if not path.startswith(self.root):
1146 1166 return False
1147 1167 subpath = path[len(self.root) + 1:]
1148 1168 normsubpath = util.pconvert(subpath)
1149 1169
1150 1170 # XXX: Checking against the current working copy is wrong in
1151 1171 # the sense that it can reject things like
1152 1172 #
1153 1173 # $ hg cat -r 10 sub/x.txt
1154 1174 #
1155 1175 # if sub/ is no longer a subrepository in the working copy
1156 1176 # parent revision.
1157 1177 #
1158 1178 # However, it can of course also allow things that would have
1159 1179 # been rejected before, such as the above cat command if sub/
1160 1180 # is a subrepository now, but was a normal directory before.
1161 1181 # The old path auditor would have rejected by mistake since it
1162 1182 # panics when it sees sub/.hg/.
1163 1183 #
1164 1184 # All in all, checking against the working copy seems sensible
1165 1185 # since we want to prevent access to nested repositories on
1166 1186 # the filesystem *now*.
1167 1187 ctx = self[None]
1168 1188 parts = util.splitpath(subpath)
1169 1189 while parts:
1170 1190 prefix = '/'.join(parts)
1171 1191 if prefix in ctx.substate:
1172 1192 if prefix == normsubpath:
1173 1193 return True
1174 1194 else:
1175 1195 sub = ctx.sub(prefix)
1176 1196 return sub.checknested(subpath[len(prefix) + 1:])
1177 1197 else:
1178 1198 parts.pop()
1179 1199 return False
1180 1200
1181 1201 def peer(self):
1182 1202 return localpeer(self) # not cached to avoid reference cycle
1183 1203
1184 1204 def unfiltered(self):
1185 1205 """Return unfiltered version of the repository
1186 1206
1187 1207 Intended to be overwritten by filtered repo."""
1188 1208 return self
1189 1209
1190 1210 def filtered(self, name, visibilityexceptions=None):
1191 1211 """Return a filtered version of a repository
1192 1212
1193 1213 The `name` parameter is the identifier of the requested view. This
1194 1214 will return a repoview object set "exactly" to the specified view.
1195 1215
1196 1216 This function does not apply recursive filtering to a repository. For
1197 1217 example calling `repo.filtered("served")` will return a repoview using
1198 1218 the "served" view, regardless of the initial view used by `repo`.
1199 1219
1200 1220 In other word, there is always only one level of `repoview` "filtering".
1201 1221 """
1202 1222 if self._extrafilterid is not None and '%' not in name:
1203 1223 name = name + '%' + self._extrafilterid
1204 1224
1205 1225 cls = repoview.newtype(self.unfiltered().__class__)
1206 1226 return cls(self, name, visibilityexceptions)
1207 1227
1208 @repofilecache('bookmarks', 'bookmarks.current')
1228 @mixedrepostorecache(('bookmarks', ''), ('bookmarks.current', ''),
1229 ('bookmarks', 'store'))
1209 1230 def _bookmarks(self):
1210 1231 return bookmarks.bmstore(self)
1211 1232
1212 1233 @property
1213 1234 def _activebookmark(self):
1214 1235 return self._bookmarks.active
1215 1236
1216 1237 # _phasesets depend on changelog. what we need is to call
1217 1238 # _phasecache.invalidate() if '00changelog.i' was changed, but it
1218 1239 # can't be easily expressed in filecache mechanism.
1219 1240 @storecache('phaseroots', '00changelog.i')
1220 1241 def _phasecache(self):
1221 1242 return phases.phasecache(self, self._phasedefaults)
1222 1243
1223 1244 @storecache('obsstore')
1224 1245 def obsstore(self):
1225 1246 return obsolete.makestore(self.ui, self)
1226 1247
1227 1248 @storecache('00changelog.i')
1228 1249 def changelog(self):
1229 1250 return changelog.changelog(self.svfs,
1230 1251 trypending=txnutil.mayhavepending(self.root))
1231 1252
1232 1253 @storecache('00manifest.i')
1233 1254 def manifestlog(self):
1234 1255 rootstore = manifest.manifestrevlog(self.svfs)
1235 1256 return manifest.manifestlog(self.svfs, self, rootstore,
1236 1257 self._storenarrowmatch)
1237 1258
1238 1259 @repofilecache('dirstate')
1239 1260 def dirstate(self):
1240 1261 return self._makedirstate()
1241 1262
1242 1263 def _makedirstate(self):
1243 1264 """Extension point for wrapping the dirstate per-repo."""
1244 1265 sparsematchfn = lambda: sparse.matcher(self)
1245 1266
1246 1267 return dirstate.dirstate(self.vfs, self.ui, self.root,
1247 1268 self._dirstatevalidate, sparsematchfn)
1248 1269
1249 1270 def _dirstatevalidate(self, node):
1250 1271 try:
1251 1272 self.changelog.rev(node)
1252 1273 return node
1253 1274 except error.LookupError:
1254 1275 if not self._dirstatevalidatewarned:
1255 1276 self._dirstatevalidatewarned = True
1256 1277 self.ui.warn(_("warning: ignoring unknown"
1257 1278 " working parent %s!\n") % short(node))
1258 1279 return nullid
1259 1280
1260 1281 @storecache(narrowspec.FILENAME)
1261 1282 def narrowpats(self):
1262 1283 """matcher patterns for this repository's narrowspec
1263 1284
1264 1285 A tuple of (includes, excludes).
1265 1286 """
1266 1287 return narrowspec.load(self)
1267 1288
1268 1289 @storecache(narrowspec.FILENAME)
1269 1290 def _storenarrowmatch(self):
1270 1291 if repository.NARROW_REQUIREMENT not in self.requirements:
1271 1292 return matchmod.always()
1272 1293 include, exclude = self.narrowpats
1273 1294 return narrowspec.match(self.root, include=include, exclude=exclude)
1274 1295
1275 1296 @storecache(narrowspec.FILENAME)
1276 1297 def _narrowmatch(self):
1277 1298 if repository.NARROW_REQUIREMENT not in self.requirements:
1278 1299 return matchmod.always()
1279 1300 narrowspec.checkworkingcopynarrowspec(self)
1280 1301 include, exclude = self.narrowpats
1281 1302 return narrowspec.match(self.root, include=include, exclude=exclude)
1282 1303
1283 1304 def narrowmatch(self, match=None, includeexact=False):
1284 1305 """matcher corresponding the the repo's narrowspec
1285 1306
1286 1307 If `match` is given, then that will be intersected with the narrow
1287 1308 matcher.
1288 1309
1289 1310 If `includeexact` is True, then any exact matches from `match` will
1290 1311 be included even if they're outside the narrowspec.
1291 1312 """
1292 1313 if match:
1293 1314 if includeexact and not self._narrowmatch.always():
1294 1315 # do not exclude explicitly-specified paths so that they can
1295 1316 # be warned later on
1296 1317 em = matchmod.exact(match.files())
1297 1318 nm = matchmod.unionmatcher([self._narrowmatch, em])
1298 1319 return matchmod.intersectmatchers(match, nm)
1299 1320 return matchmod.intersectmatchers(match, self._narrowmatch)
1300 1321 return self._narrowmatch
1301 1322
1302 1323 def setnarrowpats(self, newincludes, newexcludes):
1303 1324 narrowspec.save(self, newincludes, newexcludes)
1304 1325 self.invalidate(clearfilecache=True)
1305 1326
1306 1327 def __getitem__(self, changeid):
1307 1328 if changeid is None:
1308 1329 return context.workingctx(self)
1309 1330 if isinstance(changeid, context.basectx):
1310 1331 return changeid
1311 1332 if isinstance(changeid, slice):
1312 1333 # wdirrev isn't contiguous so the slice shouldn't include it
1313 1334 return [self[i]
1314 1335 for i in pycompat.xrange(*changeid.indices(len(self)))
1315 1336 if i not in self.changelog.filteredrevs]
1316 1337 try:
1317 1338 if isinstance(changeid, int):
1318 1339 node = self.changelog.node(changeid)
1319 1340 rev = changeid
1320 1341 elif changeid == 'null':
1321 1342 node = nullid
1322 1343 rev = nullrev
1323 1344 elif changeid == 'tip':
1324 1345 node = self.changelog.tip()
1325 1346 rev = self.changelog.rev(node)
1326 1347 elif changeid == '.':
1327 1348 # this is a hack to delay/avoid loading obsmarkers
1328 1349 # when we know that '.' won't be hidden
1329 1350 node = self.dirstate.p1()
1330 1351 rev = self.unfiltered().changelog.rev(node)
1331 1352 elif len(changeid) == 20:
1332 1353 try:
1333 1354 node = changeid
1334 1355 rev = self.changelog.rev(changeid)
1335 1356 except error.FilteredLookupError:
1336 1357 changeid = hex(changeid) # for the error message
1337 1358 raise
1338 1359 except LookupError:
1339 1360 # check if it might have come from damaged dirstate
1340 1361 #
1341 1362 # XXX we could avoid the unfiltered if we had a recognizable
1342 1363 # exception for filtered changeset access
1343 1364 if (self.local()
1344 1365 and changeid in self.unfiltered().dirstate.parents()):
1345 1366 msg = _("working directory has unknown parent '%s'!")
1346 1367 raise error.Abort(msg % short(changeid))
1347 1368 changeid = hex(changeid) # for the error message
1348 1369 raise
1349 1370
1350 1371 elif len(changeid) == 40:
1351 1372 node = bin(changeid)
1352 1373 rev = self.changelog.rev(node)
1353 1374 else:
1354 1375 raise error.ProgrammingError(
1355 1376 "unsupported changeid '%s' of type %s" %
1356 1377 (changeid, type(changeid)))
1357 1378
1358 1379 return context.changectx(self, rev, node)
1359 1380
1360 1381 except (error.FilteredIndexError, error.FilteredLookupError):
1361 1382 raise error.FilteredRepoLookupError(_("filtered revision '%s'")
1362 1383 % pycompat.bytestr(changeid))
1363 1384 except (IndexError, LookupError):
1364 1385 raise error.RepoLookupError(
1365 1386 _("unknown revision '%s'") % pycompat.bytestr(changeid))
1366 1387 except error.WdirUnsupported:
1367 1388 return context.workingctx(self)
1368 1389
1369 1390 def __contains__(self, changeid):
1370 1391 """True if the given changeid exists
1371 1392
1372 1393 error.AmbiguousPrefixLookupError is raised if an ambiguous node
1373 1394 specified.
1374 1395 """
1375 1396 try:
1376 1397 self[changeid]
1377 1398 return True
1378 1399 except error.RepoLookupError:
1379 1400 return False
1380 1401
1381 1402 def __nonzero__(self):
1382 1403 return True
1383 1404
1384 1405 __bool__ = __nonzero__
1385 1406
1386 1407 def __len__(self):
1387 1408 # no need to pay the cost of repoview.changelog
1388 1409 unfi = self.unfiltered()
1389 1410 return len(unfi.changelog)
1390 1411
1391 1412 def __iter__(self):
1392 1413 return iter(self.changelog)
1393 1414
1394 1415 def revs(self, expr, *args):
1395 1416 '''Find revisions matching a revset.
1396 1417
1397 1418 The revset is specified as a string ``expr`` that may contain
1398 1419 %-formatting to escape certain types. See ``revsetlang.formatspec``.
1399 1420
1400 1421 Revset aliases from the configuration are not expanded. To expand
1401 1422 user aliases, consider calling ``scmutil.revrange()`` or
1402 1423 ``repo.anyrevs([expr], user=True)``.
1403 1424
1404 1425 Returns a revset.abstractsmartset, which is a list-like interface
1405 1426 that contains integer revisions.
1406 1427 '''
1407 1428 tree = revsetlang.spectree(expr, *args)
1408 1429 return revset.makematcher(tree)(self)
1409 1430
1410 1431 def set(self, expr, *args):
1411 1432 '''Find revisions matching a revset and emit changectx instances.
1412 1433
1413 1434 This is a convenience wrapper around ``revs()`` that iterates the
1414 1435 result and is a generator of changectx instances.
1415 1436
1416 1437 Revset aliases from the configuration are not expanded. To expand
1417 1438 user aliases, consider calling ``scmutil.revrange()``.
1418 1439 '''
1419 1440 for r in self.revs(expr, *args):
1420 1441 yield self[r]
1421 1442
1422 1443 def anyrevs(self, specs, user=False, localalias=None):
1423 1444 '''Find revisions matching one of the given revsets.
1424 1445
1425 1446 Revset aliases from the configuration are not expanded by default. To
1426 1447 expand user aliases, specify ``user=True``. To provide some local
1427 1448 definitions overriding user aliases, set ``localalias`` to
1428 1449 ``{name: definitionstring}``.
1429 1450 '''
1430 1451 if user:
1431 1452 m = revset.matchany(self.ui, specs,
1432 1453 lookup=revset.lookupfn(self),
1433 1454 localalias=localalias)
1434 1455 else:
1435 1456 m = revset.matchany(None, specs, localalias=localalias)
1436 1457 return m(self)
1437 1458
1438 1459 def url(self):
1439 1460 return 'file:' + self.root
1440 1461
1441 1462 def hook(self, name, throw=False, **args):
1442 1463 """Call a hook, passing this repo instance.
1443 1464
1444 1465 This a convenience method to aid invoking hooks. Extensions likely
1445 1466 won't call this unless they have registered a custom hook or are
1446 1467 replacing code that is expected to call a hook.
1447 1468 """
1448 1469 return hook.hook(self.ui, self, name, throw, **args)
1449 1470
1450 1471 @filteredpropertycache
1451 1472 def _tagscache(self):
1452 1473 '''Returns a tagscache object that contains various tags related
1453 1474 caches.'''
1454 1475
1455 1476 # This simplifies its cache management by having one decorated
1456 1477 # function (this one) and the rest simply fetch things from it.
1457 1478 class tagscache(object):
1458 1479 def __init__(self):
1459 1480 # These two define the set of tags for this repository. tags
1460 1481 # maps tag name to node; tagtypes maps tag name to 'global' or
1461 1482 # 'local'. (Global tags are defined by .hgtags across all
1462 1483 # heads, and local tags are defined in .hg/localtags.)
1463 1484 # They constitute the in-memory cache of tags.
1464 1485 self.tags = self.tagtypes = None
1465 1486
1466 1487 self.nodetagscache = self.tagslist = None
1467 1488
1468 1489 cache = tagscache()
1469 1490 cache.tags, cache.tagtypes = self._findtags()
1470 1491
1471 1492 return cache
1472 1493
1473 1494 def tags(self):
1474 1495 '''return a mapping of tag to node'''
1475 1496 t = {}
1476 1497 if self.changelog.filteredrevs:
1477 1498 tags, tt = self._findtags()
1478 1499 else:
1479 1500 tags = self._tagscache.tags
1480 1501 rev = self.changelog.rev
1481 1502 for k, v in tags.iteritems():
1482 1503 try:
1483 1504 # ignore tags to unknown nodes
1484 1505 rev(v)
1485 1506 t[k] = v
1486 1507 except (error.LookupError, ValueError):
1487 1508 pass
1488 1509 return t
1489 1510
1490 1511 def _findtags(self):
1491 1512 '''Do the hard work of finding tags. Return a pair of dicts
1492 1513 (tags, tagtypes) where tags maps tag name to node, and tagtypes
1493 1514 maps tag name to a string like \'global\' or \'local\'.
1494 1515 Subclasses or extensions are free to add their own tags, but
1495 1516 should be aware that the returned dicts will be retained for the
1496 1517 duration of the localrepo object.'''
1497 1518
1498 1519 # XXX what tagtype should subclasses/extensions use? Currently
1499 1520 # mq and bookmarks add tags, but do not set the tagtype at all.
1500 1521 # Should each extension invent its own tag type? Should there
1501 1522 # be one tagtype for all such "virtual" tags? Or is the status
1502 1523 # quo fine?
1503 1524
1504 1525
1505 1526 # map tag name to (node, hist)
1506 1527 alltags = tagsmod.findglobaltags(self.ui, self)
1507 1528 # map tag name to tag type
1508 1529 tagtypes = dict((tag, 'global') for tag in alltags)
1509 1530
1510 1531 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
1511 1532
1512 1533 # Build the return dicts. Have to re-encode tag names because
1513 1534 # the tags module always uses UTF-8 (in order not to lose info
1514 1535 # writing to the cache), but the rest of Mercurial wants them in
1515 1536 # local encoding.
1516 1537 tags = {}
1517 1538 for (name, (node, hist)) in alltags.iteritems():
1518 1539 if node != nullid:
1519 1540 tags[encoding.tolocal(name)] = node
1520 1541 tags['tip'] = self.changelog.tip()
1521 1542 tagtypes = dict([(encoding.tolocal(name), value)
1522 1543 for (name, value) in tagtypes.iteritems()])
1523 1544 return (tags, tagtypes)
1524 1545
1525 1546 def tagtype(self, tagname):
1526 1547 '''
1527 1548 return the type of the given tag. result can be:
1528 1549
1529 1550 'local' : a local tag
1530 1551 'global' : a global tag
1531 1552 None : tag does not exist
1532 1553 '''
1533 1554
1534 1555 return self._tagscache.tagtypes.get(tagname)
1535 1556
1536 1557 def tagslist(self):
1537 1558 '''return a list of tags ordered by revision'''
1538 1559 if not self._tagscache.tagslist:
1539 1560 l = []
1540 1561 for t, n in self.tags().iteritems():
1541 1562 l.append((self.changelog.rev(n), t, n))
1542 1563 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
1543 1564
1544 1565 return self._tagscache.tagslist
1545 1566
1546 1567 def nodetags(self, node):
1547 1568 '''return the tags associated with a node'''
1548 1569 if not self._tagscache.nodetagscache:
1549 1570 nodetagscache = {}
1550 1571 for t, n in self._tagscache.tags.iteritems():
1551 1572 nodetagscache.setdefault(n, []).append(t)
1552 1573 for tags in nodetagscache.itervalues():
1553 1574 tags.sort()
1554 1575 self._tagscache.nodetagscache = nodetagscache
1555 1576 return self._tagscache.nodetagscache.get(node, [])
1556 1577
1557 1578 def nodebookmarks(self, node):
1558 1579 """return the list of bookmarks pointing to the specified node"""
1559 1580 return self._bookmarks.names(node)
1560 1581
1561 1582 def branchmap(self):
1562 1583 '''returns a dictionary {branch: [branchheads]} with branchheads
1563 1584 ordered by increasing revision number'''
1564 1585 return self._branchcaches[self]
1565 1586
1566 1587 @unfilteredmethod
1567 1588 def revbranchcache(self):
1568 1589 if not self._revbranchcache:
1569 1590 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
1570 1591 return self._revbranchcache
1571 1592
1572 1593 def branchtip(self, branch, ignoremissing=False):
1573 1594 '''return the tip node for a given branch
1574 1595
1575 1596 If ignoremissing is True, then this method will not raise an error.
1576 1597 This is helpful for callers that only expect None for a missing branch
1577 1598 (e.g. namespace).
1578 1599
1579 1600 '''
1580 1601 try:
1581 1602 return self.branchmap().branchtip(branch)
1582 1603 except KeyError:
1583 1604 if not ignoremissing:
1584 1605 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
1585 1606 else:
1586 1607 pass
1587 1608
1588 1609 def lookup(self, key):
1589 1610 node = scmutil.revsymbol(self, key).node()
1590 1611 if node is None:
1591 1612 raise error.RepoLookupError(_("unknown revision '%s'") % key)
1592 1613 return node
1593 1614
1594 1615 def lookupbranch(self, key):
1595 1616 if self.branchmap().hasbranch(key):
1596 1617 return key
1597 1618
1598 1619 return scmutil.revsymbol(self, key).branch()
1599 1620
1600 1621 def known(self, nodes):
1601 1622 cl = self.changelog
1602 1623 nm = cl.nodemap
1603 1624 filtered = cl.filteredrevs
1604 1625 result = []
1605 1626 for n in nodes:
1606 1627 r = nm.get(n)
1607 1628 resp = not (r is None or r in filtered)
1608 1629 result.append(resp)
1609 1630 return result
1610 1631
1611 1632 def local(self):
1612 1633 return self
1613 1634
1614 1635 def publishing(self):
1615 1636 # it's safe (and desirable) to trust the publish flag unconditionally
1616 1637 # so that we don't finalize changes shared between users via ssh or nfs
1617 1638 return self.ui.configbool('phases', 'publish', untrusted=True)
1618 1639
1619 1640 def cancopy(self):
1620 1641 # so statichttprepo's override of local() works
1621 1642 if not self.local():
1622 1643 return False
1623 1644 if not self.publishing():
1624 1645 return True
1625 1646 # if publishing we can't copy if there is filtered content
1626 1647 return not self.filtered('visible').changelog.filteredrevs
1627 1648
1628 1649 def shared(self):
1629 1650 '''the type of shared repository (None if not shared)'''
1630 1651 if self.sharedpath != self.path:
1631 1652 return 'store'
1632 1653 return None
1633 1654
1634 1655 def wjoin(self, f, *insidef):
1635 1656 return self.vfs.reljoin(self.root, f, *insidef)
1636 1657
1637 1658 def setparents(self, p1, p2=nullid):
1638 1659 with self.dirstate.parentchange():
1639 1660 copies = self.dirstate.setparents(p1, p2)
1640 1661 pctx = self[p1]
1641 1662 if copies:
1642 1663 # Adjust copy records, the dirstate cannot do it, it
1643 1664 # requires access to parents manifests. Preserve them
1644 1665 # only for entries added to first parent.
1645 1666 for f in copies:
1646 1667 if f not in pctx and copies[f] in pctx:
1647 1668 self.dirstate.copy(copies[f], f)
1648 1669 if p2 == nullid:
1649 1670 for f, s in sorted(self.dirstate.copies().items()):
1650 1671 if f not in pctx and s not in pctx:
1651 1672 self.dirstate.copy(None, f)
1652 1673
1653 1674 def filectx(self, path, changeid=None, fileid=None, changectx=None):
1654 1675 """changeid must be a changeset revision, if specified.
1655 1676 fileid can be a file revision or node."""
1656 1677 return context.filectx(self, path, changeid, fileid,
1657 1678 changectx=changectx)
1658 1679
1659 1680 def getcwd(self):
1660 1681 return self.dirstate.getcwd()
1661 1682
1662 1683 def pathto(self, f, cwd=None):
1663 1684 return self.dirstate.pathto(f, cwd)
1664 1685
1665 1686 def _loadfilter(self, filter):
1666 1687 if filter not in self._filterpats:
1667 1688 l = []
1668 1689 for pat, cmd in self.ui.configitems(filter):
1669 1690 if cmd == '!':
1670 1691 continue
1671 1692 mf = matchmod.match(self.root, '', [pat])
1672 1693 fn = None
1673 1694 params = cmd
1674 1695 for name, filterfn in self._datafilters.iteritems():
1675 1696 if cmd.startswith(name):
1676 1697 fn = filterfn
1677 1698 params = cmd[len(name):].lstrip()
1678 1699 break
1679 1700 if not fn:
1680 1701 fn = lambda s, c, **kwargs: procutil.filter(s, c)
1681 1702 # Wrap old filters not supporting keyword arguments
1682 1703 if not pycompat.getargspec(fn)[2]:
1683 1704 oldfn = fn
1684 1705 fn = lambda s, c, **kwargs: oldfn(s, c)
1685 1706 l.append((mf, fn, params))
1686 1707 self._filterpats[filter] = l
1687 1708 return self._filterpats[filter]
1688 1709
1689 1710 def _filter(self, filterpats, filename, data):
1690 1711 for mf, fn, cmd in filterpats:
1691 1712 if mf(filename):
1692 1713 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
1693 1714 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
1694 1715 break
1695 1716
1696 1717 return data
1697 1718
1698 1719 @unfilteredpropertycache
1699 1720 def _encodefilterpats(self):
1700 1721 return self._loadfilter('encode')
1701 1722
1702 1723 @unfilteredpropertycache
1703 1724 def _decodefilterpats(self):
1704 1725 return self._loadfilter('decode')
1705 1726
1706 1727 def adddatafilter(self, name, filter):
1707 1728 self._datafilters[name] = filter
1708 1729
1709 1730 def wread(self, filename):
1710 1731 if self.wvfs.islink(filename):
1711 1732 data = self.wvfs.readlink(filename)
1712 1733 else:
1713 1734 data = self.wvfs.read(filename)
1714 1735 return self._filter(self._encodefilterpats, filename, data)
1715 1736
1716 1737 def wwrite(self, filename, data, flags, backgroundclose=False, **kwargs):
1717 1738 """write ``data`` into ``filename`` in the working directory
1718 1739
1719 1740 This returns length of written (maybe decoded) data.
1720 1741 """
1721 1742 data = self._filter(self._decodefilterpats, filename, data)
1722 1743 if 'l' in flags:
1723 1744 self.wvfs.symlink(data, filename)
1724 1745 else:
1725 1746 self.wvfs.write(filename, data, backgroundclose=backgroundclose,
1726 1747 **kwargs)
1727 1748 if 'x' in flags:
1728 1749 self.wvfs.setflags(filename, False, True)
1729 1750 else:
1730 1751 self.wvfs.setflags(filename, False, False)
1731 1752 return len(data)
1732 1753
1733 1754 def wwritedata(self, filename, data):
1734 1755 return self._filter(self._decodefilterpats, filename, data)
1735 1756
1736 1757 def currenttransaction(self):
1737 1758 """return the current transaction or None if non exists"""
1738 1759 if self._transref:
1739 1760 tr = self._transref()
1740 1761 else:
1741 1762 tr = None
1742 1763
1743 1764 if tr and tr.running():
1744 1765 return tr
1745 1766 return None
1746 1767
1747 1768 def transaction(self, desc, report=None):
1748 1769 if (self.ui.configbool('devel', 'all-warnings')
1749 1770 or self.ui.configbool('devel', 'check-locks')):
1750 1771 if self._currentlock(self._lockref) is None:
1751 1772 raise error.ProgrammingError('transaction requires locking')
1752 1773 tr = self.currenttransaction()
1753 1774 if tr is not None:
1754 1775 return tr.nest(name=desc)
1755 1776
1756 1777 # abort here if the journal already exists
1757 1778 if self.svfs.exists("journal"):
1758 1779 raise error.RepoError(
1759 1780 _("abandoned transaction found"),
1760 1781 hint=_("run 'hg recover' to clean up transaction"))
1761 1782
1762 1783 idbase = "%.40f#%f" % (random.random(), time.time())
1763 1784 ha = hex(hashlib.sha1(idbase).digest())
1764 1785 txnid = 'TXN:' + ha
1765 1786 self.hook('pretxnopen', throw=True, txnname=desc, txnid=txnid)
1766 1787
1767 1788 self._writejournal(desc)
1768 1789 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
1769 1790 if report:
1770 1791 rp = report
1771 1792 else:
1772 1793 rp = self.ui.warn
1773 1794 vfsmap = {'plain': self.vfs, 'store': self.svfs} # root of .hg/
1774 1795 # we must avoid cyclic reference between repo and transaction.
1775 1796 reporef = weakref.ref(self)
1776 1797 # Code to track tag movement
1777 1798 #
1778 1799 # Since tags are all handled as file content, it is actually quite hard
1779 1800 # to track these movement from a code perspective. So we fallback to a
1780 1801 # tracking at the repository level. One could envision to track changes
1781 1802 # to the '.hgtags' file through changegroup apply but that fails to
1782 1803 # cope with case where transaction expose new heads without changegroup
1783 1804 # being involved (eg: phase movement).
1784 1805 #
1785 1806 # For now, We gate the feature behind a flag since this likely comes
1786 1807 # with performance impacts. The current code run more often than needed
1787 1808 # and do not use caches as much as it could. The current focus is on
1788 1809 # the behavior of the feature so we disable it by default. The flag
1789 1810 # will be removed when we are happy with the performance impact.
1790 1811 #
1791 1812 # Once this feature is no longer experimental move the following
1792 1813 # documentation to the appropriate help section:
1793 1814 #
1794 1815 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
1795 1816 # tags (new or changed or deleted tags). In addition the details of
1796 1817 # these changes are made available in a file at:
1797 1818 # ``REPOROOT/.hg/changes/tags.changes``.
1798 1819 # Make sure you check for HG_TAG_MOVED before reading that file as it
1799 1820 # might exist from a previous transaction even if no tag were touched
1800 1821 # in this one. Changes are recorded in a line base format::
1801 1822 #
1802 1823 # <action> <hex-node> <tag-name>\n
1803 1824 #
1804 1825 # Actions are defined as follow:
1805 1826 # "-R": tag is removed,
1806 1827 # "+A": tag is added,
1807 1828 # "-M": tag is moved (old value),
1808 1829 # "+M": tag is moved (new value),
1809 1830 tracktags = lambda x: None
1810 1831 # experimental config: experimental.hook-track-tags
1811 1832 shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags')
1812 1833 if desc != 'strip' and shouldtracktags:
1813 1834 oldheads = self.changelog.headrevs()
1814 1835 def tracktags(tr2):
1815 1836 repo = reporef()
1816 1837 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
1817 1838 newheads = repo.changelog.headrevs()
1818 1839 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
1819 1840 # notes: we compare lists here.
1820 1841 # As we do it only once buiding set would not be cheaper
1821 1842 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
1822 1843 if changes:
1823 1844 tr2.hookargs['tag_moved'] = '1'
1824 1845 with repo.vfs('changes/tags.changes', 'w',
1825 1846 atomictemp=True) as changesfile:
1826 1847 # note: we do not register the file to the transaction
1827 1848 # because we needs it to still exist on the transaction
1828 1849 # is close (for txnclose hooks)
1829 1850 tagsmod.writediff(changesfile, changes)
1830 1851 def validate(tr2):
1831 1852 """will run pre-closing hooks"""
1832 1853 # XXX the transaction API is a bit lacking here so we take a hacky
1833 1854 # path for now
1834 1855 #
1835 1856 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
1836 1857 # dict is copied before these run. In addition we needs the data
1837 1858 # available to in memory hooks too.
1838 1859 #
1839 1860 # Moreover, we also need to make sure this runs before txnclose
1840 1861 # hooks and there is no "pending" mechanism that would execute
1841 1862 # logic only if hooks are about to run.
1842 1863 #
1843 1864 # Fixing this limitation of the transaction is also needed to track
1844 1865 # other families of changes (bookmarks, phases, obsolescence).
1845 1866 #
1846 1867 # This will have to be fixed before we remove the experimental
1847 1868 # gating.
1848 1869 tracktags(tr2)
1849 1870 repo = reporef()
1850 1871 if repo.ui.configbool('experimental', 'single-head-per-branch'):
1851 1872 scmutil.enforcesinglehead(repo, tr2, desc)
1852 1873 if hook.hashook(repo.ui, 'pretxnclose-bookmark'):
1853 1874 for name, (old, new) in sorted(tr.changes['bookmarks'].items()):
1854 1875 args = tr.hookargs.copy()
1855 1876 args.update(bookmarks.preparehookargs(name, old, new))
1856 1877 repo.hook('pretxnclose-bookmark', throw=True,
1857 1878 **pycompat.strkwargs(args))
1858 1879 if hook.hashook(repo.ui, 'pretxnclose-phase'):
1859 1880 cl = repo.unfiltered().changelog
1860 1881 for rev, (old, new) in tr.changes['phases'].items():
1861 1882 args = tr.hookargs.copy()
1862 1883 node = hex(cl.node(rev))
1863 1884 args.update(phases.preparehookargs(node, old, new))
1864 1885 repo.hook('pretxnclose-phase', throw=True,
1865 1886 **pycompat.strkwargs(args))
1866 1887
1867 1888 repo.hook('pretxnclose', throw=True,
1868 1889 **pycompat.strkwargs(tr.hookargs))
1869 1890 def releasefn(tr, success):
1870 1891 repo = reporef()
1871 1892 if success:
1872 1893 # this should be explicitly invoked here, because
1873 1894 # in-memory changes aren't written out at closing
1874 1895 # transaction, if tr.addfilegenerator (via
1875 1896 # dirstate.write or so) isn't invoked while
1876 1897 # transaction running
1877 1898 repo.dirstate.write(None)
1878 1899 else:
1879 1900 # discard all changes (including ones already written
1880 1901 # out) in this transaction
1881 1902 narrowspec.restorebackup(self, 'journal.narrowspec')
1882 1903 narrowspec.restorewcbackup(self, 'journal.narrowspec.dirstate')
1883 1904 repo.dirstate.restorebackup(None, 'journal.dirstate')
1884 1905
1885 1906 repo.invalidate(clearfilecache=True)
1886 1907
1887 1908 tr = transaction.transaction(rp, self.svfs, vfsmap,
1888 1909 "journal",
1889 1910 "undo",
1890 1911 aftertrans(renames),
1891 1912 self.store.createmode,
1892 1913 validator=validate,
1893 1914 releasefn=releasefn,
1894 1915 checkambigfiles=_cachedfiles,
1895 1916 name=desc)
1896 1917 tr.changes['origrepolen'] = len(self)
1897 1918 tr.changes['obsmarkers'] = set()
1898 1919 tr.changes['phases'] = {}
1899 1920 tr.changes['bookmarks'] = {}
1900 1921
1901 1922 tr.hookargs['txnid'] = txnid
1902 1923 tr.hookargs['txnname'] = desc
1903 1924 # note: writing the fncache only during finalize mean that the file is
1904 1925 # outdated when running hooks. As fncache is used for streaming clone,
1905 1926 # this is not expected to break anything that happen during the hooks.
1906 1927 tr.addfinalize('flush-fncache', self.store.write)
1907 1928 def txnclosehook(tr2):
1908 1929 """To be run if transaction is successful, will schedule a hook run
1909 1930 """
1910 1931 # Don't reference tr2 in hook() so we don't hold a reference.
1911 1932 # This reduces memory consumption when there are multiple
1912 1933 # transactions per lock. This can likely go away if issue5045
1913 1934 # fixes the function accumulation.
1914 1935 hookargs = tr2.hookargs
1915 1936
1916 1937 def hookfunc():
1917 1938 repo = reporef()
1918 1939 if hook.hashook(repo.ui, 'txnclose-bookmark'):
1919 1940 bmchanges = sorted(tr.changes['bookmarks'].items())
1920 1941 for name, (old, new) in bmchanges:
1921 1942 args = tr.hookargs.copy()
1922 1943 args.update(bookmarks.preparehookargs(name, old, new))
1923 1944 repo.hook('txnclose-bookmark', throw=False,
1924 1945 **pycompat.strkwargs(args))
1925 1946
1926 1947 if hook.hashook(repo.ui, 'txnclose-phase'):
1927 1948 cl = repo.unfiltered().changelog
1928 1949 phasemv = sorted(tr.changes['phases'].items())
1929 1950 for rev, (old, new) in phasemv:
1930 1951 args = tr.hookargs.copy()
1931 1952 node = hex(cl.node(rev))
1932 1953 args.update(phases.preparehookargs(node, old, new))
1933 1954 repo.hook('txnclose-phase', throw=False,
1934 1955 **pycompat.strkwargs(args))
1935 1956
1936 1957 repo.hook('txnclose', throw=False,
1937 1958 **pycompat.strkwargs(hookargs))
1938 1959 reporef()._afterlock(hookfunc)
1939 1960 tr.addfinalize('txnclose-hook', txnclosehook)
1940 1961 # Include a leading "-" to make it happen before the transaction summary
1941 1962 # reports registered via scmutil.registersummarycallback() whose names
1942 1963 # are 00-txnreport etc. That way, the caches will be warm when the
1943 1964 # callbacks run.
1944 1965 tr.addpostclose('-warm-cache', self._buildcacheupdater(tr))
1945 1966 def txnaborthook(tr2):
1946 1967 """To be run if transaction is aborted
1947 1968 """
1948 1969 reporef().hook('txnabort', throw=False,
1949 1970 **pycompat.strkwargs(tr2.hookargs))
1950 1971 tr.addabort('txnabort-hook', txnaborthook)
1951 1972 # avoid eager cache invalidation. in-memory data should be identical
1952 1973 # to stored data if transaction has no error.
1953 1974 tr.addpostclose('refresh-filecachestats', self._refreshfilecachestats)
1954 1975 self._transref = weakref.ref(tr)
1955 1976 scmutil.registersummarycallback(self, tr, desc)
1956 1977 return tr
1957 1978
1958 1979 def _journalfiles(self):
1959 1980 return ((self.svfs, 'journal'),
1960 1981 (self.svfs, 'journal.narrowspec'),
1961 1982 (self.vfs, 'journal.narrowspec.dirstate'),
1962 1983 (self.vfs, 'journal.dirstate'),
1963 1984 (self.vfs, 'journal.branch'),
1964 1985 (self.vfs, 'journal.desc'),
1965 (self.vfs, 'journal.bookmarks'),
1986 (bookmarks.bookmarksvfs(self), 'journal.bookmarks'),
1966 1987 (self.svfs, 'journal.phaseroots'))
1967 1988
1968 1989 def undofiles(self):
1969 1990 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
1970 1991
1971 1992 @unfilteredmethod
1972 1993 def _writejournal(self, desc):
1973 1994 self.dirstate.savebackup(None, 'journal.dirstate')
1974 1995 narrowspec.savewcbackup(self, 'journal.narrowspec.dirstate')
1975 1996 narrowspec.savebackup(self, 'journal.narrowspec')
1976 1997 self.vfs.write("journal.branch",
1977 1998 encoding.fromlocal(self.dirstate.branch()))
1978 1999 self.vfs.write("journal.desc",
1979 2000 "%d\n%s\n" % (len(self), desc))
1980 self.vfs.write("journal.bookmarks",
1981 self.vfs.tryread("bookmarks"))
2001 bookmarksvfs = bookmarks.bookmarksvfs(self)
2002 bookmarksvfs.write("journal.bookmarks",
2003 bookmarksvfs.tryread("bookmarks"))
1982 2004 self.svfs.write("journal.phaseroots",
1983 2005 self.svfs.tryread("phaseroots"))
1984 2006
1985 2007 def recover(self):
1986 2008 with self.lock():
1987 2009 if self.svfs.exists("journal"):
1988 2010 self.ui.status(_("rolling back interrupted transaction\n"))
1989 2011 vfsmap = {'': self.svfs,
1990 2012 'plain': self.vfs,}
1991 2013 transaction.rollback(self.svfs, vfsmap, "journal",
1992 2014 self.ui.warn,
1993 2015 checkambigfiles=_cachedfiles)
1994 2016 self.invalidate()
1995 2017 return True
1996 2018 else:
1997 2019 self.ui.warn(_("no interrupted transaction available\n"))
1998 2020 return False
1999 2021
2000 2022 def rollback(self, dryrun=False, force=False):
2001 2023 wlock = lock = dsguard = None
2002 2024 try:
2003 2025 wlock = self.wlock()
2004 2026 lock = self.lock()
2005 2027 if self.svfs.exists("undo"):
2006 2028 dsguard = dirstateguard.dirstateguard(self, 'rollback')
2007 2029
2008 2030 return self._rollback(dryrun, force, dsguard)
2009 2031 else:
2010 2032 self.ui.warn(_("no rollback information available\n"))
2011 2033 return 1
2012 2034 finally:
2013 2035 release(dsguard, lock, wlock)
2014 2036
2015 2037 @unfilteredmethod # Until we get smarter cache management
2016 2038 def _rollback(self, dryrun, force, dsguard):
2017 2039 ui = self.ui
2018 2040 try:
2019 2041 args = self.vfs.read('undo.desc').splitlines()
2020 2042 (oldlen, desc, detail) = (int(args[0]), args[1], None)
2021 2043 if len(args) >= 3:
2022 2044 detail = args[2]
2023 2045 oldtip = oldlen - 1
2024 2046
2025 2047 if detail and ui.verbose:
2026 2048 msg = (_('repository tip rolled back to revision %d'
2027 2049 ' (undo %s: %s)\n')
2028 2050 % (oldtip, desc, detail))
2029 2051 else:
2030 2052 msg = (_('repository tip rolled back to revision %d'
2031 2053 ' (undo %s)\n')
2032 2054 % (oldtip, desc))
2033 2055 except IOError:
2034 2056 msg = _('rolling back unknown transaction\n')
2035 2057 desc = None
2036 2058
2037 2059 if not force and self['.'] != self['tip'] and desc == 'commit':
2038 2060 raise error.Abort(
2039 2061 _('rollback of last commit while not checked out '
2040 2062 'may lose data'), hint=_('use -f to force'))
2041 2063
2042 2064 ui.status(msg)
2043 2065 if dryrun:
2044 2066 return 0
2045 2067
2046 2068 parents = self.dirstate.parents()
2047 2069 self.destroying()
2048 2070 vfsmap = {'plain': self.vfs, '': self.svfs}
2049 2071 transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn,
2050 2072 checkambigfiles=_cachedfiles)
2051 if self.vfs.exists('undo.bookmarks'):
2052 self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
2073 bookmarksvfs = bookmarks.bookmarksvfs(self)
2074 if bookmarksvfs.exists('undo.bookmarks'):
2075 bookmarksvfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
2053 2076 if self.svfs.exists('undo.phaseroots'):
2054 2077 self.svfs.rename('undo.phaseroots', 'phaseroots', checkambig=True)
2055 2078 self.invalidate()
2056 2079
2057 2080 parentgone = any(p not in self.changelog.nodemap for p in parents)
2058 2081 if parentgone:
2059 2082 # prevent dirstateguard from overwriting already restored one
2060 2083 dsguard.close()
2061 2084
2062 2085 narrowspec.restorebackup(self, 'undo.narrowspec')
2063 2086 narrowspec.restorewcbackup(self, 'undo.narrowspec.dirstate')
2064 2087 self.dirstate.restorebackup(None, 'undo.dirstate')
2065 2088 try:
2066 2089 branch = self.vfs.read('undo.branch')
2067 2090 self.dirstate.setbranch(encoding.tolocal(branch))
2068 2091 except IOError:
2069 2092 ui.warn(_('named branch could not be reset: '
2070 2093 'current branch is still \'%s\'\n')
2071 2094 % self.dirstate.branch())
2072 2095
2073 2096 parents = tuple([p.rev() for p in self[None].parents()])
2074 2097 if len(parents) > 1:
2075 2098 ui.status(_('working directory now based on '
2076 2099 'revisions %d and %d\n') % parents)
2077 2100 else:
2078 2101 ui.status(_('working directory now based on '
2079 2102 'revision %d\n') % parents)
2080 2103 mergemod.mergestate.clean(self, self['.'].node())
2081 2104
2082 2105 # TODO: if we know which new heads may result from this rollback, pass
2083 2106 # them to destroy(), which will prevent the branchhead cache from being
2084 2107 # invalidated.
2085 2108 self.destroyed()
2086 2109 return 0
2087 2110
2088 2111 def _buildcacheupdater(self, newtransaction):
2089 2112 """called during transaction to build the callback updating cache
2090 2113
2091 2114 Lives on the repository to help extension who might want to augment
2092 2115 this logic. For this purpose, the created transaction is passed to the
2093 2116 method.
2094 2117 """
2095 2118 # we must avoid cyclic reference between repo and transaction.
2096 2119 reporef = weakref.ref(self)
2097 2120 def updater(tr):
2098 2121 repo = reporef()
2099 2122 repo.updatecaches(tr)
2100 2123 return updater
2101 2124
2102 2125 @unfilteredmethod
2103 2126 def updatecaches(self, tr=None, full=False):
2104 2127 """warm appropriate caches
2105 2128
2106 2129 If this function is called after a transaction closed. The transaction
2107 2130 will be available in the 'tr' argument. This can be used to selectively
2108 2131 update caches relevant to the changes in that transaction.
2109 2132
2110 2133 If 'full' is set, make sure all caches the function knows about have
2111 2134 up-to-date data. Even the ones usually loaded more lazily.
2112 2135 """
2113 2136 if tr is not None and tr.hookargs.get('source') == 'strip':
2114 2137 # During strip, many caches are invalid but
2115 2138 # later call to `destroyed` will refresh them.
2116 2139 return
2117 2140
2118 2141 if tr is None or tr.changes['origrepolen'] < len(self):
2119 2142 # accessing the 'ser ved' branchmap should refresh all the others,
2120 2143 self.ui.debug('updating the branch cache\n')
2121 2144 self.filtered('served').branchmap()
2122 2145 self.filtered('served.hidden').branchmap()
2123 2146
2124 2147 if full:
2125 2148 unfi = self.unfiltered()
2126 2149 rbc = unfi.revbranchcache()
2127 2150 for r in unfi.changelog:
2128 2151 rbc.branchinfo(r)
2129 2152 rbc.write()
2130 2153
2131 2154 # ensure the working copy parents are in the manifestfulltextcache
2132 2155 for ctx in self['.'].parents():
2133 2156 ctx.manifest() # accessing the manifest is enough
2134 2157
2135 2158 # accessing fnode cache warms the cache
2136 2159 tagsmod.fnoderevs(self.ui, unfi, unfi.changelog.revs())
2137 2160 # accessing tags warm the cache
2138 2161 self.tags()
2139 2162 self.filtered('served').tags()
2140 2163
2141 2164 def invalidatecaches(self):
2142 2165
2143 2166 if r'_tagscache' in vars(self):
2144 2167 # can't use delattr on proxy
2145 2168 del self.__dict__[r'_tagscache']
2146 2169
2147 2170 self._branchcaches.clear()
2148 2171 self.invalidatevolatilesets()
2149 2172 self._sparsesignaturecache.clear()
2150 2173
2151 2174 def invalidatevolatilesets(self):
2152 2175 self.filteredrevcache.clear()
2153 2176 obsolete.clearobscaches(self)
2154 2177
2155 2178 def invalidatedirstate(self):
2156 2179 '''Invalidates the dirstate, causing the next call to dirstate
2157 2180 to check if it was modified since the last time it was read,
2158 2181 rereading it if it has.
2159 2182
2160 2183 This is different to dirstate.invalidate() that it doesn't always
2161 2184 rereads the dirstate. Use dirstate.invalidate() if you want to
2162 2185 explicitly read the dirstate again (i.e. restoring it to a previous
2163 2186 known good state).'''
2164 2187 if hasunfilteredcache(self, r'dirstate'):
2165 2188 for k in self.dirstate._filecache:
2166 2189 try:
2167 2190 delattr(self.dirstate, k)
2168 2191 except AttributeError:
2169 2192 pass
2170 2193 delattr(self.unfiltered(), r'dirstate')
2171 2194
2172 2195 def invalidate(self, clearfilecache=False):
2173 2196 '''Invalidates both store and non-store parts other than dirstate
2174 2197
2175 2198 If a transaction is running, invalidation of store is omitted,
2176 2199 because discarding in-memory changes might cause inconsistency
2177 2200 (e.g. incomplete fncache causes unintentional failure, but
2178 2201 redundant one doesn't).
2179 2202 '''
2180 2203 unfiltered = self.unfiltered() # all file caches are stored unfiltered
2181 2204 for k in list(self._filecache.keys()):
2182 2205 # dirstate is invalidated separately in invalidatedirstate()
2183 2206 if k == 'dirstate':
2184 2207 continue
2185 2208 if (k == 'changelog' and
2186 2209 self.currenttransaction() and
2187 2210 self.changelog._delayed):
2188 2211 # The changelog object may store unwritten revisions. We don't
2189 2212 # want to lose them.
2190 2213 # TODO: Solve the problem instead of working around it.
2191 2214 continue
2192 2215
2193 2216 if clearfilecache:
2194 2217 del self._filecache[k]
2195 2218 try:
2196 2219 delattr(unfiltered, k)
2197 2220 except AttributeError:
2198 2221 pass
2199 2222 self.invalidatecaches()
2200 2223 if not self.currenttransaction():
2201 2224 # TODO: Changing contents of store outside transaction
2202 2225 # causes inconsistency. We should make in-memory store
2203 2226 # changes detectable, and abort if changed.
2204 2227 self.store.invalidatecaches()
2205 2228
2206 2229 def invalidateall(self):
2207 2230 '''Fully invalidates both store and non-store parts, causing the
2208 2231 subsequent operation to reread any outside changes.'''
2209 2232 # extension should hook this to invalidate its caches
2210 2233 self.invalidate()
2211 2234 self.invalidatedirstate()
2212 2235
2213 2236 @unfilteredmethod
2214 2237 def _refreshfilecachestats(self, tr):
2215 2238 """Reload stats of cached files so that they are flagged as valid"""
2216 2239 for k, ce in self._filecache.items():
2217 2240 k = pycompat.sysstr(k)
2218 2241 if k == r'dirstate' or k not in self.__dict__:
2219 2242 continue
2220 2243 ce.refresh()
2221 2244
2222 2245 def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc,
2223 2246 inheritchecker=None, parentenvvar=None):
2224 2247 parentlock = None
2225 2248 # the contents of parentenvvar are used by the underlying lock to
2226 2249 # determine whether it can be inherited
2227 2250 if parentenvvar is not None:
2228 2251 parentlock = encoding.environ.get(parentenvvar)
2229 2252
2230 2253 timeout = 0
2231 2254 warntimeout = 0
2232 2255 if wait:
2233 2256 timeout = self.ui.configint("ui", "timeout")
2234 2257 warntimeout = self.ui.configint("ui", "timeout.warn")
2235 2258 # internal config: ui.signal-safe-lock
2236 2259 signalsafe = self.ui.configbool('ui', 'signal-safe-lock')
2237 2260
2238 2261 l = lockmod.trylock(self.ui, vfs, lockname, timeout, warntimeout,
2239 2262 releasefn=releasefn,
2240 2263 acquirefn=acquirefn, desc=desc,
2241 2264 inheritchecker=inheritchecker,
2242 2265 parentlock=parentlock,
2243 2266 signalsafe=signalsafe)
2244 2267 return l
2245 2268
2246 2269 def _afterlock(self, callback):
2247 2270 """add a callback to be run when the repository is fully unlocked
2248 2271
2249 2272 The callback will be executed when the outermost lock is released
2250 2273 (with wlock being higher level than 'lock')."""
2251 2274 for ref in (self._wlockref, self._lockref):
2252 2275 l = ref and ref()
2253 2276 if l and l.held:
2254 2277 l.postrelease.append(callback)
2255 2278 break
2256 2279 else: # no lock have been found.
2257 2280 callback()
2258 2281
2259 2282 def lock(self, wait=True):
2260 2283 '''Lock the repository store (.hg/store) and return a weak reference
2261 2284 to the lock. Use this before modifying the store (e.g. committing or
2262 2285 stripping). If you are opening a transaction, get a lock as well.)
2263 2286
2264 2287 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2265 2288 'wlock' first to avoid a dead-lock hazard.'''
2266 2289 l = self._currentlock(self._lockref)
2267 2290 if l is not None:
2268 2291 l.lock()
2269 2292 return l
2270 2293
2271 2294 l = self._lock(vfs=self.svfs,
2272 2295 lockname="lock",
2273 2296 wait=wait,
2274 2297 releasefn=None,
2275 2298 acquirefn=self.invalidate,
2276 2299 desc=_('repository %s') % self.origroot)
2277 2300 self._lockref = weakref.ref(l)
2278 2301 return l
2279 2302
2280 2303 def _wlockchecktransaction(self):
2281 2304 if self.currenttransaction() is not None:
2282 2305 raise error.LockInheritanceContractViolation(
2283 2306 'wlock cannot be inherited in the middle of a transaction')
2284 2307
2285 2308 def wlock(self, wait=True):
2286 2309 '''Lock the non-store parts of the repository (everything under
2287 2310 .hg except .hg/store) and return a weak reference to the lock.
2288 2311
2289 2312 Use this before modifying files in .hg.
2290 2313
2291 2314 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
2292 2315 'wlock' first to avoid a dead-lock hazard.'''
2293 2316 l = self._wlockref and self._wlockref()
2294 2317 if l is not None and l.held:
2295 2318 l.lock()
2296 2319 return l
2297 2320
2298 2321 # We do not need to check for non-waiting lock acquisition. Such
2299 2322 # acquisition would not cause dead-lock as they would just fail.
2300 2323 if wait and (self.ui.configbool('devel', 'all-warnings')
2301 2324 or self.ui.configbool('devel', 'check-locks')):
2302 2325 if self._currentlock(self._lockref) is not None:
2303 2326 self.ui.develwarn('"wlock" acquired after "lock"')
2304 2327
2305 2328 def unlock():
2306 2329 if self.dirstate.pendingparentchange():
2307 2330 self.dirstate.invalidate()
2308 2331 else:
2309 2332 self.dirstate.write(None)
2310 2333
2311 2334 self._filecache['dirstate'].refresh()
2312 2335
2313 2336 l = self._lock(self.vfs, "wlock", wait, unlock,
2314 2337 self.invalidatedirstate, _('working directory of %s') %
2315 2338 self.origroot,
2316 2339 inheritchecker=self._wlockchecktransaction,
2317 2340 parentenvvar='HG_WLOCK_LOCKER')
2318 2341 self._wlockref = weakref.ref(l)
2319 2342 return l
2320 2343
2321 2344 def _currentlock(self, lockref):
2322 2345 """Returns the lock if it's held, or None if it's not."""
2323 2346 if lockref is None:
2324 2347 return None
2325 2348 l = lockref()
2326 2349 if l is None or not l.held:
2327 2350 return None
2328 2351 return l
2329 2352
2330 2353 def currentwlock(self):
2331 2354 """Returns the wlock if it's held, or None if it's not."""
2332 2355 return self._currentlock(self._wlockref)
2333 2356
2334 2357 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist,
2335 2358 includecopymeta):
2336 2359 """
2337 2360 commit an individual file as part of a larger transaction
2338 2361 """
2339 2362
2340 2363 fname = fctx.path()
2341 2364 fparent1 = manifest1.get(fname, nullid)
2342 2365 fparent2 = manifest2.get(fname, nullid)
2343 2366 if isinstance(fctx, context.filectx):
2344 2367 node = fctx.filenode()
2345 2368 if node in [fparent1, fparent2]:
2346 2369 self.ui.debug('reusing %s filelog entry\n' % fname)
2347 2370 if manifest1.flags(fname) != fctx.flags():
2348 2371 changelist.append(fname)
2349 2372 return node
2350 2373
2351 2374 flog = self.file(fname)
2352 2375 meta = {}
2353 2376 cfname = fctx.copysource()
2354 2377 if cfname and cfname != fname:
2355 2378 # Mark the new revision of this file as a copy of another
2356 2379 # file. This copy data will effectively act as a parent
2357 2380 # of this new revision. If this is a merge, the first
2358 2381 # parent will be the nullid (meaning "look up the copy data")
2359 2382 # and the second one will be the other parent. For example:
2360 2383 #
2361 2384 # 0 --- 1 --- 3 rev1 changes file foo
2362 2385 # \ / rev2 renames foo to bar and changes it
2363 2386 # \- 2 -/ rev3 should have bar with all changes and
2364 2387 # should record that bar descends from
2365 2388 # bar in rev2 and foo in rev1
2366 2389 #
2367 2390 # this allows this merge to succeed:
2368 2391 #
2369 2392 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
2370 2393 # \ / merging rev3 and rev4 should use bar@rev2
2371 2394 # \- 2 --- 4 as the merge base
2372 2395 #
2373 2396
2374 2397 cnode = manifest1.get(cfname)
2375 2398 newfparent = fparent2
2376 2399
2377 2400 if manifest2: # branch merge
2378 2401 if fparent2 == nullid or cnode is None: # copied on remote side
2379 2402 if cfname in manifest2:
2380 2403 cnode = manifest2[cfname]
2381 2404 newfparent = fparent1
2382 2405
2383 2406 # Here, we used to search backwards through history to try to find
2384 2407 # where the file copy came from if the source of a copy was not in
2385 2408 # the parent directory. However, this doesn't actually make sense to
2386 2409 # do (what does a copy from something not in your working copy even
2387 2410 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
2388 2411 # the user that copy information was dropped, so if they didn't
2389 2412 # expect this outcome it can be fixed, but this is the correct
2390 2413 # behavior in this circumstance.
2391 2414
2392 2415 if cnode:
2393 2416 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(cnode)))
2394 2417 if includecopymeta:
2395 2418 meta["copy"] = cfname
2396 2419 meta["copyrev"] = hex(cnode)
2397 2420 fparent1, fparent2 = nullid, newfparent
2398 2421 else:
2399 2422 self.ui.warn(_("warning: can't find ancestor for '%s' "
2400 2423 "copied from '%s'!\n") % (fname, cfname))
2401 2424
2402 2425 elif fparent1 == nullid:
2403 2426 fparent1, fparent2 = fparent2, nullid
2404 2427 elif fparent2 != nullid:
2405 2428 # is one parent an ancestor of the other?
2406 2429 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
2407 2430 if fparent1 in fparentancestors:
2408 2431 fparent1, fparent2 = fparent2, nullid
2409 2432 elif fparent2 in fparentancestors:
2410 2433 fparent2 = nullid
2411 2434
2412 2435 # is the file changed?
2413 2436 text = fctx.data()
2414 2437 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
2415 2438 changelist.append(fname)
2416 2439 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
2417 2440 # are just the flags changed during merge?
2418 2441 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
2419 2442 changelist.append(fname)
2420 2443
2421 2444 return fparent1
2422 2445
2423 2446 def checkcommitpatterns(self, wctx, vdirs, match, status, fail):
2424 2447 """check for commit arguments that aren't committable"""
2425 2448 if match.isexact() or match.prefix():
2426 2449 matched = set(status.modified + status.added + status.removed)
2427 2450
2428 2451 for f in match.files():
2429 2452 f = self.dirstate.normalize(f)
2430 2453 if f == '.' or f in matched or f in wctx.substate:
2431 2454 continue
2432 2455 if f in status.deleted:
2433 2456 fail(f, _('file not found!'))
2434 2457 if f in vdirs: # visited directory
2435 2458 d = f + '/'
2436 2459 for mf in matched:
2437 2460 if mf.startswith(d):
2438 2461 break
2439 2462 else:
2440 2463 fail(f, _("no match under directory!"))
2441 2464 elif f not in self.dirstate:
2442 2465 fail(f, _("file not tracked!"))
2443 2466
2444 2467 @unfilteredmethod
2445 2468 def commit(self, text="", user=None, date=None, match=None, force=False,
2446 2469 editor=False, extra=None):
2447 2470 """Add a new revision to current repository.
2448 2471
2449 2472 Revision information is gathered from the working directory,
2450 2473 match can be used to filter the committed files. If editor is
2451 2474 supplied, it is called to get a commit message.
2452 2475 """
2453 2476 if extra is None:
2454 2477 extra = {}
2455 2478
2456 2479 def fail(f, msg):
2457 2480 raise error.Abort('%s: %s' % (f, msg))
2458 2481
2459 2482 if not match:
2460 2483 match = matchmod.always()
2461 2484
2462 2485 if not force:
2463 2486 vdirs = []
2464 2487 match.explicitdir = vdirs.append
2465 2488 match.bad = fail
2466 2489
2467 2490 # lock() for recent changelog (see issue4368)
2468 2491 with self.wlock(), self.lock():
2469 2492 wctx = self[None]
2470 2493 merge = len(wctx.parents()) > 1
2471 2494
2472 2495 if not force and merge and not match.always():
2473 2496 raise error.Abort(_('cannot partially commit a merge '
2474 2497 '(do not specify files or patterns)'))
2475 2498
2476 2499 status = self.status(match=match, clean=force)
2477 2500 if force:
2478 2501 status.modified.extend(status.clean) # mq may commit clean files
2479 2502
2480 2503 # check subrepos
2481 2504 subs, commitsubs, newstate = subrepoutil.precommit(
2482 2505 self.ui, wctx, status, match, force=force)
2483 2506
2484 2507 # make sure all explicit patterns are matched
2485 2508 if not force:
2486 2509 self.checkcommitpatterns(wctx, vdirs, match, status, fail)
2487 2510
2488 2511 cctx = context.workingcommitctx(self, status,
2489 2512 text, user, date, extra)
2490 2513
2491 2514 # internal config: ui.allowemptycommit
2492 2515 allowemptycommit = (wctx.branch() != wctx.p1().branch()
2493 2516 or extra.get('close') or merge or cctx.files()
2494 2517 or self.ui.configbool('ui', 'allowemptycommit'))
2495 2518 if not allowemptycommit:
2496 2519 return None
2497 2520
2498 2521 if merge and cctx.deleted():
2499 2522 raise error.Abort(_("cannot commit merge with missing files"))
2500 2523
2501 2524 ms = mergemod.mergestate.read(self)
2502 2525 mergeutil.checkunresolved(ms)
2503 2526
2504 2527 if editor:
2505 2528 cctx._text = editor(self, cctx, subs)
2506 2529 edited = (text != cctx._text)
2507 2530
2508 2531 # Save commit message in case this transaction gets rolled back
2509 2532 # (e.g. by a pretxncommit hook). Leave the content alone on
2510 2533 # the assumption that the user will use the same editor again.
2511 2534 msgfn = self.savecommitmessage(cctx._text)
2512 2535
2513 2536 # commit subs and write new state
2514 2537 if subs:
2515 2538 uipathfn = scmutil.getuipathfn(self)
2516 2539 for s in sorted(commitsubs):
2517 2540 sub = wctx.sub(s)
2518 2541 self.ui.status(_('committing subrepository %s\n') %
2519 2542 uipathfn(subrepoutil.subrelpath(sub)))
2520 2543 sr = sub.commit(cctx._text, user, date)
2521 2544 newstate[s] = (newstate[s][0], sr)
2522 2545 subrepoutil.writestate(self, newstate)
2523 2546
2524 2547 p1, p2 = self.dirstate.parents()
2525 2548 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
2526 2549 try:
2527 2550 self.hook("precommit", throw=True, parent1=hookp1,
2528 2551 parent2=hookp2)
2529 2552 with self.transaction('commit'):
2530 2553 ret = self.commitctx(cctx, True)
2531 2554 # update bookmarks, dirstate and mergestate
2532 2555 bookmarks.update(self, [p1, p2], ret)
2533 2556 cctx.markcommitted(ret)
2534 2557 ms.reset()
2535 2558 except: # re-raises
2536 2559 if edited:
2537 2560 self.ui.write(
2538 2561 _('note: commit message saved in %s\n') % msgfn)
2539 2562 raise
2540 2563
2541 2564 def commithook():
2542 2565 # hack for command that use a temporary commit (eg: histedit)
2543 2566 # temporary commit got stripped before hook release
2544 2567 if self.changelog.hasnode(ret):
2545 2568 self.hook("commit", node=hex(ret), parent1=hookp1,
2546 2569 parent2=hookp2)
2547 2570 self._afterlock(commithook)
2548 2571 return ret
2549 2572
2550 2573 @unfilteredmethod
2551 2574 def commitctx(self, ctx, error=False):
2552 2575 """Add a new revision to current repository.
2553 2576 Revision information is passed via the context argument.
2554 2577
2555 2578 ctx.files() should list all files involved in this commit, i.e.
2556 2579 modified/added/removed files. On merge, it may be wider than the
2557 2580 ctx.files() to be committed, since any file nodes derived directly
2558 2581 from p1 or p2 are excluded from the committed ctx.files().
2559 2582 """
2560 2583
2561 2584 p1, p2 = ctx.p1(), ctx.p2()
2562 2585 user = ctx.user()
2563 2586
2564 2587 writecopiesto = self.ui.config('experimental', 'copies.write-to')
2565 2588 writefilecopymeta = writecopiesto != 'changeset-only'
2566 2589 p1copies, p2copies = None, None
2567 2590 if writecopiesto in ('changeset-only', 'compatibility'):
2568 2591 p1copies = ctx.p1copies()
2569 2592 p2copies = ctx.p2copies()
2570 2593 with self.lock(), self.transaction("commit") as tr:
2571 2594 trp = weakref.proxy(tr)
2572 2595
2573 2596 if ctx.manifestnode():
2574 2597 # reuse an existing manifest revision
2575 2598 self.ui.debug('reusing known manifest\n')
2576 2599 mn = ctx.manifestnode()
2577 2600 files = ctx.files()
2578 2601 elif ctx.files():
2579 2602 m1ctx = p1.manifestctx()
2580 2603 m2ctx = p2.manifestctx()
2581 2604 mctx = m1ctx.copy()
2582 2605
2583 2606 m = mctx.read()
2584 2607 m1 = m1ctx.read()
2585 2608 m2 = m2ctx.read()
2586 2609
2587 2610 # check in files
2588 2611 added = []
2589 2612 changed = []
2590 2613 removed = list(ctx.removed())
2591 2614 linkrev = len(self)
2592 2615 self.ui.note(_("committing files:\n"))
2593 2616 uipathfn = scmutil.getuipathfn(self)
2594 2617 for f in sorted(ctx.modified() + ctx.added()):
2595 2618 self.ui.note(uipathfn(f) + "\n")
2596 2619 try:
2597 2620 fctx = ctx[f]
2598 2621 if fctx is None:
2599 2622 removed.append(f)
2600 2623 else:
2601 2624 added.append(f)
2602 2625 m[f] = self._filecommit(fctx, m1, m2, linkrev,
2603 2626 trp, changed,
2604 2627 writefilecopymeta)
2605 2628 m.setflag(f, fctx.flags())
2606 2629 except OSError:
2607 2630 self.ui.warn(_("trouble committing %s!\n") %
2608 2631 uipathfn(f))
2609 2632 raise
2610 2633 except IOError as inst:
2611 2634 errcode = getattr(inst, 'errno', errno.ENOENT)
2612 2635 if error or errcode and errcode != errno.ENOENT:
2613 2636 self.ui.warn(_("trouble committing %s!\n") %
2614 2637 uipathfn(f))
2615 2638 raise
2616 2639
2617 2640 # update manifest
2618 2641 removed = [f for f in sorted(removed) if f in m1 or f in m2]
2619 2642 drop = [f for f in removed if f in m]
2620 2643 for f in drop:
2621 2644 del m[f]
2622 2645 files = changed + removed
2623 2646 md = None
2624 2647 if not files:
2625 2648 # if no "files" actually changed in terms of the changelog,
2626 2649 # try hard to detect unmodified manifest entry so that the
2627 2650 # exact same commit can be reproduced later on convert.
2628 2651 md = m1.diff(m, scmutil.matchfiles(self, ctx.files()))
2629 2652 if not files and md:
2630 2653 self.ui.debug('not reusing manifest (no file change in '
2631 2654 'changelog, but manifest differs)\n')
2632 2655 if files or md:
2633 2656 self.ui.note(_("committing manifest\n"))
2634 2657 # we're using narrowmatch here since it's already applied at
2635 2658 # other stages (such as dirstate.walk), so we're already
2636 2659 # ignoring things outside of narrowspec in most cases. The
2637 2660 # one case where we might have files outside the narrowspec
2638 2661 # at this point is merges, and we already error out in the
2639 2662 # case where the merge has files outside of the narrowspec,
2640 2663 # so this is safe.
2641 2664 mn = mctx.write(trp, linkrev,
2642 2665 p1.manifestnode(), p2.manifestnode(),
2643 2666 added, drop, match=self.narrowmatch())
2644 2667 else:
2645 2668 self.ui.debug('reusing manifest from p1 (listed files '
2646 2669 'actually unchanged)\n')
2647 2670 mn = p1.manifestnode()
2648 2671 else:
2649 2672 self.ui.debug('reusing manifest from p1 (no file change)\n')
2650 2673 mn = p1.manifestnode()
2651 2674 files = []
2652 2675
2653 2676 if writecopiesto == 'changeset-only':
2654 2677 # If writing only to changeset extras, use None to indicate that
2655 2678 # no entry should be written. If writing to both, write an empty
2656 2679 # entry to prevent the reader from falling back to reading
2657 2680 # filelogs.
2658 2681 p1copies = p1copies or None
2659 2682 p2copies = p2copies or None
2660 2683
2661 2684 # update changelog
2662 2685 self.ui.note(_("committing changelog\n"))
2663 2686 self.changelog.delayupdate(tr)
2664 2687 n = self.changelog.add(mn, files, ctx.description(),
2665 2688 trp, p1.node(), p2.node(),
2666 2689 user, ctx.date(), ctx.extra().copy(),
2667 2690 p1copies, p2copies)
2668 2691 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
2669 2692 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
2670 2693 parent2=xp2)
2671 2694 # set the new commit is proper phase
2672 2695 targetphase = subrepoutil.newcommitphase(self.ui, ctx)
2673 2696 if targetphase:
2674 2697 # retract boundary do not alter parent changeset.
2675 2698 # if a parent have higher the resulting phase will
2676 2699 # be compliant anyway
2677 2700 #
2678 2701 # if minimal phase was 0 we don't need to retract anything
2679 2702 phases.registernew(self, tr, targetphase, [n])
2680 2703 return n
2681 2704
2682 2705 @unfilteredmethod
2683 2706 def destroying(self):
2684 2707 '''Inform the repository that nodes are about to be destroyed.
2685 2708 Intended for use by strip and rollback, so there's a common
2686 2709 place for anything that has to be done before destroying history.
2687 2710
2688 2711 This is mostly useful for saving state that is in memory and waiting
2689 2712 to be flushed when the current lock is released. Because a call to
2690 2713 destroyed is imminent, the repo will be invalidated causing those
2691 2714 changes to stay in memory (waiting for the next unlock), or vanish
2692 2715 completely.
2693 2716 '''
2694 2717 # When using the same lock to commit and strip, the phasecache is left
2695 2718 # dirty after committing. Then when we strip, the repo is invalidated,
2696 2719 # causing those changes to disappear.
2697 2720 if '_phasecache' in vars(self):
2698 2721 self._phasecache.write()
2699 2722
2700 2723 @unfilteredmethod
2701 2724 def destroyed(self):
2702 2725 '''Inform the repository that nodes have been destroyed.
2703 2726 Intended for use by strip and rollback, so there's a common
2704 2727 place for anything that has to be done after destroying history.
2705 2728 '''
2706 2729 # When one tries to:
2707 2730 # 1) destroy nodes thus calling this method (e.g. strip)
2708 2731 # 2) use phasecache somewhere (e.g. commit)
2709 2732 #
2710 2733 # then 2) will fail because the phasecache contains nodes that were
2711 2734 # removed. We can either remove phasecache from the filecache,
2712 2735 # causing it to reload next time it is accessed, or simply filter
2713 2736 # the removed nodes now and write the updated cache.
2714 2737 self._phasecache.filterunknown(self)
2715 2738 self._phasecache.write()
2716 2739
2717 2740 # refresh all repository caches
2718 2741 self.updatecaches()
2719 2742
2720 2743 # Ensure the persistent tag cache is updated. Doing it now
2721 2744 # means that the tag cache only has to worry about destroyed
2722 2745 # heads immediately after a strip/rollback. That in turn
2723 2746 # guarantees that "cachetip == currenttip" (comparing both rev
2724 2747 # and node) always means no nodes have been added or destroyed.
2725 2748
2726 2749 # XXX this is suboptimal when qrefresh'ing: we strip the current
2727 2750 # head, refresh the tag cache, then immediately add a new head.
2728 2751 # But I think doing it this way is necessary for the "instant
2729 2752 # tag cache retrieval" case to work.
2730 2753 self.invalidate()
2731 2754
2732 2755 def status(self, node1='.', node2=None, match=None,
2733 2756 ignored=False, clean=False, unknown=False,
2734 2757 listsubrepos=False):
2735 2758 '''a convenience method that calls node1.status(node2)'''
2736 2759 return self[node1].status(node2, match, ignored, clean, unknown,
2737 2760 listsubrepos)
2738 2761
2739 2762 def addpostdsstatus(self, ps):
2740 2763 """Add a callback to run within the wlock, at the point at which status
2741 2764 fixups happen.
2742 2765
2743 2766 On status completion, callback(wctx, status) will be called with the
2744 2767 wlock held, unless the dirstate has changed from underneath or the wlock
2745 2768 couldn't be grabbed.
2746 2769
2747 2770 Callbacks should not capture and use a cached copy of the dirstate --
2748 2771 it might change in the meanwhile. Instead, they should access the
2749 2772 dirstate via wctx.repo().dirstate.
2750 2773
2751 2774 This list is emptied out after each status run -- extensions should
2752 2775 make sure it adds to this list each time dirstate.status is called.
2753 2776 Extensions should also make sure they don't call this for statuses
2754 2777 that don't involve the dirstate.
2755 2778 """
2756 2779
2757 2780 # The list is located here for uniqueness reasons -- it is actually
2758 2781 # managed by the workingctx, but that isn't unique per-repo.
2759 2782 self._postdsstatus.append(ps)
2760 2783
2761 2784 def postdsstatus(self):
2762 2785 """Used by workingctx to get the list of post-dirstate-status hooks."""
2763 2786 return self._postdsstatus
2764 2787
2765 2788 def clearpostdsstatus(self):
2766 2789 """Used by workingctx to clear post-dirstate-status hooks."""
2767 2790 del self._postdsstatus[:]
2768 2791
2769 2792 def heads(self, start=None):
2770 2793 if start is None:
2771 2794 cl = self.changelog
2772 2795 headrevs = reversed(cl.headrevs())
2773 2796 return [cl.node(rev) for rev in headrevs]
2774 2797
2775 2798 heads = self.changelog.heads(start)
2776 2799 # sort the output in rev descending order
2777 2800 return sorted(heads, key=self.changelog.rev, reverse=True)
2778 2801
2779 2802 def branchheads(self, branch=None, start=None, closed=False):
2780 2803 '''return a (possibly filtered) list of heads for the given branch
2781 2804
2782 2805 Heads are returned in topological order, from newest to oldest.
2783 2806 If branch is None, use the dirstate branch.
2784 2807 If start is not None, return only heads reachable from start.
2785 2808 If closed is True, return heads that are marked as closed as well.
2786 2809 '''
2787 2810 if branch is None:
2788 2811 branch = self[None].branch()
2789 2812 branches = self.branchmap()
2790 2813 if not branches.hasbranch(branch):
2791 2814 return []
2792 2815 # the cache returns heads ordered lowest to highest
2793 2816 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
2794 2817 if start is not None:
2795 2818 # filter out the heads that cannot be reached from startrev
2796 2819 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
2797 2820 bheads = [h for h in bheads if h in fbheads]
2798 2821 return bheads
2799 2822
2800 2823 def branches(self, nodes):
2801 2824 if not nodes:
2802 2825 nodes = [self.changelog.tip()]
2803 2826 b = []
2804 2827 for n in nodes:
2805 2828 t = n
2806 2829 while True:
2807 2830 p = self.changelog.parents(n)
2808 2831 if p[1] != nullid or p[0] == nullid:
2809 2832 b.append((t, n, p[0], p[1]))
2810 2833 break
2811 2834 n = p[0]
2812 2835 return b
2813 2836
2814 2837 def between(self, pairs):
2815 2838 r = []
2816 2839
2817 2840 for top, bottom in pairs:
2818 2841 n, l, i = top, [], 0
2819 2842 f = 1
2820 2843
2821 2844 while n != bottom and n != nullid:
2822 2845 p = self.changelog.parents(n)[0]
2823 2846 if i == f:
2824 2847 l.append(n)
2825 2848 f = f * 2
2826 2849 n = p
2827 2850 i += 1
2828 2851
2829 2852 r.append(l)
2830 2853
2831 2854 return r
2832 2855
2833 2856 def checkpush(self, pushop):
2834 2857 """Extensions can override this function if additional checks have
2835 2858 to be performed before pushing, or call it if they override push
2836 2859 command.
2837 2860 """
2838 2861
2839 2862 @unfilteredpropertycache
2840 2863 def prepushoutgoinghooks(self):
2841 2864 """Return util.hooks consists of a pushop with repo, remote, outgoing
2842 2865 methods, which are called before pushing changesets.
2843 2866 """
2844 2867 return util.hooks()
2845 2868
2846 2869 def pushkey(self, namespace, key, old, new):
2847 2870 try:
2848 2871 tr = self.currenttransaction()
2849 2872 hookargs = {}
2850 2873 if tr is not None:
2851 2874 hookargs.update(tr.hookargs)
2852 2875 hookargs = pycompat.strkwargs(hookargs)
2853 2876 hookargs[r'namespace'] = namespace
2854 2877 hookargs[r'key'] = key
2855 2878 hookargs[r'old'] = old
2856 2879 hookargs[r'new'] = new
2857 2880 self.hook('prepushkey', throw=True, **hookargs)
2858 2881 except error.HookAbort as exc:
2859 2882 self.ui.write_err(_("pushkey-abort: %s\n") % exc)
2860 2883 if exc.hint:
2861 2884 self.ui.write_err(_("(%s)\n") % exc.hint)
2862 2885 return False
2863 2886 self.ui.debug('pushing key for "%s:%s"\n' % (namespace, key))
2864 2887 ret = pushkey.push(self, namespace, key, old, new)
2865 2888 def runhook():
2866 2889 self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
2867 2890 ret=ret)
2868 2891 self._afterlock(runhook)
2869 2892 return ret
2870 2893
2871 2894 def listkeys(self, namespace):
2872 2895 self.hook('prelistkeys', throw=True, namespace=namespace)
2873 2896 self.ui.debug('listing keys for "%s"\n' % namespace)
2874 2897 values = pushkey.list(self, namespace)
2875 2898 self.hook('listkeys', namespace=namespace, values=values)
2876 2899 return values
2877 2900
2878 2901 def debugwireargs(self, one, two, three=None, four=None, five=None):
2879 2902 '''used to test argument passing over the wire'''
2880 2903 return "%s %s %s %s %s" % (one, two, pycompat.bytestr(three),
2881 2904 pycompat.bytestr(four),
2882 2905 pycompat.bytestr(five))
2883 2906
2884 2907 def savecommitmessage(self, text):
2885 2908 fp = self.vfs('last-message.txt', 'wb')
2886 2909 try:
2887 2910 fp.write(text)
2888 2911 finally:
2889 2912 fp.close()
2890 2913 return self.pathto(fp.name[len(self.root) + 1:])
2891 2914
2892 2915 # used to avoid circular references so destructors work
2893 2916 def aftertrans(files):
2894 2917 renamefiles = [tuple(t) for t in files]
2895 2918 def a():
2896 2919 for vfs, src, dest in renamefiles:
2897 2920 # if src and dest refer to a same file, vfs.rename is a no-op,
2898 2921 # leaving both src and dest on disk. delete dest to make sure
2899 2922 # the rename couldn't be such a no-op.
2900 2923 vfs.tryunlink(dest)
2901 2924 try:
2902 2925 vfs.rename(src, dest)
2903 2926 except OSError: # journal file does not yet exist
2904 2927 pass
2905 2928 return a
2906 2929
2907 2930 def undoname(fn):
2908 2931 base, name = os.path.split(fn)
2909 2932 assert name.startswith('journal')
2910 2933 return os.path.join(base, name.replace('journal', 'undo', 1))
2911 2934
2912 2935 def instance(ui, path, create, intents=None, createopts=None):
2913 2936 localpath = util.urllocalpath(path)
2914 2937 if create:
2915 2938 createrepository(ui, localpath, createopts=createopts)
2916 2939
2917 2940 return makelocalrepository(ui, localpath, intents=intents)
2918 2941
2919 2942 def islocal(path):
2920 2943 return True
2921 2944
2922 2945 def defaultcreateopts(ui, createopts=None):
2923 2946 """Populate the default creation options for a repository.
2924 2947
2925 2948 A dictionary of explicitly requested creation options can be passed
2926 2949 in. Missing keys will be populated.
2927 2950 """
2928 2951 createopts = dict(createopts or {})
2929 2952
2930 2953 if 'backend' not in createopts:
2931 2954 # experimental config: storage.new-repo-backend
2932 2955 createopts['backend'] = ui.config('storage', 'new-repo-backend')
2933 2956
2934 2957 return createopts
2935 2958
2936 2959 def newreporequirements(ui, createopts):
2937 2960 """Determine the set of requirements for a new local repository.
2938 2961
2939 2962 Extensions can wrap this function to specify custom requirements for
2940 2963 new repositories.
2941 2964 """
2942 2965 # If the repo is being created from a shared repository, we copy
2943 2966 # its requirements.
2944 2967 if 'sharedrepo' in createopts:
2945 2968 requirements = set(createopts['sharedrepo'].requirements)
2946 2969 if createopts.get('sharedrelative'):
2947 2970 requirements.add('relshared')
2948 2971 else:
2949 2972 requirements.add('shared')
2950 2973
2951 2974 return requirements
2952 2975
2953 2976 if 'backend' not in createopts:
2954 2977 raise error.ProgrammingError('backend key not present in createopts; '
2955 2978 'was defaultcreateopts() called?')
2956 2979
2957 2980 if createopts['backend'] != 'revlogv1':
2958 2981 raise error.Abort(_('unable to determine repository requirements for '
2959 2982 'storage backend: %s') % createopts['backend'])
2960 2983
2961 2984 requirements = {'revlogv1'}
2962 2985 if ui.configbool('format', 'usestore'):
2963 2986 requirements.add('store')
2964 2987 if ui.configbool('format', 'usefncache'):
2965 2988 requirements.add('fncache')
2966 2989 if ui.configbool('format', 'dotencode'):
2967 2990 requirements.add('dotencode')
2968 2991
2969 2992 compengine = ui.config('format', 'revlog-compression')
2970 2993 if compengine not in util.compengines:
2971 2994 raise error.Abort(_('compression engine %s defined by '
2972 2995 'format.revlog-compression not available') %
2973 2996 compengine,
2974 2997 hint=_('run "hg debuginstall" to list available '
2975 2998 'compression engines'))
2976 2999
2977 3000 # zlib is the historical default and doesn't need an explicit requirement.
2978 3001 elif compengine == 'zstd':
2979 3002 requirements.add('revlog-compression-zstd')
2980 3003 elif compengine != 'zlib':
2981 3004 requirements.add('exp-compression-%s' % compengine)
2982 3005
2983 3006 if scmutil.gdinitconfig(ui):
2984 3007 requirements.add('generaldelta')
2985 3008 if ui.configbool('format', 'sparse-revlog'):
2986 3009 requirements.add(SPARSEREVLOG_REQUIREMENT)
2987 3010 if ui.configbool('experimental', 'treemanifest'):
2988 3011 requirements.add('treemanifest')
2989 3012
2990 3013 revlogv2 = ui.config('experimental', 'revlogv2')
2991 3014 if revlogv2 == 'enable-unstable-format-and-corrupt-my-data':
2992 3015 requirements.remove('revlogv1')
2993 3016 # generaldelta is implied by revlogv2.
2994 3017 requirements.discard('generaldelta')
2995 3018 requirements.add(REVLOGV2_REQUIREMENT)
2996 3019 # experimental config: format.internal-phase
2997 3020 if ui.configbool('format', 'internal-phase'):
2998 3021 requirements.add('internal-phase')
2999 3022
3000 3023 if createopts.get('narrowfiles'):
3001 3024 requirements.add(repository.NARROW_REQUIREMENT)
3002 3025
3003 3026 if createopts.get('lfs'):
3004 3027 requirements.add('lfs')
3005 3028
3029 if ui.configbool('format', 'bookmarks-in-store'):
3030 requirements.add(bookmarks.BOOKMARKS_IN_STORE_REQUIREMENT)
3031
3006 3032 return requirements
3007 3033
3008 3034 def filterknowncreateopts(ui, createopts):
3009 3035 """Filters a dict of repo creation options against options that are known.
3010 3036
3011 3037 Receives a dict of repo creation options and returns a dict of those
3012 3038 options that we don't know how to handle.
3013 3039
3014 3040 This function is called as part of repository creation. If the
3015 3041 returned dict contains any items, repository creation will not
3016 3042 be allowed, as it means there was a request to create a repository
3017 3043 with options not recognized by loaded code.
3018 3044
3019 3045 Extensions can wrap this function to filter out creation options
3020 3046 they know how to handle.
3021 3047 """
3022 3048 known = {
3023 3049 'backend',
3024 3050 'lfs',
3025 3051 'narrowfiles',
3026 3052 'sharedrepo',
3027 3053 'sharedrelative',
3028 3054 'shareditems',
3029 3055 'shallowfilestore',
3030 3056 }
3031 3057
3032 3058 return {k: v for k, v in createopts.items() if k not in known}
3033 3059
3034 3060 def createrepository(ui, path, createopts=None):
3035 3061 """Create a new repository in a vfs.
3036 3062
3037 3063 ``path`` path to the new repo's working directory.
3038 3064 ``createopts`` options for the new repository.
3039 3065
3040 3066 The following keys for ``createopts`` are recognized:
3041 3067
3042 3068 backend
3043 3069 The storage backend to use.
3044 3070 lfs
3045 3071 Repository will be created with ``lfs`` requirement. The lfs extension
3046 3072 will automatically be loaded when the repository is accessed.
3047 3073 narrowfiles
3048 3074 Set up repository to support narrow file storage.
3049 3075 sharedrepo
3050 3076 Repository object from which storage should be shared.
3051 3077 sharedrelative
3052 3078 Boolean indicating if the path to the shared repo should be
3053 3079 stored as relative. By default, the pointer to the "parent" repo
3054 3080 is stored as an absolute path.
3055 3081 shareditems
3056 3082 Set of items to share to the new repository (in addition to storage).
3057 3083 shallowfilestore
3058 3084 Indicates that storage for files should be shallow (not all ancestor
3059 3085 revisions are known).
3060 3086 """
3061 3087 createopts = defaultcreateopts(ui, createopts=createopts)
3062 3088
3063 3089 unknownopts = filterknowncreateopts(ui, createopts)
3064 3090
3065 3091 if not isinstance(unknownopts, dict):
3066 3092 raise error.ProgrammingError('filterknowncreateopts() did not return '
3067 3093 'a dict')
3068 3094
3069 3095 if unknownopts:
3070 3096 raise error.Abort(_('unable to create repository because of unknown '
3071 3097 'creation option: %s') %
3072 3098 ', '.join(sorted(unknownopts)),
3073 3099 hint=_('is a required extension not loaded?'))
3074 3100
3075 3101 requirements = newreporequirements(ui, createopts=createopts)
3076 3102
3077 3103 wdirvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
3078 3104
3079 3105 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg'))
3080 3106 if hgvfs.exists():
3081 3107 raise error.RepoError(_('repository %s already exists') % path)
3082 3108
3083 3109 if 'sharedrepo' in createopts:
3084 3110 sharedpath = createopts['sharedrepo'].sharedpath
3085 3111
3086 3112 if createopts.get('sharedrelative'):
3087 3113 try:
3088 3114 sharedpath = os.path.relpath(sharedpath, hgvfs.base)
3089 3115 except (IOError, ValueError) as e:
3090 3116 # ValueError is raised on Windows if the drive letters differ
3091 3117 # on each path.
3092 3118 raise error.Abort(_('cannot calculate relative path'),
3093 3119 hint=stringutil.forcebytestr(e))
3094 3120
3095 3121 if not wdirvfs.exists():
3096 3122 wdirvfs.makedirs()
3097 3123
3098 3124 hgvfs.makedir(notindexed=True)
3099 3125 if 'sharedrepo' not in createopts:
3100 3126 hgvfs.mkdir(b'cache')
3101 3127 hgvfs.mkdir(b'wcache')
3102 3128
3103 3129 if b'store' in requirements and 'sharedrepo' not in createopts:
3104 3130 hgvfs.mkdir(b'store')
3105 3131
3106 3132 # We create an invalid changelog outside the store so very old
3107 3133 # Mercurial versions (which didn't know about the requirements
3108 3134 # file) encounter an error on reading the changelog. This
3109 3135 # effectively locks out old clients and prevents them from
3110 3136 # mucking with a repo in an unknown format.
3111 3137 #
3112 3138 # The revlog header has version 2, which won't be recognized by
3113 3139 # such old clients.
3114 3140 hgvfs.append(b'00changelog.i',
3115 3141 b'\0\0\0\2 dummy changelog to prevent using the old repo '
3116 3142 b'layout')
3117 3143
3118 3144 scmutil.writerequires(hgvfs, requirements)
3119 3145
3120 3146 # Write out file telling readers where to find the shared store.
3121 3147 if 'sharedrepo' in createopts:
3122 3148 hgvfs.write(b'sharedpath', sharedpath)
3123 3149
3124 3150 if createopts.get('shareditems'):
3125 3151 shared = b'\n'.join(sorted(createopts['shareditems'])) + b'\n'
3126 3152 hgvfs.write(b'shared', shared)
3127 3153
3128 3154 def poisonrepository(repo):
3129 3155 """Poison a repository instance so it can no longer be used."""
3130 3156 # Perform any cleanup on the instance.
3131 3157 repo.close()
3132 3158
3133 3159 # Our strategy is to replace the type of the object with one that
3134 3160 # has all attribute lookups result in error.
3135 3161 #
3136 3162 # But we have to allow the close() method because some constructors
3137 3163 # of repos call close() on repo references.
3138 3164 class poisonedrepository(object):
3139 3165 def __getattribute__(self, item):
3140 3166 if item == r'close':
3141 3167 return object.__getattribute__(self, item)
3142 3168
3143 3169 raise error.ProgrammingError('repo instances should not be used '
3144 3170 'after unshare')
3145 3171
3146 3172 def close(self):
3147 3173 pass
3148 3174
3149 3175 # We may have a repoview, which intercepts __setattr__. So be sure
3150 3176 # we operate at the lowest level possible.
3151 3177 object.__setattr__(repo, r'__class__', poisonedrepository)
@@ -1,654 +1,654 b''
1 1 # store.py - repository store handling for Mercurial
2 2 #
3 3 # Copyright 2008 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import functools
12 12 import hashlib
13 13 import os
14 14 import stat
15 15
16 16 from .i18n import _
17 17 from . import (
18 18 error,
19 19 node,
20 20 policy,
21 21 pycompat,
22 22 util,
23 23 vfs as vfsmod,
24 24 )
25 25
26 26 parsers = policy.importmod(r'parsers')
27 27 # how much bytes should be read from fncache in one read
28 28 # It is done to prevent loading large fncache files into memory
29 29 fncache_chunksize = 10 ** 6
30 30
31 31 def _matchtrackedpath(path, matcher):
32 32 """parses a fncache entry and returns whether the entry is tracking a path
33 33 matched by matcher or not.
34 34
35 35 If matcher is None, returns True"""
36 36
37 37 if matcher is None:
38 38 return True
39 39 path = decodedir(path)
40 40 if path.startswith('data/'):
41 41 return matcher(path[len('data/'):-len('.i')])
42 42 elif path.startswith('meta/'):
43 43 return matcher.visitdir(path[len('meta/'):-len('/00manifest.i')] or '.')
44 44
45 45 raise error.ProgrammingError("cannot decode path %s" % path)
46 46
47 47 # This avoids a collision between a file named foo and a dir named
48 48 # foo.i or foo.d
49 49 def _encodedir(path):
50 50 '''
51 51 >>> _encodedir(b'data/foo.i')
52 52 'data/foo.i'
53 53 >>> _encodedir(b'data/foo.i/bla.i')
54 54 'data/foo.i.hg/bla.i'
55 55 >>> _encodedir(b'data/foo.i.hg/bla.i')
56 56 'data/foo.i.hg.hg/bla.i'
57 57 >>> _encodedir(b'data/foo.i\\ndata/foo.i/bla.i\\ndata/foo.i.hg/bla.i\\n')
58 58 'data/foo.i\\ndata/foo.i.hg/bla.i\\ndata/foo.i.hg.hg/bla.i\\n'
59 59 '''
60 60 return (path
61 61 .replace(".hg/", ".hg.hg/")
62 62 .replace(".i/", ".i.hg/")
63 63 .replace(".d/", ".d.hg/"))
64 64
65 65 encodedir = getattr(parsers, 'encodedir', _encodedir)
66 66
67 67 def decodedir(path):
68 68 '''
69 69 >>> decodedir(b'data/foo.i')
70 70 'data/foo.i'
71 71 >>> decodedir(b'data/foo.i.hg/bla.i')
72 72 'data/foo.i/bla.i'
73 73 >>> decodedir(b'data/foo.i.hg.hg/bla.i')
74 74 'data/foo.i.hg/bla.i'
75 75 '''
76 76 if ".hg/" not in path:
77 77 return path
78 78 return (path
79 79 .replace(".d.hg/", ".d/")
80 80 .replace(".i.hg/", ".i/")
81 81 .replace(".hg.hg/", ".hg/"))
82 82
83 83 def _reserved():
84 84 ''' characters that are problematic for filesystems
85 85
86 86 * ascii escapes (0..31)
87 87 * ascii hi (126..255)
88 88 * windows specials
89 89
90 90 these characters will be escaped by encodefunctions
91 91 '''
92 92 winreserved = [ord(x) for x in u'\\:*?"<>|']
93 93 for x in range(32):
94 94 yield x
95 95 for x in range(126, 256):
96 96 yield x
97 97 for x in winreserved:
98 98 yield x
99 99
100 100 def _buildencodefun():
101 101 '''
102 102 >>> enc, dec = _buildencodefun()
103 103
104 104 >>> enc(b'nothing/special.txt')
105 105 'nothing/special.txt'
106 106 >>> dec(b'nothing/special.txt')
107 107 'nothing/special.txt'
108 108
109 109 >>> enc(b'HELLO')
110 110 '_h_e_l_l_o'
111 111 >>> dec(b'_h_e_l_l_o')
112 112 'HELLO'
113 113
114 114 >>> enc(b'hello:world?')
115 115 'hello~3aworld~3f'
116 116 >>> dec(b'hello~3aworld~3f')
117 117 'hello:world?'
118 118
119 119 >>> enc(b'the\\x07quick\\xADshot')
120 120 'the~07quick~adshot'
121 121 >>> dec(b'the~07quick~adshot')
122 122 'the\\x07quick\\xadshot'
123 123 '''
124 124 e = '_'
125 125 xchr = pycompat.bytechr
126 126 asciistr = list(map(xchr, range(127)))
127 127 capitals = list(range(ord("A"), ord("Z") + 1))
128 128
129 129 cmap = dict((x, x) for x in asciistr)
130 130 for x in _reserved():
131 131 cmap[xchr(x)] = "~%02x" % x
132 132 for x in capitals + [ord(e)]:
133 133 cmap[xchr(x)] = e + xchr(x).lower()
134 134
135 135 dmap = {}
136 136 for k, v in cmap.iteritems():
137 137 dmap[v] = k
138 138 def decode(s):
139 139 i = 0
140 140 while i < len(s):
141 141 for l in pycompat.xrange(1, 4):
142 142 try:
143 143 yield dmap[s[i:i + l]]
144 144 i += l
145 145 break
146 146 except KeyError:
147 147 pass
148 148 else:
149 149 raise KeyError
150 150 return (lambda s: ''.join([cmap[s[c:c + 1]]
151 151 for c in pycompat.xrange(len(s))]),
152 152 lambda s: ''.join(list(decode(s))))
153 153
154 154 _encodefname, _decodefname = _buildencodefun()
155 155
156 156 def encodefilename(s):
157 157 '''
158 158 >>> encodefilename(b'foo.i/bar.d/bla.hg/hi:world?/HELLO')
159 159 'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o'
160 160 '''
161 161 return _encodefname(encodedir(s))
162 162
163 163 def decodefilename(s):
164 164 '''
165 165 >>> decodefilename(b'foo.i.hg/bar.d.hg/bla.hg.hg/hi~3aworld~3f/_h_e_l_l_o')
166 166 'foo.i/bar.d/bla.hg/hi:world?/HELLO'
167 167 '''
168 168 return decodedir(_decodefname(s))
169 169
170 170 def _buildlowerencodefun():
171 171 '''
172 172 >>> f = _buildlowerencodefun()
173 173 >>> f(b'nothing/special.txt')
174 174 'nothing/special.txt'
175 175 >>> f(b'HELLO')
176 176 'hello'
177 177 >>> f(b'hello:world?')
178 178 'hello~3aworld~3f'
179 179 >>> f(b'the\\x07quick\\xADshot')
180 180 'the~07quick~adshot'
181 181 '''
182 182 xchr = pycompat.bytechr
183 183 cmap = dict([(xchr(x), xchr(x)) for x in pycompat.xrange(127)])
184 184 for x in _reserved():
185 185 cmap[xchr(x)] = "~%02x" % x
186 186 for x in range(ord("A"), ord("Z") + 1):
187 187 cmap[xchr(x)] = xchr(x).lower()
188 188 def lowerencode(s):
189 189 return "".join([cmap[c] for c in pycompat.iterbytestr(s)])
190 190 return lowerencode
191 191
192 192 lowerencode = getattr(parsers, 'lowerencode', None) or _buildlowerencodefun()
193 193
194 194 # Windows reserved names: con, prn, aux, nul, com1..com9, lpt1..lpt9
195 195 _winres3 = ('aux', 'con', 'prn', 'nul') # length 3
196 196 _winres4 = ('com', 'lpt') # length 4 (with trailing 1..9)
197 197 def _auxencode(path, dotencode):
198 198 '''
199 199 Encodes filenames containing names reserved by Windows or which end in
200 200 period or space. Does not touch other single reserved characters c.
201 201 Specifically, c in '\\:*?"<>|' or ord(c) <= 31 are *not* encoded here.
202 202 Additionally encodes space or period at the beginning, if dotencode is
203 203 True. Parameter path is assumed to be all lowercase.
204 204 A segment only needs encoding if a reserved name appears as a
205 205 basename (e.g. "aux", "aux.foo"). A directory or file named "foo.aux"
206 206 doesn't need encoding.
207 207
208 208 >>> s = b'.foo/aux.txt/txt.aux/con/prn/nul/foo.'
209 209 >>> _auxencode(s.split(b'/'), True)
210 210 ['~2efoo', 'au~78.txt', 'txt.aux', 'co~6e', 'pr~6e', 'nu~6c', 'foo~2e']
211 211 >>> s = b'.com1com2/lpt9.lpt4.lpt1/conprn/com0/lpt0/foo.'
212 212 >>> _auxencode(s.split(b'/'), False)
213 213 ['.com1com2', 'lp~749.lpt4.lpt1', 'conprn', 'com0', 'lpt0', 'foo~2e']
214 214 >>> _auxencode([b'foo. '], True)
215 215 ['foo.~20']
216 216 >>> _auxencode([b' .foo'], True)
217 217 ['~20.foo']
218 218 '''
219 219 for i, n in enumerate(path):
220 220 if not n:
221 221 continue
222 222 if dotencode and n[0] in '. ':
223 223 n = "~%02x" % ord(n[0:1]) + n[1:]
224 224 path[i] = n
225 225 else:
226 226 l = n.find('.')
227 227 if l == -1:
228 228 l = len(n)
229 229 if ((l == 3 and n[:3] in _winres3) or
230 230 (l == 4 and n[3:4] <= '9' and n[3:4] >= '1'
231 231 and n[:3] in _winres4)):
232 232 # encode third letter ('aux' -> 'au~78')
233 233 ec = "~%02x" % ord(n[2:3])
234 234 n = n[0:2] + ec + n[3:]
235 235 path[i] = n
236 236 if n[-1] in '. ':
237 237 # encode last period or space ('foo...' -> 'foo..~2e')
238 238 path[i] = n[:-1] + "~%02x" % ord(n[-1:])
239 239 return path
240 240
241 241 _maxstorepathlen = 120
242 242 _dirprefixlen = 8
243 243 _maxshortdirslen = 8 * (_dirprefixlen + 1) - 4
244 244
245 245 def _hashencode(path, dotencode):
246 246 digest = node.hex(hashlib.sha1(path).digest())
247 247 le = lowerencode(path[5:]).split('/') # skips prefix 'data/' or 'meta/'
248 248 parts = _auxencode(le, dotencode)
249 249 basename = parts[-1]
250 250 _root, ext = os.path.splitext(basename)
251 251 sdirs = []
252 252 sdirslen = 0
253 253 for p in parts[:-1]:
254 254 d = p[:_dirprefixlen]
255 255 if d[-1] in '. ':
256 256 # Windows can't access dirs ending in period or space
257 257 d = d[:-1] + '_'
258 258 if sdirslen == 0:
259 259 t = len(d)
260 260 else:
261 261 t = sdirslen + 1 + len(d)
262 262 if t > _maxshortdirslen:
263 263 break
264 264 sdirs.append(d)
265 265 sdirslen = t
266 266 dirs = '/'.join(sdirs)
267 267 if len(dirs) > 0:
268 268 dirs += '/'
269 269 res = 'dh/' + dirs + digest + ext
270 270 spaceleft = _maxstorepathlen - len(res)
271 271 if spaceleft > 0:
272 272 filler = basename[:spaceleft]
273 273 res = 'dh/' + dirs + filler + digest + ext
274 274 return res
275 275
276 276 def _hybridencode(path, dotencode):
277 277 '''encodes path with a length limit
278 278
279 279 Encodes all paths that begin with 'data/', according to the following.
280 280
281 281 Default encoding (reversible):
282 282
283 283 Encodes all uppercase letters 'X' as '_x'. All reserved or illegal
284 284 characters are encoded as '~xx', where xx is the two digit hex code
285 285 of the character (see encodefilename).
286 286 Relevant path components consisting of Windows reserved filenames are
287 287 masked by encoding the third character ('aux' -> 'au~78', see _auxencode).
288 288
289 289 Hashed encoding (not reversible):
290 290
291 291 If the default-encoded path is longer than _maxstorepathlen, a
292 292 non-reversible hybrid hashing of the path is done instead.
293 293 This encoding uses up to _dirprefixlen characters of all directory
294 294 levels of the lowerencoded path, but not more levels than can fit into
295 295 _maxshortdirslen.
296 296 Then follows the filler followed by the sha digest of the full path.
297 297 The filler is the beginning of the basename of the lowerencoded path
298 298 (the basename is everything after the last path separator). The filler
299 299 is as long as possible, filling in characters from the basename until
300 300 the encoded path has _maxstorepathlen characters (or all chars of the
301 301 basename have been taken).
302 302 The extension (e.g. '.i' or '.d') is preserved.
303 303
304 304 The string 'data/' at the beginning is replaced with 'dh/', if the hashed
305 305 encoding was used.
306 306 '''
307 307 path = encodedir(path)
308 308 ef = _encodefname(path).split('/')
309 309 res = '/'.join(_auxencode(ef, dotencode))
310 310 if len(res) > _maxstorepathlen:
311 311 res = _hashencode(path, dotencode)
312 312 return res
313 313
314 314 def _pathencode(path):
315 315 de = encodedir(path)
316 316 if len(path) > _maxstorepathlen:
317 317 return _hashencode(de, True)
318 318 ef = _encodefname(de).split('/')
319 319 res = '/'.join(_auxencode(ef, True))
320 320 if len(res) > _maxstorepathlen:
321 321 return _hashencode(de, True)
322 322 return res
323 323
324 324 _pathencode = getattr(parsers, 'pathencode', _pathencode)
325 325
326 326 def _plainhybridencode(f):
327 327 return _hybridencode(f, False)
328 328
329 329 def _calcmode(vfs):
330 330 try:
331 331 # files in .hg/ will be created using this mode
332 332 mode = vfs.stat().st_mode
333 333 # avoid some useless chmods
334 334 if (0o777 & ~util.umask) == (0o777 & mode):
335 335 mode = None
336 336 except OSError:
337 337 mode = None
338 338 return mode
339 339
340 _data = ('narrowspec data meta 00manifest.d 00manifest.i'
340 _data = ('bookmarks narrowspec data meta 00manifest.d 00manifest.i'
341 341 ' 00changelog.d 00changelog.i phaseroots obsstore')
342 342
343 343 def isrevlog(f, kind, st):
344 344 return kind == stat.S_IFREG and f[-2:] in ('.i', '.d')
345 345
346 346 class basicstore(object):
347 347 '''base class for local repository stores'''
348 348 def __init__(self, path, vfstype):
349 349 vfs = vfstype(path)
350 350 self.path = vfs.base
351 351 self.createmode = _calcmode(vfs)
352 352 vfs.createmode = self.createmode
353 353 self.rawvfs = vfs
354 354 self.vfs = vfsmod.filtervfs(vfs, encodedir)
355 355 self.opener = self.vfs
356 356
357 357 def join(self, f):
358 358 return self.path + '/' + encodedir(f)
359 359
360 360 def _walk(self, relpath, recurse, filefilter=isrevlog):
361 361 '''yields (unencoded, encoded, size)'''
362 362 path = self.path
363 363 if relpath:
364 364 path += '/' + relpath
365 365 striplen = len(self.path) + 1
366 366 l = []
367 367 if self.rawvfs.isdir(path):
368 368 visit = [path]
369 369 readdir = self.rawvfs.readdir
370 370 while visit:
371 371 p = visit.pop()
372 372 for f, kind, st in readdir(p, stat=True):
373 373 fp = p + '/' + f
374 374 if filefilter(f, kind, st):
375 375 n = util.pconvert(fp[striplen:])
376 376 l.append((decodedir(n), n, st.st_size))
377 377 elif kind == stat.S_IFDIR and recurse:
378 378 visit.append(fp)
379 379 l.sort()
380 380 return l
381 381
382 382 def datafiles(self, matcher=None):
383 383 return self._walk('data', True) + self._walk('meta', True)
384 384
385 385 def topfiles(self):
386 386 # yield manifest before changelog
387 387 return reversed(self._walk('', False))
388 388
389 389 def walk(self, matcher=None):
390 390 '''yields (unencoded, encoded, size)
391 391
392 392 if a matcher is passed, storage files of only those tracked paths
393 393 are passed with matches the matcher
394 394 '''
395 395 # yield data files first
396 396 for x in self.datafiles(matcher):
397 397 yield x
398 398 for x in self.topfiles():
399 399 yield x
400 400
401 401 def copylist(self):
402 402 return ['requires'] + _data.split()
403 403
404 404 def write(self, tr):
405 405 pass
406 406
407 407 def invalidatecaches(self):
408 408 pass
409 409
410 410 def markremoved(self, fn):
411 411 pass
412 412
413 413 def __contains__(self, path):
414 414 '''Checks if the store contains path'''
415 415 path = "/".join(("data", path))
416 416 # file?
417 417 if self.vfs.exists(path + ".i"):
418 418 return True
419 419 # dir?
420 420 if not path.endswith("/"):
421 421 path = path + "/"
422 422 return self.vfs.exists(path)
423 423
424 424 class encodedstore(basicstore):
425 425 def __init__(self, path, vfstype):
426 426 vfs = vfstype(path + '/store')
427 427 self.path = vfs.base
428 428 self.createmode = _calcmode(vfs)
429 429 vfs.createmode = self.createmode
430 430 self.rawvfs = vfs
431 431 self.vfs = vfsmod.filtervfs(vfs, encodefilename)
432 432 self.opener = self.vfs
433 433
434 434 def datafiles(self, matcher=None):
435 435 for a, b, size in super(encodedstore, self).datafiles():
436 436 try:
437 437 a = decodefilename(a)
438 438 except KeyError:
439 439 a = None
440 440 if a is not None and not _matchtrackedpath(a, matcher):
441 441 continue
442 442 yield a, b, size
443 443
444 444 def join(self, f):
445 445 return self.path + '/' + encodefilename(f)
446 446
447 447 def copylist(self):
448 448 return (['requires', '00changelog.i'] +
449 449 ['store/' + f for f in _data.split()])
450 450
451 451 class fncache(object):
452 452 # the filename used to be partially encoded
453 453 # hence the encodedir/decodedir dance
454 454 def __init__(self, vfs):
455 455 self.vfs = vfs
456 456 self.entries = None
457 457 self._dirty = False
458 458 # set of new additions to fncache
459 459 self.addls = set()
460 460
461 461 def _load(self):
462 462 '''fill the entries from the fncache file'''
463 463 self._dirty = False
464 464 try:
465 465 fp = self.vfs('fncache', mode='rb')
466 466 except IOError:
467 467 # skip nonexistent file
468 468 self.entries = set()
469 469 return
470 470
471 471 self.entries = set()
472 472 chunk = b''
473 473 for c in iter(functools.partial(fp.read, fncache_chunksize), b''):
474 474 chunk += c
475 475 try:
476 476 p = chunk.rindex(b'\n')
477 477 self.entries.update(decodedir(chunk[:p + 1]).splitlines())
478 478 chunk = chunk[p + 1:]
479 479 except ValueError:
480 480 # substring '\n' not found, maybe the entry is bigger than the
481 481 # chunksize, so let's keep iterating
482 482 pass
483 483
484 484 if chunk:
485 485 raise error.Abort(_("fncache does not ends with a newline"),
486 486 hint=_("use 'hg debugrebuildfncache' to rebuild"
487 487 " the fncache"))
488 488 self._checkentries(fp)
489 489 fp.close()
490 490
491 491 def _checkentries(self, fp):
492 492 """ make sure there is no empty string in entries """
493 493 if '' in self.entries:
494 494 fp.seek(0)
495 495 for n, line in enumerate(util.iterfile(fp)):
496 496 if not line.rstrip('\n'):
497 497 t = _('invalid entry in fncache, line %d') % (n + 1)
498 498 raise error.Abort(t)
499 499
500 500 def write(self, tr):
501 501 if self._dirty:
502 502 assert self.entries is not None
503 503 self.entries = self.entries | self.addls
504 504 self.addls = set()
505 505 tr.addbackup('fncache')
506 506 fp = self.vfs('fncache', mode='wb', atomictemp=True)
507 507 if self.entries:
508 508 fp.write(encodedir('\n'.join(self.entries) + '\n'))
509 509 fp.close()
510 510 self._dirty = False
511 511 if self.addls:
512 512 # if we have just new entries, let's append them to the fncache
513 513 tr.addbackup('fncache')
514 514 fp = self.vfs('fncache', mode='ab', atomictemp=True)
515 515 if self.addls:
516 516 fp.write(encodedir('\n'.join(self.addls) + '\n'))
517 517 fp.close()
518 518 self.entries = None
519 519 self.addls = set()
520 520
521 521 def add(self, fn):
522 522 if self.entries is None:
523 523 self._load()
524 524 if fn not in self.entries:
525 525 self.addls.add(fn)
526 526
527 527 def remove(self, fn):
528 528 if self.entries is None:
529 529 self._load()
530 530 if fn in self.addls:
531 531 self.addls.remove(fn)
532 532 return
533 533 try:
534 534 self.entries.remove(fn)
535 535 self._dirty = True
536 536 except KeyError:
537 537 pass
538 538
539 539 def __contains__(self, fn):
540 540 if fn in self.addls:
541 541 return True
542 542 if self.entries is None:
543 543 self._load()
544 544 return fn in self.entries
545 545
546 546 def __iter__(self):
547 547 if self.entries is None:
548 548 self._load()
549 549 return iter(self.entries | self.addls)
550 550
551 551 class _fncachevfs(vfsmod.proxyvfs):
552 552 def __init__(self, vfs, fnc, encode):
553 553 vfsmod.proxyvfs.__init__(self, vfs)
554 554 self.fncache = fnc
555 555 self.encode = encode
556 556
557 557 def __call__(self, path, mode='r', *args, **kw):
558 558 encoded = self.encode(path)
559 559 if mode not in ('r', 'rb') and (path.startswith('data/') or
560 560 path.startswith('meta/')):
561 561 # do not trigger a fncache load when adding a file that already is
562 562 # known to exist.
563 563 notload = self.fncache.entries is None and self.vfs.exists(encoded)
564 564 if notload and 'a' in mode and not self.vfs.stat(encoded).st_size:
565 565 # when appending to an existing file, if the file has size zero,
566 566 # it should be considered as missing. Such zero-size files are
567 567 # the result of truncation when a transaction is aborted.
568 568 notload = False
569 569 if not notload:
570 570 self.fncache.add(path)
571 571 return self.vfs(encoded, mode, *args, **kw)
572 572
573 573 def join(self, path):
574 574 if path:
575 575 return self.vfs.join(self.encode(path))
576 576 else:
577 577 return self.vfs.join(path)
578 578
579 579 class fncachestore(basicstore):
580 580 def __init__(self, path, vfstype, dotencode):
581 581 if dotencode:
582 582 encode = _pathencode
583 583 else:
584 584 encode = _plainhybridencode
585 585 self.encode = encode
586 586 vfs = vfstype(path + '/store')
587 587 self.path = vfs.base
588 588 self.pathsep = self.path + '/'
589 589 self.createmode = _calcmode(vfs)
590 590 vfs.createmode = self.createmode
591 591 self.rawvfs = vfs
592 592 fnc = fncache(vfs)
593 593 self.fncache = fnc
594 594 self.vfs = _fncachevfs(vfs, fnc, encode)
595 595 self.opener = self.vfs
596 596
597 597 def join(self, f):
598 598 return self.pathsep + self.encode(f)
599 599
600 600 def getsize(self, path):
601 601 return self.rawvfs.stat(path).st_size
602 602
603 603 def datafiles(self, matcher=None):
604 604 for f in sorted(self.fncache):
605 605 if not _matchtrackedpath(f, matcher):
606 606 continue
607 607 ef = self.encode(f)
608 608 try:
609 609 yield f, ef, self.getsize(ef)
610 610 except OSError as err:
611 611 if err.errno != errno.ENOENT:
612 612 raise
613 613
614 614 def copylist(self):
615 d = ('narrowspec data meta dh fncache phaseroots obsstore'
615 d = ('bookmarks narrowspec data meta dh fncache phaseroots obsstore'
616 616 ' 00manifest.d 00manifest.i 00changelog.d 00changelog.i')
617 617 return (['requires', '00changelog.i'] +
618 618 ['store/' + f for f in d.split()])
619 619
620 620 def write(self, tr):
621 621 self.fncache.write(tr)
622 622
623 623 def invalidatecaches(self):
624 624 self.fncache.entries = None
625 625 self.fncache.addls = set()
626 626
627 627 def markremoved(self, fn):
628 628 self.fncache.remove(fn)
629 629
630 630 def _exists(self, f):
631 631 ef = self.encode(f)
632 632 try:
633 633 self.getsize(ef)
634 634 return True
635 635 except OSError as err:
636 636 if err.errno != errno.ENOENT:
637 637 raise
638 638 # nonexistent entry
639 639 return False
640 640
641 641 def __contains__(self, path):
642 642 '''Checks if the store contains path'''
643 643 path = "/".join(("data", path))
644 644 # check for files (exact match)
645 645 e = path + '.i'
646 646 if e in self.fncache and self._exists(e):
647 647 return True
648 648 # now check for directories (prefix match)
649 649 if not path.endswith('/'):
650 650 path += '/'
651 651 for e in self.fncache:
652 652 if e.startswith(path) and self._exists(e):
653 653 return True
654 654 return False
@@ -1,3837 +1,3839 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 Extra extensions will be printed in help output in a non-reliable order since
48 48 the extension is unknown.
49 49 #if no-extraextensions
50 50
51 51 $ hg help
52 52 Mercurial Distributed SCM
53 53
54 54 list of commands:
55 55
56 56 Repository creation:
57 57
58 58 clone make a copy of an existing repository
59 59 init create a new repository in the given directory
60 60
61 61 Remote repository management:
62 62
63 63 incoming show new changesets found in source
64 64 outgoing show changesets not found in the destination
65 65 paths show aliases for remote repositories
66 66 pull pull changes from the specified source
67 67 push push changes to the specified destination
68 68 serve start stand-alone webserver
69 69
70 70 Change creation:
71 71
72 72 commit commit the specified files or all outstanding changes
73 73
74 74 Change manipulation:
75 75
76 76 backout reverse effect of earlier changeset
77 77 graft copy changes from other branches onto the current branch
78 78 merge merge another revision into working directory
79 79
80 80 Change organization:
81 81
82 82 bookmarks create a new bookmark or list existing bookmarks
83 83 branch set or show the current branch name
84 84 branches list repository named branches
85 85 phase set or show the current phase name
86 86 tag add one or more tags for the current or given revision
87 87 tags list repository tags
88 88
89 89 File content management:
90 90
91 91 annotate show changeset information by line for each file
92 92 cat output the current or given revision of files
93 93 copy mark files as copied for the next commit
94 94 diff diff repository (or selected files)
95 95 grep search revision history for a pattern in specified files
96 96
97 97 Change navigation:
98 98
99 99 bisect subdivision search of changesets
100 100 heads show branch heads
101 101 identify identify the working directory or specified revision
102 102 log show revision history of entire repository or files
103 103
104 104 Working directory management:
105 105
106 106 add add the specified files on the next commit
107 107 addremove add all new files, delete all missing files
108 108 files list tracked files
109 109 forget forget the specified files on the next commit
110 110 remove remove the specified files on the next commit
111 111 rename rename files; equivalent of copy + remove
112 112 resolve redo merges or set/view the merge status of files
113 113 revert restore files to their checkout state
114 114 root print the root (top) of the current working directory
115 115 status show changed files in the working directory
116 116 summary summarize working directory state
117 117 update update working directory (or switch revisions)
118 118
119 119 Change import/export:
120 120
121 121 archive create an unversioned archive of a repository revision
122 122 bundle create a bundle file
123 123 export dump the header and diffs for one or more changesets
124 124 import import an ordered set of patches
125 125 unbundle apply one or more bundle files
126 126
127 127 Repository maintenance:
128 128
129 129 manifest output the current or given revision of the project manifest
130 130 recover roll back an interrupted transaction
131 131 verify verify the integrity of the repository
132 132
133 133 Help:
134 134
135 135 config show combined config settings from all hgrc files
136 136 help show help for a given topic or a help overview
137 137 version output version and copyright information
138 138
139 139 additional help topics:
140 140
141 141 Mercurial identifiers:
142 142
143 143 filesets Specifying File Sets
144 144 hgignore Syntax for Mercurial Ignore Files
145 145 patterns File Name Patterns
146 146 revisions Specifying Revisions
147 147 urls URL Paths
148 148
149 149 Mercurial output:
150 150
151 151 color Colorizing Outputs
152 152 dates Date Formats
153 153 diffs Diff Formats
154 154 templating Template Usage
155 155
156 156 Mercurial configuration:
157 157
158 158 config Configuration Files
159 159 environment Environment Variables
160 160 extensions Using Additional Features
161 161 flags Command-line flags
162 162 hgweb Configuring hgweb
163 163 merge-tools Merge Tools
164 164 pager Pager Support
165 165
166 166 Concepts:
167 167
168 168 bundlespec Bundle File Formats
169 169 glossary Glossary
170 170 phases Working with Phases
171 171 subrepos Subrepositories
172 172
173 173 Miscellaneous:
174 174
175 175 deprecated Deprecated Features
176 176 internals Technical implementation topics
177 177 scripting Using Mercurial from scripts and automation
178 178
179 179 (use 'hg help -v' to show built-in aliases and global options)
180 180
181 181 $ hg -q help
182 182 Repository creation:
183 183
184 184 clone make a copy of an existing repository
185 185 init create a new repository in the given directory
186 186
187 187 Remote repository management:
188 188
189 189 incoming show new changesets found in source
190 190 outgoing show changesets not found in the destination
191 191 paths show aliases for remote repositories
192 192 pull pull changes from the specified source
193 193 push push changes to the specified destination
194 194 serve start stand-alone webserver
195 195
196 196 Change creation:
197 197
198 198 commit commit the specified files or all outstanding changes
199 199
200 200 Change manipulation:
201 201
202 202 backout reverse effect of earlier changeset
203 203 graft copy changes from other branches onto the current branch
204 204 merge merge another revision into working directory
205 205
206 206 Change organization:
207 207
208 208 bookmarks create a new bookmark or list existing bookmarks
209 209 branch set or show the current branch name
210 210 branches list repository named branches
211 211 phase set or show the current phase name
212 212 tag add one or more tags for the current or given revision
213 213 tags list repository tags
214 214
215 215 File content management:
216 216
217 217 annotate show changeset information by line for each file
218 218 cat output the current or given revision of files
219 219 copy mark files as copied for the next commit
220 220 diff diff repository (or selected files)
221 221 grep search revision history for a pattern in specified files
222 222
223 223 Change navigation:
224 224
225 225 bisect subdivision search of changesets
226 226 heads show branch heads
227 227 identify identify the working directory or specified revision
228 228 log show revision history of entire repository or files
229 229
230 230 Working directory management:
231 231
232 232 add add the specified files on the next commit
233 233 addremove add all new files, delete all missing files
234 234 files list tracked files
235 235 forget forget the specified files on the next commit
236 236 remove remove the specified files on the next commit
237 237 rename rename files; equivalent of copy + remove
238 238 resolve redo merges or set/view the merge status of files
239 239 revert restore files to their checkout state
240 240 root print the root (top) of the current working directory
241 241 status show changed files in the working directory
242 242 summary summarize working directory state
243 243 update update working directory (or switch revisions)
244 244
245 245 Change import/export:
246 246
247 247 archive create an unversioned archive of a repository revision
248 248 bundle create a bundle file
249 249 export dump the header and diffs for one or more changesets
250 250 import import an ordered set of patches
251 251 unbundle apply one or more bundle files
252 252
253 253 Repository maintenance:
254 254
255 255 manifest output the current or given revision of the project manifest
256 256 recover roll back an interrupted transaction
257 257 verify verify the integrity of the repository
258 258
259 259 Help:
260 260
261 261 config show combined config settings from all hgrc files
262 262 help show help for a given topic or a help overview
263 263 version output version and copyright information
264 264
265 265 additional help topics:
266 266
267 267 Mercurial identifiers:
268 268
269 269 filesets Specifying File Sets
270 270 hgignore Syntax for Mercurial Ignore Files
271 271 patterns File Name Patterns
272 272 revisions Specifying Revisions
273 273 urls URL Paths
274 274
275 275 Mercurial output:
276 276
277 277 color Colorizing Outputs
278 278 dates Date Formats
279 279 diffs Diff Formats
280 280 templating Template Usage
281 281
282 282 Mercurial configuration:
283 283
284 284 config Configuration Files
285 285 environment Environment Variables
286 286 extensions Using Additional Features
287 287 flags Command-line flags
288 288 hgweb Configuring hgweb
289 289 merge-tools Merge Tools
290 290 pager Pager Support
291 291
292 292 Concepts:
293 293
294 294 bundlespec Bundle File Formats
295 295 glossary Glossary
296 296 phases Working with Phases
297 297 subrepos Subrepositories
298 298
299 299 Miscellaneous:
300 300
301 301 deprecated Deprecated Features
302 302 internals Technical implementation topics
303 303 scripting Using Mercurial from scripts and automation
304 304
305 305 Test extension help:
306 306 $ hg help extensions --config extensions.rebase= --config extensions.children=
307 307 Using Additional Features
308 308 """""""""""""""""""""""""
309 309
310 310 Mercurial has the ability to add new features through the use of
311 311 extensions. Extensions may add new commands, add options to existing
312 312 commands, change the default behavior of commands, or implement hooks.
313 313
314 314 To enable the "foo" extension, either shipped with Mercurial or in the
315 315 Python search path, create an entry for it in your configuration file,
316 316 like this:
317 317
318 318 [extensions]
319 319 foo =
320 320
321 321 You may also specify the full path to an extension:
322 322
323 323 [extensions]
324 324 myfeature = ~/.hgext/myfeature.py
325 325
326 326 See 'hg help config' for more information on configuration files.
327 327
328 328 Extensions are not loaded by default for a variety of reasons: they can
329 329 increase startup overhead; they may be meant for advanced usage only; they
330 330 may provide potentially dangerous abilities (such as letting you destroy
331 331 or modify history); they might not be ready for prime time; or they may
332 332 alter some usual behaviors of stock Mercurial. It is thus up to the user
333 333 to activate extensions as needed.
334 334
335 335 To explicitly disable an extension enabled in a configuration file of
336 336 broader scope, prepend its path with !:
337 337
338 338 [extensions]
339 339 # disabling extension bar residing in /path/to/extension/bar.py
340 340 bar = !/path/to/extension/bar.py
341 341 # ditto, but no path was supplied for extension baz
342 342 baz = !
343 343
344 344 enabled extensions:
345 345
346 346 children command to display child changesets (DEPRECATED)
347 347 rebase command to move sets of revisions to a different ancestor
348 348
349 349 disabled extensions:
350 350
351 351 acl hooks for controlling repository access
352 352 blackbox log repository events to a blackbox for debugging
353 353 bugzilla hooks for integrating with the Bugzilla bug tracker
354 354 censor erase file content at a given revision
355 355 churn command to display statistics about repository history
356 356 clonebundles advertise pre-generated bundles to seed clones
357 357 closehead close arbitrary heads without checking them out first
358 358 convert import revisions from foreign VCS repositories into
359 359 Mercurial
360 360 eol automatically manage newlines in repository files
361 361 extdiff command to allow external programs to compare revisions
362 362 factotum http authentication with factotum
363 363 githelp try mapping git commands to Mercurial commands
364 364 gpg commands to sign and verify changesets
365 365 hgk browse the repository in a graphical way
366 366 highlight syntax highlighting for hgweb (requires Pygments)
367 367 histedit interactive history editing
368 368 keyword expand keywords in tracked files
369 369 largefiles track large binary files
370 370 mq manage a stack of patches
371 371 notify hooks for sending email push notifications
372 372 patchbomb command to send changesets as (a series of) patch emails
373 373 purge command to delete untracked files from the working
374 374 directory
375 375 relink recreates hardlinks between repository clones
376 376 schemes extend schemes with shortcuts to repository swarms
377 377 share share a common history between several working directories
378 378 shelve save and restore changes to the working directory
379 379 strip strip changesets and their descendants from history
380 380 transplant command to transplant changesets from another branch
381 381 win32mbcs allow the use of MBCS paths with problematic encodings
382 382 zeroconf discover and advertise repositories on the local network
383 383
384 384 #endif
385 385
386 386 Verify that deprecated extensions are included if --verbose:
387 387
388 388 $ hg -v help extensions | grep children
389 389 children command to display child changesets (DEPRECATED)
390 390
391 391 Verify that extension keywords appear in help templates
392 392
393 393 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
394 394
395 395 Test short command list with verbose option
396 396
397 397 $ hg -v help shortlist
398 398 Mercurial Distributed SCM
399 399
400 400 basic commands:
401 401
402 402 add add the specified files on the next commit
403 403 annotate, blame
404 404 show changeset information by line for each file
405 405 clone make a copy of an existing repository
406 406 commit, ci commit the specified files or all outstanding changes
407 407 diff diff repository (or selected files)
408 408 export dump the header and diffs for one or more changesets
409 409 forget forget the specified files on the next commit
410 410 init create a new repository in the given directory
411 411 log, history show revision history of entire repository or files
412 412 merge merge another revision into working directory
413 413 pull pull changes from the specified source
414 414 push push changes to the specified destination
415 415 remove, rm remove the specified files on the next commit
416 416 serve start stand-alone webserver
417 417 status, st show changed files in the working directory
418 418 summary, sum summarize working directory state
419 419 update, up, checkout, co
420 420 update working directory (or switch revisions)
421 421
422 422 global options ([+] can be repeated):
423 423
424 424 -R --repository REPO repository root directory or name of overlay bundle
425 425 file
426 426 --cwd DIR change working directory
427 427 -y --noninteractive do not prompt, automatically pick the first choice for
428 428 all prompts
429 429 -q --quiet suppress output
430 430 -v --verbose enable additional output
431 431 --color TYPE when to colorize (boolean, always, auto, never, or
432 432 debug)
433 433 --config CONFIG [+] set/override config option (use 'section.name=value')
434 434 --debug enable debugging output
435 435 --debugger start debugger
436 436 --encoding ENCODE set the charset encoding (default: ascii)
437 437 --encodingmode MODE set the charset encoding mode (default: strict)
438 438 --traceback always print a traceback on exception
439 439 --time time how long the command takes
440 440 --profile print command execution profile
441 441 --version output version information and exit
442 442 -h --help display help and exit
443 443 --hidden consider hidden changesets
444 444 --pager TYPE when to paginate (boolean, always, auto, or never)
445 445 (default: auto)
446 446
447 447 (use 'hg help' for the full list of commands)
448 448
449 449 $ hg add -h
450 450 hg add [OPTION]... [FILE]...
451 451
452 452 add the specified files on the next commit
453 453
454 454 Schedule files to be version controlled and added to the repository.
455 455
456 456 The files will be added to the repository at the next commit. To undo an
457 457 add before that, see 'hg forget'.
458 458
459 459 If no names are given, add all files to the repository (except files
460 460 matching ".hgignore").
461 461
462 462 Returns 0 if all files are successfully added.
463 463
464 464 options ([+] can be repeated):
465 465
466 466 -I --include PATTERN [+] include names matching the given patterns
467 467 -X --exclude PATTERN [+] exclude names matching the given patterns
468 468 -S --subrepos recurse into subrepositories
469 469 -n --dry-run do not perform actions, just print output
470 470
471 471 (some details hidden, use --verbose to show complete help)
472 472
473 473 Verbose help for add
474 474
475 475 $ hg add -hv
476 476 hg add [OPTION]... [FILE]...
477 477
478 478 add the specified files on the next commit
479 479
480 480 Schedule files to be version controlled and added to the repository.
481 481
482 482 The files will be added to the repository at the next commit. To undo an
483 483 add before that, see 'hg forget'.
484 484
485 485 If no names are given, add all files to the repository (except files
486 486 matching ".hgignore").
487 487
488 488 Examples:
489 489
490 490 - New (unknown) files are added automatically by 'hg add':
491 491
492 492 $ ls
493 493 foo.c
494 494 $ hg status
495 495 ? foo.c
496 496 $ hg add
497 497 adding foo.c
498 498 $ hg status
499 499 A foo.c
500 500
501 501 - Specific files to be added can be specified:
502 502
503 503 $ ls
504 504 bar.c foo.c
505 505 $ hg status
506 506 ? bar.c
507 507 ? foo.c
508 508 $ hg add bar.c
509 509 $ hg status
510 510 A bar.c
511 511 ? foo.c
512 512
513 513 Returns 0 if all files are successfully added.
514 514
515 515 options ([+] can be repeated):
516 516
517 517 -I --include PATTERN [+] include names matching the given patterns
518 518 -X --exclude PATTERN [+] exclude names matching the given patterns
519 519 -S --subrepos recurse into subrepositories
520 520 -n --dry-run do not perform actions, just print output
521 521
522 522 global options ([+] can be repeated):
523 523
524 524 -R --repository REPO repository root directory or name of overlay bundle
525 525 file
526 526 --cwd DIR change working directory
527 527 -y --noninteractive do not prompt, automatically pick the first choice for
528 528 all prompts
529 529 -q --quiet suppress output
530 530 -v --verbose enable additional output
531 531 --color TYPE when to colorize (boolean, always, auto, never, or
532 532 debug)
533 533 --config CONFIG [+] set/override config option (use 'section.name=value')
534 534 --debug enable debugging output
535 535 --debugger start debugger
536 536 --encoding ENCODE set the charset encoding (default: ascii)
537 537 --encodingmode MODE set the charset encoding mode (default: strict)
538 538 --traceback always print a traceback on exception
539 539 --time time how long the command takes
540 540 --profile print command execution profile
541 541 --version output version information and exit
542 542 -h --help display help and exit
543 543 --hidden consider hidden changesets
544 544 --pager TYPE when to paginate (boolean, always, auto, or never)
545 545 (default: auto)
546 546
547 547 Test the textwidth config option
548 548
549 549 $ hg root -h --config ui.textwidth=50
550 550 hg root
551 551
552 552 print the root (top) of the current working
553 553 directory
554 554
555 555 Print the root directory of the current
556 556 repository.
557 557
558 558 Returns 0 on success.
559 559
560 560 (some details hidden, use --verbose to show
561 561 complete help)
562 562
563 563 Test help option with version option
564 564
565 565 $ hg add -h --version
566 566 Mercurial Distributed SCM (version *) (glob)
567 567 (see https://mercurial-scm.org for more information)
568 568
569 569 Copyright (C) 2005-* Matt Mackall and others (glob)
570 570 This is free software; see the source for copying conditions. There is NO
571 571 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
572 572
573 573 $ hg add --skjdfks
574 574 hg add: option --skjdfks not recognized
575 575 hg add [OPTION]... [FILE]...
576 576
577 577 add the specified files on the next commit
578 578
579 579 options ([+] can be repeated):
580 580
581 581 -I --include PATTERN [+] include names matching the given patterns
582 582 -X --exclude PATTERN [+] exclude names matching the given patterns
583 583 -S --subrepos recurse into subrepositories
584 584 -n --dry-run do not perform actions, just print output
585 585
586 586 (use 'hg add -h' to show more help)
587 587 [255]
588 588
589 589 Test ambiguous command help
590 590
591 591 $ hg help ad
592 592 list of commands:
593 593
594 594 add add the specified files on the next commit
595 595 addremove add all new files, delete all missing files
596 596
597 597 (use 'hg help -v ad' to show built-in aliases and global options)
598 598
599 599 Test command without options
600 600
601 601 $ hg help verify
602 602 hg verify
603 603
604 604 verify the integrity of the repository
605 605
606 606 Verify the integrity of the current repository.
607 607
608 608 This will perform an extensive check of the repository's integrity,
609 609 validating the hashes and checksums of each entry in the changelog,
610 610 manifest, and tracked files, as well as the integrity of their crosslinks
611 611 and indices.
612 612
613 613 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
614 614 information about recovery from corruption of the repository.
615 615
616 616 Returns 0 on success, 1 if errors are encountered.
617 617
618 618 options:
619 619
620 620 (some details hidden, use --verbose to show complete help)
621 621
622 622 $ hg help diff
623 623 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
624 624
625 625 diff repository (or selected files)
626 626
627 627 Show differences between revisions for the specified files.
628 628
629 629 Differences between files are shown using the unified diff format.
630 630
631 631 Note:
632 632 'hg diff' may generate unexpected results for merges, as it will
633 633 default to comparing against the working directory's first parent
634 634 changeset if no revisions are specified.
635 635
636 636 When two revision arguments are given, then changes are shown between
637 637 those revisions. If only one revision is specified then that revision is
638 638 compared to the working directory, and, when no revisions are specified,
639 639 the working directory files are compared to its first parent.
640 640
641 641 Alternatively you can specify -c/--change with a revision to see the
642 642 changes in that changeset relative to its first parent.
643 643
644 644 Without the -a/--text option, diff will avoid generating diffs of files it
645 645 detects as binary. With -a, diff will generate a diff anyway, probably
646 646 with undesirable results.
647 647
648 648 Use the -g/--git option to generate diffs in the git extended diff format.
649 649 For more information, read 'hg help diffs'.
650 650
651 651 Returns 0 on success.
652 652
653 653 options ([+] can be repeated):
654 654
655 655 -r --rev REV [+] revision
656 656 -c --change REV change made by revision
657 657 -a --text treat all files as text
658 658 -g --git use git extended diff format
659 659 --binary generate binary diffs in git mode (default)
660 660 --nodates omit dates from diff headers
661 661 --noprefix omit a/ and b/ prefixes from filenames
662 662 -p --show-function show which function each change is in
663 663 --reverse produce a diff that undoes the changes
664 664 -w --ignore-all-space ignore white space when comparing lines
665 665 -b --ignore-space-change ignore changes in the amount of white space
666 666 -B --ignore-blank-lines ignore changes whose lines are all blank
667 667 -Z --ignore-space-at-eol ignore changes in whitespace at EOL
668 668 -U --unified NUM number of lines of context to show
669 669 --stat output diffstat-style summary of changes
670 670 --root DIR produce diffs relative to subdirectory
671 671 -I --include PATTERN [+] include names matching the given patterns
672 672 -X --exclude PATTERN [+] exclude names matching the given patterns
673 673 -S --subrepos recurse into subrepositories
674 674
675 675 (some details hidden, use --verbose to show complete help)
676 676
677 677 $ hg help status
678 678 hg status [OPTION]... [FILE]...
679 679
680 680 aliases: st
681 681
682 682 show changed files in the working directory
683 683
684 684 Show status of files in the repository. If names are given, only files
685 685 that match are shown. Files that are clean or ignored or the source of a
686 686 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
687 687 -C/--copies or -A/--all are given. Unless options described with "show
688 688 only ..." are given, the options -mardu are used.
689 689
690 690 Option -q/--quiet hides untracked (unknown and ignored) files unless
691 691 explicitly requested with -u/--unknown or -i/--ignored.
692 692
693 693 Note:
694 694 'hg status' may appear to disagree with diff if permissions have
695 695 changed or a merge has occurred. The standard diff format does not
696 696 report permission changes and diff only reports changes relative to one
697 697 merge parent.
698 698
699 699 If one revision is given, it is used as the base revision. If two
700 700 revisions are given, the differences between them are shown. The --change
701 701 option can also be used as a shortcut to list the changed files of a
702 702 revision from its first parent.
703 703
704 704 The codes used to show the status of files are:
705 705
706 706 M = modified
707 707 A = added
708 708 R = removed
709 709 C = clean
710 710 ! = missing (deleted by non-hg command, but still tracked)
711 711 ? = not tracked
712 712 I = ignored
713 713 = origin of the previous file (with --copies)
714 714
715 715 Returns 0 on success.
716 716
717 717 options ([+] can be repeated):
718 718
719 719 -A --all show status of all files
720 720 -m --modified show only modified files
721 721 -a --added show only added files
722 722 -r --removed show only removed files
723 723 -d --deleted show only deleted (but tracked) files
724 724 -c --clean show only files without changes
725 725 -u --unknown show only unknown (not tracked) files
726 726 -i --ignored show only ignored files
727 727 -n --no-status hide status prefix
728 728 -C --copies show source of copied files
729 729 -0 --print0 end filenames with NUL, for use with xargs
730 730 --rev REV [+] show difference from revision
731 731 --change REV list the changed files of a revision
732 732 -I --include PATTERN [+] include names matching the given patterns
733 733 -X --exclude PATTERN [+] exclude names matching the given patterns
734 734 -S --subrepos recurse into subrepositories
735 735 -T --template TEMPLATE display with template
736 736
737 737 (some details hidden, use --verbose to show complete help)
738 738
739 739 $ hg -q help status
740 740 hg status [OPTION]... [FILE]...
741 741
742 742 show changed files in the working directory
743 743
744 744 $ hg help foo
745 745 abort: no such help topic: foo
746 746 (try 'hg help --keyword foo')
747 747 [255]
748 748
749 749 $ hg skjdfks
750 750 hg: unknown command 'skjdfks'
751 751 (use 'hg help' for a list of commands)
752 752 [255]
753 753
754 754 Typoed command gives suggestion
755 755 $ hg puls
756 756 hg: unknown command 'puls'
757 757 (did you mean one of pull, push?)
758 758 [255]
759 759
760 760 Not enabled extension gets suggested
761 761
762 762 $ hg rebase
763 763 hg: unknown command 'rebase'
764 764 'rebase' is provided by the following extension:
765 765
766 766 rebase command to move sets of revisions to a different ancestor
767 767
768 768 (use 'hg help extensions' for information on enabling extensions)
769 769 [255]
770 770
771 771 Disabled extension gets suggested
772 772 $ hg --config extensions.rebase=! rebase
773 773 hg: unknown command 'rebase'
774 774 'rebase' is provided by the following extension:
775 775
776 776 rebase command to move sets of revisions to a different ancestor
777 777
778 778 (use 'hg help extensions' for information on enabling extensions)
779 779 [255]
780 780
781 781 Make sure that we don't run afoul of the help system thinking that
782 782 this is a section and erroring out weirdly.
783 783
784 784 $ hg .log
785 785 hg: unknown command '.log'
786 786 (did you mean log?)
787 787 [255]
788 788
789 789 $ hg log.
790 790 hg: unknown command 'log.'
791 791 (did you mean log?)
792 792 [255]
793 793 $ hg pu.lh
794 794 hg: unknown command 'pu.lh'
795 795 (did you mean one of pull, push?)
796 796 [255]
797 797
798 798 $ cat > helpext.py <<EOF
799 799 > import os
800 800 > from mercurial import commands, fancyopts, registrar
801 801 >
802 802 > def func(arg):
803 803 > return '%sfoo' % arg
804 804 > class customopt(fancyopts.customopt):
805 805 > def newstate(self, oldstate, newparam, abort):
806 806 > return '%sbar' % oldstate
807 807 > cmdtable = {}
808 808 > command = registrar.command(cmdtable)
809 809 >
810 810 > @command(b'nohelp',
811 811 > [(b'', b'longdesc', 3, b'x'*67),
812 812 > (b'n', b'', None, b'normal desc'),
813 813 > (b'', b'newline', b'', b'line1\nline2'),
814 814 > (b'', b'default-off', False, b'enable X'),
815 815 > (b'', b'default-on', True, b'enable Y'),
816 816 > (b'', b'callableopt', func, b'adds foo'),
817 817 > (b'', b'customopt', customopt(''), b'adds bar'),
818 818 > (b'', b'customopt-withdefault', customopt('foo'), b'adds bar')],
819 819 > b'hg nohelp',
820 820 > norepo=True)
821 821 > @command(b'debugoptADV', [(b'', b'aopt', None, b'option is (ADVANCED)')])
822 822 > @command(b'debugoptDEP', [(b'', b'dopt', None, b'option is (DEPRECATED)')])
823 823 > @command(b'debugoptEXP', [(b'', b'eopt', None, b'option is (EXPERIMENTAL)')])
824 824 > def nohelp(ui, *args, **kwargs):
825 825 > pass
826 826 >
827 827 > @command(b'hashelp', [], b'hg hashelp', norepo=True)
828 828 > def hashelp(ui, *args, **kwargs):
829 829 > """Extension command's help"""
830 830 >
831 831 > def uisetup(ui):
832 832 > ui.setconfig(b'alias', b'shellalias', b'!echo hi', b'helpext')
833 833 > ui.setconfig(b'alias', b'hgalias', b'summary', b'helpext')
834 834 > ui.setconfig(b'alias', b'hgalias:doc', b'My doc', b'helpext')
835 835 > ui.setconfig(b'alias', b'hgalias:category', b'navigation', b'helpext')
836 836 > ui.setconfig(b'alias', b'hgaliasnodoc', b'summary', b'helpext')
837 837 >
838 838 > EOF
839 839 $ echo '[extensions]' >> $HGRCPATH
840 840 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
841 841
842 842 Test for aliases
843 843
844 844 $ hg help | grep hgalias
845 845 hgalias My doc
846 846
847 847 $ hg help hgalias
848 848 hg hgalias [--remote]
849 849
850 850 alias for: hg summary
851 851
852 852 My doc
853 853
854 854 defined by: helpext
855 855
856 856 options:
857 857
858 858 --remote check for push and pull
859 859
860 860 (some details hidden, use --verbose to show complete help)
861 861 $ hg help hgaliasnodoc
862 862 hg hgaliasnodoc [--remote]
863 863
864 864 alias for: hg summary
865 865
866 866 summarize working directory state
867 867
868 868 This generates a brief summary of the working directory state, including
869 869 parents, branch, commit status, phase and available updates.
870 870
871 871 With the --remote option, this will check the default paths for incoming
872 872 and outgoing changes. This can be time-consuming.
873 873
874 874 Returns 0 on success.
875 875
876 876 defined by: helpext
877 877
878 878 options:
879 879
880 880 --remote check for push and pull
881 881
882 882 (some details hidden, use --verbose to show complete help)
883 883
884 884 $ hg help shellalias
885 885 hg shellalias
886 886
887 887 shell alias for: echo hi
888 888
889 889 (no help text available)
890 890
891 891 defined by: helpext
892 892
893 893 (some details hidden, use --verbose to show complete help)
894 894
895 895 Test command with no help text
896 896
897 897 $ hg help nohelp
898 898 hg nohelp
899 899
900 900 (no help text available)
901 901
902 902 options:
903 903
904 904 --longdesc VALUE
905 905 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
906 906 xxxxxxxxxxxxxxxxxxxxxxx (default: 3)
907 907 -n -- normal desc
908 908 --newline VALUE line1 line2
909 909 --default-off enable X
910 910 --[no-]default-on enable Y (default: on)
911 911 --callableopt VALUE adds foo
912 912 --customopt VALUE adds bar
913 913 --customopt-withdefault VALUE adds bar (default: foo)
914 914
915 915 (some details hidden, use --verbose to show complete help)
916 916
917 917 Test that default list of commands includes extension commands that have help,
918 918 but not those that don't, except in verbose mode, when a keyword is passed, or
919 919 when help about the extension is requested.
920 920
921 921 #if no-extraextensions
922 922
923 923 $ hg help | grep hashelp
924 924 hashelp Extension command's help
925 925 $ hg help | grep nohelp
926 926 [1]
927 927 $ hg help -v | grep nohelp
928 928 nohelp (no help text available)
929 929
930 930 $ hg help -k nohelp
931 931 Commands:
932 932
933 933 nohelp hg nohelp
934 934
935 935 Extension Commands:
936 936
937 937 nohelp (no help text available)
938 938
939 939 $ hg help helpext
940 940 helpext extension - no help text available
941 941
942 942 list of commands:
943 943
944 944 hashelp Extension command's help
945 945 nohelp (no help text available)
946 946
947 947 (use 'hg help -v helpext' to show built-in aliases and global options)
948 948
949 949 #endif
950 950
951 951 Test list of internal help commands
952 952
953 953 $ hg help debug
954 954 debug commands (internal and unsupported):
955 955
956 956 debugancestor
957 957 find the ancestor revision of two revisions in a given index
958 958 debugapplystreamclonebundle
959 959 apply a stream clone bundle file
960 960 debugbuilddag
961 961 builds a repo with a given DAG from scratch in the current
962 962 empty repo
963 963 debugbundle lists the contents of a bundle
964 964 debugcapabilities
965 965 lists the capabilities of a remote peer
966 966 debugcheckstate
967 967 validate the correctness of the current dirstate
968 968 debugcolor show available color, effects or style
969 969 debugcommands
970 970 list all available commands and options
971 971 debugcomplete
972 972 returns the completion list associated with the given command
973 973 debugcreatestreamclonebundle
974 974 create a stream clone bundle file
975 975 debugdag format the changelog or an index DAG as a concise textual
976 976 description
977 977 debugdata dump the contents of a data file revision
978 978 debugdate parse and display a date
979 979 debugdeltachain
980 980 dump information about delta chains in a revlog
981 981 debugdirstate
982 982 show the contents of the current dirstate
983 983 debugdiscovery
984 984 runs the changeset discovery protocol in isolation
985 985 debugdownload
986 986 download a resource using Mercurial logic and config
987 987 debugextensions
988 988 show information about active extensions
989 989 debugfileset parse and apply a fileset specification
990 990 debugformat display format information about the current repository
991 991 debugfsinfo show information detected about current filesystem
992 992 debuggetbundle
993 993 retrieves a bundle from a repo
994 994 debugignore display the combined ignore pattern and information about
995 995 ignored files
996 996 debugindex dump index data for a storage primitive
997 997 debugindexdot
998 998 dump an index DAG as a graphviz dot file
999 999 debugindexstats
1000 1000 show stats related to the changelog index
1001 1001 debuginstall test Mercurial installation
1002 1002 debugknown test whether node ids are known to a repo
1003 1003 debuglocks show or modify state of locks
1004 1004 debugmanifestfulltextcache
1005 1005 show, clear or amend the contents of the manifest fulltext
1006 1006 cache
1007 1007 debugmergestate
1008 1008 print merge state
1009 1009 debugnamecomplete
1010 1010 complete "names" - tags, open branch names, bookmark names
1011 1011 debugobsolete
1012 1012 create arbitrary obsolete marker
1013 1013 debugoptADV (no help text available)
1014 1014 debugoptDEP (no help text available)
1015 1015 debugoptEXP (no help text available)
1016 1016 debugp1copies
1017 1017 dump copy information compared to p1
1018 1018 debugp2copies
1019 1019 dump copy information compared to p2
1020 1020 debugpathcomplete
1021 1021 complete part or all of a tracked path
1022 1022 debugpathcopies
1023 1023 show copies between two revisions
1024 1024 debugpeer establish a connection to a peer repository
1025 1025 debugpickmergetool
1026 1026 examine which merge tool is chosen for specified file
1027 1027 debugpushkey access the pushkey key/value protocol
1028 1028 debugpvec (no help text available)
1029 1029 debugrebuilddirstate
1030 1030 rebuild the dirstate as it would look like for the given
1031 1031 revision
1032 1032 debugrebuildfncache
1033 1033 rebuild the fncache file
1034 1034 debugrename dump rename information
1035 1035 debugrevlog show data and statistics about a revlog
1036 1036 debugrevlogindex
1037 1037 dump the contents of a revlog index
1038 1038 debugrevspec parse and apply a revision specification
1039 1039 debugserve run a server with advanced settings
1040 1040 debugsetparents
1041 1041 manually set the parents of the current working directory
1042 1042 debugssl test a secure connection to a server
1043 1043 debugsub (no help text available)
1044 1044 debugsuccessorssets
1045 1045 show set of successors for revision
1046 1046 debugtemplate
1047 1047 parse and apply a template
1048 1048 debuguigetpass
1049 1049 show prompt to type password
1050 1050 debuguiprompt
1051 1051 show plain prompt
1052 1052 debugupdatecaches
1053 1053 warm all known caches in the repository
1054 1054 debugupgraderepo
1055 1055 upgrade a repository to use different features
1056 1056 debugwalk show how files match on given patterns
1057 1057 debugwhyunstable
1058 1058 explain instabilities of a changeset
1059 1059 debugwireargs
1060 1060 (no help text available)
1061 1061 debugwireproto
1062 1062 send wire protocol commands to a server
1063 1063
1064 1064 (use 'hg help -v debug' to show built-in aliases and global options)
1065 1065
1066 1066 internals topic renders index of available sub-topics
1067 1067
1068 1068 $ hg help internals
1069 1069 Technical implementation topics
1070 1070 """""""""""""""""""""""""""""""
1071 1071
1072 1072 To access a subtopic, use "hg help internals.{subtopic-name}"
1073 1073
1074 1074 bundle2 Bundle2
1075 1075 bundles Bundles
1076 1076 cbor CBOR
1077 1077 censor Censor
1078 1078 changegroups Changegroups
1079 1079 config Config Registrar
1080 1080 extensions Extension API
1081 1081 requirements Repository Requirements
1082 1082 revlogs Revision Logs
1083 1083 wireprotocol Wire Protocol
1084 1084 wireprotocolrpc
1085 1085 Wire Protocol RPC
1086 1086 wireprotocolv2
1087 1087 Wire Protocol Version 2
1088 1088
1089 1089 sub-topics can be accessed
1090 1090
1091 1091 $ hg help internals.changegroups
1092 1092 Changegroups
1093 1093 """"""""""""
1094 1094
1095 1095 Changegroups are representations of repository revlog data, specifically
1096 1096 the changelog data, root/flat manifest data, treemanifest data, and
1097 1097 filelogs.
1098 1098
1099 1099 There are 3 versions of changegroups: "1", "2", and "3". From a high-
1100 1100 level, versions "1" and "2" are almost exactly the same, with the only
1101 1101 difference being an additional item in the *delta header*. Version "3"
1102 1102 adds support for storage flags in the *delta header* and optionally
1103 1103 exchanging treemanifests (enabled by setting an option on the
1104 1104 "changegroup" part in the bundle2).
1105 1105
1106 1106 Changegroups when not exchanging treemanifests consist of 3 logical
1107 1107 segments:
1108 1108
1109 1109 +---------------------------------+
1110 1110 | | | |
1111 1111 | changeset | manifest | filelogs |
1112 1112 | | | |
1113 1113 | | | |
1114 1114 +---------------------------------+
1115 1115
1116 1116 When exchanging treemanifests, there are 4 logical segments:
1117 1117
1118 1118 +-------------------------------------------------+
1119 1119 | | | | |
1120 1120 | changeset | root | treemanifests | filelogs |
1121 1121 | | manifest | | |
1122 1122 | | | | |
1123 1123 +-------------------------------------------------+
1124 1124
1125 1125 The principle building block of each segment is a *chunk*. A *chunk* is a
1126 1126 framed piece of data:
1127 1127
1128 1128 +---------------------------------------+
1129 1129 | | |
1130 1130 | length | data |
1131 1131 | (4 bytes) | (<length - 4> bytes) |
1132 1132 | | |
1133 1133 +---------------------------------------+
1134 1134
1135 1135 All integers are big-endian signed integers. Each chunk starts with a
1136 1136 32-bit integer indicating the length of the entire chunk (including the
1137 1137 length field itself).
1138 1138
1139 1139 There is a special case chunk that has a value of 0 for the length
1140 1140 ("0x00000000"). We call this an *empty chunk*.
1141 1141
1142 1142 Delta Groups
1143 1143 ============
1144 1144
1145 1145 A *delta group* expresses the content of a revlog as a series of deltas,
1146 1146 or patches against previous revisions.
1147 1147
1148 1148 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
1149 1149 to signal the end of the delta group:
1150 1150
1151 1151 +------------------------------------------------------------------------+
1152 1152 | | | | | |
1153 1153 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
1154 1154 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
1155 1155 | | | | | |
1156 1156 +------------------------------------------------------------------------+
1157 1157
1158 1158 Each *chunk*'s data consists of the following:
1159 1159
1160 1160 +---------------------------------------+
1161 1161 | | |
1162 1162 | delta header | delta data |
1163 1163 | (various by version) | (various) |
1164 1164 | | |
1165 1165 +---------------------------------------+
1166 1166
1167 1167 The *delta data* is a series of *delta*s that describe a diff from an
1168 1168 existing entry (either that the recipient already has, or previously
1169 1169 specified in the bundle/changegroup).
1170 1170
1171 1171 The *delta header* is different between versions "1", "2", and "3" of the
1172 1172 changegroup format.
1173 1173
1174 1174 Version 1 (headerlen=80):
1175 1175
1176 1176 +------------------------------------------------------+
1177 1177 | | | | |
1178 1178 | node | p1 node | p2 node | link node |
1179 1179 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1180 1180 | | | | |
1181 1181 +------------------------------------------------------+
1182 1182
1183 1183 Version 2 (headerlen=100):
1184 1184
1185 1185 +------------------------------------------------------------------+
1186 1186 | | | | | |
1187 1187 | node | p1 node | p2 node | base node | link node |
1188 1188 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1189 1189 | | | | | |
1190 1190 +------------------------------------------------------------------+
1191 1191
1192 1192 Version 3 (headerlen=102):
1193 1193
1194 1194 +------------------------------------------------------------------------------+
1195 1195 | | | | | | |
1196 1196 | node | p1 node | p2 node | base node | link node | flags |
1197 1197 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1198 1198 | | | | | | |
1199 1199 +------------------------------------------------------------------------------+
1200 1200
1201 1201 The *delta data* consists of "chunklen - 4 - headerlen" bytes, which
1202 1202 contain a series of *delta*s, densely packed (no separators). These deltas
1203 1203 describe a diff from an existing entry (either that the recipient already
1204 1204 has, or previously specified in the bundle/changegroup). The format is
1205 1205 described more fully in "hg help internals.bdiff", but briefly:
1206 1206
1207 1207 +---------------------------------------------------------------+
1208 1208 | | | | |
1209 1209 | start offset | end offset | new length | content |
1210 1210 | (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
1211 1211 | | | | |
1212 1212 +---------------------------------------------------------------+
1213 1213
1214 1214 Please note that the length field in the delta data does *not* include
1215 1215 itself.
1216 1216
1217 1217 In version 1, the delta is always applied against the previous node from
1218 1218 the changegroup or the first parent if this is the first entry in the
1219 1219 changegroup.
1220 1220
1221 1221 In version 2 and up, the delta base node is encoded in the entry in the
1222 1222 changegroup. This allows the delta to be expressed against any parent,
1223 1223 which can result in smaller deltas and more efficient encoding of data.
1224 1224
1225 1225 The *flags* field holds bitwise flags affecting the processing of revision
1226 1226 data. The following flags are defined:
1227 1227
1228 1228 32768
1229 1229 Censored revision. The revision's fulltext has been replaced by censor
1230 1230 metadata. May only occur on file revisions.
1231 1231
1232 1232 16384
1233 1233 Ellipsis revision. Revision hash does not match data (likely due to
1234 1234 rewritten parents).
1235 1235
1236 1236 8192
1237 1237 Externally stored. The revision fulltext contains "key:value" "\n"
1238 1238 delimited metadata defining an object stored elsewhere. Used by the LFS
1239 1239 extension.
1240 1240
1241 1241 For historical reasons, the integer values are identical to revlog version
1242 1242 1 per-revision storage flags and correspond to bits being set in this
1243 1243 2-byte field. Bits were allocated starting from the most-significant bit,
1244 1244 hence the reverse ordering and allocation of these flags.
1245 1245
1246 1246 Changeset Segment
1247 1247 =================
1248 1248
1249 1249 The *changeset segment* consists of a single *delta group* holding
1250 1250 changelog data. The *empty chunk* at the end of the *delta group* denotes
1251 1251 the boundary to the *manifest segment*.
1252 1252
1253 1253 Manifest Segment
1254 1254 ================
1255 1255
1256 1256 The *manifest segment* consists of a single *delta group* holding manifest
1257 1257 data. If treemanifests are in use, it contains only the manifest for the
1258 1258 root directory of the repository. Otherwise, it contains the entire
1259 1259 manifest data. The *empty chunk* at the end of the *delta group* denotes
1260 1260 the boundary to the next segment (either the *treemanifests segment* or
1261 1261 the *filelogs segment*, depending on version and the request options).
1262 1262
1263 1263 Treemanifests Segment
1264 1264 ---------------------
1265 1265
1266 1266 The *treemanifests segment* only exists in changegroup version "3", and
1267 1267 only if the 'treemanifest' param is part of the bundle2 changegroup part
1268 1268 (it is not possible to use changegroup version 3 outside of bundle2).
1269 1269 Aside from the filenames in the *treemanifests segment* containing a
1270 1270 trailing "/" character, it behaves identically to the *filelogs segment*
1271 1271 (see below). The final sub-segment is followed by an *empty chunk*
1272 1272 (logically, a sub-segment with filename size 0). This denotes the boundary
1273 1273 to the *filelogs segment*.
1274 1274
1275 1275 Filelogs Segment
1276 1276 ================
1277 1277
1278 1278 The *filelogs segment* consists of multiple sub-segments, each
1279 1279 corresponding to an individual file whose data is being described:
1280 1280
1281 1281 +--------------------------------------------------+
1282 1282 | | | | | |
1283 1283 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
1284 1284 | | | | | (4 bytes) |
1285 1285 | | | | | |
1286 1286 +--------------------------------------------------+
1287 1287
1288 1288 The final filelog sub-segment is followed by an *empty chunk* (logically,
1289 1289 a sub-segment with filename size 0). This denotes the end of the segment
1290 1290 and of the overall changegroup.
1291 1291
1292 1292 Each filelog sub-segment consists of the following:
1293 1293
1294 1294 +------------------------------------------------------+
1295 1295 | | | |
1296 1296 | filename length | filename | delta group |
1297 1297 | (4 bytes) | (<length - 4> bytes) | (various) |
1298 1298 | | | |
1299 1299 +------------------------------------------------------+
1300 1300
1301 1301 That is, a *chunk* consisting of the filename (not terminated or padded)
1302 1302 followed by N chunks constituting the *delta group* for this file. The
1303 1303 *empty chunk* at the end of each *delta group* denotes the boundary to the
1304 1304 next filelog sub-segment.
1305 1305
1306 1306 test advanced, deprecated and experimental options are hidden in command help
1307 1307 $ hg help debugoptADV
1308 1308 hg debugoptADV
1309 1309
1310 1310 (no help text available)
1311 1311
1312 1312 options:
1313 1313
1314 1314 (some details hidden, use --verbose to show complete help)
1315 1315 $ hg help debugoptDEP
1316 1316 hg debugoptDEP
1317 1317
1318 1318 (no help text available)
1319 1319
1320 1320 options:
1321 1321
1322 1322 (some details hidden, use --verbose to show complete help)
1323 1323
1324 1324 $ hg help debugoptEXP
1325 1325 hg debugoptEXP
1326 1326
1327 1327 (no help text available)
1328 1328
1329 1329 options:
1330 1330
1331 1331 (some details hidden, use --verbose to show complete help)
1332 1332
1333 1333 test advanced, deprecated and experimental options are shown with -v
1334 1334 $ hg help -v debugoptADV | grep aopt
1335 1335 --aopt option is (ADVANCED)
1336 1336 $ hg help -v debugoptDEP | grep dopt
1337 1337 --dopt option is (DEPRECATED)
1338 1338 $ hg help -v debugoptEXP | grep eopt
1339 1339 --eopt option is (EXPERIMENTAL)
1340 1340
1341 1341 #if gettext
1342 1342 test deprecated option is hidden with translation with untranslated description
1343 1343 (use many globy for not failing on changed transaction)
1344 1344 $ LANGUAGE=sv hg help debugoptDEP
1345 1345 hg debugoptDEP
1346 1346
1347 1347 (*) (glob)
1348 1348
1349 1349 options:
1350 1350
1351 1351 (some details hidden, use --verbose to show complete help)
1352 1352 #endif
1353 1353
1354 1354 Test commands that collide with topics (issue4240)
1355 1355
1356 1356 $ hg config -hq
1357 1357 hg config [-u] [NAME]...
1358 1358
1359 1359 show combined config settings from all hgrc files
1360 1360 $ hg showconfig -hq
1361 1361 hg config [-u] [NAME]...
1362 1362
1363 1363 show combined config settings from all hgrc files
1364 1364
1365 1365 Test a help topic
1366 1366
1367 1367 $ hg help dates
1368 1368 Date Formats
1369 1369 """"""""""""
1370 1370
1371 1371 Some commands allow the user to specify a date, e.g.:
1372 1372
1373 1373 - backout, commit, import, tag: Specify the commit date.
1374 1374 - log, revert, update: Select revision(s) by date.
1375 1375
1376 1376 Many date formats are valid. Here are some examples:
1377 1377
1378 1378 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1379 1379 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1380 1380 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1381 1381 - "Dec 6" (midnight)
1382 1382 - "13:18" (today assumed)
1383 1383 - "3:39" (3:39AM assumed)
1384 1384 - "3:39pm" (15:39)
1385 1385 - "2006-12-06 13:18:29" (ISO 8601 format)
1386 1386 - "2006-12-6 13:18"
1387 1387 - "2006-12-6"
1388 1388 - "12-6"
1389 1389 - "12/6"
1390 1390 - "12/6/6" (Dec 6 2006)
1391 1391 - "today" (midnight)
1392 1392 - "yesterday" (midnight)
1393 1393 - "now" - right now
1394 1394
1395 1395 Lastly, there is Mercurial's internal format:
1396 1396
1397 1397 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1398 1398
1399 1399 This is the internal representation format for dates. The first number is
1400 1400 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1401 1401 is the offset of the local timezone, in seconds west of UTC (negative if
1402 1402 the timezone is east of UTC).
1403 1403
1404 1404 The log command also accepts date ranges:
1405 1405
1406 1406 - "<DATE" - at or before a given date/time
1407 1407 - ">DATE" - on or after a given date/time
1408 1408 - "DATE to DATE" - a date range, inclusive
1409 1409 - "-DAYS" - within a given number of days of today
1410 1410
1411 1411 Test repeated config section name
1412 1412
1413 1413 $ hg help config.host
1414 1414 "http_proxy.host"
1415 1415 Host name and (optional) port of the proxy server, for example
1416 1416 "myproxy:8000".
1417 1417
1418 1418 "smtp.host"
1419 1419 Host name of mail server, e.g. "mail.example.com".
1420 1420
1421 1421
1422 1422 Test section name with dot
1423 1423
1424 1424 $ hg help config.ui.username
1425 1425 "ui.username"
1426 1426 The committer of a changeset created when running "commit". Typically
1427 1427 a person's name and email address, e.g. "Fred Widget
1428 1428 <fred@example.com>". Environment variables in the username are
1429 1429 expanded.
1430 1430
1431 1431 (default: "$EMAIL" or "username@hostname". If the username in hgrc is
1432 1432 empty, e.g. if the system admin set "username =" in the system hgrc,
1433 1433 it has to be specified manually or in a different hgrc file)
1434 1434
1435 1435
1436 1436 $ hg help config.annotate.git
1437 1437 abort: help section not found: config.annotate.git
1438 1438 [255]
1439 1439
1440 1440 $ hg help config.update.check
1441 1441 "commands.update.check"
1442 1442 Determines what level of checking 'hg update' will perform before
1443 1443 moving to a destination revision. Valid values are "abort", "none",
1444 1444 "linear", and "noconflict". "abort" always fails if the working
1445 1445 directory has uncommitted changes. "none" performs no checking, and
1446 1446 may result in a merge with uncommitted changes. "linear" allows any
1447 1447 update as long as it follows a straight line in the revision history,
1448 1448 and may trigger a merge with uncommitted changes. "noconflict" will
1449 1449 allow any update which would not trigger a merge with uncommitted
1450 1450 changes, if any are present. (default: "linear")
1451 1451
1452 1452
1453 1453 $ hg help config.commands.update.check
1454 1454 "commands.update.check"
1455 1455 Determines what level of checking 'hg update' will perform before
1456 1456 moving to a destination revision. Valid values are "abort", "none",
1457 1457 "linear", and "noconflict". "abort" always fails if the working
1458 1458 directory has uncommitted changes. "none" performs no checking, and
1459 1459 may result in a merge with uncommitted changes. "linear" allows any
1460 1460 update as long as it follows a straight line in the revision history,
1461 1461 and may trigger a merge with uncommitted changes. "noconflict" will
1462 1462 allow any update which would not trigger a merge with uncommitted
1463 1463 changes, if any are present. (default: "linear")
1464 1464
1465 1465
1466 1466 $ hg help config.ommands.update.check
1467 1467 abort: help section not found: config.ommands.update.check
1468 1468 [255]
1469 1469
1470 1470 Unrelated trailing paragraphs shouldn't be included
1471 1471
1472 1472 $ hg help config.extramsg | grep '^$'
1473 1473
1474 1474
1475 1475 Test capitalized section name
1476 1476
1477 1477 $ hg help scripting.HGPLAIN > /dev/null
1478 1478
1479 1479 Help subsection:
1480 1480
1481 1481 $ hg help config.charsets |grep "Email example:" > /dev/null
1482 1482 [1]
1483 1483
1484 1484 Show nested definitions
1485 1485 ("profiling.type"[break]"ls"[break]"stat"[break])
1486 1486
1487 1487 $ hg help config.type | egrep '^$'|wc -l
1488 1488 \s*3 (re)
1489 1489
1490 1490 $ hg help config.profiling.type.ls
1491 1491 "profiling.type.ls"
1492 1492 Use Python's built-in instrumenting profiler. This profiler works on
1493 1493 all platforms, but each line number it reports is the first line of
1494 1494 a function. This restriction makes it difficult to identify the
1495 1495 expensive parts of a non-trivial function.
1496 1496
1497 1497
1498 1498 Separate sections from subsections
1499 1499
1500 1500 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1501 1501 "format"
1502 1502 --------
1503 1503
1504 1504 "usegeneraldelta"
1505 1505
1506 1506 "dotencode"
1507 1507
1508 1508 "usefncache"
1509 1509
1510 1510 "usestore"
1511 1511
1512 1512 "sparse-revlog"
1513 1513
1514 1514 "revlog-compression"
1515 1515
1516 "bookmarks-in-store"
1517
1516 1518 "profiling"
1517 1519 -----------
1518 1520
1519 1521 "format"
1520 1522
1521 1523 "progress"
1522 1524 ----------
1523 1525
1524 1526 "format"
1525 1527
1526 1528
1527 1529 Last item in help config.*:
1528 1530
1529 1531 $ hg help config.`hg help config|grep '^ "'| \
1530 1532 > tail -1|sed 's![ "]*!!g'`| \
1531 1533 > grep 'hg help -c config' > /dev/null
1532 1534 [1]
1533 1535
1534 1536 note to use help -c for general hg help config:
1535 1537
1536 1538 $ hg help config |grep 'hg help -c config' > /dev/null
1537 1539
1538 1540 Test templating help
1539 1541
1540 1542 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1541 1543 desc String. The text of the changeset description.
1542 1544 diffstat String. Statistics of changes with the following format:
1543 1545 firstline Any text. Returns the first line of text.
1544 1546 nonempty Any text. Returns '(none)' if the string is empty.
1545 1547
1546 1548 Test deprecated items
1547 1549
1548 1550 $ hg help -v templating | grep currentbookmark
1549 1551 currentbookmark
1550 1552 $ hg help templating | (grep currentbookmark || true)
1551 1553
1552 1554 Test help hooks
1553 1555
1554 1556 $ cat > helphook1.py <<EOF
1555 1557 > from mercurial import help
1556 1558 >
1557 1559 > def rewrite(ui, topic, doc):
1558 1560 > return doc + b'\nhelphook1\n'
1559 1561 >
1560 1562 > def extsetup(ui):
1561 1563 > help.addtopichook(b'revisions', rewrite)
1562 1564 > EOF
1563 1565 $ cat > helphook2.py <<EOF
1564 1566 > from mercurial import help
1565 1567 >
1566 1568 > def rewrite(ui, topic, doc):
1567 1569 > return doc + b'\nhelphook2\n'
1568 1570 >
1569 1571 > def extsetup(ui):
1570 1572 > help.addtopichook(b'revisions', rewrite)
1571 1573 > EOF
1572 1574 $ echo '[extensions]' >> $HGRCPATH
1573 1575 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1574 1576 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1575 1577 $ hg help revsets | grep helphook
1576 1578 helphook1
1577 1579 helphook2
1578 1580
1579 1581 help -c should only show debug --debug
1580 1582
1581 1583 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1582 1584 [1]
1583 1585
1584 1586 help -c should only show deprecated for -v
1585 1587
1586 1588 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1587 1589 [1]
1588 1590
1589 1591 Test -s / --system
1590 1592
1591 1593 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1592 1594 > wc -l | sed -e 's/ //g'
1593 1595 0
1594 1596 $ hg help config.files --system unix | grep 'USER' | \
1595 1597 > wc -l | sed -e 's/ //g'
1596 1598 0
1597 1599
1598 1600 Test -e / -c / -k combinations
1599 1601
1600 1602 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1601 1603 Commands:
1602 1604 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1603 1605 Extensions:
1604 1606 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1605 1607 Topics:
1606 1608 Commands:
1607 1609 Extensions:
1608 1610 Extension Commands:
1609 1611 $ hg help -c schemes
1610 1612 abort: no such help topic: schemes
1611 1613 (try 'hg help --keyword schemes')
1612 1614 [255]
1613 1615 $ hg help -e schemes |head -1
1614 1616 schemes extension - extend schemes with shortcuts to repository swarms
1615 1617 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1616 1618 Commands:
1617 1619 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1618 1620 Extensions:
1619 1621 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1620 1622 Extensions:
1621 1623 Commands:
1622 1624 $ hg help -c commit > /dev/null
1623 1625 $ hg help -e -c commit > /dev/null
1624 1626 $ hg help -e commit
1625 1627 abort: no such help topic: commit
1626 1628 (try 'hg help --keyword commit')
1627 1629 [255]
1628 1630
1629 1631 Test keyword search help
1630 1632
1631 1633 $ cat > prefixedname.py <<EOF
1632 1634 > '''matched against word "clone"
1633 1635 > '''
1634 1636 > EOF
1635 1637 $ echo '[extensions]' >> $HGRCPATH
1636 1638 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1637 1639 $ hg help -k clone
1638 1640 Topics:
1639 1641
1640 1642 config Configuration Files
1641 1643 extensions Using Additional Features
1642 1644 glossary Glossary
1643 1645 phases Working with Phases
1644 1646 subrepos Subrepositories
1645 1647 urls URL Paths
1646 1648
1647 1649 Commands:
1648 1650
1649 1651 bookmarks create a new bookmark or list existing bookmarks
1650 1652 clone make a copy of an existing repository
1651 1653 paths show aliases for remote repositories
1652 1654 pull pull changes from the specified source
1653 1655 update update working directory (or switch revisions)
1654 1656
1655 1657 Extensions:
1656 1658
1657 1659 clonebundles advertise pre-generated bundles to seed clones
1658 1660 narrow create clones which fetch history data for subset of files
1659 1661 (EXPERIMENTAL)
1660 1662 prefixedname matched against word "clone"
1661 1663 relink recreates hardlinks between repository clones
1662 1664
1663 1665 Extension Commands:
1664 1666
1665 1667 qclone clone main and patch repository at same time
1666 1668
1667 1669 Test unfound topic
1668 1670
1669 1671 $ hg help nonexistingtopicthatwillneverexisteverever
1670 1672 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1671 1673 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1672 1674 [255]
1673 1675
1674 1676 Test unfound keyword
1675 1677
1676 1678 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1677 1679 abort: no matches
1678 1680 (try 'hg help' for a list of topics)
1679 1681 [255]
1680 1682
1681 1683 Test omit indicating for help
1682 1684
1683 1685 $ cat > addverboseitems.py <<EOF
1684 1686 > r'''extension to test omit indicating.
1685 1687 >
1686 1688 > This paragraph is never omitted (for extension)
1687 1689 >
1688 1690 > .. container:: verbose
1689 1691 >
1690 1692 > This paragraph is omitted,
1691 1693 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1692 1694 >
1693 1695 > This paragraph is never omitted, too (for extension)
1694 1696 > '''
1695 1697 > from __future__ import absolute_import
1696 1698 > from mercurial import commands, help
1697 1699 > testtopic = br"""This paragraph is never omitted (for topic).
1698 1700 >
1699 1701 > .. container:: verbose
1700 1702 >
1701 1703 > This paragraph is omitted,
1702 1704 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1703 1705 >
1704 1706 > This paragraph is never omitted, too (for topic)
1705 1707 > """
1706 1708 > def extsetup(ui):
1707 1709 > help.helptable.append(([b"topic-containing-verbose"],
1708 1710 > b"This is the topic to test omit indicating.",
1709 1711 > lambda ui: testtopic))
1710 1712 > EOF
1711 1713 $ echo '[extensions]' >> $HGRCPATH
1712 1714 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1713 1715 $ hg help addverboseitems
1714 1716 addverboseitems extension - extension to test omit indicating.
1715 1717
1716 1718 This paragraph is never omitted (for extension)
1717 1719
1718 1720 This paragraph is never omitted, too (for extension)
1719 1721
1720 1722 (some details hidden, use --verbose to show complete help)
1721 1723
1722 1724 no commands defined
1723 1725 $ hg help -v addverboseitems
1724 1726 addverboseitems extension - extension to test omit indicating.
1725 1727
1726 1728 This paragraph is never omitted (for extension)
1727 1729
1728 1730 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1729 1731 extension)
1730 1732
1731 1733 This paragraph is never omitted, too (for extension)
1732 1734
1733 1735 no commands defined
1734 1736 $ hg help topic-containing-verbose
1735 1737 This is the topic to test omit indicating.
1736 1738 """"""""""""""""""""""""""""""""""""""""""
1737 1739
1738 1740 This paragraph is never omitted (for topic).
1739 1741
1740 1742 This paragraph is never omitted, too (for topic)
1741 1743
1742 1744 (some details hidden, use --verbose to show complete help)
1743 1745 $ hg help -v topic-containing-verbose
1744 1746 This is the topic to test omit indicating.
1745 1747 """"""""""""""""""""""""""""""""""""""""""
1746 1748
1747 1749 This paragraph is never omitted (for topic).
1748 1750
1749 1751 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1750 1752 topic)
1751 1753
1752 1754 This paragraph is never omitted, too (for topic)
1753 1755
1754 1756 Test section lookup
1755 1757
1756 1758 $ hg help revset.merge
1757 1759 "merge()"
1758 1760 Changeset is a merge changeset.
1759 1761
1760 1762 $ hg help glossary.dag
1761 1763 DAG
1762 1764 The repository of changesets of a distributed version control system
1763 1765 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1764 1766 of nodes and edges, where nodes correspond to changesets and edges
1765 1767 imply a parent -> child relation. This graph can be visualized by
1766 1768 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1767 1769 limited by the requirement for children to have at most two parents.
1768 1770
1769 1771
1770 1772 $ hg help hgrc.paths
1771 1773 "paths"
1772 1774 -------
1773 1775
1774 1776 Assigns symbolic names and behavior to repositories.
1775 1777
1776 1778 Options are symbolic names defining the URL or directory that is the
1777 1779 location of the repository. Example:
1778 1780
1779 1781 [paths]
1780 1782 my_server = https://example.com/my_repo
1781 1783 local_path = /home/me/repo
1782 1784
1783 1785 These symbolic names can be used from the command line. To pull from
1784 1786 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1785 1787 local_path'.
1786 1788
1787 1789 Options containing colons (":") denote sub-options that can influence
1788 1790 behavior for that specific path. Example:
1789 1791
1790 1792 [paths]
1791 1793 my_server = https://example.com/my_path
1792 1794 my_server:pushurl = ssh://example.com/my_path
1793 1795
1794 1796 The following sub-options can be defined:
1795 1797
1796 1798 "pushurl"
1797 1799 The URL to use for push operations. If not defined, the location
1798 1800 defined by the path's main entry is used.
1799 1801
1800 1802 "pushrev"
1801 1803 A revset defining which revisions to push by default.
1802 1804
1803 1805 When 'hg push' is executed without a "-r" argument, the revset defined
1804 1806 by this sub-option is evaluated to determine what to push.
1805 1807
1806 1808 For example, a value of "." will push the working directory's revision
1807 1809 by default.
1808 1810
1809 1811 Revsets specifying bookmarks will not result in the bookmark being
1810 1812 pushed.
1811 1813
1812 1814 The following special named paths exist:
1813 1815
1814 1816 "default"
1815 1817 The URL or directory to use when no source or remote is specified.
1816 1818
1817 1819 'hg clone' will automatically define this path to the location the
1818 1820 repository was cloned from.
1819 1821
1820 1822 "default-push"
1821 1823 (deprecated) The URL or directory for the default 'hg push' location.
1822 1824 "default:pushurl" should be used instead.
1823 1825
1824 1826 $ hg help glossary.mcguffin
1825 1827 abort: help section not found: glossary.mcguffin
1826 1828 [255]
1827 1829
1828 1830 $ hg help glossary.mc.guffin
1829 1831 abort: help section not found: glossary.mc.guffin
1830 1832 [255]
1831 1833
1832 1834 $ hg help template.files
1833 1835 files List of strings. All files modified, added, or removed by
1834 1836 this changeset.
1835 1837 files(pattern)
1836 1838 All files of the current changeset matching the pattern. See
1837 1839 'hg help patterns'.
1838 1840
1839 1841 Test section lookup by translated message
1840 1842
1841 1843 str.lower() instead of encoding.lower(str) on translated message might
1842 1844 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1843 1845 as the second or later byte of multi-byte character.
1844 1846
1845 1847 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1846 1848 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1847 1849 replacement makes message meaningless.
1848 1850
1849 1851 This tests that section lookup by translated string isn't broken by
1850 1852 such str.lower().
1851 1853
1852 1854 $ "$PYTHON" <<EOF
1853 1855 > def escape(s):
1854 1856 > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
1855 1857 > # translation of "record" in ja_JP.cp932
1856 1858 > upper = b"\x8bL\x98^"
1857 1859 > # str.lower()-ed section name should be treated as different one
1858 1860 > lower = b"\x8bl\x98^"
1859 1861 > with open('ambiguous.py', 'wb') as fp:
1860 1862 > fp.write(b"""# ambiguous section names in ja_JP.cp932
1861 1863 > u'''summary of extension
1862 1864 >
1863 1865 > %s
1864 1866 > ----
1865 1867 >
1866 1868 > Upper name should show only this message
1867 1869 >
1868 1870 > %s
1869 1871 > ----
1870 1872 >
1871 1873 > Lower name should show only this message
1872 1874 >
1873 1875 > subsequent section
1874 1876 > ------------------
1875 1877 >
1876 1878 > This should be hidden at 'hg help ambiguous' with section name.
1877 1879 > '''
1878 1880 > """ % (escape(upper), escape(lower)))
1879 1881 > EOF
1880 1882
1881 1883 $ cat >> $HGRCPATH <<EOF
1882 1884 > [extensions]
1883 1885 > ambiguous = ./ambiguous.py
1884 1886 > EOF
1885 1887
1886 1888 $ "$PYTHON" <<EOF | sh
1887 1889 > from mercurial import pycompat
1888 1890 > upper = b"\x8bL\x98^"
1889 1891 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % upper)
1890 1892 > EOF
1891 1893 \x8bL\x98^ (esc)
1892 1894 ----
1893 1895
1894 1896 Upper name should show only this message
1895 1897
1896 1898
1897 1899 $ "$PYTHON" <<EOF | sh
1898 1900 > from mercurial import pycompat
1899 1901 > lower = b"\x8bl\x98^"
1900 1902 > pycompat.stdout.write(b"hg --encoding cp932 help -e ambiguous.%s\n" % lower)
1901 1903 > EOF
1902 1904 \x8bl\x98^ (esc)
1903 1905 ----
1904 1906
1905 1907 Lower name should show only this message
1906 1908
1907 1909
1908 1910 $ cat >> $HGRCPATH <<EOF
1909 1911 > [extensions]
1910 1912 > ambiguous = !
1911 1913 > EOF
1912 1914
1913 1915 Show help content of disabled extensions
1914 1916
1915 1917 $ cat >> $HGRCPATH <<EOF
1916 1918 > [extensions]
1917 1919 > ambiguous = !./ambiguous.py
1918 1920 > EOF
1919 1921 $ hg help -e ambiguous
1920 1922 ambiguous extension - (no help text available)
1921 1923
1922 1924 (use 'hg help extensions' for information on enabling extensions)
1923 1925
1924 1926 Test dynamic list of merge tools only shows up once
1925 1927 $ hg help merge-tools
1926 1928 Merge Tools
1927 1929 """""""""""
1928 1930
1929 1931 To merge files Mercurial uses merge tools.
1930 1932
1931 1933 A merge tool combines two different versions of a file into a merged file.
1932 1934 Merge tools are given the two files and the greatest common ancestor of
1933 1935 the two file versions, so they can determine the changes made on both
1934 1936 branches.
1935 1937
1936 1938 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1937 1939 backout' and in several extensions.
1938 1940
1939 1941 Usually, the merge tool tries to automatically reconcile the files by
1940 1942 combining all non-overlapping changes that occurred separately in the two
1941 1943 different evolutions of the same initial base file. Furthermore, some
1942 1944 interactive merge programs make it easier to manually resolve conflicting
1943 1945 merges, either in a graphical way, or by inserting some conflict markers.
1944 1946 Mercurial does not include any interactive merge programs but relies on
1945 1947 external tools for that.
1946 1948
1947 1949 Available merge tools
1948 1950 =====================
1949 1951
1950 1952 External merge tools and their properties are configured in the merge-
1951 1953 tools configuration section - see hgrc(5) - but they can often just be
1952 1954 named by their executable.
1953 1955
1954 1956 A merge tool is generally usable if its executable can be found on the
1955 1957 system and if it can handle the merge. The executable is found if it is an
1956 1958 absolute or relative executable path or the name of an application in the
1957 1959 executable search path. The tool is assumed to be able to handle the merge
1958 1960 if it can handle symlinks if the file is a symlink, if it can handle
1959 1961 binary files if the file is binary, and if a GUI is available if the tool
1960 1962 requires a GUI.
1961 1963
1962 1964 There are some internal merge tools which can be used. The internal merge
1963 1965 tools are:
1964 1966
1965 1967 ":dump"
1966 1968 Creates three versions of the files to merge, containing the contents of
1967 1969 local, other and base. These files can then be used to perform a merge
1968 1970 manually. If the file to be merged is named "a.txt", these files will
1969 1971 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1970 1972 they will be placed in the same directory as "a.txt".
1971 1973
1972 1974 This implies premerge. Therefore, files aren't dumped, if premerge runs
1973 1975 successfully. Use :forcedump to forcibly write files out.
1974 1976
1975 1977 (actual capabilities: binary, symlink)
1976 1978
1977 1979 ":fail"
1978 1980 Rather than attempting to merge files that were modified on both
1979 1981 branches, it marks them as unresolved. The resolve command must be used
1980 1982 to resolve these conflicts.
1981 1983
1982 1984 (actual capabilities: binary, symlink)
1983 1985
1984 1986 ":forcedump"
1985 1987 Creates three versions of the files as same as :dump, but omits
1986 1988 premerge.
1987 1989
1988 1990 (actual capabilities: binary, symlink)
1989 1991
1990 1992 ":local"
1991 1993 Uses the local 'p1()' version of files as the merged version.
1992 1994
1993 1995 (actual capabilities: binary, symlink)
1994 1996
1995 1997 ":merge"
1996 1998 Uses the internal non-interactive simple merge algorithm for merging
1997 1999 files. It will fail if there are any conflicts and leave markers in the
1998 2000 partially merged file. Markers will have two sections, one for each side
1999 2001 of merge.
2000 2002
2001 2003 ":merge-local"
2002 2004 Like :merge, but resolve all conflicts non-interactively in favor of the
2003 2005 local 'p1()' changes.
2004 2006
2005 2007 ":merge-other"
2006 2008 Like :merge, but resolve all conflicts non-interactively in favor of the
2007 2009 other 'p2()' changes.
2008 2010
2009 2011 ":merge3"
2010 2012 Uses the internal non-interactive simple merge algorithm for merging
2011 2013 files. It will fail if there are any conflicts and leave markers in the
2012 2014 partially merged file. Marker will have three sections, one from each
2013 2015 side of the merge and one for the base content.
2014 2016
2015 2017 ":other"
2016 2018 Uses the other 'p2()' version of files as the merged version.
2017 2019
2018 2020 (actual capabilities: binary, symlink)
2019 2021
2020 2022 ":prompt"
2021 2023 Asks the user which of the local 'p1()' or the other 'p2()' version to
2022 2024 keep as the merged version.
2023 2025
2024 2026 (actual capabilities: binary, symlink)
2025 2027
2026 2028 ":tagmerge"
2027 2029 Uses the internal tag merge algorithm (experimental).
2028 2030
2029 2031 ":union"
2030 2032 Uses the internal non-interactive simple merge algorithm for merging
2031 2033 files. It will use both left and right sides for conflict regions. No
2032 2034 markers are inserted.
2033 2035
2034 2036 Internal tools are always available and do not require a GUI but will by
2035 2037 default not handle symlinks or binary files. See next section for detail
2036 2038 about "actual capabilities" described above.
2037 2039
2038 2040 Choosing a merge tool
2039 2041 =====================
2040 2042
2041 2043 Mercurial uses these rules when deciding which merge tool to use:
2042 2044
2043 2045 1. If a tool has been specified with the --tool option to merge or
2044 2046 resolve, it is used. If it is the name of a tool in the merge-tools
2045 2047 configuration, its configuration is used. Otherwise the specified tool
2046 2048 must be executable by the shell.
2047 2049 2. If the "HGMERGE" environment variable is present, its value is used and
2048 2050 must be executable by the shell.
2049 2051 3. If the filename of the file to be merged matches any of the patterns in
2050 2052 the merge-patterns configuration section, the first usable merge tool
2051 2053 corresponding to a matching pattern is used.
2052 2054 4. If ui.merge is set it will be considered next. If the value is not the
2053 2055 name of a configured tool, the specified value is used and must be
2054 2056 executable by the shell. Otherwise the named tool is used if it is
2055 2057 usable.
2056 2058 5. If any usable merge tools are present in the merge-tools configuration
2057 2059 section, the one with the highest priority is used.
2058 2060 6. If a program named "hgmerge" can be found on the system, it is used -
2059 2061 but it will by default not be used for symlinks and binary files.
2060 2062 7. If the file to be merged is not binary and is not a symlink, then
2061 2063 internal ":merge" is used.
2062 2064 8. Otherwise, ":prompt" is used.
2063 2065
2064 2066 For historical reason, Mercurial treats merge tools as below while
2065 2067 examining rules above.
2066 2068
2067 2069 step specified via binary symlink
2068 2070 ----------------------------------
2069 2071 1. --tool o/o o/o
2070 2072 2. HGMERGE o/o o/o
2071 2073 3. merge-patterns o/o(*) x/?(*)
2072 2074 4. ui.merge x/?(*) x/?(*)
2073 2075
2074 2076 Each capability column indicates Mercurial behavior for internal/external
2075 2077 merge tools at examining each rule.
2076 2078
2077 2079 - "o": "assume that a tool has capability"
2078 2080 - "x": "assume that a tool does not have capability"
2079 2081 - "?": "check actual capability of a tool"
2080 2082
2081 2083 If "merge.strict-capability-check" configuration is true, Mercurial checks
2082 2084 capabilities of merge tools strictly in (*) cases above (= each capability
2083 2085 column becomes "?/?"). It is false by default for backward compatibility.
2084 2086
2085 2087 Note:
2086 2088 After selecting a merge program, Mercurial will by default attempt to
2087 2089 merge the files using a simple merge algorithm first. Only if it
2088 2090 doesn't succeed because of conflicting changes will Mercurial actually
2089 2091 execute the merge program. Whether to use the simple merge algorithm
2090 2092 first can be controlled by the premerge setting of the merge tool.
2091 2093 Premerge is enabled by default unless the file is binary or a symlink.
2092 2094
2093 2095 See the merge-tools and ui sections of hgrc(5) for details on the
2094 2096 configuration of merge tools.
2095 2097
2096 2098 Compression engines listed in `hg help bundlespec`
2097 2099
2098 2100 $ hg help bundlespec | grep gzip
2099 2101 "v1" bundles can only use the "gzip", "bzip2", and "none" compression
2100 2102 An algorithm that produces smaller bundles than "gzip".
2101 2103 This engine will likely produce smaller bundles than "gzip" but will be
2102 2104 "gzip"
2103 2105 better compression than "gzip". It also frequently yields better (?)
2104 2106
2105 2107 Test usage of section marks in help documents
2106 2108
2107 2109 $ cd "$TESTDIR"/../doc
2108 2110 $ "$PYTHON" check-seclevel.py
2109 2111 $ cd $TESTTMP
2110 2112
2111 2113 #if serve
2112 2114
2113 2115 Test the help pages in hgweb.
2114 2116
2115 2117 Dish up an empty repo; serve it cold.
2116 2118
2117 2119 $ hg init "$TESTTMP/test"
2118 2120 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
2119 2121 $ cat hg.pid >> $DAEMON_PIDS
2120 2122
2121 2123 $ get-with-headers.py $LOCALIP:$HGPORT "help"
2122 2124 200 Script output follows
2123 2125
2124 2126 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2125 2127 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2126 2128 <head>
2127 2129 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2128 2130 <meta name="robots" content="index, nofollow" />
2129 2131 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2130 2132 <script type="text/javascript" src="/static/mercurial.js"></script>
2131 2133
2132 2134 <title>Help: Index</title>
2133 2135 </head>
2134 2136 <body>
2135 2137
2136 2138 <div class="container">
2137 2139 <div class="menu">
2138 2140 <div class="logo">
2139 2141 <a href="https://mercurial-scm.org/">
2140 2142 <img src="/static/hglogo.png" alt="mercurial" /></a>
2141 2143 </div>
2142 2144 <ul>
2143 2145 <li><a href="/shortlog">log</a></li>
2144 2146 <li><a href="/graph">graph</a></li>
2145 2147 <li><a href="/tags">tags</a></li>
2146 2148 <li><a href="/bookmarks">bookmarks</a></li>
2147 2149 <li><a href="/branches">branches</a></li>
2148 2150 </ul>
2149 2151 <ul>
2150 2152 <li class="active">help</li>
2151 2153 </ul>
2152 2154 </div>
2153 2155
2154 2156 <div class="main">
2155 2157 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2156 2158
2157 2159 <form class="search" action="/log">
2158 2160
2159 2161 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2160 2162 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2161 2163 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2162 2164 </form>
2163 2165 <table class="bigtable">
2164 2166 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2165 2167
2166 2168 <tr><td>
2167 2169 <a href="/help/bundlespec">
2168 2170 bundlespec
2169 2171 </a>
2170 2172 </td><td>
2171 2173 Bundle File Formats
2172 2174 </td></tr>
2173 2175 <tr><td>
2174 2176 <a href="/help/color">
2175 2177 color
2176 2178 </a>
2177 2179 </td><td>
2178 2180 Colorizing Outputs
2179 2181 </td></tr>
2180 2182 <tr><td>
2181 2183 <a href="/help/config">
2182 2184 config
2183 2185 </a>
2184 2186 </td><td>
2185 2187 Configuration Files
2186 2188 </td></tr>
2187 2189 <tr><td>
2188 2190 <a href="/help/dates">
2189 2191 dates
2190 2192 </a>
2191 2193 </td><td>
2192 2194 Date Formats
2193 2195 </td></tr>
2194 2196 <tr><td>
2195 2197 <a href="/help/deprecated">
2196 2198 deprecated
2197 2199 </a>
2198 2200 </td><td>
2199 2201 Deprecated Features
2200 2202 </td></tr>
2201 2203 <tr><td>
2202 2204 <a href="/help/diffs">
2203 2205 diffs
2204 2206 </a>
2205 2207 </td><td>
2206 2208 Diff Formats
2207 2209 </td></tr>
2208 2210 <tr><td>
2209 2211 <a href="/help/environment">
2210 2212 environment
2211 2213 </a>
2212 2214 </td><td>
2213 2215 Environment Variables
2214 2216 </td></tr>
2215 2217 <tr><td>
2216 2218 <a href="/help/extensions">
2217 2219 extensions
2218 2220 </a>
2219 2221 </td><td>
2220 2222 Using Additional Features
2221 2223 </td></tr>
2222 2224 <tr><td>
2223 2225 <a href="/help/filesets">
2224 2226 filesets
2225 2227 </a>
2226 2228 </td><td>
2227 2229 Specifying File Sets
2228 2230 </td></tr>
2229 2231 <tr><td>
2230 2232 <a href="/help/flags">
2231 2233 flags
2232 2234 </a>
2233 2235 </td><td>
2234 2236 Command-line flags
2235 2237 </td></tr>
2236 2238 <tr><td>
2237 2239 <a href="/help/glossary">
2238 2240 glossary
2239 2241 </a>
2240 2242 </td><td>
2241 2243 Glossary
2242 2244 </td></tr>
2243 2245 <tr><td>
2244 2246 <a href="/help/hgignore">
2245 2247 hgignore
2246 2248 </a>
2247 2249 </td><td>
2248 2250 Syntax for Mercurial Ignore Files
2249 2251 </td></tr>
2250 2252 <tr><td>
2251 2253 <a href="/help/hgweb">
2252 2254 hgweb
2253 2255 </a>
2254 2256 </td><td>
2255 2257 Configuring hgweb
2256 2258 </td></tr>
2257 2259 <tr><td>
2258 2260 <a href="/help/internals">
2259 2261 internals
2260 2262 </a>
2261 2263 </td><td>
2262 2264 Technical implementation topics
2263 2265 </td></tr>
2264 2266 <tr><td>
2265 2267 <a href="/help/merge-tools">
2266 2268 merge-tools
2267 2269 </a>
2268 2270 </td><td>
2269 2271 Merge Tools
2270 2272 </td></tr>
2271 2273 <tr><td>
2272 2274 <a href="/help/pager">
2273 2275 pager
2274 2276 </a>
2275 2277 </td><td>
2276 2278 Pager Support
2277 2279 </td></tr>
2278 2280 <tr><td>
2279 2281 <a href="/help/patterns">
2280 2282 patterns
2281 2283 </a>
2282 2284 </td><td>
2283 2285 File Name Patterns
2284 2286 </td></tr>
2285 2287 <tr><td>
2286 2288 <a href="/help/phases">
2287 2289 phases
2288 2290 </a>
2289 2291 </td><td>
2290 2292 Working with Phases
2291 2293 </td></tr>
2292 2294 <tr><td>
2293 2295 <a href="/help/revisions">
2294 2296 revisions
2295 2297 </a>
2296 2298 </td><td>
2297 2299 Specifying Revisions
2298 2300 </td></tr>
2299 2301 <tr><td>
2300 2302 <a href="/help/scripting">
2301 2303 scripting
2302 2304 </a>
2303 2305 </td><td>
2304 2306 Using Mercurial from scripts and automation
2305 2307 </td></tr>
2306 2308 <tr><td>
2307 2309 <a href="/help/subrepos">
2308 2310 subrepos
2309 2311 </a>
2310 2312 </td><td>
2311 2313 Subrepositories
2312 2314 </td></tr>
2313 2315 <tr><td>
2314 2316 <a href="/help/templating">
2315 2317 templating
2316 2318 </a>
2317 2319 </td><td>
2318 2320 Template Usage
2319 2321 </td></tr>
2320 2322 <tr><td>
2321 2323 <a href="/help/urls">
2322 2324 urls
2323 2325 </a>
2324 2326 </td><td>
2325 2327 URL Paths
2326 2328 </td></tr>
2327 2329 <tr><td>
2328 2330 <a href="/help/topic-containing-verbose">
2329 2331 topic-containing-verbose
2330 2332 </a>
2331 2333 </td><td>
2332 2334 This is the topic to test omit indicating.
2333 2335 </td></tr>
2334 2336
2335 2337
2336 2338 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
2337 2339
2338 2340 <tr><td>
2339 2341 <a href="/help/add">
2340 2342 add
2341 2343 </a>
2342 2344 </td><td>
2343 2345 add the specified files on the next commit
2344 2346 </td></tr>
2345 2347 <tr><td>
2346 2348 <a href="/help/annotate">
2347 2349 annotate
2348 2350 </a>
2349 2351 </td><td>
2350 2352 show changeset information by line for each file
2351 2353 </td></tr>
2352 2354 <tr><td>
2353 2355 <a href="/help/clone">
2354 2356 clone
2355 2357 </a>
2356 2358 </td><td>
2357 2359 make a copy of an existing repository
2358 2360 </td></tr>
2359 2361 <tr><td>
2360 2362 <a href="/help/commit">
2361 2363 commit
2362 2364 </a>
2363 2365 </td><td>
2364 2366 commit the specified files or all outstanding changes
2365 2367 </td></tr>
2366 2368 <tr><td>
2367 2369 <a href="/help/diff">
2368 2370 diff
2369 2371 </a>
2370 2372 </td><td>
2371 2373 diff repository (or selected files)
2372 2374 </td></tr>
2373 2375 <tr><td>
2374 2376 <a href="/help/export">
2375 2377 export
2376 2378 </a>
2377 2379 </td><td>
2378 2380 dump the header and diffs for one or more changesets
2379 2381 </td></tr>
2380 2382 <tr><td>
2381 2383 <a href="/help/forget">
2382 2384 forget
2383 2385 </a>
2384 2386 </td><td>
2385 2387 forget the specified files on the next commit
2386 2388 </td></tr>
2387 2389 <tr><td>
2388 2390 <a href="/help/init">
2389 2391 init
2390 2392 </a>
2391 2393 </td><td>
2392 2394 create a new repository in the given directory
2393 2395 </td></tr>
2394 2396 <tr><td>
2395 2397 <a href="/help/log">
2396 2398 log
2397 2399 </a>
2398 2400 </td><td>
2399 2401 show revision history of entire repository or files
2400 2402 </td></tr>
2401 2403 <tr><td>
2402 2404 <a href="/help/merge">
2403 2405 merge
2404 2406 </a>
2405 2407 </td><td>
2406 2408 merge another revision into working directory
2407 2409 </td></tr>
2408 2410 <tr><td>
2409 2411 <a href="/help/pull">
2410 2412 pull
2411 2413 </a>
2412 2414 </td><td>
2413 2415 pull changes from the specified source
2414 2416 </td></tr>
2415 2417 <tr><td>
2416 2418 <a href="/help/push">
2417 2419 push
2418 2420 </a>
2419 2421 </td><td>
2420 2422 push changes to the specified destination
2421 2423 </td></tr>
2422 2424 <tr><td>
2423 2425 <a href="/help/remove">
2424 2426 remove
2425 2427 </a>
2426 2428 </td><td>
2427 2429 remove the specified files on the next commit
2428 2430 </td></tr>
2429 2431 <tr><td>
2430 2432 <a href="/help/serve">
2431 2433 serve
2432 2434 </a>
2433 2435 </td><td>
2434 2436 start stand-alone webserver
2435 2437 </td></tr>
2436 2438 <tr><td>
2437 2439 <a href="/help/status">
2438 2440 status
2439 2441 </a>
2440 2442 </td><td>
2441 2443 show changed files in the working directory
2442 2444 </td></tr>
2443 2445 <tr><td>
2444 2446 <a href="/help/summary">
2445 2447 summary
2446 2448 </a>
2447 2449 </td><td>
2448 2450 summarize working directory state
2449 2451 </td></tr>
2450 2452 <tr><td>
2451 2453 <a href="/help/update">
2452 2454 update
2453 2455 </a>
2454 2456 </td><td>
2455 2457 update working directory (or switch revisions)
2456 2458 </td></tr>
2457 2459
2458 2460
2459 2461
2460 2462 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2461 2463
2462 2464 <tr><td>
2463 2465 <a href="/help/addremove">
2464 2466 addremove
2465 2467 </a>
2466 2468 </td><td>
2467 2469 add all new files, delete all missing files
2468 2470 </td></tr>
2469 2471 <tr><td>
2470 2472 <a href="/help/archive">
2471 2473 archive
2472 2474 </a>
2473 2475 </td><td>
2474 2476 create an unversioned archive of a repository revision
2475 2477 </td></tr>
2476 2478 <tr><td>
2477 2479 <a href="/help/backout">
2478 2480 backout
2479 2481 </a>
2480 2482 </td><td>
2481 2483 reverse effect of earlier changeset
2482 2484 </td></tr>
2483 2485 <tr><td>
2484 2486 <a href="/help/bisect">
2485 2487 bisect
2486 2488 </a>
2487 2489 </td><td>
2488 2490 subdivision search of changesets
2489 2491 </td></tr>
2490 2492 <tr><td>
2491 2493 <a href="/help/bookmarks">
2492 2494 bookmarks
2493 2495 </a>
2494 2496 </td><td>
2495 2497 create a new bookmark or list existing bookmarks
2496 2498 </td></tr>
2497 2499 <tr><td>
2498 2500 <a href="/help/branch">
2499 2501 branch
2500 2502 </a>
2501 2503 </td><td>
2502 2504 set or show the current branch name
2503 2505 </td></tr>
2504 2506 <tr><td>
2505 2507 <a href="/help/branches">
2506 2508 branches
2507 2509 </a>
2508 2510 </td><td>
2509 2511 list repository named branches
2510 2512 </td></tr>
2511 2513 <tr><td>
2512 2514 <a href="/help/bundle">
2513 2515 bundle
2514 2516 </a>
2515 2517 </td><td>
2516 2518 create a bundle file
2517 2519 </td></tr>
2518 2520 <tr><td>
2519 2521 <a href="/help/cat">
2520 2522 cat
2521 2523 </a>
2522 2524 </td><td>
2523 2525 output the current or given revision of files
2524 2526 </td></tr>
2525 2527 <tr><td>
2526 2528 <a href="/help/config">
2527 2529 config
2528 2530 </a>
2529 2531 </td><td>
2530 2532 show combined config settings from all hgrc files
2531 2533 </td></tr>
2532 2534 <tr><td>
2533 2535 <a href="/help/copy">
2534 2536 copy
2535 2537 </a>
2536 2538 </td><td>
2537 2539 mark files as copied for the next commit
2538 2540 </td></tr>
2539 2541 <tr><td>
2540 2542 <a href="/help/files">
2541 2543 files
2542 2544 </a>
2543 2545 </td><td>
2544 2546 list tracked files
2545 2547 </td></tr>
2546 2548 <tr><td>
2547 2549 <a href="/help/graft">
2548 2550 graft
2549 2551 </a>
2550 2552 </td><td>
2551 2553 copy changes from other branches onto the current branch
2552 2554 </td></tr>
2553 2555 <tr><td>
2554 2556 <a href="/help/grep">
2555 2557 grep
2556 2558 </a>
2557 2559 </td><td>
2558 2560 search revision history for a pattern in specified files
2559 2561 </td></tr>
2560 2562 <tr><td>
2561 2563 <a href="/help/hashelp">
2562 2564 hashelp
2563 2565 </a>
2564 2566 </td><td>
2565 2567 Extension command's help
2566 2568 </td></tr>
2567 2569 <tr><td>
2568 2570 <a href="/help/heads">
2569 2571 heads
2570 2572 </a>
2571 2573 </td><td>
2572 2574 show branch heads
2573 2575 </td></tr>
2574 2576 <tr><td>
2575 2577 <a href="/help/help">
2576 2578 help
2577 2579 </a>
2578 2580 </td><td>
2579 2581 show help for a given topic or a help overview
2580 2582 </td></tr>
2581 2583 <tr><td>
2582 2584 <a href="/help/hgalias">
2583 2585 hgalias
2584 2586 </a>
2585 2587 </td><td>
2586 2588 My doc
2587 2589 </td></tr>
2588 2590 <tr><td>
2589 2591 <a href="/help/hgaliasnodoc">
2590 2592 hgaliasnodoc
2591 2593 </a>
2592 2594 </td><td>
2593 2595 summarize working directory state
2594 2596 </td></tr>
2595 2597 <tr><td>
2596 2598 <a href="/help/identify">
2597 2599 identify
2598 2600 </a>
2599 2601 </td><td>
2600 2602 identify the working directory or specified revision
2601 2603 </td></tr>
2602 2604 <tr><td>
2603 2605 <a href="/help/import">
2604 2606 import
2605 2607 </a>
2606 2608 </td><td>
2607 2609 import an ordered set of patches
2608 2610 </td></tr>
2609 2611 <tr><td>
2610 2612 <a href="/help/incoming">
2611 2613 incoming
2612 2614 </a>
2613 2615 </td><td>
2614 2616 show new changesets found in source
2615 2617 </td></tr>
2616 2618 <tr><td>
2617 2619 <a href="/help/manifest">
2618 2620 manifest
2619 2621 </a>
2620 2622 </td><td>
2621 2623 output the current or given revision of the project manifest
2622 2624 </td></tr>
2623 2625 <tr><td>
2624 2626 <a href="/help/nohelp">
2625 2627 nohelp
2626 2628 </a>
2627 2629 </td><td>
2628 2630 (no help text available)
2629 2631 </td></tr>
2630 2632 <tr><td>
2631 2633 <a href="/help/outgoing">
2632 2634 outgoing
2633 2635 </a>
2634 2636 </td><td>
2635 2637 show changesets not found in the destination
2636 2638 </td></tr>
2637 2639 <tr><td>
2638 2640 <a href="/help/paths">
2639 2641 paths
2640 2642 </a>
2641 2643 </td><td>
2642 2644 show aliases for remote repositories
2643 2645 </td></tr>
2644 2646 <tr><td>
2645 2647 <a href="/help/phase">
2646 2648 phase
2647 2649 </a>
2648 2650 </td><td>
2649 2651 set or show the current phase name
2650 2652 </td></tr>
2651 2653 <tr><td>
2652 2654 <a href="/help/recover">
2653 2655 recover
2654 2656 </a>
2655 2657 </td><td>
2656 2658 roll back an interrupted transaction
2657 2659 </td></tr>
2658 2660 <tr><td>
2659 2661 <a href="/help/rename">
2660 2662 rename
2661 2663 </a>
2662 2664 </td><td>
2663 2665 rename files; equivalent of copy + remove
2664 2666 </td></tr>
2665 2667 <tr><td>
2666 2668 <a href="/help/resolve">
2667 2669 resolve
2668 2670 </a>
2669 2671 </td><td>
2670 2672 redo merges or set/view the merge status of files
2671 2673 </td></tr>
2672 2674 <tr><td>
2673 2675 <a href="/help/revert">
2674 2676 revert
2675 2677 </a>
2676 2678 </td><td>
2677 2679 restore files to their checkout state
2678 2680 </td></tr>
2679 2681 <tr><td>
2680 2682 <a href="/help/root">
2681 2683 root
2682 2684 </a>
2683 2685 </td><td>
2684 2686 print the root (top) of the current working directory
2685 2687 </td></tr>
2686 2688 <tr><td>
2687 2689 <a href="/help/shellalias">
2688 2690 shellalias
2689 2691 </a>
2690 2692 </td><td>
2691 2693 (no help text available)
2692 2694 </td></tr>
2693 2695 <tr><td>
2694 2696 <a href="/help/tag">
2695 2697 tag
2696 2698 </a>
2697 2699 </td><td>
2698 2700 add one or more tags for the current or given revision
2699 2701 </td></tr>
2700 2702 <tr><td>
2701 2703 <a href="/help/tags">
2702 2704 tags
2703 2705 </a>
2704 2706 </td><td>
2705 2707 list repository tags
2706 2708 </td></tr>
2707 2709 <tr><td>
2708 2710 <a href="/help/unbundle">
2709 2711 unbundle
2710 2712 </a>
2711 2713 </td><td>
2712 2714 apply one or more bundle files
2713 2715 </td></tr>
2714 2716 <tr><td>
2715 2717 <a href="/help/verify">
2716 2718 verify
2717 2719 </a>
2718 2720 </td><td>
2719 2721 verify the integrity of the repository
2720 2722 </td></tr>
2721 2723 <tr><td>
2722 2724 <a href="/help/version">
2723 2725 version
2724 2726 </a>
2725 2727 </td><td>
2726 2728 output version and copyright information
2727 2729 </td></tr>
2728 2730
2729 2731
2730 2732 </table>
2731 2733 </div>
2732 2734 </div>
2733 2735
2734 2736
2735 2737
2736 2738 </body>
2737 2739 </html>
2738 2740
2739 2741
2740 2742 $ get-with-headers.py $LOCALIP:$HGPORT "help/add"
2741 2743 200 Script output follows
2742 2744
2743 2745 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2744 2746 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2745 2747 <head>
2746 2748 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2747 2749 <meta name="robots" content="index, nofollow" />
2748 2750 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2749 2751 <script type="text/javascript" src="/static/mercurial.js"></script>
2750 2752
2751 2753 <title>Help: add</title>
2752 2754 </head>
2753 2755 <body>
2754 2756
2755 2757 <div class="container">
2756 2758 <div class="menu">
2757 2759 <div class="logo">
2758 2760 <a href="https://mercurial-scm.org/">
2759 2761 <img src="/static/hglogo.png" alt="mercurial" /></a>
2760 2762 </div>
2761 2763 <ul>
2762 2764 <li><a href="/shortlog">log</a></li>
2763 2765 <li><a href="/graph">graph</a></li>
2764 2766 <li><a href="/tags">tags</a></li>
2765 2767 <li><a href="/bookmarks">bookmarks</a></li>
2766 2768 <li><a href="/branches">branches</a></li>
2767 2769 </ul>
2768 2770 <ul>
2769 2771 <li class="active"><a href="/help">help</a></li>
2770 2772 </ul>
2771 2773 </div>
2772 2774
2773 2775 <div class="main">
2774 2776 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2775 2777 <h3>Help: add</h3>
2776 2778
2777 2779 <form class="search" action="/log">
2778 2780
2779 2781 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2780 2782 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2781 2783 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2782 2784 </form>
2783 2785 <div id="doc">
2784 2786 <p>
2785 2787 hg add [OPTION]... [FILE]...
2786 2788 </p>
2787 2789 <p>
2788 2790 add the specified files on the next commit
2789 2791 </p>
2790 2792 <p>
2791 2793 Schedule files to be version controlled and added to the
2792 2794 repository.
2793 2795 </p>
2794 2796 <p>
2795 2797 The files will be added to the repository at the next commit. To
2796 2798 undo an add before that, see 'hg forget'.
2797 2799 </p>
2798 2800 <p>
2799 2801 If no names are given, add all files to the repository (except
2800 2802 files matching &quot;.hgignore&quot;).
2801 2803 </p>
2802 2804 <p>
2803 2805 Examples:
2804 2806 </p>
2805 2807 <ul>
2806 2808 <li> New (unknown) files are added automatically by 'hg add':
2807 2809 <pre>
2808 2810 \$ ls (re)
2809 2811 foo.c
2810 2812 \$ hg status (re)
2811 2813 ? foo.c
2812 2814 \$ hg add (re)
2813 2815 adding foo.c
2814 2816 \$ hg status (re)
2815 2817 A foo.c
2816 2818 </pre>
2817 2819 <li> Specific files to be added can be specified:
2818 2820 <pre>
2819 2821 \$ ls (re)
2820 2822 bar.c foo.c
2821 2823 \$ hg status (re)
2822 2824 ? bar.c
2823 2825 ? foo.c
2824 2826 \$ hg add bar.c (re)
2825 2827 \$ hg status (re)
2826 2828 A bar.c
2827 2829 ? foo.c
2828 2830 </pre>
2829 2831 </ul>
2830 2832 <p>
2831 2833 Returns 0 if all files are successfully added.
2832 2834 </p>
2833 2835 <p>
2834 2836 options ([+] can be repeated):
2835 2837 </p>
2836 2838 <table>
2837 2839 <tr><td>-I</td>
2838 2840 <td>--include PATTERN [+]</td>
2839 2841 <td>include names matching the given patterns</td></tr>
2840 2842 <tr><td>-X</td>
2841 2843 <td>--exclude PATTERN [+]</td>
2842 2844 <td>exclude names matching the given patterns</td></tr>
2843 2845 <tr><td>-S</td>
2844 2846 <td>--subrepos</td>
2845 2847 <td>recurse into subrepositories</td></tr>
2846 2848 <tr><td>-n</td>
2847 2849 <td>--dry-run</td>
2848 2850 <td>do not perform actions, just print output</td></tr>
2849 2851 </table>
2850 2852 <p>
2851 2853 global options ([+] can be repeated):
2852 2854 </p>
2853 2855 <table>
2854 2856 <tr><td>-R</td>
2855 2857 <td>--repository REPO</td>
2856 2858 <td>repository root directory or name of overlay bundle file</td></tr>
2857 2859 <tr><td></td>
2858 2860 <td>--cwd DIR</td>
2859 2861 <td>change working directory</td></tr>
2860 2862 <tr><td>-y</td>
2861 2863 <td>--noninteractive</td>
2862 2864 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2863 2865 <tr><td>-q</td>
2864 2866 <td>--quiet</td>
2865 2867 <td>suppress output</td></tr>
2866 2868 <tr><td>-v</td>
2867 2869 <td>--verbose</td>
2868 2870 <td>enable additional output</td></tr>
2869 2871 <tr><td></td>
2870 2872 <td>--color TYPE</td>
2871 2873 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
2872 2874 <tr><td></td>
2873 2875 <td>--config CONFIG [+]</td>
2874 2876 <td>set/override config option (use 'section.name=value')</td></tr>
2875 2877 <tr><td></td>
2876 2878 <td>--debug</td>
2877 2879 <td>enable debugging output</td></tr>
2878 2880 <tr><td></td>
2879 2881 <td>--debugger</td>
2880 2882 <td>start debugger</td></tr>
2881 2883 <tr><td></td>
2882 2884 <td>--encoding ENCODE</td>
2883 2885 <td>set the charset encoding (default: ascii)</td></tr>
2884 2886 <tr><td></td>
2885 2887 <td>--encodingmode MODE</td>
2886 2888 <td>set the charset encoding mode (default: strict)</td></tr>
2887 2889 <tr><td></td>
2888 2890 <td>--traceback</td>
2889 2891 <td>always print a traceback on exception</td></tr>
2890 2892 <tr><td></td>
2891 2893 <td>--time</td>
2892 2894 <td>time how long the command takes</td></tr>
2893 2895 <tr><td></td>
2894 2896 <td>--profile</td>
2895 2897 <td>print command execution profile</td></tr>
2896 2898 <tr><td></td>
2897 2899 <td>--version</td>
2898 2900 <td>output version information and exit</td></tr>
2899 2901 <tr><td>-h</td>
2900 2902 <td>--help</td>
2901 2903 <td>display help and exit</td></tr>
2902 2904 <tr><td></td>
2903 2905 <td>--hidden</td>
2904 2906 <td>consider hidden changesets</td></tr>
2905 2907 <tr><td></td>
2906 2908 <td>--pager TYPE</td>
2907 2909 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2908 2910 </table>
2909 2911
2910 2912 </div>
2911 2913 </div>
2912 2914 </div>
2913 2915
2914 2916
2915 2917
2916 2918 </body>
2917 2919 </html>
2918 2920
2919 2921
2920 2922 $ get-with-headers.py $LOCALIP:$HGPORT "help/remove"
2921 2923 200 Script output follows
2922 2924
2923 2925 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2924 2926 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2925 2927 <head>
2926 2928 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2927 2929 <meta name="robots" content="index, nofollow" />
2928 2930 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2929 2931 <script type="text/javascript" src="/static/mercurial.js"></script>
2930 2932
2931 2933 <title>Help: remove</title>
2932 2934 </head>
2933 2935 <body>
2934 2936
2935 2937 <div class="container">
2936 2938 <div class="menu">
2937 2939 <div class="logo">
2938 2940 <a href="https://mercurial-scm.org/">
2939 2941 <img src="/static/hglogo.png" alt="mercurial" /></a>
2940 2942 </div>
2941 2943 <ul>
2942 2944 <li><a href="/shortlog">log</a></li>
2943 2945 <li><a href="/graph">graph</a></li>
2944 2946 <li><a href="/tags">tags</a></li>
2945 2947 <li><a href="/bookmarks">bookmarks</a></li>
2946 2948 <li><a href="/branches">branches</a></li>
2947 2949 </ul>
2948 2950 <ul>
2949 2951 <li class="active"><a href="/help">help</a></li>
2950 2952 </ul>
2951 2953 </div>
2952 2954
2953 2955 <div class="main">
2954 2956 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2955 2957 <h3>Help: remove</h3>
2956 2958
2957 2959 <form class="search" action="/log">
2958 2960
2959 2961 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
2960 2962 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2961 2963 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2962 2964 </form>
2963 2965 <div id="doc">
2964 2966 <p>
2965 2967 hg remove [OPTION]... FILE...
2966 2968 </p>
2967 2969 <p>
2968 2970 aliases: rm
2969 2971 </p>
2970 2972 <p>
2971 2973 remove the specified files on the next commit
2972 2974 </p>
2973 2975 <p>
2974 2976 Schedule the indicated files for removal from the current branch.
2975 2977 </p>
2976 2978 <p>
2977 2979 This command schedules the files to be removed at the next commit.
2978 2980 To undo a remove before that, see 'hg revert'. To undo added
2979 2981 files, see 'hg forget'.
2980 2982 </p>
2981 2983 <p>
2982 2984 -A/--after can be used to remove only files that have already
2983 2985 been deleted, -f/--force can be used to force deletion, and -Af
2984 2986 can be used to remove files from the next revision without
2985 2987 deleting them from the working directory.
2986 2988 </p>
2987 2989 <p>
2988 2990 The following table details the behavior of remove for different
2989 2991 file states (columns) and option combinations (rows). The file
2990 2992 states are Added [A], Clean [C], Modified [M] and Missing [!]
2991 2993 (as reported by 'hg status'). The actions are Warn, Remove
2992 2994 (from branch) and Delete (from disk):
2993 2995 </p>
2994 2996 <table>
2995 2997 <tr><td>opt/state</td>
2996 2998 <td>A</td>
2997 2999 <td>C</td>
2998 3000 <td>M</td>
2999 3001 <td>!</td></tr>
3000 3002 <tr><td>none</td>
3001 3003 <td>W</td>
3002 3004 <td>RD</td>
3003 3005 <td>W</td>
3004 3006 <td>R</td></tr>
3005 3007 <tr><td>-f</td>
3006 3008 <td>R</td>
3007 3009 <td>RD</td>
3008 3010 <td>RD</td>
3009 3011 <td>R</td></tr>
3010 3012 <tr><td>-A</td>
3011 3013 <td>W</td>
3012 3014 <td>W</td>
3013 3015 <td>W</td>
3014 3016 <td>R</td></tr>
3015 3017 <tr><td>-Af</td>
3016 3018 <td>R</td>
3017 3019 <td>R</td>
3018 3020 <td>R</td>
3019 3021 <td>R</td></tr>
3020 3022 </table>
3021 3023 <p>
3022 3024 <b>Note:</b>
3023 3025 </p>
3024 3026 <p>
3025 3027 'hg remove' never deletes files in Added [A] state from the
3026 3028 working directory, not even if &quot;--force&quot; is specified.
3027 3029 </p>
3028 3030 <p>
3029 3031 Returns 0 on success, 1 if any warnings encountered.
3030 3032 </p>
3031 3033 <p>
3032 3034 options ([+] can be repeated):
3033 3035 </p>
3034 3036 <table>
3035 3037 <tr><td>-A</td>
3036 3038 <td>--after</td>
3037 3039 <td>record delete for missing files</td></tr>
3038 3040 <tr><td>-f</td>
3039 3041 <td>--force</td>
3040 3042 <td>forget added files, delete modified files</td></tr>
3041 3043 <tr><td>-S</td>
3042 3044 <td>--subrepos</td>
3043 3045 <td>recurse into subrepositories</td></tr>
3044 3046 <tr><td>-I</td>
3045 3047 <td>--include PATTERN [+]</td>
3046 3048 <td>include names matching the given patterns</td></tr>
3047 3049 <tr><td>-X</td>
3048 3050 <td>--exclude PATTERN [+]</td>
3049 3051 <td>exclude names matching the given patterns</td></tr>
3050 3052 <tr><td>-n</td>
3051 3053 <td>--dry-run</td>
3052 3054 <td>do not perform actions, just print output</td></tr>
3053 3055 </table>
3054 3056 <p>
3055 3057 global options ([+] can be repeated):
3056 3058 </p>
3057 3059 <table>
3058 3060 <tr><td>-R</td>
3059 3061 <td>--repository REPO</td>
3060 3062 <td>repository root directory or name of overlay bundle file</td></tr>
3061 3063 <tr><td></td>
3062 3064 <td>--cwd DIR</td>
3063 3065 <td>change working directory</td></tr>
3064 3066 <tr><td>-y</td>
3065 3067 <td>--noninteractive</td>
3066 3068 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
3067 3069 <tr><td>-q</td>
3068 3070 <td>--quiet</td>
3069 3071 <td>suppress output</td></tr>
3070 3072 <tr><td>-v</td>
3071 3073 <td>--verbose</td>
3072 3074 <td>enable additional output</td></tr>
3073 3075 <tr><td></td>
3074 3076 <td>--color TYPE</td>
3075 3077 <td>when to colorize (boolean, always, auto, never, or debug)</td></tr>
3076 3078 <tr><td></td>
3077 3079 <td>--config CONFIG [+]</td>
3078 3080 <td>set/override config option (use 'section.name=value')</td></tr>
3079 3081 <tr><td></td>
3080 3082 <td>--debug</td>
3081 3083 <td>enable debugging output</td></tr>
3082 3084 <tr><td></td>
3083 3085 <td>--debugger</td>
3084 3086 <td>start debugger</td></tr>
3085 3087 <tr><td></td>
3086 3088 <td>--encoding ENCODE</td>
3087 3089 <td>set the charset encoding (default: ascii)</td></tr>
3088 3090 <tr><td></td>
3089 3091 <td>--encodingmode MODE</td>
3090 3092 <td>set the charset encoding mode (default: strict)</td></tr>
3091 3093 <tr><td></td>
3092 3094 <td>--traceback</td>
3093 3095 <td>always print a traceback on exception</td></tr>
3094 3096 <tr><td></td>
3095 3097 <td>--time</td>
3096 3098 <td>time how long the command takes</td></tr>
3097 3099 <tr><td></td>
3098 3100 <td>--profile</td>
3099 3101 <td>print command execution profile</td></tr>
3100 3102 <tr><td></td>
3101 3103 <td>--version</td>
3102 3104 <td>output version information and exit</td></tr>
3103 3105 <tr><td>-h</td>
3104 3106 <td>--help</td>
3105 3107 <td>display help and exit</td></tr>
3106 3108 <tr><td></td>
3107 3109 <td>--hidden</td>
3108 3110 <td>consider hidden changesets</td></tr>
3109 3111 <tr><td></td>
3110 3112 <td>--pager TYPE</td>
3111 3113 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
3112 3114 </table>
3113 3115
3114 3116 </div>
3115 3117 </div>
3116 3118 </div>
3117 3119
3118 3120
3119 3121
3120 3122 </body>
3121 3123 </html>
3122 3124
3123 3125
3124 3126 $ get-with-headers.py $LOCALIP:$HGPORT "help/dates"
3125 3127 200 Script output follows
3126 3128
3127 3129 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3128 3130 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3129 3131 <head>
3130 3132 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3131 3133 <meta name="robots" content="index, nofollow" />
3132 3134 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3133 3135 <script type="text/javascript" src="/static/mercurial.js"></script>
3134 3136
3135 3137 <title>Help: dates</title>
3136 3138 </head>
3137 3139 <body>
3138 3140
3139 3141 <div class="container">
3140 3142 <div class="menu">
3141 3143 <div class="logo">
3142 3144 <a href="https://mercurial-scm.org/">
3143 3145 <img src="/static/hglogo.png" alt="mercurial" /></a>
3144 3146 </div>
3145 3147 <ul>
3146 3148 <li><a href="/shortlog">log</a></li>
3147 3149 <li><a href="/graph">graph</a></li>
3148 3150 <li><a href="/tags">tags</a></li>
3149 3151 <li><a href="/bookmarks">bookmarks</a></li>
3150 3152 <li><a href="/branches">branches</a></li>
3151 3153 </ul>
3152 3154 <ul>
3153 3155 <li class="active"><a href="/help">help</a></li>
3154 3156 </ul>
3155 3157 </div>
3156 3158
3157 3159 <div class="main">
3158 3160 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3159 3161 <h3>Help: dates</h3>
3160 3162
3161 3163 <form class="search" action="/log">
3162 3164
3163 3165 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3164 3166 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3165 3167 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3166 3168 </form>
3167 3169 <div id="doc">
3168 3170 <h1>Date Formats</h1>
3169 3171 <p>
3170 3172 Some commands allow the user to specify a date, e.g.:
3171 3173 </p>
3172 3174 <ul>
3173 3175 <li> backout, commit, import, tag: Specify the commit date.
3174 3176 <li> log, revert, update: Select revision(s) by date.
3175 3177 </ul>
3176 3178 <p>
3177 3179 Many date formats are valid. Here are some examples:
3178 3180 </p>
3179 3181 <ul>
3180 3182 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
3181 3183 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
3182 3184 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
3183 3185 <li> &quot;Dec 6&quot; (midnight)
3184 3186 <li> &quot;13:18&quot; (today assumed)
3185 3187 <li> &quot;3:39&quot; (3:39AM assumed)
3186 3188 <li> &quot;3:39pm&quot; (15:39)
3187 3189 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
3188 3190 <li> &quot;2006-12-6 13:18&quot;
3189 3191 <li> &quot;2006-12-6&quot;
3190 3192 <li> &quot;12-6&quot;
3191 3193 <li> &quot;12/6&quot;
3192 3194 <li> &quot;12/6/6&quot; (Dec 6 2006)
3193 3195 <li> &quot;today&quot; (midnight)
3194 3196 <li> &quot;yesterday&quot; (midnight)
3195 3197 <li> &quot;now&quot; - right now
3196 3198 </ul>
3197 3199 <p>
3198 3200 Lastly, there is Mercurial's internal format:
3199 3201 </p>
3200 3202 <ul>
3201 3203 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
3202 3204 </ul>
3203 3205 <p>
3204 3206 This is the internal representation format for dates. The first number
3205 3207 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
3206 3208 second is the offset of the local timezone, in seconds west of UTC
3207 3209 (negative if the timezone is east of UTC).
3208 3210 </p>
3209 3211 <p>
3210 3212 The log command also accepts date ranges:
3211 3213 </p>
3212 3214 <ul>
3213 3215 <li> &quot;&lt;DATE&quot; - at or before a given date/time
3214 3216 <li> &quot;&gt;DATE&quot; - on or after a given date/time
3215 3217 <li> &quot;DATE to DATE&quot; - a date range, inclusive
3216 3218 <li> &quot;-DAYS&quot; - within a given number of days of today
3217 3219 </ul>
3218 3220
3219 3221 </div>
3220 3222 </div>
3221 3223 </div>
3222 3224
3223 3225
3224 3226
3225 3227 </body>
3226 3228 </html>
3227 3229
3228 3230
3229 3231 $ get-with-headers.py $LOCALIP:$HGPORT "help/pager"
3230 3232 200 Script output follows
3231 3233
3232 3234 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3233 3235 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3234 3236 <head>
3235 3237 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3236 3238 <meta name="robots" content="index, nofollow" />
3237 3239 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3238 3240 <script type="text/javascript" src="/static/mercurial.js"></script>
3239 3241
3240 3242 <title>Help: pager</title>
3241 3243 </head>
3242 3244 <body>
3243 3245
3244 3246 <div class="container">
3245 3247 <div class="menu">
3246 3248 <div class="logo">
3247 3249 <a href="https://mercurial-scm.org/">
3248 3250 <img src="/static/hglogo.png" alt="mercurial" /></a>
3249 3251 </div>
3250 3252 <ul>
3251 3253 <li><a href="/shortlog">log</a></li>
3252 3254 <li><a href="/graph">graph</a></li>
3253 3255 <li><a href="/tags">tags</a></li>
3254 3256 <li><a href="/bookmarks">bookmarks</a></li>
3255 3257 <li><a href="/branches">branches</a></li>
3256 3258 </ul>
3257 3259 <ul>
3258 3260 <li class="active"><a href="/help">help</a></li>
3259 3261 </ul>
3260 3262 </div>
3261 3263
3262 3264 <div class="main">
3263 3265 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3264 3266 <h3>Help: pager</h3>
3265 3267
3266 3268 <form class="search" action="/log">
3267 3269
3268 3270 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3269 3271 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3270 3272 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3271 3273 </form>
3272 3274 <div id="doc">
3273 3275 <h1>Pager Support</h1>
3274 3276 <p>
3275 3277 Some Mercurial commands can produce a lot of output, and Mercurial will
3276 3278 attempt to use a pager to make those commands more pleasant.
3277 3279 </p>
3278 3280 <p>
3279 3281 To set the pager that should be used, set the application variable:
3280 3282 </p>
3281 3283 <pre>
3282 3284 [pager]
3283 3285 pager = less -FRX
3284 3286 </pre>
3285 3287 <p>
3286 3288 If no pager is set in the user or repository configuration, Mercurial uses the
3287 3289 environment variable $PAGER. If $PAGER is not set, pager.pager from the default
3288 3290 or system configuration is used. If none of these are set, a default pager will
3289 3291 be used, typically 'less' on Unix and 'more' on Windows.
3290 3292 </p>
3291 3293 <p>
3292 3294 You can disable the pager for certain commands by adding them to the
3293 3295 pager.ignore list:
3294 3296 </p>
3295 3297 <pre>
3296 3298 [pager]
3297 3299 ignore = version, help, update
3298 3300 </pre>
3299 3301 <p>
3300 3302 To ignore global commands like 'hg version' or 'hg help', you have
3301 3303 to specify them in your user configuration file.
3302 3304 </p>
3303 3305 <p>
3304 3306 To control whether the pager is used at all for an individual command,
3305 3307 you can use --pager=&lt;value&gt;:
3306 3308 </p>
3307 3309 <ul>
3308 3310 <li> use as needed: 'auto'.
3309 3311 <li> require the pager: 'yes' or 'on'.
3310 3312 <li> suppress the pager: 'no' or 'off' (any unrecognized value will also work).
3311 3313 </ul>
3312 3314 <p>
3313 3315 To globally turn off all attempts to use a pager, set:
3314 3316 </p>
3315 3317 <pre>
3316 3318 [ui]
3317 3319 paginate = never
3318 3320 </pre>
3319 3321 <p>
3320 3322 which will prevent the pager from running.
3321 3323 </p>
3322 3324
3323 3325 </div>
3324 3326 </div>
3325 3327 </div>
3326 3328
3327 3329
3328 3330
3329 3331 </body>
3330 3332 </html>
3331 3333
3332 3334
3333 3335 Sub-topic indexes rendered properly
3334 3336
3335 3337 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals"
3336 3338 200 Script output follows
3337 3339
3338 3340 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3339 3341 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3340 3342 <head>
3341 3343 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3342 3344 <meta name="robots" content="index, nofollow" />
3343 3345 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3344 3346 <script type="text/javascript" src="/static/mercurial.js"></script>
3345 3347
3346 3348 <title>Help: internals</title>
3347 3349 </head>
3348 3350 <body>
3349 3351
3350 3352 <div class="container">
3351 3353 <div class="menu">
3352 3354 <div class="logo">
3353 3355 <a href="https://mercurial-scm.org/">
3354 3356 <img src="/static/hglogo.png" alt="mercurial" /></a>
3355 3357 </div>
3356 3358 <ul>
3357 3359 <li><a href="/shortlog">log</a></li>
3358 3360 <li><a href="/graph">graph</a></li>
3359 3361 <li><a href="/tags">tags</a></li>
3360 3362 <li><a href="/bookmarks">bookmarks</a></li>
3361 3363 <li><a href="/branches">branches</a></li>
3362 3364 </ul>
3363 3365 <ul>
3364 3366 <li><a href="/help">help</a></li>
3365 3367 </ul>
3366 3368 </div>
3367 3369
3368 3370 <div class="main">
3369 3371 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3370 3372
3371 3373 <form class="search" action="/log">
3372 3374
3373 3375 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3374 3376 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3375 3377 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3376 3378 </form>
3377 3379 <table class="bigtable">
3378 3380 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
3379 3381
3380 3382 <tr><td>
3381 3383 <a href="/help/internals.bundle2">
3382 3384 bundle2
3383 3385 </a>
3384 3386 </td><td>
3385 3387 Bundle2
3386 3388 </td></tr>
3387 3389 <tr><td>
3388 3390 <a href="/help/internals.bundles">
3389 3391 bundles
3390 3392 </a>
3391 3393 </td><td>
3392 3394 Bundles
3393 3395 </td></tr>
3394 3396 <tr><td>
3395 3397 <a href="/help/internals.cbor">
3396 3398 cbor
3397 3399 </a>
3398 3400 </td><td>
3399 3401 CBOR
3400 3402 </td></tr>
3401 3403 <tr><td>
3402 3404 <a href="/help/internals.censor">
3403 3405 censor
3404 3406 </a>
3405 3407 </td><td>
3406 3408 Censor
3407 3409 </td></tr>
3408 3410 <tr><td>
3409 3411 <a href="/help/internals.changegroups">
3410 3412 changegroups
3411 3413 </a>
3412 3414 </td><td>
3413 3415 Changegroups
3414 3416 </td></tr>
3415 3417 <tr><td>
3416 3418 <a href="/help/internals.config">
3417 3419 config
3418 3420 </a>
3419 3421 </td><td>
3420 3422 Config Registrar
3421 3423 </td></tr>
3422 3424 <tr><td>
3423 3425 <a href="/help/internals.extensions">
3424 3426 extensions
3425 3427 </a>
3426 3428 </td><td>
3427 3429 Extension API
3428 3430 </td></tr>
3429 3431 <tr><td>
3430 3432 <a href="/help/internals.requirements">
3431 3433 requirements
3432 3434 </a>
3433 3435 </td><td>
3434 3436 Repository Requirements
3435 3437 </td></tr>
3436 3438 <tr><td>
3437 3439 <a href="/help/internals.revlogs">
3438 3440 revlogs
3439 3441 </a>
3440 3442 </td><td>
3441 3443 Revision Logs
3442 3444 </td></tr>
3443 3445 <tr><td>
3444 3446 <a href="/help/internals.wireprotocol">
3445 3447 wireprotocol
3446 3448 </a>
3447 3449 </td><td>
3448 3450 Wire Protocol
3449 3451 </td></tr>
3450 3452 <tr><td>
3451 3453 <a href="/help/internals.wireprotocolrpc">
3452 3454 wireprotocolrpc
3453 3455 </a>
3454 3456 </td><td>
3455 3457 Wire Protocol RPC
3456 3458 </td></tr>
3457 3459 <tr><td>
3458 3460 <a href="/help/internals.wireprotocolv2">
3459 3461 wireprotocolv2
3460 3462 </a>
3461 3463 </td><td>
3462 3464 Wire Protocol Version 2
3463 3465 </td></tr>
3464 3466
3465 3467
3466 3468
3467 3469
3468 3470
3469 3471 </table>
3470 3472 </div>
3471 3473 </div>
3472 3474
3473 3475
3474 3476
3475 3477 </body>
3476 3478 </html>
3477 3479
3478 3480
3479 3481 Sub-topic topics rendered properly
3480 3482
3481 3483 $ get-with-headers.py $LOCALIP:$HGPORT "help/internals.changegroups"
3482 3484 200 Script output follows
3483 3485
3484 3486 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3485 3487 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3486 3488 <head>
3487 3489 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3488 3490 <meta name="robots" content="index, nofollow" />
3489 3491 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3490 3492 <script type="text/javascript" src="/static/mercurial.js"></script>
3491 3493
3492 3494 <title>Help: internals.changegroups</title>
3493 3495 </head>
3494 3496 <body>
3495 3497
3496 3498 <div class="container">
3497 3499 <div class="menu">
3498 3500 <div class="logo">
3499 3501 <a href="https://mercurial-scm.org/">
3500 3502 <img src="/static/hglogo.png" alt="mercurial" /></a>
3501 3503 </div>
3502 3504 <ul>
3503 3505 <li><a href="/shortlog">log</a></li>
3504 3506 <li><a href="/graph">graph</a></li>
3505 3507 <li><a href="/tags">tags</a></li>
3506 3508 <li><a href="/bookmarks">bookmarks</a></li>
3507 3509 <li><a href="/branches">branches</a></li>
3508 3510 </ul>
3509 3511 <ul>
3510 3512 <li class="active"><a href="/help">help</a></li>
3511 3513 </ul>
3512 3514 </div>
3513 3515
3514 3516 <div class="main">
3515 3517 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3516 3518 <h3>Help: internals.changegroups</h3>
3517 3519
3518 3520 <form class="search" action="/log">
3519 3521
3520 3522 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3521 3523 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3522 3524 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3523 3525 </form>
3524 3526 <div id="doc">
3525 3527 <h1>Changegroups</h1>
3526 3528 <p>
3527 3529 Changegroups are representations of repository revlog data, specifically
3528 3530 the changelog data, root/flat manifest data, treemanifest data, and
3529 3531 filelogs.
3530 3532 </p>
3531 3533 <p>
3532 3534 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
3533 3535 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with the
3534 3536 only difference being an additional item in the *delta header*. Version
3535 3537 &quot;3&quot; adds support for storage flags in the *delta header* and optionally
3536 3538 exchanging treemanifests (enabled by setting an option on the
3537 3539 &quot;changegroup&quot; part in the bundle2).
3538 3540 </p>
3539 3541 <p>
3540 3542 Changegroups when not exchanging treemanifests consist of 3 logical
3541 3543 segments:
3542 3544 </p>
3543 3545 <pre>
3544 3546 +---------------------------------+
3545 3547 | | | |
3546 3548 | changeset | manifest | filelogs |
3547 3549 | | | |
3548 3550 | | | |
3549 3551 +---------------------------------+
3550 3552 </pre>
3551 3553 <p>
3552 3554 When exchanging treemanifests, there are 4 logical segments:
3553 3555 </p>
3554 3556 <pre>
3555 3557 +-------------------------------------------------+
3556 3558 | | | | |
3557 3559 | changeset | root | treemanifests | filelogs |
3558 3560 | | manifest | | |
3559 3561 | | | | |
3560 3562 +-------------------------------------------------+
3561 3563 </pre>
3562 3564 <p>
3563 3565 The principle building block of each segment is a *chunk*. A *chunk*
3564 3566 is a framed piece of data:
3565 3567 </p>
3566 3568 <pre>
3567 3569 +---------------------------------------+
3568 3570 | | |
3569 3571 | length | data |
3570 3572 | (4 bytes) | (&lt;length - 4&gt; bytes) |
3571 3573 | | |
3572 3574 +---------------------------------------+
3573 3575 </pre>
3574 3576 <p>
3575 3577 All integers are big-endian signed integers. Each chunk starts with a 32-bit
3576 3578 integer indicating the length of the entire chunk (including the length field
3577 3579 itself).
3578 3580 </p>
3579 3581 <p>
3580 3582 There is a special case chunk that has a value of 0 for the length
3581 3583 (&quot;0x00000000&quot;). We call this an *empty chunk*.
3582 3584 </p>
3583 3585 <h2>Delta Groups</h2>
3584 3586 <p>
3585 3587 A *delta group* expresses the content of a revlog as a series of deltas,
3586 3588 or patches against previous revisions.
3587 3589 </p>
3588 3590 <p>
3589 3591 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3590 3592 to signal the end of the delta group:
3591 3593 </p>
3592 3594 <pre>
3593 3595 +------------------------------------------------------------------------+
3594 3596 | | | | | |
3595 3597 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3596 3598 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
3597 3599 | | | | | |
3598 3600 +------------------------------------------------------------------------+
3599 3601 </pre>
3600 3602 <p>
3601 3603 Each *chunk*'s data consists of the following:
3602 3604 </p>
3603 3605 <pre>
3604 3606 +---------------------------------------+
3605 3607 | | |
3606 3608 | delta header | delta data |
3607 3609 | (various by version) | (various) |
3608 3610 | | |
3609 3611 +---------------------------------------+
3610 3612 </pre>
3611 3613 <p>
3612 3614 The *delta data* is a series of *delta*s that describe a diff from an existing
3613 3615 entry (either that the recipient already has, or previously specified in the
3614 3616 bundle/changegroup).
3615 3617 </p>
3616 3618 <p>
3617 3619 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3618 3620 &quot;3&quot; of the changegroup format.
3619 3621 </p>
3620 3622 <p>
3621 3623 Version 1 (headerlen=80):
3622 3624 </p>
3623 3625 <pre>
3624 3626 +------------------------------------------------------+
3625 3627 | | | | |
3626 3628 | node | p1 node | p2 node | link node |
3627 3629 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3628 3630 | | | | |
3629 3631 +------------------------------------------------------+
3630 3632 </pre>
3631 3633 <p>
3632 3634 Version 2 (headerlen=100):
3633 3635 </p>
3634 3636 <pre>
3635 3637 +------------------------------------------------------------------+
3636 3638 | | | | | |
3637 3639 | node | p1 node | p2 node | base node | link node |
3638 3640 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3639 3641 | | | | | |
3640 3642 +------------------------------------------------------------------+
3641 3643 </pre>
3642 3644 <p>
3643 3645 Version 3 (headerlen=102):
3644 3646 </p>
3645 3647 <pre>
3646 3648 +------------------------------------------------------------------------------+
3647 3649 | | | | | | |
3648 3650 | node | p1 node | p2 node | base node | link node | flags |
3649 3651 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3650 3652 | | | | | | |
3651 3653 +------------------------------------------------------------------------------+
3652 3654 </pre>
3653 3655 <p>
3654 3656 The *delta data* consists of &quot;chunklen - 4 - headerlen&quot; bytes, which contain a
3655 3657 series of *delta*s, densely packed (no separators). These deltas describe a diff
3656 3658 from an existing entry (either that the recipient already has, or previously
3657 3659 specified in the bundle/changegroup). The format is described more fully in
3658 3660 &quot;hg help internals.bdiff&quot;, but briefly:
3659 3661 </p>
3660 3662 <pre>
3661 3663 +---------------------------------------------------------------+
3662 3664 | | | | |
3663 3665 | start offset | end offset | new length | content |
3664 3666 | (4 bytes) | (4 bytes) | (4 bytes) | (&lt;new length&gt; bytes) |
3665 3667 | | | | |
3666 3668 +---------------------------------------------------------------+
3667 3669 </pre>
3668 3670 <p>
3669 3671 Please note that the length field in the delta data does *not* include itself.
3670 3672 </p>
3671 3673 <p>
3672 3674 In version 1, the delta is always applied against the previous node from
3673 3675 the changegroup or the first parent if this is the first entry in the
3674 3676 changegroup.
3675 3677 </p>
3676 3678 <p>
3677 3679 In version 2 and up, the delta base node is encoded in the entry in the
3678 3680 changegroup. This allows the delta to be expressed against any parent,
3679 3681 which can result in smaller deltas and more efficient encoding of data.
3680 3682 </p>
3681 3683 <p>
3682 3684 The *flags* field holds bitwise flags affecting the processing of revision
3683 3685 data. The following flags are defined:
3684 3686 </p>
3685 3687 <dl>
3686 3688 <dt>32768
3687 3689 <dd>Censored revision. The revision's fulltext has been replaced by censor metadata. May only occur on file revisions.
3688 3690 <dt>16384
3689 3691 <dd>Ellipsis revision. Revision hash does not match data (likely due to rewritten parents).
3690 3692 <dt>8192
3691 3693 <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.
3692 3694 </dl>
3693 3695 <p>
3694 3696 For historical reasons, the integer values are identical to revlog version 1
3695 3697 per-revision storage flags and correspond to bits being set in this 2-byte
3696 3698 field. Bits were allocated starting from the most-significant bit, hence the
3697 3699 reverse ordering and allocation of these flags.
3698 3700 </p>
3699 3701 <h2>Changeset Segment</h2>
3700 3702 <p>
3701 3703 The *changeset segment* consists of a single *delta group* holding
3702 3704 changelog data. The *empty chunk* at the end of the *delta group* denotes
3703 3705 the boundary to the *manifest segment*.
3704 3706 </p>
3705 3707 <h2>Manifest Segment</h2>
3706 3708 <p>
3707 3709 The *manifest segment* consists of a single *delta group* holding manifest
3708 3710 data. If treemanifests are in use, it contains only the manifest for the
3709 3711 root directory of the repository. Otherwise, it contains the entire
3710 3712 manifest data. The *empty chunk* at the end of the *delta group* denotes
3711 3713 the boundary to the next segment (either the *treemanifests segment* or the
3712 3714 *filelogs segment*, depending on version and the request options).
3713 3715 </p>
3714 3716 <h3>Treemanifests Segment</h3>
3715 3717 <p>
3716 3718 The *treemanifests segment* only exists in changegroup version &quot;3&quot;, and
3717 3719 only if the 'treemanifest' param is part of the bundle2 changegroup part
3718 3720 (it is not possible to use changegroup version 3 outside of bundle2).
3719 3721 Aside from the filenames in the *treemanifests segment* containing a
3720 3722 trailing &quot;/&quot; character, it behaves identically to the *filelogs segment*
3721 3723 (see below). The final sub-segment is followed by an *empty chunk* (logically,
3722 3724 a sub-segment with filename size 0). This denotes the boundary to the
3723 3725 *filelogs segment*.
3724 3726 </p>
3725 3727 <h2>Filelogs Segment</h2>
3726 3728 <p>
3727 3729 The *filelogs segment* consists of multiple sub-segments, each
3728 3730 corresponding to an individual file whose data is being described:
3729 3731 </p>
3730 3732 <pre>
3731 3733 +--------------------------------------------------+
3732 3734 | | | | | |
3733 3735 | filelog0 | filelog1 | filelog2 | ... | 0x0 |
3734 3736 | | | | | (4 bytes) |
3735 3737 | | | | | |
3736 3738 +--------------------------------------------------+
3737 3739 </pre>
3738 3740 <p>
3739 3741 The final filelog sub-segment is followed by an *empty chunk* (logically,
3740 3742 a sub-segment with filename size 0). This denotes the end of the segment
3741 3743 and of the overall changegroup.
3742 3744 </p>
3743 3745 <p>
3744 3746 Each filelog sub-segment consists of the following:
3745 3747 </p>
3746 3748 <pre>
3747 3749 +------------------------------------------------------+
3748 3750 | | | |
3749 3751 | filename length | filename | delta group |
3750 3752 | (4 bytes) | (&lt;length - 4&gt; bytes) | (various) |
3751 3753 | | | |
3752 3754 +------------------------------------------------------+
3753 3755 </pre>
3754 3756 <p>
3755 3757 That is, a *chunk* consisting of the filename (not terminated or padded)
3756 3758 followed by N chunks constituting the *delta group* for this file. The
3757 3759 *empty chunk* at the end of each *delta group* denotes the boundary to the
3758 3760 next filelog sub-segment.
3759 3761 </p>
3760 3762
3761 3763 </div>
3762 3764 </div>
3763 3765 </div>
3764 3766
3765 3767
3766 3768
3767 3769 </body>
3768 3770 </html>
3769 3771
3770 3772
3771 3773 $ get-with-headers.py 127.0.0.1:$HGPORT "help/unknowntopic"
3772 3774 404 Not Found
3773 3775
3774 3776 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3775 3777 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
3776 3778 <head>
3777 3779 <link rel="icon" href="/static/hgicon.png" type="image/png" />
3778 3780 <meta name="robots" content="index, nofollow" />
3779 3781 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
3780 3782 <script type="text/javascript" src="/static/mercurial.js"></script>
3781 3783
3782 3784 <title>test: error</title>
3783 3785 </head>
3784 3786 <body>
3785 3787
3786 3788 <div class="container">
3787 3789 <div class="menu">
3788 3790 <div class="logo">
3789 3791 <a href="https://mercurial-scm.org/">
3790 3792 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
3791 3793 </div>
3792 3794 <ul>
3793 3795 <li><a href="/shortlog">log</a></li>
3794 3796 <li><a href="/graph">graph</a></li>
3795 3797 <li><a href="/tags">tags</a></li>
3796 3798 <li><a href="/bookmarks">bookmarks</a></li>
3797 3799 <li><a href="/branches">branches</a></li>
3798 3800 </ul>
3799 3801 <ul>
3800 3802 <li><a href="/help">help</a></li>
3801 3803 </ul>
3802 3804 </div>
3803 3805
3804 3806 <div class="main">
3805 3807
3806 3808 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
3807 3809 <h3>error</h3>
3808 3810
3809 3811
3810 3812 <form class="search" action="/log">
3811 3813
3812 3814 <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
3813 3815 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
3814 3816 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
3815 3817 </form>
3816 3818
3817 3819 <div class="description">
3818 3820 <p>
3819 3821 An error occurred while processing your request:
3820 3822 </p>
3821 3823 <p>
3822 3824 Not Found
3823 3825 </p>
3824 3826 </div>
3825 3827 </div>
3826 3828 </div>
3827 3829
3828 3830
3829 3831
3830 3832 </body>
3831 3833 </html>
3832 3834
3833 3835 [1]
3834 3836
3835 3837 $ killdaemons.py
3836 3838
3837 3839 #endif
@@ -1,257 +1,281 b''
1 #testcases vfs svfs
2
1 3 $ echo "[extensions]" >> $HGRCPATH
2 4 $ echo "share = " >> $HGRCPATH
3 5
6 #if svfs
7 $ echo "[format]" >> $HGRCPATH
8 $ echo "bookmarks-in-store = yes " >> $HGRCPATH
9 #endif
10
4 11 prepare repo1
5 12
6 13 $ hg init repo1
7 14 $ cd repo1
8 15 $ echo a > a
9 16 $ hg commit -A -m'init'
10 17 adding a
11 18 $ echo a >> a
12 19 $ hg commit -m'change in shared clone'
13 20 $ echo b > b
14 21 $ hg commit -A -m'another file'
15 22 adding b
16 23
17 24 share it
18 25
19 26 $ cd ..
20 27 $ hg share repo1 repo2
21 28 updating working directory
22 29 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
23 30
24 31 test sharing bookmarks
25 32
26 33 $ hg share -B repo1 repo3
27 34 updating working directory
28 35 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 36 $ cd repo1
30 37 $ hg bookmark bm1
31 38 $ hg bookmarks
32 39 * bm1 2:c2e0ac586386
33 40 $ cd ../repo2
34 41 $ hg book bm2
35 42 $ hg bookmarks
43 bm1 2:c2e0ac586386 (svfs !)
36 44 * bm2 2:c2e0ac586386
37 45 $ cd ../repo3
38 46 $ hg bookmarks
39 47 bm1 2:c2e0ac586386
48 bm2 2:c2e0ac586386 (svfs !)
40 49 $ hg book bm3
41 50 $ hg bookmarks
42 51 bm1 2:c2e0ac586386
52 bm2 2:c2e0ac586386 (svfs !)
43 53 * bm3 2:c2e0ac586386
44 54 $ cd ../repo1
45 55 $ hg bookmarks
46 56 * bm1 2:c2e0ac586386
57 bm2 2:c2e0ac586386 (svfs !)
47 58 bm3 2:c2e0ac586386
48 59
49 60 check whether HG_PENDING makes pending changes only in relatd
50 61 repositories visible to an external hook.
51 62
52 63 In "hg share" case, another transaction can't run in other
53 64 repositories sharing same source repository, because starting
54 65 transaction requires locking store of source repository.
55 66
56 67 Therefore, this test scenario ignores checking visibility of
57 68 .hg/bookmarks.pending in repo2, which shares repo1 without bookmarks.
58 69
59 70 $ cat > $TESTTMP/checkbookmarks.sh <<EOF
60 71 > echo "@repo1"
61 72 > hg -R "$TESTTMP/repo1" bookmarks
62 73 > echo "@repo2"
63 74 > hg -R "$TESTTMP/repo2" bookmarks
64 75 > echo "@repo3"
65 76 > hg -R "$TESTTMP/repo3" bookmarks
66 77 > exit 1 # to avoid adding new bookmark for subsequent tests
67 78 > EOF
68 79
69 80 $ cd ../repo1
70 81 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
71 82 @repo1
72 83 bm1 2:c2e0ac586386
84 bm2 2:c2e0ac586386 (svfs !)
73 85 bm3 2:c2e0ac586386
74 86 * bmX 2:c2e0ac586386
75 87 @repo2
88 bm1 2:c2e0ac586386 (svfs !)
76 89 * bm2 2:c2e0ac586386
90 bm3 2:c2e0ac586386 (svfs !)
77 91 @repo3
78 92 bm1 2:c2e0ac586386
93 bm2 2:c2e0ac586386 (svfs !)
79 94 * bm3 2:c2e0ac586386
80 bmX 2:c2e0ac586386
95 bmX 2:c2e0ac586386 (vfs !)
81 96 transaction abort!
82 97 rollback completed
83 98 abort: pretxnclose hook exited with status 1
84 99 [255]
85 100 $ hg book bm1
86 101
87 102 FYI, in contrast to above test, bmX is invisible in repo1 (= shared
88 103 src), because (1) HG_PENDING refers only repo3 and (2)
89 104 "bookmarks.pending" is written only into repo3.
90 105
91 106 $ cd ../repo3
92 107 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkbookmarks.sh" -q book bmX
93 108 @repo1
94 109 * bm1 2:c2e0ac586386
110 bm2 2:c2e0ac586386 (svfs !)
95 111 bm3 2:c2e0ac586386
96 112 @repo2
113 bm1 2:c2e0ac586386 (svfs !)
97 114 * bm2 2:c2e0ac586386
115 bm3 2:c2e0ac586386 (svfs !)
98 116 @repo3
99 117 bm1 2:c2e0ac586386
118 bm2 2:c2e0ac586386 (svfs !)
100 119 bm3 2:c2e0ac586386
101 120 * bmX 2:c2e0ac586386
102 121 transaction abort!
103 122 rollback completed
104 123 abort: pretxnclose hook exited with status 1
105 124 [255]
106 125 $ hg book bm3
107 126
127 clean up bm2 since it's uninteresting (not shared in the vfs case and
128 same as bm3 in the svfs case)
129 $ cd ../repo2
130 $ hg book -d bm2
131
108 132 $ cd ../repo1
109 133
110 134 test that commits work
111 135
112 136 $ echo 'shared bookmarks' > a
113 137 $ hg commit -m 'testing shared bookmarks'
114 138 $ hg bookmarks
115 139 * bm1 3:b87954705719
116 140 bm3 2:c2e0ac586386
117 141 $ cd ../repo3
118 142 $ hg bookmarks
119 143 bm1 3:b87954705719
120 144 * bm3 2:c2e0ac586386
121 145 $ echo 'more shared bookmarks' > a
122 146 $ hg commit -m 'testing shared bookmarks'
123 147 created new head
124 148 $ hg bookmarks
125 149 bm1 3:b87954705719
126 150 * bm3 4:62f4ded848e4
127 151 $ cd ../repo1
128 152 $ hg bookmarks
129 153 * bm1 3:b87954705719
130 154 bm3 4:62f4ded848e4
131 155 $ cd ..
132 156
133 157 test pushing bookmarks works
134 158
135 159 $ hg clone repo3 repo4
136 160 updating to branch default
137 161 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 162 $ cd repo4
139 163 $ hg boo bm4
140 164 $ echo foo > b
141 165 $ hg commit -m 'foo in b'
142 166 $ hg boo
143 167 bm1 3:b87954705719
144 168 bm3 4:62f4ded848e4
145 169 * bm4 5:92793bfc8cad
146 170 $ hg push -B bm4
147 171 pushing to $TESTTMP/repo3
148 172 searching for changes
149 173 adding changesets
150 174 adding manifests
151 175 adding file changes
152 176 added 1 changesets with 1 changes to 1 files
153 177 exporting bookmark bm4
154 178 $ cd ../repo1
155 179 $ hg bookmarks
156 180 * bm1 3:b87954705719
157 181 bm3 4:62f4ded848e4
158 182 bm4 5:92793bfc8cad
159 183 $ cd ../repo3
160 184 $ hg bookmarks
161 185 bm1 3:b87954705719
162 186 * bm3 4:62f4ded848e4
163 187 bm4 5:92793bfc8cad
164 188 $ cd ..
165 189
166 190 test behavior when sharing a shared repo
167 191
168 192 $ hg share -B repo3 missingdir/repo5
169 193 updating working directory
170 194 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 195 $ cd missingdir/repo5
172 196 $ hg book
173 197 bm1 3:b87954705719
174 198 bm3 4:62f4ded848e4
175 199 bm4 5:92793bfc8cad
176 200 $ cd ../..
177 201
178 202 test what happens when an active bookmark is deleted
179 203
180 204 $ cd repo1
181 205 $ hg boo -d bm3
182 206 $ hg boo
183 207 * bm1 3:b87954705719
184 208 bm4 5:92793bfc8cad
185 209 $ cd ../repo3
186 210 $ hg boo
187 211 bm1 3:b87954705719
188 212 bm4 5:92793bfc8cad
189 213 $ cd ..
190 214
191 215 verify that bookmarks are not written on failed transaction
192 216
193 217 $ cat > failpullbookmarks.py << EOF
194 218 > """A small extension that makes bookmark pulls fail, for testing"""
195 219 > from __future__ import absolute_import
196 220 > from mercurial import (
197 221 > error,
198 222 > exchange,
199 223 > extensions,
200 224 > )
201 225 > def _pullbookmarks(orig, pullop):
202 226 > orig(pullop)
203 227 > raise error.HookAbort('forced failure by extension')
204 228 > def extsetup(ui):
205 229 > extensions.wrapfunction(exchange, '_pullbookmarks', _pullbookmarks)
206 230 > EOF
207 231 $ cd repo4
208 232 $ hg boo
209 233 bm1 3:b87954705719
210 234 bm3 4:62f4ded848e4
211 235 * bm4 5:92793bfc8cad
212 236 $ cd ../repo3
213 237 $ hg boo
214 238 bm1 3:b87954705719
215 239 bm4 5:92793bfc8cad
216 240 $ hg --config "extensions.failpullbookmarks=$TESTTMP/failpullbookmarks.py" pull $TESTTMP/repo4
217 241 pulling from $TESTTMP/repo4
218 242 searching for changes
219 243 no changes found
220 244 adding remote bookmark bm3
221 245 abort: forced failure by extension
222 246 [255]
223 247 $ hg boo
224 248 bm1 3:b87954705719
225 249 bm4 5:92793bfc8cad
226 250 $ hg pull $TESTTMP/repo4
227 251 pulling from $TESTTMP/repo4
228 252 searching for changes
229 253 no changes found
230 254 adding remote bookmark bm3
231 255 1 local changesets published
232 256 $ hg boo
233 257 bm1 3:b87954705719
234 258 * bm3 4:62f4ded848e4
235 259 bm4 5:92793bfc8cad
236 260 $ cd ..
237 261
238 262 verify bookmark behavior after unshare
239 263
240 264 $ cd repo3
241 265 $ hg unshare
242 266 $ hg boo
243 267 bm1 3:b87954705719
244 268 * bm3 4:62f4ded848e4
245 269 bm4 5:92793bfc8cad
246 270 $ hg boo -d bm4
247 271 $ hg boo bm5
248 272 $ hg boo
249 273 bm1 3:b87954705719
250 274 bm3 4:62f4ded848e4
251 275 * bm5 4:62f4ded848e4
252 276 $ cd ../repo1
253 277 $ hg boo
254 278 * bm1 3:b87954705719
255 279 bm3 4:62f4ded848e4
256 280 bm4 5:92793bfc8cad
257 281 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now