##// END OF EJS Templates
bookmark: add a dedicated txnclose-bookmark hook...
Boris Feld -
r34709:ee5f0d04 default
parent child Browse files
Show More
@@ -1,848 +1,857 b''
1 # Mercurial bookmark support code
1 # Mercurial bookmark support code
2 #
2 #
3 # Copyright 2008 David Soria Parra <dsp@php.net>
3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11
11
12 from .i18n import _
12 from .i18n import _
13 from .node import (
13 from .node import (
14 bin,
14 bin,
15 hex,
15 hex,
16 short,
16 short,
17 )
17 )
18 from . import (
18 from . import (
19 encoding,
19 encoding,
20 error,
20 error,
21 lock as lockmod,
21 lock as lockmod,
22 obsutil,
22 obsutil,
23 pycompat,
23 pycompat,
24 scmutil,
24 scmutil,
25 txnutil,
25 txnutil,
26 util,
26 util,
27 )
27 )
28
28
29 # label constants
29 # label constants
30 # until 3.5, bookmarks.current was the advertised name, not
30 # until 3.5, bookmarks.current was the advertised name, not
31 # bookmarks.active, so we must use both to avoid breaking old
31 # bookmarks.active, so we must use both to avoid breaking old
32 # custom styles
32 # custom styles
33 activebookmarklabel = 'bookmarks.active bookmarks.current'
33 activebookmarklabel = 'bookmarks.active bookmarks.current'
34
34
35 def _getbkfile(repo):
35 def _getbkfile(repo):
36 """Hook so that extensions that mess with the store can hook bm storage.
36 """Hook so that extensions that mess with the store can hook bm storage.
37
37
38 For core, this just handles wether we should see pending
38 For core, this just handles wether we should see pending
39 bookmarks or the committed ones. Other extensions (like share)
39 bookmarks or the committed ones. Other extensions (like share)
40 may need to tweak this behavior further.
40 may need to tweak this behavior further.
41 """
41 """
42 fp, pending = txnutil.trypending(repo.root, repo.vfs, 'bookmarks')
42 fp, pending = txnutil.trypending(repo.root, repo.vfs, 'bookmarks')
43 return fp
43 return fp
44
44
45 class bmstore(dict):
45 class bmstore(dict):
46 """Storage for bookmarks.
46 """Storage for bookmarks.
47
47
48 This object should do all bookmark-related reads and writes, so
48 This object should do all bookmark-related reads and writes, so
49 that it's fairly simple to replace the storage underlying
49 that it's fairly simple to replace the storage underlying
50 bookmarks without having to clone the logic surrounding
50 bookmarks without having to clone the logic surrounding
51 bookmarks. This type also should manage the active bookmark, if
51 bookmarks. This type also should manage the active bookmark, if
52 any.
52 any.
53
53
54 This particular bmstore implementation stores bookmarks as
54 This particular bmstore implementation stores bookmarks as
55 {hash}\s{name}\n (the same format as localtags) in
55 {hash}\s{name}\n (the same format as localtags) in
56 .hg/bookmarks. The mapping is stored as {name: nodeid}.
56 .hg/bookmarks. The mapping is stored as {name: nodeid}.
57 """
57 """
58
58
59 def __init__(self, repo):
59 def __init__(self, repo):
60 dict.__init__(self)
60 dict.__init__(self)
61 self._repo = repo
61 self._repo = repo
62 self._clean = True
62 self._clean = True
63 self._aclean = True
63 self._aclean = True
64 nm = repo.changelog.nodemap
64 nm = repo.changelog.nodemap
65 tonode = bin # force local lookup
65 tonode = bin # force local lookup
66 setitem = dict.__setitem__
66 setitem = dict.__setitem__
67 try:
67 try:
68 with _getbkfile(repo) as bkfile:
68 with _getbkfile(repo) as bkfile:
69 for line in bkfile:
69 for line in bkfile:
70 line = line.strip()
70 line = line.strip()
71 if not line:
71 if not line:
72 continue
72 continue
73 try:
73 try:
74 sha, refspec = line.split(' ', 1)
74 sha, refspec = line.split(' ', 1)
75 node = tonode(sha)
75 node = tonode(sha)
76 if node in nm:
76 if node in nm:
77 refspec = encoding.tolocal(refspec)
77 refspec = encoding.tolocal(refspec)
78 setitem(self, refspec, node)
78 setitem(self, refspec, node)
79 except (TypeError, ValueError):
79 except (TypeError, ValueError):
80 # TypeError:
80 # TypeError:
81 # - bin(...)
81 # - bin(...)
82 # ValueError:
82 # ValueError:
83 # - node in nm, for non-20-bytes entry
83 # - node in nm, for non-20-bytes entry
84 # - split(...), for string without ' '
84 # - split(...), for string without ' '
85 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
85 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
86 % line)
86 % line)
87 except IOError as inst:
87 except IOError as inst:
88 if inst.errno != errno.ENOENT:
88 if inst.errno != errno.ENOENT:
89 raise
89 raise
90 self._active = _readactive(repo, self)
90 self._active = _readactive(repo, self)
91
91
92 @property
92 @property
93 def active(self):
93 def active(self):
94 return self._active
94 return self._active
95
95
96 @active.setter
96 @active.setter
97 def active(self, mark):
97 def active(self, mark):
98 if mark is not None and mark not in self:
98 if mark is not None and mark not in self:
99 raise AssertionError('bookmark %s does not exist!' % mark)
99 raise AssertionError('bookmark %s does not exist!' % mark)
100
100
101 self._active = mark
101 self._active = mark
102 self._aclean = False
102 self._aclean = False
103
103
104 def __setitem__(self, *args, **kwargs):
104 def __setitem__(self, *args, **kwargs):
105 msg = ("'bookmarks[name] = node' is deprecated, "
105 msg = ("'bookmarks[name] = node' is deprecated, "
106 "use 'bookmarks.applychanges'")
106 "use 'bookmarks.applychanges'")
107 self._repo.ui.deprecwarn(msg, '4.3')
107 self._repo.ui.deprecwarn(msg, '4.3')
108 self._set(*args, **kwargs)
108 self._set(*args, **kwargs)
109
109
110 def _set(self, key, value):
110 def _set(self, key, value):
111 self._clean = False
111 self._clean = False
112 return dict.__setitem__(self, key, value)
112 return dict.__setitem__(self, key, value)
113
113
114 def __delitem__(self, key):
114 def __delitem__(self, key):
115 msg = ("'del bookmarks[name]' is deprecated, "
115 msg = ("'del bookmarks[name]' is deprecated, "
116 "use 'bookmarks.applychanges'")
116 "use 'bookmarks.applychanges'")
117 self._repo.ui.deprecwarn(msg, '4.3')
117 self._repo.ui.deprecwarn(msg, '4.3')
118 self._del(key)
118 self._del(key)
119
119
120 def _del(self, key):
120 def _del(self, key):
121 self._clean = False
121 self._clean = False
122 return dict.__delitem__(self, key)
122 return dict.__delitem__(self, key)
123
123
124 def applychanges(self, repo, tr, changes):
124 def applychanges(self, repo, tr, changes):
125 """Apply a list of changes to bookmarks
125 """Apply a list of changes to bookmarks
126 """
126 """
127 bmchanges = tr.changes.get('bookmarks')
127 bmchanges = tr.changes.get('bookmarks')
128 for name, node in changes:
128 for name, node in changes:
129 old = self.get(name)
129 old = self.get(name)
130 if node is None:
130 if node is None:
131 self._del(name)
131 self._del(name)
132 else:
132 else:
133 self._set(name, node)
133 self._set(name, node)
134 if bmchanges is not None:
134 if bmchanges is not None:
135 # if a previous value exist preserve the "initial" value
135 # if a previous value exist preserve the "initial" value
136 previous = bmchanges.get(name)
136 previous = bmchanges.get(name)
137 if previous is not None:
137 if previous is not None:
138 old = previous[0]
138 old = previous[0]
139 bmchanges[name] = (old, node)
139 bmchanges[name] = (old, node)
140 self._recordchange(tr)
140 self._recordchange(tr)
141
141
142 def recordchange(self, tr):
142 def recordchange(self, tr):
143 msg = ("'bookmarks.recorchange' is deprecated, "
143 msg = ("'bookmarks.recorchange' is deprecated, "
144 "use 'bookmarks.applychanges'")
144 "use 'bookmarks.applychanges'")
145 self._repo.ui.deprecwarn(msg, '4.3')
145 self._repo.ui.deprecwarn(msg, '4.3')
146 return self._recordchange(tr)
146 return self._recordchange(tr)
147
147
148 def _recordchange(self, tr):
148 def _recordchange(self, tr):
149 """record that bookmarks have been changed in a transaction
149 """record that bookmarks have been changed in a transaction
150
150
151 The transaction is then responsible for updating the file content."""
151 The transaction is then responsible for updating the file content."""
152 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
152 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
153 location='plain')
153 location='plain')
154 tr.hookargs['bookmark_moved'] = '1'
154 tr.hookargs['bookmark_moved'] = '1'
155
155
156 def _writerepo(self, repo):
156 def _writerepo(self, repo):
157 """Factored out for extensibility"""
157 """Factored out for extensibility"""
158 rbm = repo._bookmarks
158 rbm = repo._bookmarks
159 if rbm.active not in self:
159 if rbm.active not in self:
160 rbm.active = None
160 rbm.active = None
161 rbm._writeactive()
161 rbm._writeactive()
162
162
163 with repo.wlock():
163 with repo.wlock():
164 file_ = repo.vfs('bookmarks', 'w', atomictemp=True,
164 file_ = repo.vfs('bookmarks', 'w', atomictemp=True,
165 checkambig=True)
165 checkambig=True)
166 try:
166 try:
167 self._write(file_)
167 self._write(file_)
168 except: # re-raises
168 except: # re-raises
169 file_.discard()
169 file_.discard()
170 raise
170 raise
171 finally:
171 finally:
172 file_.close()
172 file_.close()
173
173
174 def _writeactive(self):
174 def _writeactive(self):
175 if self._aclean:
175 if self._aclean:
176 return
176 return
177 with self._repo.wlock():
177 with self._repo.wlock():
178 if self._active is not None:
178 if self._active is not None:
179 f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
179 f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
180 checkambig=True)
180 checkambig=True)
181 try:
181 try:
182 f.write(encoding.fromlocal(self._active))
182 f.write(encoding.fromlocal(self._active))
183 finally:
183 finally:
184 f.close()
184 f.close()
185 else:
185 else:
186 self._repo.vfs.tryunlink('bookmarks.current')
186 self._repo.vfs.tryunlink('bookmarks.current')
187 self._aclean = True
187 self._aclean = True
188
188
189 def _write(self, fp):
189 def _write(self, fp):
190 for name, node in self.iteritems():
190 for name, node in self.iteritems():
191 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
191 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
192 self._clean = True
192 self._clean = True
193 self._repo.invalidatevolatilesets()
193 self._repo.invalidatevolatilesets()
194
194
195 def expandname(self, bname):
195 def expandname(self, bname):
196 if bname == '.':
196 if bname == '.':
197 if self.active:
197 if self.active:
198 return self.active
198 return self.active
199 else:
199 else:
200 raise error.Abort(_("no active bookmark"))
200 raise error.Abort(_("no active bookmark"))
201 return bname
201 return bname
202
202
203 def checkconflict(self, mark, force=False, target=None):
203 def checkconflict(self, mark, force=False, target=None):
204 """check repo for a potential clash of mark with an existing bookmark,
204 """check repo for a potential clash of mark with an existing bookmark,
205 branch, or hash
205 branch, or hash
206
206
207 If target is supplied, then check that we are moving the bookmark
207 If target is supplied, then check that we are moving the bookmark
208 forward.
208 forward.
209
209
210 If force is supplied, then forcibly move the bookmark to a new commit
210 If force is supplied, then forcibly move the bookmark to a new commit
211 regardless if it is a move forward.
211 regardless if it is a move forward.
212
212
213 If divergent bookmark are to be deleted, they will be returned as list.
213 If divergent bookmark are to be deleted, they will be returned as list.
214 """
214 """
215 cur = self._repo.changectx('.').node()
215 cur = self._repo.changectx('.').node()
216 if mark in self and not force:
216 if mark in self and not force:
217 if target:
217 if target:
218 if self[mark] == target and target == cur:
218 if self[mark] == target and target == cur:
219 # re-activating a bookmark
219 # re-activating a bookmark
220 return []
220 return []
221 rev = self._repo[target].rev()
221 rev = self._repo[target].rev()
222 anc = self._repo.changelog.ancestors([rev])
222 anc = self._repo.changelog.ancestors([rev])
223 bmctx = self._repo[self[mark]]
223 bmctx = self._repo[self[mark]]
224 divs = [self._repo[b].node() for b in self
224 divs = [self._repo[b].node() for b in self
225 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
225 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
226
226
227 # allow resolving a single divergent bookmark even if moving
227 # allow resolving a single divergent bookmark even if moving
228 # the bookmark across branches when a revision is specified
228 # the bookmark across branches when a revision is specified
229 # that contains a divergent bookmark
229 # that contains a divergent bookmark
230 if bmctx.rev() not in anc and target in divs:
230 if bmctx.rev() not in anc and target in divs:
231 return divergent2delete(self._repo, [target], mark)
231 return divergent2delete(self._repo, [target], mark)
232
232
233 deletefrom = [b for b in divs
233 deletefrom = [b for b in divs
234 if self._repo[b].rev() in anc or b == target]
234 if self._repo[b].rev() in anc or b == target]
235 delbms = divergent2delete(self._repo, deletefrom, mark)
235 delbms = divergent2delete(self._repo, deletefrom, mark)
236 if validdest(self._repo, bmctx, self._repo[target]):
236 if validdest(self._repo, bmctx, self._repo[target]):
237 self._repo.ui.status(
237 self._repo.ui.status(
238 _("moving bookmark '%s' forward from %s\n") %
238 _("moving bookmark '%s' forward from %s\n") %
239 (mark, short(bmctx.node())))
239 (mark, short(bmctx.node())))
240 return delbms
240 return delbms
241 raise error.Abort(_("bookmark '%s' already exists "
241 raise error.Abort(_("bookmark '%s' already exists "
242 "(use -f to force)") % mark)
242 "(use -f to force)") % mark)
243 if ((mark in self._repo.branchmap() or
243 if ((mark in self._repo.branchmap() or
244 mark == self._repo.dirstate.branch()) and not force):
244 mark == self._repo.dirstate.branch()) and not force):
245 raise error.Abort(
245 raise error.Abort(
246 _("a bookmark cannot have the name of an existing branch"))
246 _("a bookmark cannot have the name of an existing branch"))
247 if len(mark) > 3 and not force:
247 if len(mark) > 3 and not force:
248 try:
248 try:
249 shadowhash = (mark in self._repo)
249 shadowhash = (mark in self._repo)
250 except error.LookupError: # ambiguous identifier
250 except error.LookupError: # ambiguous identifier
251 shadowhash = False
251 shadowhash = False
252 if shadowhash:
252 if shadowhash:
253 self._repo.ui.warn(
253 self._repo.ui.warn(
254 _("bookmark %s matches a changeset hash\n"
254 _("bookmark %s matches a changeset hash\n"
255 "(did you leave a -r out of an 'hg bookmark' "
255 "(did you leave a -r out of an 'hg bookmark' "
256 "command?)\n")
256 "command?)\n")
257 % mark)
257 % mark)
258 return []
258 return []
259
259
260 def _readactive(repo, marks):
260 def _readactive(repo, marks):
261 """
261 """
262 Get the active bookmark. We can have an active bookmark that updates
262 Get the active bookmark. We can have an active bookmark that updates
263 itself as we commit. This function returns the name of that bookmark.
263 itself as we commit. This function returns the name of that bookmark.
264 It is stored in .hg/bookmarks.current
264 It is stored in .hg/bookmarks.current
265 """
265 """
266 mark = None
266 mark = None
267 try:
267 try:
268 file = repo.vfs('bookmarks.current')
268 file = repo.vfs('bookmarks.current')
269 except IOError as inst:
269 except IOError as inst:
270 if inst.errno != errno.ENOENT:
270 if inst.errno != errno.ENOENT:
271 raise
271 raise
272 return None
272 return None
273 try:
273 try:
274 # No readline() in osutil.posixfile, reading everything is
274 # No readline() in osutil.posixfile, reading everything is
275 # cheap.
275 # cheap.
276 # Note that it's possible for readlines() here to raise
276 # Note that it's possible for readlines() here to raise
277 # IOError, since we might be reading the active mark over
277 # IOError, since we might be reading the active mark over
278 # static-http which only tries to load the file when we try
278 # static-http which only tries to load the file when we try
279 # to read from it.
279 # to read from it.
280 mark = encoding.tolocal((file.readlines() or [''])[0])
280 mark = encoding.tolocal((file.readlines() or [''])[0])
281 if mark == '' or mark not in marks:
281 if mark == '' or mark not in marks:
282 mark = None
282 mark = None
283 except IOError as inst:
283 except IOError as inst:
284 if inst.errno != errno.ENOENT:
284 if inst.errno != errno.ENOENT:
285 raise
285 raise
286 return None
286 return None
287 finally:
287 finally:
288 file.close()
288 file.close()
289 return mark
289 return mark
290
290
291 def activate(repo, mark):
291 def activate(repo, mark):
292 """
292 """
293 Set the given bookmark to be 'active', meaning that this bookmark will
293 Set the given bookmark to be 'active', meaning that this bookmark will
294 follow new commits that are made.
294 follow new commits that are made.
295 The name is recorded in .hg/bookmarks.current
295 The name is recorded in .hg/bookmarks.current
296 """
296 """
297 repo._bookmarks.active = mark
297 repo._bookmarks.active = mark
298 repo._bookmarks._writeactive()
298 repo._bookmarks._writeactive()
299
299
300 def deactivate(repo):
300 def deactivate(repo):
301 """
301 """
302 Unset the active bookmark in this repository.
302 Unset the active bookmark in this repository.
303 """
303 """
304 repo._bookmarks.active = None
304 repo._bookmarks.active = None
305 repo._bookmarks._writeactive()
305 repo._bookmarks._writeactive()
306
306
307 def isactivewdirparent(repo):
307 def isactivewdirparent(repo):
308 """
308 """
309 Tell whether the 'active' bookmark (the one that follows new commits)
309 Tell whether the 'active' bookmark (the one that follows new commits)
310 points to one of the parents of the current working directory (wdir).
310 points to one of the parents of the current working directory (wdir).
311
311
312 While this is normally the case, it can on occasion be false; for example,
312 While this is normally the case, it can on occasion be false; for example,
313 immediately after a pull, the active bookmark can be moved to point
313 immediately after a pull, the active bookmark can be moved to point
314 to a place different than the wdir. This is solved by running `hg update`.
314 to a place different than the wdir. This is solved by running `hg update`.
315 """
315 """
316 mark = repo._activebookmark
316 mark = repo._activebookmark
317 marks = repo._bookmarks
317 marks = repo._bookmarks
318 parents = [p.node() for p in repo[None].parents()]
318 parents = [p.node() for p in repo[None].parents()]
319 return (mark in marks and marks[mark] in parents)
319 return (mark in marks and marks[mark] in parents)
320
320
321 def divergent2delete(repo, deletefrom, bm):
321 def divergent2delete(repo, deletefrom, bm):
322 """find divergent versions of bm on nodes in deletefrom.
322 """find divergent versions of bm on nodes in deletefrom.
323
323
324 the list of bookmark to delete."""
324 the list of bookmark to delete."""
325 todelete = []
325 todelete = []
326 marks = repo._bookmarks
326 marks = repo._bookmarks
327 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
327 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
328 for mark in divergent:
328 for mark in divergent:
329 if mark == '@' or '@' not in mark:
329 if mark == '@' or '@' not in mark:
330 # can't be divergent by definition
330 # can't be divergent by definition
331 continue
331 continue
332 if mark and marks[mark] in deletefrom:
332 if mark and marks[mark] in deletefrom:
333 if mark != bm:
333 if mark != bm:
334 todelete.append(mark)
334 todelete.append(mark)
335 return todelete
335 return todelete
336
336
337 def headsforactive(repo):
337 def headsforactive(repo):
338 """Given a repo with an active bookmark, return divergent bookmark nodes.
338 """Given a repo with an active bookmark, return divergent bookmark nodes.
339
339
340 Args:
340 Args:
341 repo: A repository with an active bookmark.
341 repo: A repository with an active bookmark.
342
342
343 Returns:
343 Returns:
344 A list of binary node ids that is the full list of other
344 A list of binary node ids that is the full list of other
345 revisions with bookmarks divergent from the active bookmark. If
345 revisions with bookmarks divergent from the active bookmark. If
346 there were no divergent bookmarks, then this list will contain
346 there were no divergent bookmarks, then this list will contain
347 only one entry.
347 only one entry.
348 """
348 """
349 if not repo._activebookmark:
349 if not repo._activebookmark:
350 raise ValueError(
350 raise ValueError(
351 'headsforactive() only makes sense with an active bookmark')
351 'headsforactive() only makes sense with an active bookmark')
352 name = repo._activebookmark.split('@', 1)[0]
352 name = repo._activebookmark.split('@', 1)[0]
353 heads = []
353 heads = []
354 for mark, n in repo._bookmarks.iteritems():
354 for mark, n in repo._bookmarks.iteritems():
355 if mark.split('@', 1)[0] == name:
355 if mark.split('@', 1)[0] == name:
356 heads.append(n)
356 heads.append(n)
357 return heads
357 return heads
358
358
359 def calculateupdate(ui, repo, checkout):
359 def calculateupdate(ui, repo, checkout):
360 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
360 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
361 check out and where to move the active bookmark from, if needed.'''
361 check out and where to move the active bookmark from, if needed.'''
362 movemarkfrom = None
362 movemarkfrom = None
363 if checkout is None:
363 if checkout is None:
364 activemark = repo._activebookmark
364 activemark = repo._activebookmark
365 if isactivewdirparent(repo):
365 if isactivewdirparent(repo):
366 movemarkfrom = repo['.'].node()
366 movemarkfrom = repo['.'].node()
367 elif activemark:
367 elif activemark:
368 ui.status(_("updating to active bookmark %s\n") % activemark)
368 ui.status(_("updating to active bookmark %s\n") % activemark)
369 checkout = activemark
369 checkout = activemark
370 return (checkout, movemarkfrom)
370 return (checkout, movemarkfrom)
371
371
372 def update(repo, parents, node):
372 def update(repo, parents, node):
373 deletefrom = parents
373 deletefrom = parents
374 marks = repo._bookmarks
374 marks = repo._bookmarks
375 active = marks.active
375 active = marks.active
376 if not active:
376 if not active:
377 return False
377 return False
378
378
379 bmchanges = []
379 bmchanges = []
380 if marks[active] in parents:
380 if marks[active] in parents:
381 new = repo[node]
381 new = repo[node]
382 divs = [repo[b] for b in marks
382 divs = [repo[b] for b in marks
383 if b.split('@', 1)[0] == active.split('@', 1)[0]]
383 if b.split('@', 1)[0] == active.split('@', 1)[0]]
384 anc = repo.changelog.ancestors([new.rev()])
384 anc = repo.changelog.ancestors([new.rev()])
385 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
385 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
386 if validdest(repo, repo[marks[active]], new):
386 if validdest(repo, repo[marks[active]], new):
387 bmchanges.append((active, new.node()))
387 bmchanges.append((active, new.node()))
388
388
389 for bm in divergent2delete(repo, deletefrom, active):
389 for bm in divergent2delete(repo, deletefrom, active):
390 bmchanges.append((bm, None))
390 bmchanges.append((bm, None))
391
391
392 if bmchanges:
392 if bmchanges:
393 lock = tr = None
393 lock = tr = None
394 try:
394 try:
395 lock = repo.lock()
395 lock = repo.lock()
396 tr = repo.transaction('bookmark')
396 tr = repo.transaction('bookmark')
397 marks.applychanges(repo, tr, bmchanges)
397 marks.applychanges(repo, tr, bmchanges)
398 tr.close()
398 tr.close()
399 finally:
399 finally:
400 lockmod.release(tr, lock)
400 lockmod.release(tr, lock)
401 return bool(bmchanges)
401 return bool(bmchanges)
402
402
403 def listbinbookmarks(repo):
403 def listbinbookmarks(repo):
404 # We may try to list bookmarks on a repo type that does not
404 # We may try to list bookmarks on a repo type that does not
405 # support it (e.g., statichttprepository).
405 # support it (e.g., statichttprepository).
406 marks = getattr(repo, '_bookmarks', {})
406 marks = getattr(repo, '_bookmarks', {})
407
407
408 hasnode = repo.changelog.hasnode
408 hasnode = repo.changelog.hasnode
409 for k, v in marks.iteritems():
409 for k, v in marks.iteritems():
410 # don't expose local divergent bookmarks
410 # don't expose local divergent bookmarks
411 if hasnode(v) and ('@' not in k or k.endswith('@')):
411 if hasnode(v) and ('@' not in k or k.endswith('@')):
412 yield k, v
412 yield k, v
413
413
414 def listbookmarks(repo):
414 def listbookmarks(repo):
415 d = {}
415 d = {}
416 for book, node in listbinbookmarks(repo):
416 for book, node in listbinbookmarks(repo):
417 d[book] = hex(node)
417 d[book] = hex(node)
418 return d
418 return d
419
419
420 def pushbookmark(repo, key, old, new):
420 def pushbookmark(repo, key, old, new):
421 w = l = tr = None
421 w = l = tr = None
422 try:
422 try:
423 w = repo.wlock()
423 w = repo.wlock()
424 l = repo.lock()
424 l = repo.lock()
425 tr = repo.transaction('bookmarks')
425 tr = repo.transaction('bookmarks')
426 marks = repo._bookmarks
426 marks = repo._bookmarks
427 existing = hex(marks.get(key, ''))
427 existing = hex(marks.get(key, ''))
428 if existing != old and existing != new:
428 if existing != old and existing != new:
429 return False
429 return False
430 if new == '':
430 if new == '':
431 changes = [(key, None)]
431 changes = [(key, None)]
432 else:
432 else:
433 if new not in repo:
433 if new not in repo:
434 return False
434 return False
435 changes = [(key, repo[new].node())]
435 changes = [(key, repo[new].node())]
436 marks.applychanges(repo, tr, changes)
436 marks.applychanges(repo, tr, changes)
437 tr.close()
437 tr.close()
438 return True
438 return True
439 finally:
439 finally:
440 lockmod.release(tr, l, w)
440 lockmod.release(tr, l, w)
441
441
442 def comparebookmarks(repo, srcmarks, dstmarks, targets=None):
442 def comparebookmarks(repo, srcmarks, dstmarks, targets=None):
443 '''Compare bookmarks between srcmarks and dstmarks
443 '''Compare bookmarks between srcmarks and dstmarks
444
444
445 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
445 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
446 differ, invalid)", each are list of bookmarks below:
446 differ, invalid)", each are list of bookmarks below:
447
447
448 :addsrc: added on src side (removed on dst side, perhaps)
448 :addsrc: added on src side (removed on dst side, perhaps)
449 :adddst: added on dst side (removed on src side, perhaps)
449 :adddst: added on dst side (removed on src side, perhaps)
450 :advsrc: advanced on src side
450 :advsrc: advanced on src side
451 :advdst: advanced on dst side
451 :advdst: advanced on dst side
452 :diverge: diverge
452 :diverge: diverge
453 :differ: changed, but changeset referred on src is unknown on dst
453 :differ: changed, but changeset referred on src is unknown on dst
454 :invalid: unknown on both side
454 :invalid: unknown on both side
455 :same: same on both side
455 :same: same on both side
456
456
457 Each elements of lists in result tuple is tuple "(bookmark name,
457 Each elements of lists in result tuple is tuple "(bookmark name,
458 changeset ID on source side, changeset ID on destination
458 changeset ID on source side, changeset ID on destination
459 side)". Each changeset IDs are 40 hexadecimal digit string or
459 side)". Each changeset IDs are 40 hexadecimal digit string or
460 None.
460 None.
461
461
462 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
462 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
463 "invalid" list may be unknown for repo.
463 "invalid" list may be unknown for repo.
464
464
465 If "targets" is specified, only bookmarks listed in it are
465 If "targets" is specified, only bookmarks listed in it are
466 examined.
466 examined.
467 '''
467 '''
468
468
469 if targets:
469 if targets:
470 bset = set(targets)
470 bset = set(targets)
471 else:
471 else:
472 srcmarkset = set(srcmarks)
472 srcmarkset = set(srcmarks)
473 dstmarkset = set(dstmarks)
473 dstmarkset = set(dstmarks)
474 bset = srcmarkset | dstmarkset
474 bset = srcmarkset | dstmarkset
475
475
476 results = ([], [], [], [], [], [], [], [])
476 results = ([], [], [], [], [], [], [], [])
477 addsrc = results[0].append
477 addsrc = results[0].append
478 adddst = results[1].append
478 adddst = results[1].append
479 advsrc = results[2].append
479 advsrc = results[2].append
480 advdst = results[3].append
480 advdst = results[3].append
481 diverge = results[4].append
481 diverge = results[4].append
482 differ = results[5].append
482 differ = results[5].append
483 invalid = results[6].append
483 invalid = results[6].append
484 same = results[7].append
484 same = results[7].append
485
485
486 for b in sorted(bset):
486 for b in sorted(bset):
487 if b not in srcmarks:
487 if b not in srcmarks:
488 if b in dstmarks:
488 if b in dstmarks:
489 adddst((b, None, dstmarks[b]))
489 adddst((b, None, dstmarks[b]))
490 else:
490 else:
491 invalid((b, None, None))
491 invalid((b, None, None))
492 elif b not in dstmarks:
492 elif b not in dstmarks:
493 addsrc((b, srcmarks[b], None))
493 addsrc((b, srcmarks[b], None))
494 else:
494 else:
495 scid = srcmarks[b]
495 scid = srcmarks[b]
496 dcid = dstmarks[b]
496 dcid = dstmarks[b]
497 if scid == dcid:
497 if scid == dcid:
498 same((b, scid, dcid))
498 same((b, scid, dcid))
499 elif scid in repo and dcid in repo:
499 elif scid in repo and dcid in repo:
500 sctx = repo[scid]
500 sctx = repo[scid]
501 dctx = repo[dcid]
501 dctx = repo[dcid]
502 if sctx.rev() < dctx.rev():
502 if sctx.rev() < dctx.rev():
503 if validdest(repo, sctx, dctx):
503 if validdest(repo, sctx, dctx):
504 advdst((b, scid, dcid))
504 advdst((b, scid, dcid))
505 else:
505 else:
506 diverge((b, scid, dcid))
506 diverge((b, scid, dcid))
507 else:
507 else:
508 if validdest(repo, dctx, sctx):
508 if validdest(repo, dctx, sctx):
509 advsrc((b, scid, dcid))
509 advsrc((b, scid, dcid))
510 else:
510 else:
511 diverge((b, scid, dcid))
511 diverge((b, scid, dcid))
512 else:
512 else:
513 # it is too expensive to examine in detail, in this case
513 # it is too expensive to examine in detail, in this case
514 differ((b, scid, dcid))
514 differ((b, scid, dcid))
515
515
516 return results
516 return results
517
517
518 def _diverge(ui, b, path, localmarks, remotenode):
518 def _diverge(ui, b, path, localmarks, remotenode):
519 '''Return appropriate diverged bookmark for specified ``path``
519 '''Return appropriate diverged bookmark for specified ``path``
520
520
521 This returns None, if it is failed to assign any divergent
521 This returns None, if it is failed to assign any divergent
522 bookmark name.
522 bookmark name.
523
523
524 This reuses already existing one with "@number" suffix, if it
524 This reuses already existing one with "@number" suffix, if it
525 refers ``remotenode``.
525 refers ``remotenode``.
526 '''
526 '''
527 if b == '@':
527 if b == '@':
528 b = ''
528 b = ''
529 # try to use an @pathalias suffix
529 # try to use an @pathalias suffix
530 # if an @pathalias already exists, we overwrite (update) it
530 # if an @pathalias already exists, we overwrite (update) it
531 if path.startswith("file:"):
531 if path.startswith("file:"):
532 path = util.url(path).path
532 path = util.url(path).path
533 for p, u in ui.configitems("paths"):
533 for p, u in ui.configitems("paths"):
534 if u.startswith("file:"):
534 if u.startswith("file:"):
535 u = util.url(u).path
535 u = util.url(u).path
536 if path == u:
536 if path == u:
537 return '%s@%s' % (b, p)
537 return '%s@%s' % (b, p)
538
538
539 # assign a unique "@number" suffix newly
539 # assign a unique "@number" suffix newly
540 for x in range(1, 100):
540 for x in range(1, 100):
541 n = '%s@%d' % (b, x)
541 n = '%s@%d' % (b, x)
542 if n not in localmarks or localmarks[n] == remotenode:
542 if n not in localmarks or localmarks[n] == remotenode:
543 return n
543 return n
544
544
545 return None
545 return None
546
546
547 def unhexlifybookmarks(marks):
547 def unhexlifybookmarks(marks):
548 binremotemarks = {}
548 binremotemarks = {}
549 for name, node in marks.items():
549 for name, node in marks.items():
550 binremotemarks[name] = bin(node)
550 binremotemarks[name] = bin(node)
551 return binremotemarks
551 return binremotemarks
552
552
553 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
553 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
554 ui.debug("checking for updated bookmarks\n")
554 ui.debug("checking for updated bookmarks\n")
555 localmarks = repo._bookmarks
555 localmarks = repo._bookmarks
556 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
556 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
557 ) = comparebookmarks(repo, remotemarks, localmarks)
557 ) = comparebookmarks(repo, remotemarks, localmarks)
558
558
559 status = ui.status
559 status = ui.status
560 warn = ui.warn
560 warn = ui.warn
561 if ui.configbool('ui', 'quietbookmarkmove'):
561 if ui.configbool('ui', 'quietbookmarkmove'):
562 status = warn = ui.debug
562 status = warn = ui.debug
563
563
564 explicit = set(explicit)
564 explicit = set(explicit)
565 changed = []
565 changed = []
566 for b, scid, dcid in addsrc:
566 for b, scid, dcid in addsrc:
567 if scid in repo: # add remote bookmarks for changes we already have
567 if scid in repo: # add remote bookmarks for changes we already have
568 changed.append((b, scid, status,
568 changed.append((b, scid, status,
569 _("adding remote bookmark %s\n") % (b)))
569 _("adding remote bookmark %s\n") % (b)))
570 elif b in explicit:
570 elif b in explicit:
571 explicit.remove(b)
571 explicit.remove(b)
572 ui.warn(_("remote bookmark %s points to locally missing %s\n")
572 ui.warn(_("remote bookmark %s points to locally missing %s\n")
573 % (b, hex(scid)[:12]))
573 % (b, hex(scid)[:12]))
574
574
575 for b, scid, dcid in advsrc:
575 for b, scid, dcid in advsrc:
576 changed.append((b, scid, status,
576 changed.append((b, scid, status,
577 _("updating bookmark %s\n") % (b)))
577 _("updating bookmark %s\n") % (b)))
578 # remove normal movement from explicit set
578 # remove normal movement from explicit set
579 explicit.difference_update(d[0] for d in changed)
579 explicit.difference_update(d[0] for d in changed)
580
580
581 for b, scid, dcid in diverge:
581 for b, scid, dcid in diverge:
582 if b in explicit:
582 if b in explicit:
583 explicit.discard(b)
583 explicit.discard(b)
584 changed.append((b, scid, status,
584 changed.append((b, scid, status,
585 _("importing bookmark %s\n") % (b)))
585 _("importing bookmark %s\n") % (b)))
586 else:
586 else:
587 db = _diverge(ui, b, path, localmarks, scid)
587 db = _diverge(ui, b, path, localmarks, scid)
588 if db:
588 if db:
589 changed.append((db, scid, warn,
589 changed.append((db, scid, warn,
590 _("divergent bookmark %s stored as %s\n") %
590 _("divergent bookmark %s stored as %s\n") %
591 (b, db)))
591 (b, db)))
592 else:
592 else:
593 warn(_("warning: failed to assign numbered name "
593 warn(_("warning: failed to assign numbered name "
594 "to divergent bookmark %s\n") % (b))
594 "to divergent bookmark %s\n") % (b))
595 for b, scid, dcid in adddst + advdst:
595 for b, scid, dcid in adddst + advdst:
596 if b in explicit:
596 if b in explicit:
597 explicit.discard(b)
597 explicit.discard(b)
598 changed.append((b, scid, status,
598 changed.append((b, scid, status,
599 _("importing bookmark %s\n") % (b)))
599 _("importing bookmark %s\n") % (b)))
600 for b, scid, dcid in differ:
600 for b, scid, dcid in differ:
601 if b in explicit:
601 if b in explicit:
602 explicit.remove(b)
602 explicit.remove(b)
603 ui.warn(_("remote bookmark %s points to locally missing %s\n")
603 ui.warn(_("remote bookmark %s points to locally missing %s\n")
604 % (b, hex(scid)[:12]))
604 % (b, hex(scid)[:12]))
605
605
606 if changed:
606 if changed:
607 tr = trfunc()
607 tr = trfunc()
608 changes = []
608 changes = []
609 for b, node, writer, msg in sorted(changed):
609 for b, node, writer, msg in sorted(changed):
610 changes.append((b, node))
610 changes.append((b, node))
611 writer(msg)
611 writer(msg)
612 localmarks.applychanges(repo, tr, changes)
612 localmarks.applychanges(repo, tr, changes)
613
613
614 def incoming(ui, repo, other):
614 def incoming(ui, repo, other):
615 '''Show bookmarks incoming from other to repo
615 '''Show bookmarks incoming from other to repo
616 '''
616 '''
617 ui.status(_("searching for changed bookmarks\n"))
617 ui.status(_("searching for changed bookmarks\n"))
618
618
619 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
619 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
620 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
620 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
621 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
621 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
622
622
623 incomings = []
623 incomings = []
624 if ui.debugflag:
624 if ui.debugflag:
625 getid = lambda id: id
625 getid = lambda id: id
626 else:
626 else:
627 getid = lambda id: id[:12]
627 getid = lambda id: id[:12]
628 if ui.verbose:
628 if ui.verbose:
629 def add(b, id, st):
629 def add(b, id, st):
630 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
630 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
631 else:
631 else:
632 def add(b, id, st):
632 def add(b, id, st):
633 incomings.append(" %-25s %s\n" % (b, getid(id)))
633 incomings.append(" %-25s %s\n" % (b, getid(id)))
634 for b, scid, dcid in addsrc:
634 for b, scid, dcid in addsrc:
635 # i18n: "added" refers to a bookmark
635 # i18n: "added" refers to a bookmark
636 add(b, hex(scid), _('added'))
636 add(b, hex(scid), _('added'))
637 for b, scid, dcid in advsrc:
637 for b, scid, dcid in advsrc:
638 # i18n: "advanced" refers to a bookmark
638 # i18n: "advanced" refers to a bookmark
639 add(b, hex(scid), _('advanced'))
639 add(b, hex(scid), _('advanced'))
640 for b, scid, dcid in diverge:
640 for b, scid, dcid in diverge:
641 # i18n: "diverged" refers to a bookmark
641 # i18n: "diverged" refers to a bookmark
642 add(b, hex(scid), _('diverged'))
642 add(b, hex(scid), _('diverged'))
643 for b, scid, dcid in differ:
643 for b, scid, dcid in differ:
644 # i18n: "changed" refers to a bookmark
644 # i18n: "changed" refers to a bookmark
645 add(b, hex(scid), _('changed'))
645 add(b, hex(scid), _('changed'))
646
646
647 if not incomings:
647 if not incomings:
648 ui.status(_("no changed bookmarks found\n"))
648 ui.status(_("no changed bookmarks found\n"))
649 return 1
649 return 1
650
650
651 for s in sorted(incomings):
651 for s in sorted(incomings):
652 ui.write(s)
652 ui.write(s)
653
653
654 return 0
654 return 0
655
655
656 def outgoing(ui, repo, other):
656 def outgoing(ui, repo, other):
657 '''Show bookmarks outgoing from repo to other
657 '''Show bookmarks outgoing from repo to other
658 '''
658 '''
659 ui.status(_("searching for changed bookmarks\n"))
659 ui.status(_("searching for changed bookmarks\n"))
660
660
661 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
661 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
662 r = comparebookmarks(repo, repo._bookmarks, remotemarks)
662 r = comparebookmarks(repo, repo._bookmarks, remotemarks)
663 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
663 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
664
664
665 outgoings = []
665 outgoings = []
666 if ui.debugflag:
666 if ui.debugflag:
667 getid = lambda id: id
667 getid = lambda id: id
668 else:
668 else:
669 getid = lambda id: id[:12]
669 getid = lambda id: id[:12]
670 if ui.verbose:
670 if ui.verbose:
671 def add(b, id, st):
671 def add(b, id, st):
672 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
672 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
673 else:
673 else:
674 def add(b, id, st):
674 def add(b, id, st):
675 outgoings.append(" %-25s %s\n" % (b, getid(id)))
675 outgoings.append(" %-25s %s\n" % (b, getid(id)))
676 for b, scid, dcid in addsrc:
676 for b, scid, dcid in addsrc:
677 # i18n: "added refers to a bookmark
677 # i18n: "added refers to a bookmark
678 add(b, hex(scid), _('added'))
678 add(b, hex(scid), _('added'))
679 for b, scid, dcid in adddst:
679 for b, scid, dcid in adddst:
680 # i18n: "deleted" refers to a bookmark
680 # i18n: "deleted" refers to a bookmark
681 add(b, ' ' * 40, _('deleted'))
681 add(b, ' ' * 40, _('deleted'))
682 for b, scid, dcid in advsrc:
682 for b, scid, dcid in advsrc:
683 # i18n: "advanced" refers to a bookmark
683 # i18n: "advanced" refers to a bookmark
684 add(b, hex(scid), _('advanced'))
684 add(b, hex(scid), _('advanced'))
685 for b, scid, dcid in diverge:
685 for b, scid, dcid in diverge:
686 # i18n: "diverged" refers to a bookmark
686 # i18n: "diverged" refers to a bookmark
687 add(b, hex(scid), _('diverged'))
687 add(b, hex(scid), _('diverged'))
688 for b, scid, dcid in differ:
688 for b, scid, dcid in differ:
689 # i18n: "changed" refers to a bookmark
689 # i18n: "changed" refers to a bookmark
690 add(b, hex(scid), _('changed'))
690 add(b, hex(scid), _('changed'))
691
691
692 if not outgoings:
692 if not outgoings:
693 ui.status(_("no changed bookmarks found\n"))
693 ui.status(_("no changed bookmarks found\n"))
694 return 1
694 return 1
695
695
696 for s in sorted(outgoings):
696 for s in sorted(outgoings):
697 ui.write(s)
697 ui.write(s)
698
698
699 return 0
699 return 0
700
700
701 def summary(repo, other):
701 def summary(repo, other):
702 '''Compare bookmarks between repo and other for "hg summary" output
702 '''Compare bookmarks between repo and other for "hg summary" output
703
703
704 This returns "(# of incoming, # of outgoing)" tuple.
704 This returns "(# of incoming, # of outgoing)" tuple.
705 '''
705 '''
706 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
706 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
707 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
707 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
708 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
708 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
709 return (len(addsrc), len(adddst))
709 return (len(addsrc), len(adddst))
710
710
711 def validdest(repo, old, new):
711 def validdest(repo, old, new):
712 """Is the new bookmark destination a valid update from the old one"""
712 """Is the new bookmark destination a valid update from the old one"""
713 repo = repo.unfiltered()
713 repo = repo.unfiltered()
714 if old == new:
714 if old == new:
715 # Old == new -> nothing to update.
715 # Old == new -> nothing to update.
716 return False
716 return False
717 elif not old:
717 elif not old:
718 # old is nullrev, anything is valid.
718 # old is nullrev, anything is valid.
719 # (new != nullrev has been excluded by the previous check)
719 # (new != nullrev has been excluded by the previous check)
720 return True
720 return True
721 elif repo.obsstore:
721 elif repo.obsstore:
722 return new.node() in obsutil.foreground(repo, [old.node()])
722 return new.node() in obsutil.foreground(repo, [old.node()])
723 else:
723 else:
724 # still an independent clause as it is lazier (and therefore faster)
724 # still an independent clause as it is lazier (and therefore faster)
725 return old.descendant(new)
725 return old.descendant(new)
726
726
727 def checkformat(repo, mark):
727 def checkformat(repo, mark):
728 """return a valid version of a potential bookmark name
728 """return a valid version of a potential bookmark name
729
729
730 Raises an abort error if the bookmark name is not valid.
730 Raises an abort error if the bookmark name is not valid.
731 """
731 """
732 mark = mark.strip()
732 mark = mark.strip()
733 if not mark:
733 if not mark:
734 raise error.Abort(_("bookmark names cannot consist entirely of "
734 raise error.Abort(_("bookmark names cannot consist entirely of "
735 "whitespace"))
735 "whitespace"))
736 scmutil.checknewlabel(repo, mark, 'bookmark')
736 scmutil.checknewlabel(repo, mark, 'bookmark')
737 return mark
737 return mark
738
738
739 def delete(repo, tr, names):
739 def delete(repo, tr, names):
740 """remove a mark from the bookmark store
740 """remove a mark from the bookmark store
741
741
742 Raises an abort error if mark does not exist.
742 Raises an abort error if mark does not exist.
743 """
743 """
744 marks = repo._bookmarks
744 marks = repo._bookmarks
745 changes = []
745 changes = []
746 for mark in names:
746 for mark in names:
747 if mark not in marks:
747 if mark not in marks:
748 raise error.Abort(_("bookmark '%s' does not exist") % mark)
748 raise error.Abort(_("bookmark '%s' does not exist") % mark)
749 if mark == repo._activebookmark:
749 if mark == repo._activebookmark:
750 deactivate(repo)
750 deactivate(repo)
751 changes.append((mark, None))
751 changes.append((mark, None))
752 marks.applychanges(repo, tr, changes)
752 marks.applychanges(repo, tr, changes)
753
753
754 def rename(repo, tr, old, new, force=False, inactive=False):
754 def rename(repo, tr, old, new, force=False, inactive=False):
755 """rename a bookmark from old to new
755 """rename a bookmark from old to new
756
756
757 If force is specified, then the new name can overwrite an existing
757 If force is specified, then the new name can overwrite an existing
758 bookmark.
758 bookmark.
759
759
760 If inactive is specified, then do not activate the new bookmark.
760 If inactive is specified, then do not activate the new bookmark.
761
761
762 Raises an abort error if old is not in the bookmark store.
762 Raises an abort error if old is not in the bookmark store.
763 """
763 """
764 marks = repo._bookmarks
764 marks = repo._bookmarks
765 mark = checkformat(repo, new)
765 mark = checkformat(repo, new)
766 if old not in marks:
766 if old not in marks:
767 raise error.Abort(_("bookmark '%s' does not exist") % old)
767 raise error.Abort(_("bookmark '%s' does not exist") % old)
768 changes = []
768 changes = []
769 for bm in marks.checkconflict(mark, force):
769 for bm in marks.checkconflict(mark, force):
770 changes.append((bm, None))
770 changes.append((bm, None))
771 changes.extend([(mark, marks[old]), (old, None)])
771 changes.extend([(mark, marks[old]), (old, None)])
772 marks.applychanges(repo, tr, changes)
772 marks.applychanges(repo, tr, changes)
773 if repo._activebookmark == old and not inactive:
773 if repo._activebookmark == old and not inactive:
774 activate(repo, mark)
774 activate(repo, mark)
775
775
776 def addbookmarks(repo, tr, names, rev=None, force=False, inactive=False):
776 def addbookmarks(repo, tr, names, rev=None, force=False, inactive=False):
777 """add a list of bookmarks
777 """add a list of bookmarks
778
778
779 If force is specified, then the new name can overwrite an existing
779 If force is specified, then the new name can overwrite an existing
780 bookmark.
780 bookmark.
781
781
782 If inactive is specified, then do not activate any bookmark. Otherwise, the
782 If inactive is specified, then do not activate any bookmark. Otherwise, the
783 first bookmark is activated.
783 first bookmark is activated.
784
784
785 Raises an abort error if old is not in the bookmark store.
785 Raises an abort error if old is not in the bookmark store.
786 """
786 """
787 marks = repo._bookmarks
787 marks = repo._bookmarks
788 cur = repo.changectx('.').node()
788 cur = repo.changectx('.').node()
789 newact = None
789 newact = None
790 changes = []
790 changes = []
791 for mark in names:
791 for mark in names:
792 mark = checkformat(repo, mark)
792 mark = checkformat(repo, mark)
793 if newact is None:
793 if newact is None:
794 newact = mark
794 newact = mark
795 if inactive and mark == repo._activebookmark:
795 if inactive and mark == repo._activebookmark:
796 deactivate(repo)
796 deactivate(repo)
797 return
797 return
798 tgt = cur
798 tgt = cur
799 if rev:
799 if rev:
800 tgt = scmutil.revsingle(repo, rev).node()
800 tgt = scmutil.revsingle(repo, rev).node()
801 for bm in marks.checkconflict(mark, force, tgt):
801 for bm in marks.checkconflict(mark, force, tgt):
802 changes.append((bm, None))
802 changes.append((bm, None))
803 changes.append((mark, tgt))
803 changes.append((mark, tgt))
804 marks.applychanges(repo, tr, changes)
804 marks.applychanges(repo, tr, changes)
805 if not inactive and cur == marks[newact] and not rev:
805 if not inactive and cur == marks[newact] and not rev:
806 activate(repo, newact)
806 activate(repo, newact)
807 elif cur != tgt and newact == repo._activebookmark:
807 elif cur != tgt and newact == repo._activebookmark:
808 deactivate(repo)
808 deactivate(repo)
809
809
810 def _printbookmarks(ui, repo, bmarks, **opts):
810 def _printbookmarks(ui, repo, bmarks, **opts):
811 """private method to print bookmarks
811 """private method to print bookmarks
812
812
813 Provides a way for extensions to control how bookmarks are printed (e.g.
813 Provides a way for extensions to control how bookmarks are printed (e.g.
814 prepend or postpend names)
814 prepend or postpend names)
815 """
815 """
816 opts = pycompat.byteskwargs(opts)
816 opts = pycompat.byteskwargs(opts)
817 fm = ui.formatter('bookmarks', opts)
817 fm = ui.formatter('bookmarks', opts)
818 hexfn = fm.hexfunc
818 hexfn = fm.hexfunc
819 if len(bmarks) == 0 and fm.isplain():
819 if len(bmarks) == 0 and fm.isplain():
820 ui.status(_("no bookmarks set\n"))
820 ui.status(_("no bookmarks set\n"))
821 for bmark, (n, prefix, label) in sorted(bmarks.iteritems()):
821 for bmark, (n, prefix, label) in sorted(bmarks.iteritems()):
822 fm.startitem()
822 fm.startitem()
823 if not ui.quiet:
823 if not ui.quiet:
824 fm.plain(' %s ' % prefix, label=label)
824 fm.plain(' %s ' % prefix, label=label)
825 fm.write('bookmark', '%s', bmark, label=label)
825 fm.write('bookmark', '%s', bmark, label=label)
826 pad = " " * (25 - encoding.colwidth(bmark))
826 pad = " " * (25 - encoding.colwidth(bmark))
827 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
827 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
828 repo.changelog.rev(n), hexfn(n), label=label)
828 repo.changelog.rev(n), hexfn(n), label=label)
829 fm.data(active=(activebookmarklabel in label))
829 fm.data(active=(activebookmarklabel in label))
830 fm.plain('\n')
830 fm.plain('\n')
831 fm.end()
831 fm.end()
832
832
833 def printbookmarks(ui, repo, **opts):
833 def printbookmarks(ui, repo, **opts):
834 """print bookmarks to a formatter
834 """print bookmarks to a formatter
835
835
836 Provides a way for extensions to control how bookmarks are printed.
836 Provides a way for extensions to control how bookmarks are printed.
837 """
837 """
838 marks = repo._bookmarks
838 marks = repo._bookmarks
839 bmarks = {}
839 bmarks = {}
840 for bmark, n in sorted(marks.iteritems()):
840 for bmark, n in sorted(marks.iteritems()):
841 active = repo._activebookmark
841 active = repo._activebookmark
842 if bmark == active:
842 if bmark == active:
843 prefix, label = '*', activebookmarklabel
843 prefix, label = '*', activebookmarklabel
844 else:
844 else:
845 prefix, label = ' ', ''
845 prefix, label = ' ', ''
846
846
847 bmarks[bmark] = (n, prefix, label)
847 bmarks[bmark] = (n, prefix, label)
848 _printbookmarks(ui, repo, bmarks, **opts)
848 _printbookmarks(ui, repo, bmarks, **opts)
849
850 def preparehookargs(name, old, new):
851 if new is None:
852 new = ''
853 if old is None:
854 old = ''
855 return {'bookmark': name,
856 'node': hex(new),
857 'oldnode': hex(old)}
@@ -1,2486 +1,2498 b''
1 The Mercurial system uses a set of configuration files to control
1 The Mercurial system uses a set of configuration files to control
2 aspects of its behavior.
2 aspects of its behavior.
3
3
4 Troubleshooting
4 Troubleshooting
5 ===============
5 ===============
6
6
7 If you're having problems with your configuration,
7 If you're having problems with your configuration,
8 :hg:`config --debug` can help you understand what is introducing
8 :hg:`config --debug` can help you understand what is introducing
9 a setting into your environment.
9 a setting into your environment.
10
10
11 See :hg:`help config.syntax` and :hg:`help config.files`
11 See :hg:`help config.syntax` and :hg:`help config.files`
12 for information about how and where to override things.
12 for information about how and where to override things.
13
13
14 Structure
14 Structure
15 =========
15 =========
16
16
17 The configuration files use a simple ini-file format. A configuration
17 The configuration files use a simple ini-file format. A configuration
18 file consists of sections, led by a ``[section]`` header and followed
18 file consists of sections, led by a ``[section]`` header and followed
19 by ``name = value`` entries::
19 by ``name = value`` entries::
20
20
21 [ui]
21 [ui]
22 username = Firstname Lastname <firstname.lastname@example.net>
22 username = Firstname Lastname <firstname.lastname@example.net>
23 verbose = True
23 verbose = True
24
24
25 The above entries will be referred to as ``ui.username`` and
25 The above entries will be referred to as ``ui.username`` and
26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
27
27
28 Files
28 Files
29 =====
29 =====
30
30
31 Mercurial reads configuration data from several files, if they exist.
31 Mercurial reads configuration data from several files, if they exist.
32 These files do not exist by default and you will have to create the
32 These files do not exist by default and you will have to create the
33 appropriate configuration files yourself:
33 appropriate configuration files yourself:
34
34
35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
36
36
37 Global configuration like the username setting is typically put into:
37 Global configuration like the username setting is typically put into:
38
38
39 .. container:: windows
39 .. container:: windows
40
40
41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
42
42
43 .. container:: unix.plan9
43 .. container:: unix.plan9
44
44
45 - ``$HOME/.hgrc`` (on Unix, Plan9)
45 - ``$HOME/.hgrc`` (on Unix, Plan9)
46
46
47 The names of these files depend on the system on which Mercurial is
47 The names of these files depend on the system on which Mercurial is
48 installed. ``*.rc`` files from a single directory are read in
48 installed. ``*.rc`` files from a single directory are read in
49 alphabetical order, later ones overriding earlier ones. Where multiple
49 alphabetical order, later ones overriding earlier ones. Where multiple
50 paths are given below, settings from earlier paths override later
50 paths are given below, settings from earlier paths override later
51 ones.
51 ones.
52
52
53 .. container:: verbose.unix
53 .. container:: verbose.unix
54
54
55 On Unix, the following files are consulted:
55 On Unix, the following files are consulted:
56
56
57 - ``<repo>/.hg/hgrc`` (per-repository)
57 - ``<repo>/.hg/hgrc`` (per-repository)
58 - ``$HOME/.hgrc`` (per-user)
58 - ``$HOME/.hgrc`` (per-user)
59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
62 - ``/etc/mercurial/hgrc`` (per-system)
62 - ``/etc/mercurial/hgrc`` (per-system)
63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
64 - ``<internal>/default.d/*.rc`` (defaults)
64 - ``<internal>/default.d/*.rc`` (defaults)
65
65
66 .. container:: verbose.windows
66 .. container:: verbose.windows
67
67
68 On Windows, the following files are consulted:
68 On Windows, the following files are consulted:
69
69
70 - ``<repo>/.hg/hgrc`` (per-repository)
70 - ``<repo>/.hg/hgrc`` (per-repository)
71 - ``%USERPROFILE%\.hgrc`` (per-user)
71 - ``%USERPROFILE%\.hgrc`` (per-user)
72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
73 - ``%HOME%\.hgrc`` (per-user)
73 - ``%HOME%\.hgrc`` (per-user)
74 - ``%HOME%\Mercurial.ini`` (per-user)
74 - ``%HOME%\Mercurial.ini`` (per-user)
75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
77 - ``<install-dir>\Mercurial.ini`` (per-installation)
77 - ``<install-dir>\Mercurial.ini`` (per-installation)
78 - ``<internal>/default.d/*.rc`` (defaults)
78 - ``<internal>/default.d/*.rc`` (defaults)
79
79
80 .. note::
80 .. note::
81
81
82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
83 is used when running 32-bit Python on 64-bit Windows.
83 is used when running 32-bit Python on 64-bit Windows.
84
84
85 .. container:: windows
85 .. container:: windows
86
86
87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
88
88
89 .. container:: verbose.plan9
89 .. container:: verbose.plan9
90
90
91 On Plan9, the following files are consulted:
91 On Plan9, the following files are consulted:
92
92
93 - ``<repo>/.hg/hgrc`` (per-repository)
93 - ``<repo>/.hg/hgrc`` (per-repository)
94 - ``$home/lib/hgrc`` (per-user)
94 - ``$home/lib/hgrc`` (per-user)
95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
97 - ``/lib/mercurial/hgrc`` (per-system)
97 - ``/lib/mercurial/hgrc`` (per-system)
98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
99 - ``<internal>/default.d/*.rc`` (defaults)
99 - ``<internal>/default.d/*.rc`` (defaults)
100
100
101 Per-repository configuration options only apply in a
101 Per-repository configuration options only apply in a
102 particular repository. This file is not version-controlled, and
102 particular repository. This file is not version-controlled, and
103 will not get transferred during a "clone" operation. Options in
103 will not get transferred during a "clone" operation. Options in
104 this file override options in all other configuration files.
104 this file override options in all other configuration files.
105
105
106 .. container:: unix.plan9
106 .. container:: unix.plan9
107
107
108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
109 belong to a trusted user or to a trusted group. See
109 belong to a trusted user or to a trusted group. See
110 :hg:`help config.trusted` for more details.
110 :hg:`help config.trusted` for more details.
111
111
112 Per-user configuration file(s) are for the user running Mercurial. Options
112 Per-user configuration file(s) are for the user running Mercurial. Options
113 in these files apply to all Mercurial commands executed by this user in any
113 in these files apply to all Mercurial commands executed by this user in any
114 directory. Options in these files override per-system and per-installation
114 directory. Options in these files override per-system and per-installation
115 options.
115 options.
116
116
117 Per-installation configuration files are searched for in the
117 Per-installation configuration files are searched for in the
118 directory where Mercurial is installed. ``<install-root>`` is the
118 directory where Mercurial is installed. ``<install-root>`` is the
119 parent directory of the **hg** executable (or symlink) being run.
119 parent directory of the **hg** executable (or symlink) being run.
120
120
121 .. container:: unix.plan9
121 .. container:: unix.plan9
122
122
123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
125 files apply to all Mercurial commands executed by any user in any
125 files apply to all Mercurial commands executed by any user in any
126 directory.
126 directory.
127
127
128 Per-installation configuration files are for the system on
128 Per-installation configuration files are for the system on
129 which Mercurial is running. Options in these files apply to all
129 which Mercurial is running. Options in these files apply to all
130 Mercurial commands executed by any user in any directory. Registry
130 Mercurial commands executed by any user in any directory. Registry
131 keys contain PATH-like strings, every part of which must reference
131 keys contain PATH-like strings, every part of which must reference
132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
133 be read. Mercurial checks each of these locations in the specified
133 be read. Mercurial checks each of these locations in the specified
134 order until one or more configuration files are detected.
134 order until one or more configuration files are detected.
135
135
136 Per-system configuration files are for the system on which Mercurial
136 Per-system configuration files are for the system on which Mercurial
137 is running. Options in these files apply to all Mercurial commands
137 is running. Options in these files apply to all Mercurial commands
138 executed by any user in any directory. Options in these files
138 executed by any user in any directory. Options in these files
139 override per-installation options.
139 override per-installation options.
140
140
141 Mercurial comes with some default configuration. The default configuration
141 Mercurial comes with some default configuration. The default configuration
142 files are installed with Mercurial and will be overwritten on upgrades. Default
142 files are installed with Mercurial and will be overwritten on upgrades. Default
143 configuration files should never be edited by users or administrators but can
143 configuration files should never be edited by users or administrators but can
144 be overridden in other configuration files. So far the directory only contains
144 be overridden in other configuration files. So far the directory only contains
145 merge tool configuration but packagers can also put other default configuration
145 merge tool configuration but packagers can also put other default configuration
146 there.
146 there.
147
147
148 Syntax
148 Syntax
149 ======
149 ======
150
150
151 A configuration file consists of sections, led by a ``[section]`` header
151 A configuration file consists of sections, led by a ``[section]`` header
152 and followed by ``name = value`` entries (sometimes called
152 and followed by ``name = value`` entries (sometimes called
153 ``configuration keys``)::
153 ``configuration keys``)::
154
154
155 [spam]
155 [spam]
156 eggs=ham
156 eggs=ham
157 green=
157 green=
158 eggs
158 eggs
159
159
160 Each line contains one entry. If the lines that follow are indented,
160 Each line contains one entry. If the lines that follow are indented,
161 they are treated as continuations of that entry. Leading whitespace is
161 they are treated as continuations of that entry. Leading whitespace is
162 removed from values. Empty lines are skipped. Lines beginning with
162 removed from values. Empty lines are skipped. Lines beginning with
163 ``#`` or ``;`` are ignored and may be used to provide comments.
163 ``#`` or ``;`` are ignored and may be used to provide comments.
164
164
165 Configuration keys can be set multiple times, in which case Mercurial
165 Configuration keys can be set multiple times, in which case Mercurial
166 will use the value that was configured last. As an example::
166 will use the value that was configured last. As an example::
167
167
168 [spam]
168 [spam]
169 eggs=large
169 eggs=large
170 ham=serrano
170 ham=serrano
171 eggs=small
171 eggs=small
172
172
173 This would set the configuration key named ``eggs`` to ``small``.
173 This would set the configuration key named ``eggs`` to ``small``.
174
174
175 It is also possible to define a section multiple times. A section can
175 It is also possible to define a section multiple times. A section can
176 be redefined on the same and/or on different configuration files. For
176 be redefined on the same and/or on different configuration files. For
177 example::
177 example::
178
178
179 [foo]
179 [foo]
180 eggs=large
180 eggs=large
181 ham=serrano
181 ham=serrano
182 eggs=small
182 eggs=small
183
183
184 [bar]
184 [bar]
185 eggs=ham
185 eggs=ham
186 green=
186 green=
187 eggs
187 eggs
188
188
189 [foo]
189 [foo]
190 ham=prosciutto
190 ham=prosciutto
191 eggs=medium
191 eggs=medium
192 bread=toasted
192 bread=toasted
193
193
194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
196 respectively. As you can see there only thing that matters is the last
196 respectively. As you can see there only thing that matters is the last
197 value that was set for each of the configuration keys.
197 value that was set for each of the configuration keys.
198
198
199 If a configuration key is set multiple times in different
199 If a configuration key is set multiple times in different
200 configuration files the final value will depend on the order in which
200 configuration files the final value will depend on the order in which
201 the different configuration files are read, with settings from earlier
201 the different configuration files are read, with settings from earlier
202 paths overriding later ones as described on the ``Files`` section
202 paths overriding later ones as described on the ``Files`` section
203 above.
203 above.
204
204
205 A line of the form ``%include file`` will include ``file`` into the
205 A line of the form ``%include file`` will include ``file`` into the
206 current configuration file. The inclusion is recursive, which means
206 current configuration file. The inclusion is recursive, which means
207 that included files can include other files. Filenames are relative to
207 that included files can include other files. Filenames are relative to
208 the configuration file in which the ``%include`` directive is found.
208 the configuration file in which the ``%include`` directive is found.
209 Environment variables and ``~user`` constructs are expanded in
209 Environment variables and ``~user`` constructs are expanded in
210 ``file``. This lets you do something like::
210 ``file``. This lets you do something like::
211
211
212 %include ~/.hgrc.d/$HOST.rc
212 %include ~/.hgrc.d/$HOST.rc
213
213
214 to include a different configuration file on each computer you use.
214 to include a different configuration file on each computer you use.
215
215
216 A line with ``%unset name`` will remove ``name`` from the current
216 A line with ``%unset name`` will remove ``name`` from the current
217 section, if it has been set previously.
217 section, if it has been set previously.
218
218
219 The values are either free-form text strings, lists of text strings,
219 The values are either free-form text strings, lists of text strings,
220 or Boolean values. Boolean values can be set to true using any of "1",
220 or Boolean values. Boolean values can be set to true using any of "1",
221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
222 (all case insensitive).
222 (all case insensitive).
223
223
224 List values are separated by whitespace or comma, except when values are
224 List values are separated by whitespace or comma, except when values are
225 placed in double quotation marks::
225 placed in double quotation marks::
226
226
227 allow_read = "John Doe, PhD", brian, betty
227 allow_read = "John Doe, PhD", brian, betty
228
228
229 Quotation marks can be escaped by prefixing them with a backslash. Only
229 Quotation marks can be escaped by prefixing them with a backslash. Only
230 quotation marks at the beginning of a word is counted as a quotation
230 quotation marks at the beginning of a word is counted as a quotation
231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
232
232
233 Sections
233 Sections
234 ========
234 ========
235
235
236 This section describes the different sections that may appear in a
236 This section describes the different sections that may appear in a
237 Mercurial configuration file, the purpose of each section, its possible
237 Mercurial configuration file, the purpose of each section, its possible
238 keys, and their possible values.
238 keys, and their possible values.
239
239
240 ``alias``
240 ``alias``
241 ---------
241 ---------
242
242
243 Defines command aliases.
243 Defines command aliases.
244
244
245 Aliases allow you to define your own commands in terms of other
245 Aliases allow you to define your own commands in terms of other
246 commands (or aliases), optionally including arguments. Positional
246 commands (or aliases), optionally including arguments. Positional
247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
248 are expanded by Mercurial before execution. Positional arguments not
248 are expanded by Mercurial before execution. Positional arguments not
249 already used by ``$N`` in the definition are put at the end of the
249 already used by ``$N`` in the definition are put at the end of the
250 command to be executed.
250 command to be executed.
251
251
252 Alias definitions consist of lines of the form::
252 Alias definitions consist of lines of the form::
253
253
254 <alias> = <command> [<argument>]...
254 <alias> = <command> [<argument>]...
255
255
256 For example, this definition::
256 For example, this definition::
257
257
258 latest = log --limit 5
258 latest = log --limit 5
259
259
260 creates a new command ``latest`` that shows only the five most recent
260 creates a new command ``latest`` that shows only the five most recent
261 changesets. You can define subsequent aliases using earlier ones::
261 changesets. You can define subsequent aliases using earlier ones::
262
262
263 stable5 = latest -b stable
263 stable5 = latest -b stable
264
264
265 .. note::
265 .. note::
266
266
267 It is possible to create aliases with the same names as
267 It is possible to create aliases with the same names as
268 existing commands, which will then override the original
268 existing commands, which will then override the original
269 definitions. This is almost always a bad idea!
269 definitions. This is almost always a bad idea!
270
270
271 An alias can start with an exclamation point (``!``) to make it a
271 An alias can start with an exclamation point (``!``) to make it a
272 shell alias. A shell alias is executed with the shell and will let you
272 shell alias. A shell alias is executed with the shell and will let you
273 run arbitrary commands. As an example, ::
273 run arbitrary commands. As an example, ::
274
274
275 echo = !echo $@
275 echo = !echo $@
276
276
277 will let you do ``hg echo foo`` to have ``foo`` printed in your
277 will let you do ``hg echo foo`` to have ``foo`` printed in your
278 terminal. A better example might be::
278 terminal. A better example might be::
279
279
280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
281
281
282 which will make ``hg purge`` delete all unknown files in the
282 which will make ``hg purge`` delete all unknown files in the
283 repository in the same manner as the purge extension.
283 repository in the same manner as the purge extension.
284
284
285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
286 expand to the command arguments. Unmatched arguments are
286 expand to the command arguments. Unmatched arguments are
287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
289 arguments quoted individually and separated by a space. These expansions
289 arguments quoted individually and separated by a space. These expansions
290 happen before the command is passed to the shell.
290 happen before the command is passed to the shell.
291
291
292 Shell aliases are executed in an environment where ``$HG`` expands to
292 Shell aliases are executed in an environment where ``$HG`` expands to
293 the path of the Mercurial that was used to execute the alias. This is
293 the path of the Mercurial that was used to execute the alias. This is
294 useful when you want to call further Mercurial commands in a shell
294 useful when you want to call further Mercurial commands in a shell
295 alias, as was done above for the purge alias. In addition,
295 alias, as was done above for the purge alias. In addition,
296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
298
298
299 .. note::
299 .. note::
300
300
301 Some global configuration options such as ``-R`` are
301 Some global configuration options such as ``-R`` are
302 processed before shell aliases and will thus not be passed to
302 processed before shell aliases and will thus not be passed to
303 aliases.
303 aliases.
304
304
305
305
306 ``annotate``
306 ``annotate``
307 ------------
307 ------------
308
308
309 Settings used when displaying file annotations. All values are
309 Settings used when displaying file annotations. All values are
310 Booleans and default to False. See :hg:`help config.diff` for
310 Booleans and default to False. See :hg:`help config.diff` for
311 related options for the diff command.
311 related options for the diff command.
312
312
313 ``ignorews``
313 ``ignorews``
314 Ignore white space when comparing lines.
314 Ignore white space when comparing lines.
315
315
316 ``ignorewseol``
316 ``ignorewseol``
317 Ignore white space at the end of a line when comparing lines.
317 Ignore white space at the end of a line when comparing lines.
318
318
319 ``ignorewsamount``
319 ``ignorewsamount``
320 Ignore changes in the amount of white space.
320 Ignore changes in the amount of white space.
321
321
322 ``ignoreblanklines``
322 ``ignoreblanklines``
323 Ignore changes whose lines are all blank.
323 Ignore changes whose lines are all blank.
324
324
325
325
326 ``auth``
326 ``auth``
327 --------
327 --------
328
328
329 Authentication credentials and other authentication-like configuration
329 Authentication credentials and other authentication-like configuration
330 for HTTP connections. This section allows you to store usernames and
330 for HTTP connections. This section allows you to store usernames and
331 passwords for use when logging *into* HTTP servers. See
331 passwords for use when logging *into* HTTP servers. See
332 :hg:`help config.web` if you want to configure *who* can login to
332 :hg:`help config.web` if you want to configure *who* can login to
333 your HTTP server.
333 your HTTP server.
334
334
335 The following options apply to all hosts.
335 The following options apply to all hosts.
336
336
337 ``cookiefile``
337 ``cookiefile``
338 Path to a file containing HTTP cookie lines. Cookies matching a
338 Path to a file containing HTTP cookie lines. Cookies matching a
339 host will be sent automatically.
339 host will be sent automatically.
340
340
341 The file format uses the Mozilla cookies.txt format, which defines cookies
341 The file format uses the Mozilla cookies.txt format, which defines cookies
342 on their own lines. Each line contains 7 fields delimited by the tab
342 on their own lines. Each line contains 7 fields delimited by the tab
343 character (domain, is_domain_cookie, path, is_secure, expires, name,
343 character (domain, is_domain_cookie, path, is_secure, expires, name,
344 value). For more info, do an Internet search for "Netscape cookies.txt
344 value). For more info, do an Internet search for "Netscape cookies.txt
345 format."
345 format."
346
346
347 Note: the cookies parser does not handle port numbers on domains. You
347 Note: the cookies parser does not handle port numbers on domains. You
348 will need to remove ports from the domain for the cookie to be recognized.
348 will need to remove ports from the domain for the cookie to be recognized.
349 This could result in a cookie being disclosed to an unwanted server.
349 This could result in a cookie being disclosed to an unwanted server.
350
350
351 The cookies file is read-only.
351 The cookies file is read-only.
352
352
353 Other options in this section are grouped by name and have the following
353 Other options in this section are grouped by name and have the following
354 format::
354 format::
355
355
356 <name>.<argument> = <value>
356 <name>.<argument> = <value>
357
357
358 where ``<name>`` is used to group arguments into authentication
358 where ``<name>`` is used to group arguments into authentication
359 entries. Example::
359 entries. Example::
360
360
361 foo.prefix = hg.intevation.de/mercurial
361 foo.prefix = hg.intevation.de/mercurial
362 foo.username = foo
362 foo.username = foo
363 foo.password = bar
363 foo.password = bar
364 foo.schemes = http https
364 foo.schemes = http https
365
365
366 bar.prefix = secure.example.org
366 bar.prefix = secure.example.org
367 bar.key = path/to/file.key
367 bar.key = path/to/file.key
368 bar.cert = path/to/file.cert
368 bar.cert = path/to/file.cert
369 bar.schemes = https
369 bar.schemes = https
370
370
371 Supported arguments:
371 Supported arguments:
372
372
373 ``prefix``
373 ``prefix``
374 Either ``*`` or a URI prefix with or without the scheme part.
374 Either ``*`` or a URI prefix with or without the scheme part.
375 The authentication entry with the longest matching prefix is used
375 The authentication entry with the longest matching prefix is used
376 (where ``*`` matches everything and counts as a match of length
376 (where ``*`` matches everything and counts as a match of length
377 1). If the prefix doesn't include a scheme, the match is performed
377 1). If the prefix doesn't include a scheme, the match is performed
378 against the URI with its scheme stripped as well, and the schemes
378 against the URI with its scheme stripped as well, and the schemes
379 argument, q.v., is then subsequently consulted.
379 argument, q.v., is then subsequently consulted.
380
380
381 ``username``
381 ``username``
382 Optional. Username to authenticate with. If not given, and the
382 Optional. Username to authenticate with. If not given, and the
383 remote site requires basic or digest authentication, the user will
383 remote site requires basic or digest authentication, the user will
384 be prompted for it. Environment variables are expanded in the
384 be prompted for it. Environment variables are expanded in the
385 username letting you do ``foo.username = $USER``. If the URI
385 username letting you do ``foo.username = $USER``. If the URI
386 includes a username, only ``[auth]`` entries with a matching
386 includes a username, only ``[auth]`` entries with a matching
387 username or without a username will be considered.
387 username or without a username will be considered.
388
388
389 ``password``
389 ``password``
390 Optional. Password to authenticate with. If not given, and the
390 Optional. Password to authenticate with. If not given, and the
391 remote site requires basic or digest authentication, the user
391 remote site requires basic or digest authentication, the user
392 will be prompted for it.
392 will be prompted for it.
393
393
394 ``key``
394 ``key``
395 Optional. PEM encoded client certificate key file. Environment
395 Optional. PEM encoded client certificate key file. Environment
396 variables are expanded in the filename.
396 variables are expanded in the filename.
397
397
398 ``cert``
398 ``cert``
399 Optional. PEM encoded client certificate chain file. Environment
399 Optional. PEM encoded client certificate chain file. Environment
400 variables are expanded in the filename.
400 variables are expanded in the filename.
401
401
402 ``schemes``
402 ``schemes``
403 Optional. Space separated list of URI schemes to use this
403 Optional. Space separated list of URI schemes to use this
404 authentication entry with. Only used if the prefix doesn't include
404 authentication entry with. Only used if the prefix doesn't include
405 a scheme. Supported schemes are http and https. They will match
405 a scheme. Supported schemes are http and https. They will match
406 static-http and static-https respectively, as well.
406 static-http and static-https respectively, as well.
407 (default: https)
407 (default: https)
408
408
409 If no suitable authentication entry is found, the user is prompted
409 If no suitable authentication entry is found, the user is prompted
410 for credentials as usual if required by the remote.
410 for credentials as usual if required by the remote.
411
411
412 ``color``
412 ``color``
413 ---------
413 ---------
414
414
415 Configure the Mercurial color mode. For details about how to define your custom
415 Configure the Mercurial color mode. For details about how to define your custom
416 effect and style see :hg:`help color`.
416 effect and style see :hg:`help color`.
417
417
418 ``mode``
418 ``mode``
419 String: control the method used to output color. One of ``auto``, ``ansi``,
419 String: control the method used to output color. One of ``auto``, ``ansi``,
420 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
420 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
421 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
421 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
422 terminal. Any invalid value will disable color.
422 terminal. Any invalid value will disable color.
423
423
424 ``pagermode``
424 ``pagermode``
425 String: optional override of ``color.mode`` used with pager.
425 String: optional override of ``color.mode`` used with pager.
426
426
427 On some systems, terminfo mode may cause problems when using
427 On some systems, terminfo mode may cause problems when using
428 color with ``less -R`` as a pager program. less with the -R option
428 color with ``less -R`` as a pager program. less with the -R option
429 will only display ECMA-48 color codes, and terminfo mode may sometimes
429 will only display ECMA-48 color codes, and terminfo mode may sometimes
430 emit codes that less doesn't understand. You can work around this by
430 emit codes that less doesn't understand. You can work around this by
431 either using ansi mode (or auto mode), or by using less -r (which will
431 either using ansi mode (or auto mode), or by using less -r (which will
432 pass through all terminal control codes, not just color control
432 pass through all terminal control codes, not just color control
433 codes).
433 codes).
434
434
435 On some systems (such as MSYS in Windows), the terminal may support
435 On some systems (such as MSYS in Windows), the terminal may support
436 a different color mode than the pager program.
436 a different color mode than the pager program.
437
437
438 ``commands``
438 ``commands``
439 ------------
439 ------------
440
440
441 ``status.relative``
441 ``status.relative``
442 Make paths in :hg:`status` output relative to the current directory.
442 Make paths in :hg:`status` output relative to the current directory.
443 (default: False)
443 (default: False)
444
444
445 ``update.check``
445 ``update.check``
446 Determines what level of checking :hg:`update` will perform before moving
446 Determines what level of checking :hg:`update` will perform before moving
447 to a destination revision. Valid values are ``abort``, ``none``,
447 to a destination revision. Valid values are ``abort``, ``none``,
448 ``linear``, and ``noconflict``. ``abort`` always fails if the working
448 ``linear``, and ``noconflict``. ``abort`` always fails if the working
449 directory has uncommitted changes. ``none`` performs no checking, and may
449 directory has uncommitted changes. ``none`` performs no checking, and may
450 result in a merge with uncommitted changes. ``linear`` allows any update
450 result in a merge with uncommitted changes. ``linear`` allows any update
451 as long as it follows a straight line in the revision history, and may
451 as long as it follows a straight line in the revision history, and may
452 trigger a merge with uncommitted changes. ``noconflict`` will allow any
452 trigger a merge with uncommitted changes. ``noconflict`` will allow any
453 update which would not trigger a merge with uncommitted changes, if any
453 update which would not trigger a merge with uncommitted changes, if any
454 are present.
454 are present.
455 (default: ``linear``)
455 (default: ``linear``)
456
456
457 ``update.requiredest``
457 ``update.requiredest``
458 Require that the user pass a destination when running :hg:`update`.
458 Require that the user pass a destination when running :hg:`update`.
459 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
459 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
460 will be disallowed.
460 will be disallowed.
461 (default: False)
461 (default: False)
462
462
463 ``committemplate``
463 ``committemplate``
464 ------------------
464 ------------------
465
465
466 ``changeset``
466 ``changeset``
467 String: configuration in this section is used as the template to
467 String: configuration in this section is used as the template to
468 customize the text shown in the editor when committing.
468 customize the text shown in the editor when committing.
469
469
470 In addition to pre-defined template keywords, commit log specific one
470 In addition to pre-defined template keywords, commit log specific one
471 below can be used for customization:
471 below can be used for customization:
472
472
473 ``extramsg``
473 ``extramsg``
474 String: Extra message (typically 'Leave message empty to abort
474 String: Extra message (typically 'Leave message empty to abort
475 commit.'). This may be changed by some commands or extensions.
475 commit.'). This may be changed by some commands or extensions.
476
476
477 For example, the template configuration below shows as same text as
477 For example, the template configuration below shows as same text as
478 one shown by default::
478 one shown by default::
479
479
480 [committemplate]
480 [committemplate]
481 changeset = {desc}\n\n
481 changeset = {desc}\n\n
482 HG: Enter commit message. Lines beginning with 'HG:' are removed.
482 HG: Enter commit message. Lines beginning with 'HG:' are removed.
483 HG: {extramsg}
483 HG: {extramsg}
484 HG: --
484 HG: --
485 HG: user: {author}\n{ifeq(p2rev, "-1", "",
485 HG: user: {author}\n{ifeq(p2rev, "-1", "",
486 "HG: branch merge\n")
486 "HG: branch merge\n")
487 }HG: branch '{branch}'\n{if(activebookmark,
487 }HG: branch '{branch}'\n{if(activebookmark,
488 "HG: bookmark '{activebookmark}'\n") }{subrepos %
488 "HG: bookmark '{activebookmark}'\n") }{subrepos %
489 "HG: subrepo {subrepo}\n" }{file_adds %
489 "HG: subrepo {subrepo}\n" }{file_adds %
490 "HG: added {file}\n" }{file_mods %
490 "HG: added {file}\n" }{file_mods %
491 "HG: changed {file}\n" }{file_dels %
491 "HG: changed {file}\n" }{file_dels %
492 "HG: removed {file}\n" }{if(files, "",
492 "HG: removed {file}\n" }{if(files, "",
493 "HG: no files changed\n")}
493 "HG: no files changed\n")}
494
494
495 ``diff()``
495 ``diff()``
496 String: show the diff (see :hg:`help templates` for detail)
496 String: show the diff (see :hg:`help templates` for detail)
497
497
498 Sometimes it is helpful to show the diff of the changeset in the editor without
498 Sometimes it is helpful to show the diff of the changeset in the editor without
499 having to prefix 'HG: ' to each line so that highlighting works correctly. For
499 having to prefix 'HG: ' to each line so that highlighting works correctly. For
500 this, Mercurial provides a special string which will ignore everything below
500 this, Mercurial provides a special string which will ignore everything below
501 it::
501 it::
502
502
503 HG: ------------------------ >8 ------------------------
503 HG: ------------------------ >8 ------------------------
504
504
505 For example, the template configuration below will show the diff below the
505 For example, the template configuration below will show the diff below the
506 extra message::
506 extra message::
507
507
508 [committemplate]
508 [committemplate]
509 changeset = {desc}\n\n
509 changeset = {desc}\n\n
510 HG: Enter commit message. Lines beginning with 'HG:' are removed.
510 HG: Enter commit message. Lines beginning with 'HG:' are removed.
511 HG: {extramsg}
511 HG: {extramsg}
512 HG: ------------------------ >8 ------------------------
512 HG: ------------------------ >8 ------------------------
513 HG: Do not touch the line above.
513 HG: Do not touch the line above.
514 HG: Everything below will be removed.
514 HG: Everything below will be removed.
515 {diff()}
515 {diff()}
516
516
517 .. note::
517 .. note::
518
518
519 For some problematic encodings (see :hg:`help win32mbcs` for
519 For some problematic encodings (see :hg:`help win32mbcs` for
520 detail), this customization should be configured carefully, to
520 detail), this customization should be configured carefully, to
521 avoid showing broken characters.
521 avoid showing broken characters.
522
522
523 For example, if a multibyte character ending with backslash (0x5c) is
523 For example, if a multibyte character ending with backslash (0x5c) is
524 followed by the ASCII character 'n' in the customized template,
524 followed by the ASCII character 'n' in the customized template,
525 the sequence of backslash and 'n' is treated as line-feed unexpectedly
525 the sequence of backslash and 'n' is treated as line-feed unexpectedly
526 (and the multibyte character is broken, too).
526 (and the multibyte character is broken, too).
527
527
528 Customized template is used for commands below (``--edit`` may be
528 Customized template is used for commands below (``--edit`` may be
529 required):
529 required):
530
530
531 - :hg:`backout`
531 - :hg:`backout`
532 - :hg:`commit`
532 - :hg:`commit`
533 - :hg:`fetch` (for merge commit only)
533 - :hg:`fetch` (for merge commit only)
534 - :hg:`graft`
534 - :hg:`graft`
535 - :hg:`histedit`
535 - :hg:`histedit`
536 - :hg:`import`
536 - :hg:`import`
537 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
537 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
538 - :hg:`rebase`
538 - :hg:`rebase`
539 - :hg:`shelve`
539 - :hg:`shelve`
540 - :hg:`sign`
540 - :hg:`sign`
541 - :hg:`tag`
541 - :hg:`tag`
542 - :hg:`transplant`
542 - :hg:`transplant`
543
543
544 Configuring items below instead of ``changeset`` allows showing
544 Configuring items below instead of ``changeset`` allows showing
545 customized message only for specific actions, or showing different
545 customized message only for specific actions, or showing different
546 messages for each action.
546 messages for each action.
547
547
548 - ``changeset.backout`` for :hg:`backout`
548 - ``changeset.backout`` for :hg:`backout`
549 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
549 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
550 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
550 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
551 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
551 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
552 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
552 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
553 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
553 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
554 - ``changeset.gpg.sign`` for :hg:`sign`
554 - ``changeset.gpg.sign`` for :hg:`sign`
555 - ``changeset.graft`` for :hg:`graft`
555 - ``changeset.graft`` for :hg:`graft`
556 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
556 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
557 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
557 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
558 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
558 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
559 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
559 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
560 - ``changeset.import.bypass`` for :hg:`import --bypass`
560 - ``changeset.import.bypass`` for :hg:`import --bypass`
561 - ``changeset.import.normal.merge`` for :hg:`import` on merges
561 - ``changeset.import.normal.merge`` for :hg:`import` on merges
562 - ``changeset.import.normal.normal`` for :hg:`import` on other
562 - ``changeset.import.normal.normal`` for :hg:`import` on other
563 - ``changeset.mq.qnew`` for :hg:`qnew`
563 - ``changeset.mq.qnew`` for :hg:`qnew`
564 - ``changeset.mq.qfold`` for :hg:`qfold`
564 - ``changeset.mq.qfold`` for :hg:`qfold`
565 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
565 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
566 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
566 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
567 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
567 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
568 - ``changeset.rebase.normal`` for :hg:`rebase` on other
568 - ``changeset.rebase.normal`` for :hg:`rebase` on other
569 - ``changeset.shelve.shelve`` for :hg:`shelve`
569 - ``changeset.shelve.shelve`` for :hg:`shelve`
570 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
570 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
571 - ``changeset.tag.remove`` for :hg:`tag --remove`
571 - ``changeset.tag.remove`` for :hg:`tag --remove`
572 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
572 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
573 - ``changeset.transplant.normal`` for :hg:`transplant` on other
573 - ``changeset.transplant.normal`` for :hg:`transplant` on other
574
574
575 These dot-separated lists of names are treated as hierarchical ones.
575 These dot-separated lists of names are treated as hierarchical ones.
576 For example, ``changeset.tag.remove`` customizes the commit message
576 For example, ``changeset.tag.remove`` customizes the commit message
577 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
577 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
578 commit message for :hg:`tag` regardless of ``--remove`` option.
578 commit message for :hg:`tag` regardless of ``--remove`` option.
579
579
580 When the external editor is invoked for a commit, the corresponding
580 When the external editor is invoked for a commit, the corresponding
581 dot-separated list of names without the ``changeset.`` prefix
581 dot-separated list of names without the ``changeset.`` prefix
582 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
582 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
583 variable.
583 variable.
584
584
585 In this section, items other than ``changeset`` can be referred from
585 In this section, items other than ``changeset`` can be referred from
586 others. For example, the configuration to list committed files up
586 others. For example, the configuration to list committed files up
587 below can be referred as ``{listupfiles}``::
587 below can be referred as ``{listupfiles}``::
588
588
589 [committemplate]
589 [committemplate]
590 listupfiles = {file_adds %
590 listupfiles = {file_adds %
591 "HG: added {file}\n" }{file_mods %
591 "HG: added {file}\n" }{file_mods %
592 "HG: changed {file}\n" }{file_dels %
592 "HG: changed {file}\n" }{file_dels %
593 "HG: removed {file}\n" }{if(files, "",
593 "HG: removed {file}\n" }{if(files, "",
594 "HG: no files changed\n")}
594 "HG: no files changed\n")}
595
595
596 ``decode/encode``
596 ``decode/encode``
597 -----------------
597 -----------------
598
598
599 Filters for transforming files on checkout/checkin. This would
599 Filters for transforming files on checkout/checkin. This would
600 typically be used for newline processing or other
600 typically be used for newline processing or other
601 localization/canonicalization of files.
601 localization/canonicalization of files.
602
602
603 Filters consist of a filter pattern followed by a filter command.
603 Filters consist of a filter pattern followed by a filter command.
604 Filter patterns are globs by default, rooted at the repository root.
604 Filter patterns are globs by default, rooted at the repository root.
605 For example, to match any file ending in ``.txt`` in the root
605 For example, to match any file ending in ``.txt`` in the root
606 directory only, use the pattern ``*.txt``. To match any file ending
606 directory only, use the pattern ``*.txt``. To match any file ending
607 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
607 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
608 For each file only the first matching filter applies.
608 For each file only the first matching filter applies.
609
609
610 The filter command can start with a specifier, either ``pipe:`` or
610 The filter command can start with a specifier, either ``pipe:`` or
611 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
611 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
612
612
613 A ``pipe:`` command must accept data on stdin and return the transformed
613 A ``pipe:`` command must accept data on stdin and return the transformed
614 data on stdout.
614 data on stdout.
615
615
616 Pipe example::
616 Pipe example::
617
617
618 [encode]
618 [encode]
619 # uncompress gzip files on checkin to improve delta compression
619 # uncompress gzip files on checkin to improve delta compression
620 # note: not necessarily a good idea, just an example
620 # note: not necessarily a good idea, just an example
621 *.gz = pipe: gunzip
621 *.gz = pipe: gunzip
622
622
623 [decode]
623 [decode]
624 # recompress gzip files when writing them to the working dir (we
624 # recompress gzip files when writing them to the working dir (we
625 # can safely omit "pipe:", because it's the default)
625 # can safely omit "pipe:", because it's the default)
626 *.gz = gzip
626 *.gz = gzip
627
627
628 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
628 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
629 with the name of a temporary file that contains the data to be
629 with the name of a temporary file that contains the data to be
630 filtered by the command. The string ``OUTFILE`` is replaced with the name
630 filtered by the command. The string ``OUTFILE`` is replaced with the name
631 of an empty temporary file, where the filtered data must be written by
631 of an empty temporary file, where the filtered data must be written by
632 the command.
632 the command.
633
633
634 .. container:: windows
634 .. container:: windows
635
635
636 .. note::
636 .. note::
637
637
638 The tempfile mechanism is recommended for Windows systems,
638 The tempfile mechanism is recommended for Windows systems,
639 where the standard shell I/O redirection operators often have
639 where the standard shell I/O redirection operators often have
640 strange effects and may corrupt the contents of your files.
640 strange effects and may corrupt the contents of your files.
641
641
642 This filter mechanism is used internally by the ``eol`` extension to
642 This filter mechanism is used internally by the ``eol`` extension to
643 translate line ending characters between Windows (CRLF) and Unix (LF)
643 translate line ending characters between Windows (CRLF) and Unix (LF)
644 format. We suggest you use the ``eol`` extension for convenience.
644 format. We suggest you use the ``eol`` extension for convenience.
645
645
646
646
647 ``defaults``
647 ``defaults``
648 ------------
648 ------------
649
649
650 (defaults are deprecated. Don't use them. Use aliases instead.)
650 (defaults are deprecated. Don't use them. Use aliases instead.)
651
651
652 Use the ``[defaults]`` section to define command defaults, i.e. the
652 Use the ``[defaults]`` section to define command defaults, i.e. the
653 default options/arguments to pass to the specified commands.
653 default options/arguments to pass to the specified commands.
654
654
655 The following example makes :hg:`log` run in verbose mode, and
655 The following example makes :hg:`log` run in verbose mode, and
656 :hg:`status` show only the modified files, by default::
656 :hg:`status` show only the modified files, by default::
657
657
658 [defaults]
658 [defaults]
659 log = -v
659 log = -v
660 status = -m
660 status = -m
661
661
662 The actual commands, instead of their aliases, must be used when
662 The actual commands, instead of their aliases, must be used when
663 defining command defaults. The command defaults will also be applied
663 defining command defaults. The command defaults will also be applied
664 to the aliases of the commands defined.
664 to the aliases of the commands defined.
665
665
666
666
667 ``diff``
667 ``diff``
668 --------
668 --------
669
669
670 Settings used when displaying diffs. Everything except for ``unified``
670 Settings used when displaying diffs. Everything except for ``unified``
671 is a Boolean and defaults to False. See :hg:`help config.annotate`
671 is a Boolean and defaults to False. See :hg:`help config.annotate`
672 for related options for the annotate command.
672 for related options for the annotate command.
673
673
674 ``git``
674 ``git``
675 Use git extended diff format.
675 Use git extended diff format.
676
676
677 ``nobinary``
677 ``nobinary``
678 Omit git binary patches.
678 Omit git binary patches.
679
679
680 ``nodates``
680 ``nodates``
681 Don't include dates in diff headers.
681 Don't include dates in diff headers.
682
682
683 ``noprefix``
683 ``noprefix``
684 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
684 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
685
685
686 ``showfunc``
686 ``showfunc``
687 Show which function each change is in.
687 Show which function each change is in.
688
688
689 ``ignorews``
689 ``ignorews``
690 Ignore white space when comparing lines.
690 Ignore white space when comparing lines.
691
691
692 ``ignorewsamount``
692 ``ignorewsamount``
693 Ignore changes in the amount of white space.
693 Ignore changes in the amount of white space.
694
694
695 ``ignoreblanklines``
695 ``ignoreblanklines``
696 Ignore changes whose lines are all blank.
696 Ignore changes whose lines are all blank.
697
697
698 ``unified``
698 ``unified``
699 Number of lines of context to show.
699 Number of lines of context to show.
700
700
701 ``email``
701 ``email``
702 ---------
702 ---------
703
703
704 Settings for extensions that send email messages.
704 Settings for extensions that send email messages.
705
705
706 ``from``
706 ``from``
707 Optional. Email address to use in "From" header and SMTP envelope
707 Optional. Email address to use in "From" header and SMTP envelope
708 of outgoing messages.
708 of outgoing messages.
709
709
710 ``to``
710 ``to``
711 Optional. Comma-separated list of recipients' email addresses.
711 Optional. Comma-separated list of recipients' email addresses.
712
712
713 ``cc``
713 ``cc``
714 Optional. Comma-separated list of carbon copy recipients'
714 Optional. Comma-separated list of carbon copy recipients'
715 email addresses.
715 email addresses.
716
716
717 ``bcc``
717 ``bcc``
718 Optional. Comma-separated list of blind carbon copy recipients'
718 Optional. Comma-separated list of blind carbon copy recipients'
719 email addresses.
719 email addresses.
720
720
721 ``method``
721 ``method``
722 Optional. Method to use to send email messages. If value is ``smtp``
722 Optional. Method to use to send email messages. If value is ``smtp``
723 (default), use SMTP (see the ``[smtp]`` section for configuration).
723 (default), use SMTP (see the ``[smtp]`` section for configuration).
724 Otherwise, use as name of program to run that acts like sendmail
724 Otherwise, use as name of program to run that acts like sendmail
725 (takes ``-f`` option for sender, list of recipients on command line,
725 (takes ``-f`` option for sender, list of recipients on command line,
726 message on stdin). Normally, setting this to ``sendmail`` or
726 message on stdin). Normally, setting this to ``sendmail`` or
727 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
727 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
728
728
729 ``charsets``
729 ``charsets``
730 Optional. Comma-separated list of character sets considered
730 Optional. Comma-separated list of character sets considered
731 convenient for recipients. Addresses, headers, and parts not
731 convenient for recipients. Addresses, headers, and parts not
732 containing patches of outgoing messages will be encoded in the
732 containing patches of outgoing messages will be encoded in the
733 first character set to which conversion from local encoding
733 first character set to which conversion from local encoding
734 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
734 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
735 conversion fails, the text in question is sent as is.
735 conversion fails, the text in question is sent as is.
736 (default: '')
736 (default: '')
737
737
738 Order of outgoing email character sets:
738 Order of outgoing email character sets:
739
739
740 1. ``us-ascii``: always first, regardless of settings
740 1. ``us-ascii``: always first, regardless of settings
741 2. ``email.charsets``: in order given by user
741 2. ``email.charsets``: in order given by user
742 3. ``ui.fallbackencoding``: if not in email.charsets
742 3. ``ui.fallbackencoding``: if not in email.charsets
743 4. ``$HGENCODING``: if not in email.charsets
743 4. ``$HGENCODING``: if not in email.charsets
744 5. ``utf-8``: always last, regardless of settings
744 5. ``utf-8``: always last, regardless of settings
745
745
746 Email example::
746 Email example::
747
747
748 [email]
748 [email]
749 from = Joseph User <joe.user@example.com>
749 from = Joseph User <joe.user@example.com>
750 method = /usr/sbin/sendmail
750 method = /usr/sbin/sendmail
751 # charsets for western Europeans
751 # charsets for western Europeans
752 # us-ascii, utf-8 omitted, as they are tried first and last
752 # us-ascii, utf-8 omitted, as they are tried first and last
753 charsets = iso-8859-1, iso-8859-15, windows-1252
753 charsets = iso-8859-1, iso-8859-15, windows-1252
754
754
755
755
756 ``extensions``
756 ``extensions``
757 --------------
757 --------------
758
758
759 Mercurial has an extension mechanism for adding new features. To
759 Mercurial has an extension mechanism for adding new features. To
760 enable an extension, create an entry for it in this section.
760 enable an extension, create an entry for it in this section.
761
761
762 If you know that the extension is already in Python's search path,
762 If you know that the extension is already in Python's search path,
763 you can give the name of the module, followed by ``=``, with nothing
763 you can give the name of the module, followed by ``=``, with nothing
764 after the ``=``.
764 after the ``=``.
765
765
766 Otherwise, give a name that you choose, followed by ``=``, followed by
766 Otherwise, give a name that you choose, followed by ``=``, followed by
767 the path to the ``.py`` file (including the file name extension) that
767 the path to the ``.py`` file (including the file name extension) that
768 defines the extension.
768 defines the extension.
769
769
770 To explicitly disable an extension that is enabled in an hgrc of
770 To explicitly disable an extension that is enabled in an hgrc of
771 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
771 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
772 or ``foo = !`` when path is not supplied.
772 or ``foo = !`` when path is not supplied.
773
773
774 Example for ``~/.hgrc``::
774 Example for ``~/.hgrc``::
775
775
776 [extensions]
776 [extensions]
777 # (the churn extension will get loaded from Mercurial's path)
777 # (the churn extension will get loaded from Mercurial's path)
778 churn =
778 churn =
779 # (this extension will get loaded from the file specified)
779 # (this extension will get loaded from the file specified)
780 myfeature = ~/.hgext/myfeature.py
780 myfeature = ~/.hgext/myfeature.py
781
781
782
782
783 ``format``
783 ``format``
784 ----------
784 ----------
785
785
786 ``usegeneraldelta``
786 ``usegeneraldelta``
787 Enable or disable the "generaldelta" repository format which improves
787 Enable or disable the "generaldelta" repository format which improves
788 repository compression by allowing "revlog" to store delta against arbitrary
788 repository compression by allowing "revlog" to store delta against arbitrary
789 revision instead of the previous stored one. This provides significant
789 revision instead of the previous stored one. This provides significant
790 improvement for repositories with branches.
790 improvement for repositories with branches.
791
791
792 Repositories with this on-disk format require Mercurial version 1.9.
792 Repositories with this on-disk format require Mercurial version 1.9.
793
793
794 Enabled by default.
794 Enabled by default.
795
795
796 ``dotencode``
796 ``dotencode``
797 Enable or disable the "dotencode" repository format which enhances
797 Enable or disable the "dotencode" repository format which enhances
798 the "fncache" repository format (which has to be enabled to use
798 the "fncache" repository format (which has to be enabled to use
799 dotencode) to avoid issues with filenames starting with ._ on
799 dotencode) to avoid issues with filenames starting with ._ on
800 Mac OS X and spaces on Windows.
800 Mac OS X and spaces on Windows.
801
801
802 Repositories with this on-disk format require Mercurial version 1.7.
802 Repositories with this on-disk format require Mercurial version 1.7.
803
803
804 Enabled by default.
804 Enabled by default.
805
805
806 ``usefncache``
806 ``usefncache``
807 Enable or disable the "fncache" repository format which enhances
807 Enable or disable the "fncache" repository format which enhances
808 the "store" repository format (which has to be enabled to use
808 the "store" repository format (which has to be enabled to use
809 fncache) to allow longer filenames and avoids using Windows
809 fncache) to allow longer filenames and avoids using Windows
810 reserved names, e.g. "nul".
810 reserved names, e.g. "nul".
811
811
812 Repositories with this on-disk format require Mercurial version 1.1.
812 Repositories with this on-disk format require Mercurial version 1.1.
813
813
814 Enabled by default.
814 Enabled by default.
815
815
816 ``usestore``
816 ``usestore``
817 Enable or disable the "store" repository format which improves
817 Enable or disable the "store" repository format which improves
818 compatibility with systems that fold case or otherwise mangle
818 compatibility with systems that fold case or otherwise mangle
819 filenames. Disabling this option will allow you to store longer filenames
819 filenames. Disabling this option will allow you to store longer filenames
820 in some situations at the expense of compatibility.
820 in some situations at the expense of compatibility.
821
821
822 Repositories with this on-disk format require Mercurial version 0.9.4.
822 Repositories with this on-disk format require Mercurial version 0.9.4.
823
823
824 Enabled by default.
824 Enabled by default.
825
825
826 ``graph``
826 ``graph``
827 ---------
827 ---------
828
828
829 Web graph view configuration. This section let you change graph
829 Web graph view configuration. This section let you change graph
830 elements display properties by branches, for instance to make the
830 elements display properties by branches, for instance to make the
831 ``default`` branch stand out.
831 ``default`` branch stand out.
832
832
833 Each line has the following format::
833 Each line has the following format::
834
834
835 <branch>.<argument> = <value>
835 <branch>.<argument> = <value>
836
836
837 where ``<branch>`` is the name of the branch being
837 where ``<branch>`` is the name of the branch being
838 customized. Example::
838 customized. Example::
839
839
840 [graph]
840 [graph]
841 # 2px width
841 # 2px width
842 default.width = 2
842 default.width = 2
843 # red color
843 # red color
844 default.color = FF0000
844 default.color = FF0000
845
845
846 Supported arguments:
846 Supported arguments:
847
847
848 ``width``
848 ``width``
849 Set branch edges width in pixels.
849 Set branch edges width in pixels.
850
850
851 ``color``
851 ``color``
852 Set branch edges color in hexadecimal RGB notation.
852 Set branch edges color in hexadecimal RGB notation.
853
853
854 ``hooks``
854 ``hooks``
855 ---------
855 ---------
856
856
857 Commands or Python functions that get automatically executed by
857 Commands or Python functions that get automatically executed by
858 various actions such as starting or finishing a commit. Multiple
858 various actions such as starting or finishing a commit. Multiple
859 hooks can be run for the same action by appending a suffix to the
859 hooks can be run for the same action by appending a suffix to the
860 action. Overriding a site-wide hook can be done by changing its
860 action. Overriding a site-wide hook can be done by changing its
861 value or setting it to an empty string. Hooks can be prioritized
861 value or setting it to an empty string. Hooks can be prioritized
862 by adding a prefix of ``priority.`` to the hook name on a new line
862 by adding a prefix of ``priority.`` to the hook name on a new line
863 and setting the priority. The default priority is 0.
863 and setting the priority. The default priority is 0.
864
864
865 Example ``.hg/hgrc``::
865 Example ``.hg/hgrc``::
866
866
867 [hooks]
867 [hooks]
868 # update working directory after adding changesets
868 # update working directory after adding changesets
869 changegroup.update = hg update
869 changegroup.update = hg update
870 # do not use the site-wide hook
870 # do not use the site-wide hook
871 incoming =
871 incoming =
872 incoming.email = /my/email/hook
872 incoming.email = /my/email/hook
873 incoming.autobuild = /my/build/hook
873 incoming.autobuild = /my/build/hook
874 # force autobuild hook to run before other incoming hooks
874 # force autobuild hook to run before other incoming hooks
875 priority.incoming.autobuild = 1
875 priority.incoming.autobuild = 1
876
876
877 Most hooks are run with environment variables set that give useful
877 Most hooks are run with environment variables set that give useful
878 additional information. For each hook below, the environment variables
878 additional information. For each hook below, the environment variables
879 it is passed are listed with names in the form ``$HG_foo``. The
879 it is passed are listed with names in the form ``$HG_foo``. The
880 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
880 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
881 They contain the type of hook which triggered the run and the full name
881 They contain the type of hook which triggered the run and the full name
882 of the hook in the config, respectively. In the example above, this will
882 of the hook in the config, respectively. In the example above, this will
883 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
883 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
884
884
885 ``changegroup``
885 ``changegroup``
886 Run after a changegroup has been added via push, pull or unbundle. The ID of
886 Run after a changegroup has been added via push, pull or unbundle. The ID of
887 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
887 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
888 The URL from which changes came is in ``$HG_URL``.
888 The URL from which changes came is in ``$HG_URL``.
889
889
890 ``commit``
890 ``commit``
891 Run after a changeset has been created in the local repository. The ID
891 Run after a changeset has been created in the local repository. The ID
892 of the newly created changeset is in ``$HG_NODE``. Parent changeset
892 of the newly created changeset is in ``$HG_NODE``. Parent changeset
893 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
893 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
894
894
895 ``incoming``
895 ``incoming``
896 Run after a changeset has been pulled, pushed, or unbundled into
896 Run after a changeset has been pulled, pushed, or unbundled into
897 the local repository. The ID of the newly arrived changeset is in
897 the local repository. The ID of the newly arrived changeset is in
898 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
898 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
899
899
900 ``outgoing``
900 ``outgoing``
901 Run after sending changes from the local repository to another. The ID of
901 Run after sending changes from the local repository to another. The ID of
902 first changeset sent is in ``$HG_NODE``. The source of operation is in
902 first changeset sent is in ``$HG_NODE``. The source of operation is in
903 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
903 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
904
904
905 ``post-<command>``
905 ``post-<command>``
906 Run after successful invocations of the associated command. The
906 Run after successful invocations of the associated command. The
907 contents of the command line are passed as ``$HG_ARGS`` and the result
907 contents of the command line are passed as ``$HG_ARGS`` and the result
908 code in ``$HG_RESULT``. Parsed command line arguments are passed as
908 code in ``$HG_RESULT``. Parsed command line arguments are passed as
909 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
909 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
910 the python data internally passed to <command>. ``$HG_OPTS`` is a
910 the python data internally passed to <command>. ``$HG_OPTS`` is a
911 dictionary of options (with unspecified options set to their defaults).
911 dictionary of options (with unspecified options set to their defaults).
912 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
912 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
913
913
914 ``fail-<command>``
914 ``fail-<command>``
915 Run after a failed invocation of an associated command. The contents
915 Run after a failed invocation of an associated command. The contents
916 of the command line are passed as ``$HG_ARGS``. Parsed command line
916 of the command line are passed as ``$HG_ARGS``. Parsed command line
917 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
917 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
918 string representations of the python data internally passed to
918 string representations of the python data internally passed to
919 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
919 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
920 options set to their defaults). ``$HG_PATS`` is a list of arguments.
920 options set to their defaults). ``$HG_PATS`` is a list of arguments.
921 Hook failure is ignored.
921 Hook failure is ignored.
922
922
923 ``pre-<command>``
923 ``pre-<command>``
924 Run before executing the associated command. The contents of the
924 Run before executing the associated command. The contents of the
925 command line are passed as ``$HG_ARGS``. Parsed command line arguments
925 command line are passed as ``$HG_ARGS``. Parsed command line arguments
926 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
926 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
927 representations of the data internally passed to <command>. ``$HG_OPTS``
927 representations of the data internally passed to <command>. ``$HG_OPTS``
928 is a dictionary of options (with unspecified options set to their
928 is a dictionary of options (with unspecified options set to their
929 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
929 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
930 failure, the command doesn't execute and Mercurial returns the failure
930 failure, the command doesn't execute and Mercurial returns the failure
931 code.
931 code.
932
932
933 ``prechangegroup``
933 ``prechangegroup``
934 Run before a changegroup is added via push, pull or unbundle. Exit
934 Run before a changegroup is added via push, pull or unbundle. Exit
935 status 0 allows the changegroup to proceed. A non-zero status will
935 status 0 allows the changegroup to proceed. A non-zero status will
936 cause the push, pull or unbundle to fail. The URL from which changes
936 cause the push, pull or unbundle to fail. The URL from which changes
937 will come is in ``$HG_URL``.
937 will come is in ``$HG_URL``.
938
938
939 ``precommit``
939 ``precommit``
940 Run before starting a local commit. Exit status 0 allows the
940 Run before starting a local commit. Exit status 0 allows the
941 commit to proceed. A non-zero status will cause the commit to fail.
941 commit to proceed. A non-zero status will cause the commit to fail.
942 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
942 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
943
943
944 ``prelistkeys``
944 ``prelistkeys``
945 Run before listing pushkeys (like bookmarks) in the
945 Run before listing pushkeys (like bookmarks) in the
946 repository. A non-zero status will cause failure. The key namespace is
946 repository. A non-zero status will cause failure. The key namespace is
947 in ``$HG_NAMESPACE``.
947 in ``$HG_NAMESPACE``.
948
948
949 ``preoutgoing``
949 ``preoutgoing``
950 Run before collecting changes to send from the local repository to
950 Run before collecting changes to send from the local repository to
951 another. A non-zero status will cause failure. This lets you prevent
951 another. A non-zero status will cause failure. This lets you prevent
952 pull over HTTP or SSH. It can also prevent propagating commits (via
952 pull over HTTP or SSH. It can also prevent propagating commits (via
953 local pull, push (outbound) or bundle commands), but not completely,
953 local pull, push (outbound) or bundle commands), but not completely,
954 since you can just copy files instead. The source of operation is in
954 since you can just copy files instead. The source of operation is in
955 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
955 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
956 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
956 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
957 is happening on behalf of a repository on same system.
957 is happening on behalf of a repository on same system.
958
958
959 ``prepushkey``
959 ``prepushkey``
960 Run before a pushkey (like a bookmark) is added to the
960 Run before a pushkey (like a bookmark) is added to the
961 repository. A non-zero status will cause the key to be rejected. The
961 repository. A non-zero status will cause the key to be rejected. The
962 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
962 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
963 the old value (if any) is in ``$HG_OLD``, and the new value is in
963 the old value (if any) is in ``$HG_OLD``, and the new value is in
964 ``$HG_NEW``.
964 ``$HG_NEW``.
965
965
966 ``pretag``
966 ``pretag``
967 Run before creating a tag. Exit status 0 allows the tag to be
967 Run before creating a tag. Exit status 0 allows the tag to be
968 created. A non-zero status will cause the tag to fail. The ID of the
968 created. A non-zero status will cause the tag to fail. The ID of the
969 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
969 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
970 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
970 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
971
971
972 ``pretxnopen``
972 ``pretxnopen``
973 Run before any new repository transaction is open. The reason for the
973 Run before any new repository transaction is open. The reason for the
974 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
974 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
975 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
975 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
976 transaction from being opened.
976 transaction from being opened.
977
977
978 ``pretxnclose``
978 ``pretxnclose``
979 Run right before the transaction is actually finalized. Any repository change
979 Run right before the transaction is actually finalized. Any repository change
980 will be visible to the hook program. This lets you validate the transaction
980 will be visible to the hook program. This lets you validate the transaction
981 content or change it. Exit status 0 allows the commit to proceed. A non-zero
981 content or change it. Exit status 0 allows the commit to proceed. A non-zero
982 status will cause the transaction to be rolled back. The reason for the
982 status will cause the transaction to be rolled back. The reason for the
983 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
983 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
984 the transaction will be in ``HG_TXNID``. The rest of the available data will
984 the transaction will be in ``HG_TXNID``. The rest of the available data will
985 vary according the transaction type. New changesets will add ``$HG_NODE``
985 vary according the transaction type. New changesets will add ``$HG_NODE``
986 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
986 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
987 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
987 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
988 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
988 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
989 respectively, etc.
989 respectively, etc.
990
990
991 ``txnclose``
991 ``txnclose``
992 Run after any repository transaction has been committed. At this
992 Run after any repository transaction has been committed. At this
993 point, the transaction can no longer be rolled back. The hook will run
993 point, the transaction can no longer be rolled back. The hook will run
994 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
994 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
995 details about available variables.
995 details about available variables.
996
996
997 ``txnclose-bookmark``
998 Run after any bookmark change has been committed. At this point, the
999 transaction can no longer be rolled back. The hook will run after the lock
1000 is released.
1001 The name of the bookmark will be available in ``$HG_BOOKMARK``, the new
1002 bookmark location will be available in ``$HG_NODE`` while the previous
1003 location will be available in ``$HG_OLDNODE``. In case of a bookmark
1004 creation ``$HG_OLDNODE`` will be empty. In case of deletion ``$HG_NODE``
1005 will be empty. In addition, the reason for the transaction opening will be
1006 in ``$HG_TXNNAME``, and a unique identifier for the transaction will be in
1007 ``HG_TXNID``.
1008
997 ``txnabort``
1009 ``txnabort``
998 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
1010 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
999 for details about available variables.
1011 for details about available variables.
1000
1012
1001 ``pretxnchangegroup``
1013 ``pretxnchangegroup``
1002 Run after a changegroup has been added via push, pull or unbundle, but before
1014 Run after a changegroup has been added via push, pull or unbundle, but before
1003 the transaction has been committed. The changegroup is visible to the hook
1015 the transaction has been committed. The changegroup is visible to the hook
1004 program. This allows validation of incoming changes before accepting them.
1016 program. This allows validation of incoming changes before accepting them.
1005 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1017 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1006 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1018 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1007 status will cause the transaction to be rolled back, and the push, pull or
1019 status will cause the transaction to be rolled back, and the push, pull or
1008 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1020 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1009
1021
1010 ``pretxncommit``
1022 ``pretxncommit``
1011 Run after a changeset has been created, but before the transaction is
1023 Run after a changeset has been created, but before the transaction is
1012 committed. The changeset is visible to the hook program. This allows
1024 committed. The changeset is visible to the hook program. This allows
1013 validation of the commit message and changes. Exit status 0 allows the
1025 validation of the commit message and changes. Exit status 0 allows the
1014 commit to proceed. A non-zero status will cause the transaction to
1026 commit to proceed. A non-zero status will cause the transaction to
1015 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1027 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1016 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1028 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1017
1029
1018 ``preupdate``
1030 ``preupdate``
1019 Run before updating the working directory. Exit status 0 allows
1031 Run before updating the working directory. Exit status 0 allows
1020 the update to proceed. A non-zero status will prevent the update.
1032 the update to proceed. A non-zero status will prevent the update.
1021 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1033 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1022 merge, the ID of second new parent is in ``$HG_PARENT2``.
1034 merge, the ID of second new parent is in ``$HG_PARENT2``.
1023
1035
1024 ``listkeys``
1036 ``listkeys``
1025 Run after listing pushkeys (like bookmarks) in the repository. The
1037 Run after listing pushkeys (like bookmarks) in the repository. The
1026 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1038 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1027 dictionary containing the keys and values.
1039 dictionary containing the keys and values.
1028
1040
1029 ``pushkey``
1041 ``pushkey``
1030 Run after a pushkey (like a bookmark) is added to the
1042 Run after a pushkey (like a bookmark) is added to the
1031 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1043 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1032 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1044 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1033 value is in ``$HG_NEW``.
1045 value is in ``$HG_NEW``.
1034
1046
1035 ``tag``
1047 ``tag``
1036 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1048 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1037 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1049 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1038 the repository if ``$HG_LOCAL=0``.
1050 the repository if ``$HG_LOCAL=0``.
1039
1051
1040 ``update``
1052 ``update``
1041 Run after updating the working directory. The changeset ID of first
1053 Run after updating the working directory. The changeset ID of first
1042 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1054 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1043 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1055 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1044 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1056 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1045
1057
1046 .. note::
1058 .. note::
1047
1059
1048 It is generally better to use standard hooks rather than the
1060 It is generally better to use standard hooks rather than the
1049 generic pre- and post- command hooks, as they are guaranteed to be
1061 generic pre- and post- command hooks, as they are guaranteed to be
1050 called in the appropriate contexts for influencing transactions.
1062 called in the appropriate contexts for influencing transactions.
1051 Also, hooks like "commit" will be called in all contexts that
1063 Also, hooks like "commit" will be called in all contexts that
1052 generate a commit (e.g. tag) and not just the commit command.
1064 generate a commit (e.g. tag) and not just the commit command.
1053
1065
1054 .. note::
1066 .. note::
1055
1067
1056 Environment variables with empty values may not be passed to
1068 Environment variables with empty values may not be passed to
1057 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1069 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1058 will have an empty value under Unix-like platforms for non-merge
1070 will have an empty value under Unix-like platforms for non-merge
1059 changesets, while it will not be available at all under Windows.
1071 changesets, while it will not be available at all under Windows.
1060
1072
1061 The syntax for Python hooks is as follows::
1073 The syntax for Python hooks is as follows::
1062
1074
1063 hookname = python:modulename.submodule.callable
1075 hookname = python:modulename.submodule.callable
1064 hookname = python:/path/to/python/module.py:callable
1076 hookname = python:/path/to/python/module.py:callable
1065
1077
1066 Python hooks are run within the Mercurial process. Each hook is
1078 Python hooks are run within the Mercurial process. Each hook is
1067 called with at least three keyword arguments: a ui object (keyword
1079 called with at least three keyword arguments: a ui object (keyword
1068 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1080 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1069 keyword that tells what kind of hook is used. Arguments listed as
1081 keyword that tells what kind of hook is used. Arguments listed as
1070 environment variables above are passed as keyword arguments, with no
1082 environment variables above are passed as keyword arguments, with no
1071 ``HG_`` prefix, and names in lower case.
1083 ``HG_`` prefix, and names in lower case.
1072
1084
1073 If a Python hook returns a "true" value or raises an exception, this
1085 If a Python hook returns a "true" value or raises an exception, this
1074 is treated as a failure.
1086 is treated as a failure.
1075
1087
1076
1088
1077 ``hostfingerprints``
1089 ``hostfingerprints``
1078 --------------------
1090 --------------------
1079
1091
1080 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1092 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1081
1093
1082 Fingerprints of the certificates of known HTTPS servers.
1094 Fingerprints of the certificates of known HTTPS servers.
1083
1095
1084 A HTTPS connection to a server with a fingerprint configured here will
1096 A HTTPS connection to a server with a fingerprint configured here will
1085 only succeed if the servers certificate matches the fingerprint.
1097 only succeed if the servers certificate matches the fingerprint.
1086 This is very similar to how ssh known hosts works.
1098 This is very similar to how ssh known hosts works.
1087
1099
1088 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1100 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1089 Multiple values can be specified (separated by spaces or commas). This can
1101 Multiple values can be specified (separated by spaces or commas). This can
1090 be used to define both old and new fingerprints while a host transitions
1102 be used to define both old and new fingerprints while a host transitions
1091 to a new certificate.
1103 to a new certificate.
1092
1104
1093 The CA chain and web.cacerts is not used for servers with a fingerprint.
1105 The CA chain and web.cacerts is not used for servers with a fingerprint.
1094
1106
1095 For example::
1107 For example::
1096
1108
1097 [hostfingerprints]
1109 [hostfingerprints]
1098 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1110 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1099 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1111 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1100
1112
1101 ``hostsecurity``
1113 ``hostsecurity``
1102 ----------------
1114 ----------------
1103
1115
1104 Used to specify global and per-host security settings for connecting to
1116 Used to specify global and per-host security settings for connecting to
1105 other machines.
1117 other machines.
1106
1118
1107 The following options control default behavior for all hosts.
1119 The following options control default behavior for all hosts.
1108
1120
1109 ``ciphers``
1121 ``ciphers``
1110 Defines the cryptographic ciphers to use for connections.
1122 Defines the cryptographic ciphers to use for connections.
1111
1123
1112 Value must be a valid OpenSSL Cipher List Format as documented at
1124 Value must be a valid OpenSSL Cipher List Format as documented at
1113 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1125 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1114
1126
1115 This setting is for advanced users only. Setting to incorrect values
1127 This setting is for advanced users only. Setting to incorrect values
1116 can significantly lower connection security or decrease performance.
1128 can significantly lower connection security or decrease performance.
1117 You have been warned.
1129 You have been warned.
1118
1130
1119 This option requires Python 2.7.
1131 This option requires Python 2.7.
1120
1132
1121 ``minimumprotocol``
1133 ``minimumprotocol``
1122 Defines the minimum channel encryption protocol to use.
1134 Defines the minimum channel encryption protocol to use.
1123
1135
1124 By default, the highest version of TLS supported by both client and server
1136 By default, the highest version of TLS supported by both client and server
1125 is used.
1137 is used.
1126
1138
1127 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1139 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1128
1140
1129 When running on an old Python version, only ``tls1.0`` is allowed since
1141 When running on an old Python version, only ``tls1.0`` is allowed since
1130 old versions of Python only support up to TLS 1.0.
1142 old versions of Python only support up to TLS 1.0.
1131
1143
1132 When running a Python that supports modern TLS versions, the default is
1144 When running a Python that supports modern TLS versions, the default is
1133 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1145 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1134 weakens security and should only be used as a feature of last resort if
1146 weakens security and should only be used as a feature of last resort if
1135 a server does not support TLS 1.1+.
1147 a server does not support TLS 1.1+.
1136
1148
1137 Options in the ``[hostsecurity]`` section can have the form
1149 Options in the ``[hostsecurity]`` section can have the form
1138 ``hostname``:``setting``. This allows multiple settings to be defined on a
1150 ``hostname``:``setting``. This allows multiple settings to be defined on a
1139 per-host basis.
1151 per-host basis.
1140
1152
1141 The following per-host settings can be defined.
1153 The following per-host settings can be defined.
1142
1154
1143 ``ciphers``
1155 ``ciphers``
1144 This behaves like ``ciphers`` as described above except it only applies
1156 This behaves like ``ciphers`` as described above except it only applies
1145 to the host on which it is defined.
1157 to the host on which it is defined.
1146
1158
1147 ``fingerprints``
1159 ``fingerprints``
1148 A list of hashes of the DER encoded peer/remote certificate. Values have
1160 A list of hashes of the DER encoded peer/remote certificate. Values have
1149 the form ``algorithm``:``fingerprint``. e.g.
1161 the form ``algorithm``:``fingerprint``. e.g.
1150 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1162 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1151 In addition, colons (``:``) can appear in the fingerprint part.
1163 In addition, colons (``:``) can appear in the fingerprint part.
1152
1164
1153 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1165 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1154 ``sha512``.
1166 ``sha512``.
1155
1167
1156 Use of ``sha256`` or ``sha512`` is preferred.
1168 Use of ``sha256`` or ``sha512`` is preferred.
1157
1169
1158 If a fingerprint is specified, the CA chain is not validated for this
1170 If a fingerprint is specified, the CA chain is not validated for this
1159 host and Mercurial will require the remote certificate to match one
1171 host and Mercurial will require the remote certificate to match one
1160 of the fingerprints specified. This means if the server updates its
1172 of the fingerprints specified. This means if the server updates its
1161 certificate, Mercurial will abort until a new fingerprint is defined.
1173 certificate, Mercurial will abort until a new fingerprint is defined.
1162 This can provide stronger security than traditional CA-based validation
1174 This can provide stronger security than traditional CA-based validation
1163 at the expense of convenience.
1175 at the expense of convenience.
1164
1176
1165 This option takes precedence over ``verifycertsfile``.
1177 This option takes precedence over ``verifycertsfile``.
1166
1178
1167 ``minimumprotocol``
1179 ``minimumprotocol``
1168 This behaves like ``minimumprotocol`` as described above except it
1180 This behaves like ``minimumprotocol`` as described above except it
1169 only applies to the host on which it is defined.
1181 only applies to the host on which it is defined.
1170
1182
1171 ``verifycertsfile``
1183 ``verifycertsfile``
1172 Path to file a containing a list of PEM encoded certificates used to
1184 Path to file a containing a list of PEM encoded certificates used to
1173 verify the server certificate. Environment variables and ``~user``
1185 verify the server certificate. Environment variables and ``~user``
1174 constructs are expanded in the filename.
1186 constructs are expanded in the filename.
1175
1187
1176 The server certificate or the certificate's certificate authority (CA)
1188 The server certificate or the certificate's certificate authority (CA)
1177 must match a certificate from this file or certificate verification
1189 must match a certificate from this file or certificate verification
1178 will fail and connections to the server will be refused.
1190 will fail and connections to the server will be refused.
1179
1191
1180 If defined, only certificates provided by this file will be used:
1192 If defined, only certificates provided by this file will be used:
1181 ``web.cacerts`` and any system/default certificates will not be
1193 ``web.cacerts`` and any system/default certificates will not be
1182 used.
1194 used.
1183
1195
1184 This option has no effect if the per-host ``fingerprints`` option
1196 This option has no effect if the per-host ``fingerprints`` option
1185 is set.
1197 is set.
1186
1198
1187 The format of the file is as follows::
1199 The format of the file is as follows::
1188
1200
1189 -----BEGIN CERTIFICATE-----
1201 -----BEGIN CERTIFICATE-----
1190 ... (certificate in base64 PEM encoding) ...
1202 ... (certificate in base64 PEM encoding) ...
1191 -----END CERTIFICATE-----
1203 -----END CERTIFICATE-----
1192 -----BEGIN CERTIFICATE-----
1204 -----BEGIN CERTIFICATE-----
1193 ... (certificate in base64 PEM encoding) ...
1205 ... (certificate in base64 PEM encoding) ...
1194 -----END CERTIFICATE-----
1206 -----END CERTIFICATE-----
1195
1207
1196 For example::
1208 For example::
1197
1209
1198 [hostsecurity]
1210 [hostsecurity]
1199 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1211 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1200 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
1212 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
1201 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
1213 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
1202 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1214 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1203
1215
1204 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1216 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1205 when connecting to ``hg.example.com``::
1217 when connecting to ``hg.example.com``::
1206
1218
1207 [hostsecurity]
1219 [hostsecurity]
1208 minimumprotocol = tls1.2
1220 minimumprotocol = tls1.2
1209 hg.example.com:minimumprotocol = tls1.1
1221 hg.example.com:minimumprotocol = tls1.1
1210
1222
1211 ``http_proxy``
1223 ``http_proxy``
1212 --------------
1224 --------------
1213
1225
1214 Used to access web-based Mercurial repositories through a HTTP
1226 Used to access web-based Mercurial repositories through a HTTP
1215 proxy.
1227 proxy.
1216
1228
1217 ``host``
1229 ``host``
1218 Host name and (optional) port of the proxy server, for example
1230 Host name and (optional) port of the proxy server, for example
1219 "myproxy:8000".
1231 "myproxy:8000".
1220
1232
1221 ``no``
1233 ``no``
1222 Optional. Comma-separated list of host names that should bypass
1234 Optional. Comma-separated list of host names that should bypass
1223 the proxy.
1235 the proxy.
1224
1236
1225 ``passwd``
1237 ``passwd``
1226 Optional. Password to authenticate with at the proxy server.
1238 Optional. Password to authenticate with at the proxy server.
1227
1239
1228 ``user``
1240 ``user``
1229 Optional. User name to authenticate with at the proxy server.
1241 Optional. User name to authenticate with at the proxy server.
1230
1242
1231 ``always``
1243 ``always``
1232 Optional. Always use the proxy, even for localhost and any entries
1244 Optional. Always use the proxy, even for localhost and any entries
1233 in ``http_proxy.no``. (default: False)
1245 in ``http_proxy.no``. (default: False)
1234
1246
1235 ``merge``
1247 ``merge``
1236 ---------
1248 ---------
1237
1249
1238 This section specifies behavior during merges and updates.
1250 This section specifies behavior during merges and updates.
1239
1251
1240 ``checkignored``
1252 ``checkignored``
1241 Controls behavior when an ignored file on disk has the same name as a tracked
1253 Controls behavior when an ignored file on disk has the same name as a tracked
1242 file in the changeset being merged or updated to, and has different
1254 file in the changeset being merged or updated to, and has different
1243 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1255 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1244 abort on such files. With ``warn``, warn on such files and back them up as
1256 abort on such files. With ``warn``, warn on such files and back them up as
1245 ``.orig``. With ``ignore``, don't print a warning and back them up as
1257 ``.orig``. With ``ignore``, don't print a warning and back them up as
1246 ``.orig``. (default: ``abort``)
1258 ``.orig``. (default: ``abort``)
1247
1259
1248 ``checkunknown``
1260 ``checkunknown``
1249 Controls behavior when an unknown file that isn't ignored has the same name
1261 Controls behavior when an unknown file that isn't ignored has the same name
1250 as a tracked file in the changeset being merged or updated to, and has
1262 as a tracked file in the changeset being merged or updated to, and has
1251 different contents. Similar to ``merge.checkignored``, except for files that
1263 different contents. Similar to ``merge.checkignored``, except for files that
1252 are not ignored. (default: ``abort``)
1264 are not ignored. (default: ``abort``)
1253
1265
1254 ``merge-patterns``
1266 ``merge-patterns``
1255 ------------------
1267 ------------------
1256
1268
1257 This section specifies merge tools to associate with particular file
1269 This section specifies merge tools to associate with particular file
1258 patterns. Tools matched here will take precedence over the default
1270 patterns. Tools matched here will take precedence over the default
1259 merge tool. Patterns are globs by default, rooted at the repository
1271 merge tool. Patterns are globs by default, rooted at the repository
1260 root.
1272 root.
1261
1273
1262 Example::
1274 Example::
1263
1275
1264 [merge-patterns]
1276 [merge-patterns]
1265 **.c = kdiff3
1277 **.c = kdiff3
1266 **.jpg = myimgmerge
1278 **.jpg = myimgmerge
1267
1279
1268 ``merge-tools``
1280 ``merge-tools``
1269 ---------------
1281 ---------------
1270
1282
1271 This section configures external merge tools to use for file-level
1283 This section configures external merge tools to use for file-level
1272 merges. This section has likely been preconfigured at install time.
1284 merges. This section has likely been preconfigured at install time.
1273 Use :hg:`config merge-tools` to check the existing configuration.
1285 Use :hg:`config merge-tools` to check the existing configuration.
1274 Also see :hg:`help merge-tools` for more details.
1286 Also see :hg:`help merge-tools` for more details.
1275
1287
1276 Example ``~/.hgrc``::
1288 Example ``~/.hgrc``::
1277
1289
1278 [merge-tools]
1290 [merge-tools]
1279 # Override stock tool location
1291 # Override stock tool location
1280 kdiff3.executable = ~/bin/kdiff3
1292 kdiff3.executable = ~/bin/kdiff3
1281 # Specify command line
1293 # Specify command line
1282 kdiff3.args = $base $local $other -o $output
1294 kdiff3.args = $base $local $other -o $output
1283 # Give higher priority
1295 # Give higher priority
1284 kdiff3.priority = 1
1296 kdiff3.priority = 1
1285
1297
1286 # Changing the priority of preconfigured tool
1298 # Changing the priority of preconfigured tool
1287 meld.priority = 0
1299 meld.priority = 0
1288
1300
1289 # Disable a preconfigured tool
1301 # Disable a preconfigured tool
1290 vimdiff.disabled = yes
1302 vimdiff.disabled = yes
1291
1303
1292 # Define new tool
1304 # Define new tool
1293 myHtmlTool.args = -m $local $other $base $output
1305 myHtmlTool.args = -m $local $other $base $output
1294 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1306 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1295 myHtmlTool.priority = 1
1307 myHtmlTool.priority = 1
1296
1308
1297 Supported arguments:
1309 Supported arguments:
1298
1310
1299 ``priority``
1311 ``priority``
1300 The priority in which to evaluate this tool.
1312 The priority in which to evaluate this tool.
1301 (default: 0)
1313 (default: 0)
1302
1314
1303 ``executable``
1315 ``executable``
1304 Either just the name of the executable or its pathname.
1316 Either just the name of the executable or its pathname.
1305
1317
1306 .. container:: windows
1318 .. container:: windows
1307
1319
1308 On Windows, the path can use environment variables with ${ProgramFiles}
1320 On Windows, the path can use environment variables with ${ProgramFiles}
1309 syntax.
1321 syntax.
1310
1322
1311 (default: the tool name)
1323 (default: the tool name)
1312
1324
1313 ``args``
1325 ``args``
1314 The arguments to pass to the tool executable. You can refer to the
1326 The arguments to pass to the tool executable. You can refer to the
1315 files being merged as well as the output file through these
1327 files being merged as well as the output file through these
1316 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1328 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1317 of ``$local`` and ``$other`` can vary depending on which action is being
1329 of ``$local`` and ``$other`` can vary depending on which action is being
1318 performed. During and update or merge, ``$local`` represents the original
1330 performed. During and update or merge, ``$local`` represents the original
1319 state of the file, while ``$other`` represents the commit you are updating
1331 state of the file, while ``$other`` represents the commit you are updating
1320 to or the commit you are merging with. During a rebase ``$local``
1332 to or the commit you are merging with. During a rebase ``$local``
1321 represents the destination of the rebase, and ``$other`` represents the
1333 represents the destination of the rebase, and ``$other`` represents the
1322 commit being rebased.
1334 commit being rebased.
1323 (default: ``$local $base $other``)
1335 (default: ``$local $base $other``)
1324
1336
1325 ``premerge``
1337 ``premerge``
1326 Attempt to run internal non-interactive 3-way merge tool before
1338 Attempt to run internal non-interactive 3-way merge tool before
1327 launching external tool. Options are ``true``, ``false``, ``keep`` or
1339 launching external tool. Options are ``true``, ``false``, ``keep`` or
1328 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1340 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1329 premerge fails. The ``keep-merge3`` will do the same but include information
1341 premerge fails. The ``keep-merge3`` will do the same but include information
1330 about the base of the merge in the marker (see internal :merge3 in
1342 about the base of the merge in the marker (see internal :merge3 in
1331 :hg:`help merge-tools`).
1343 :hg:`help merge-tools`).
1332 (default: True)
1344 (default: True)
1333
1345
1334 ``binary``
1346 ``binary``
1335 This tool can merge binary files. (default: False, unless tool
1347 This tool can merge binary files. (default: False, unless tool
1336 was selected by file pattern match)
1348 was selected by file pattern match)
1337
1349
1338 ``symlink``
1350 ``symlink``
1339 This tool can merge symlinks. (default: False)
1351 This tool can merge symlinks. (default: False)
1340
1352
1341 ``check``
1353 ``check``
1342 A list of merge success-checking options:
1354 A list of merge success-checking options:
1343
1355
1344 ``changed``
1356 ``changed``
1345 Ask whether merge was successful when the merged file shows no changes.
1357 Ask whether merge was successful when the merged file shows no changes.
1346 ``conflicts``
1358 ``conflicts``
1347 Check whether there are conflicts even though the tool reported success.
1359 Check whether there are conflicts even though the tool reported success.
1348 ``prompt``
1360 ``prompt``
1349 Always prompt for merge success, regardless of success reported by tool.
1361 Always prompt for merge success, regardless of success reported by tool.
1350
1362
1351 ``fixeol``
1363 ``fixeol``
1352 Attempt to fix up EOL changes caused by the merge tool.
1364 Attempt to fix up EOL changes caused by the merge tool.
1353 (default: False)
1365 (default: False)
1354
1366
1355 ``gui``
1367 ``gui``
1356 This tool requires a graphical interface to run. (default: False)
1368 This tool requires a graphical interface to run. (default: False)
1357
1369
1358 .. container:: windows
1370 .. container:: windows
1359
1371
1360 ``regkey``
1372 ``regkey``
1361 Windows registry key which describes install location of this
1373 Windows registry key which describes install location of this
1362 tool. Mercurial will search for this key first under
1374 tool. Mercurial will search for this key first under
1363 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1375 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1364 (default: None)
1376 (default: None)
1365
1377
1366 ``regkeyalt``
1378 ``regkeyalt``
1367 An alternate Windows registry key to try if the first key is not
1379 An alternate Windows registry key to try if the first key is not
1368 found. The alternate key uses the same ``regname`` and ``regappend``
1380 found. The alternate key uses the same ``regname`` and ``regappend``
1369 semantics of the primary key. The most common use for this key
1381 semantics of the primary key. The most common use for this key
1370 is to search for 32bit applications on 64bit operating systems.
1382 is to search for 32bit applications on 64bit operating systems.
1371 (default: None)
1383 (default: None)
1372
1384
1373 ``regname``
1385 ``regname``
1374 Name of value to read from specified registry key.
1386 Name of value to read from specified registry key.
1375 (default: the unnamed (default) value)
1387 (default: the unnamed (default) value)
1376
1388
1377 ``regappend``
1389 ``regappend``
1378 String to append to the value read from the registry, typically
1390 String to append to the value read from the registry, typically
1379 the executable name of the tool.
1391 the executable name of the tool.
1380 (default: None)
1392 (default: None)
1381
1393
1382 ``pager``
1394 ``pager``
1383 ---------
1395 ---------
1384
1396
1385 Setting used to control when to paginate and with what external tool. See
1397 Setting used to control when to paginate and with what external tool. See
1386 :hg:`help pager` for details.
1398 :hg:`help pager` for details.
1387
1399
1388 ``pager``
1400 ``pager``
1389 Define the external tool used as pager.
1401 Define the external tool used as pager.
1390
1402
1391 If no pager is set, Mercurial uses the environment variable $PAGER.
1403 If no pager is set, Mercurial uses the environment variable $PAGER.
1392 If neither pager.pager, nor $PAGER is set, a default pager will be
1404 If neither pager.pager, nor $PAGER is set, a default pager will be
1393 used, typically `less` on Unix and `more` on Windows. Example::
1405 used, typically `less` on Unix and `more` on Windows. Example::
1394
1406
1395 [pager]
1407 [pager]
1396 pager = less -FRX
1408 pager = less -FRX
1397
1409
1398 ``ignore``
1410 ``ignore``
1399 List of commands to disable the pager for. Example::
1411 List of commands to disable the pager for. Example::
1400
1412
1401 [pager]
1413 [pager]
1402 ignore = version, help, update
1414 ignore = version, help, update
1403
1415
1404 ``patch``
1416 ``patch``
1405 ---------
1417 ---------
1406
1418
1407 Settings used when applying patches, for instance through the 'import'
1419 Settings used when applying patches, for instance through the 'import'
1408 command or with Mercurial Queues extension.
1420 command or with Mercurial Queues extension.
1409
1421
1410 ``eol``
1422 ``eol``
1411 When set to 'strict' patch content and patched files end of lines
1423 When set to 'strict' patch content and patched files end of lines
1412 are preserved. When set to ``lf`` or ``crlf``, both files end of
1424 are preserved. When set to ``lf`` or ``crlf``, both files end of
1413 lines are ignored when patching and the result line endings are
1425 lines are ignored when patching and the result line endings are
1414 normalized to either LF (Unix) or CRLF (Windows). When set to
1426 normalized to either LF (Unix) or CRLF (Windows). When set to
1415 ``auto``, end of lines are again ignored while patching but line
1427 ``auto``, end of lines are again ignored while patching but line
1416 endings in patched files are normalized to their original setting
1428 endings in patched files are normalized to their original setting
1417 on a per-file basis. If target file does not exist or has no end
1429 on a per-file basis. If target file does not exist or has no end
1418 of line, patch line endings are preserved.
1430 of line, patch line endings are preserved.
1419 (default: strict)
1431 (default: strict)
1420
1432
1421 ``fuzz``
1433 ``fuzz``
1422 The number of lines of 'fuzz' to allow when applying patches. This
1434 The number of lines of 'fuzz' to allow when applying patches. This
1423 controls how much context the patcher is allowed to ignore when
1435 controls how much context the patcher is allowed to ignore when
1424 trying to apply a patch.
1436 trying to apply a patch.
1425 (default: 2)
1437 (default: 2)
1426
1438
1427 ``paths``
1439 ``paths``
1428 ---------
1440 ---------
1429
1441
1430 Assigns symbolic names and behavior to repositories.
1442 Assigns symbolic names and behavior to repositories.
1431
1443
1432 Options are symbolic names defining the URL or directory that is the
1444 Options are symbolic names defining the URL or directory that is the
1433 location of the repository. Example::
1445 location of the repository. Example::
1434
1446
1435 [paths]
1447 [paths]
1436 my_server = https://example.com/my_repo
1448 my_server = https://example.com/my_repo
1437 local_path = /home/me/repo
1449 local_path = /home/me/repo
1438
1450
1439 These symbolic names can be used from the command line. To pull
1451 These symbolic names can be used from the command line. To pull
1440 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1452 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1441 :hg:`push local_path`.
1453 :hg:`push local_path`.
1442
1454
1443 Options containing colons (``:``) denote sub-options that can influence
1455 Options containing colons (``:``) denote sub-options that can influence
1444 behavior for that specific path. Example::
1456 behavior for that specific path. Example::
1445
1457
1446 [paths]
1458 [paths]
1447 my_server = https://example.com/my_path
1459 my_server = https://example.com/my_path
1448 my_server:pushurl = ssh://example.com/my_path
1460 my_server:pushurl = ssh://example.com/my_path
1449
1461
1450 The following sub-options can be defined:
1462 The following sub-options can be defined:
1451
1463
1452 ``pushurl``
1464 ``pushurl``
1453 The URL to use for push operations. If not defined, the location
1465 The URL to use for push operations. If not defined, the location
1454 defined by the path's main entry is used.
1466 defined by the path's main entry is used.
1455
1467
1456 ``pushrev``
1468 ``pushrev``
1457 A revset defining which revisions to push by default.
1469 A revset defining which revisions to push by default.
1458
1470
1459 When :hg:`push` is executed without a ``-r`` argument, the revset
1471 When :hg:`push` is executed without a ``-r`` argument, the revset
1460 defined by this sub-option is evaluated to determine what to push.
1472 defined by this sub-option is evaluated to determine what to push.
1461
1473
1462 For example, a value of ``.`` will push the working directory's
1474 For example, a value of ``.`` will push the working directory's
1463 revision by default.
1475 revision by default.
1464
1476
1465 Revsets specifying bookmarks will not result in the bookmark being
1477 Revsets specifying bookmarks will not result in the bookmark being
1466 pushed.
1478 pushed.
1467
1479
1468 The following special named paths exist:
1480 The following special named paths exist:
1469
1481
1470 ``default``
1482 ``default``
1471 The URL or directory to use when no source or remote is specified.
1483 The URL or directory to use when no source or remote is specified.
1472
1484
1473 :hg:`clone` will automatically define this path to the location the
1485 :hg:`clone` will automatically define this path to the location the
1474 repository was cloned from.
1486 repository was cloned from.
1475
1487
1476 ``default-push``
1488 ``default-push``
1477 (deprecated) The URL or directory for the default :hg:`push` location.
1489 (deprecated) The URL or directory for the default :hg:`push` location.
1478 ``default:pushurl`` should be used instead.
1490 ``default:pushurl`` should be used instead.
1479
1491
1480 ``phases``
1492 ``phases``
1481 ----------
1493 ----------
1482
1494
1483 Specifies default handling of phases. See :hg:`help phases` for more
1495 Specifies default handling of phases. See :hg:`help phases` for more
1484 information about working with phases.
1496 information about working with phases.
1485
1497
1486 ``publish``
1498 ``publish``
1487 Controls draft phase behavior when working as a server. When true,
1499 Controls draft phase behavior when working as a server. When true,
1488 pushed changesets are set to public in both client and server and
1500 pushed changesets are set to public in both client and server and
1489 pulled or cloned changesets are set to public in the client.
1501 pulled or cloned changesets are set to public in the client.
1490 (default: True)
1502 (default: True)
1491
1503
1492 ``new-commit``
1504 ``new-commit``
1493 Phase of newly-created commits.
1505 Phase of newly-created commits.
1494 (default: draft)
1506 (default: draft)
1495
1507
1496 ``checksubrepos``
1508 ``checksubrepos``
1497 Check the phase of the current revision of each subrepository. Allowed
1509 Check the phase of the current revision of each subrepository. Allowed
1498 values are "ignore", "follow" and "abort". For settings other than
1510 values are "ignore", "follow" and "abort". For settings other than
1499 "ignore", the phase of the current revision of each subrepository is
1511 "ignore", the phase of the current revision of each subrepository is
1500 checked before committing the parent repository. If any of those phases is
1512 checked before committing the parent repository. If any of those phases is
1501 greater than the phase of the parent repository (e.g. if a subrepo is in a
1513 greater than the phase of the parent repository (e.g. if a subrepo is in a
1502 "secret" phase while the parent repo is in "draft" phase), the commit is
1514 "secret" phase while the parent repo is in "draft" phase), the commit is
1503 either aborted (if checksubrepos is set to "abort") or the higher phase is
1515 either aborted (if checksubrepos is set to "abort") or the higher phase is
1504 used for the parent repository commit (if set to "follow").
1516 used for the parent repository commit (if set to "follow").
1505 (default: follow)
1517 (default: follow)
1506
1518
1507
1519
1508 ``profiling``
1520 ``profiling``
1509 -------------
1521 -------------
1510
1522
1511 Specifies profiling type, format, and file output. Two profilers are
1523 Specifies profiling type, format, and file output. Two profilers are
1512 supported: an instrumenting profiler (named ``ls``), and a sampling
1524 supported: an instrumenting profiler (named ``ls``), and a sampling
1513 profiler (named ``stat``).
1525 profiler (named ``stat``).
1514
1526
1515 In this section description, 'profiling data' stands for the raw data
1527 In this section description, 'profiling data' stands for the raw data
1516 collected during profiling, while 'profiling report' stands for a
1528 collected during profiling, while 'profiling report' stands for a
1517 statistical text report generated from the profiling data. The
1529 statistical text report generated from the profiling data. The
1518 profiling is done using lsprof.
1530 profiling is done using lsprof.
1519
1531
1520 ``enabled``
1532 ``enabled``
1521 Enable the profiler.
1533 Enable the profiler.
1522 (default: false)
1534 (default: false)
1523
1535
1524 This is equivalent to passing ``--profile`` on the command line.
1536 This is equivalent to passing ``--profile`` on the command line.
1525
1537
1526 ``type``
1538 ``type``
1527 The type of profiler to use.
1539 The type of profiler to use.
1528 (default: stat)
1540 (default: stat)
1529
1541
1530 ``ls``
1542 ``ls``
1531 Use Python's built-in instrumenting profiler. This profiler
1543 Use Python's built-in instrumenting profiler. This profiler
1532 works on all platforms, but each line number it reports is the
1544 works on all platforms, but each line number it reports is the
1533 first line of a function. This restriction makes it difficult to
1545 first line of a function. This restriction makes it difficult to
1534 identify the expensive parts of a non-trivial function.
1546 identify the expensive parts of a non-trivial function.
1535 ``stat``
1547 ``stat``
1536 Use a statistical profiler, statprof. This profiler is most
1548 Use a statistical profiler, statprof. This profiler is most
1537 useful for profiling commands that run for longer than about 0.1
1549 useful for profiling commands that run for longer than about 0.1
1538 seconds.
1550 seconds.
1539
1551
1540 ``format``
1552 ``format``
1541 Profiling format. Specific to the ``ls`` instrumenting profiler.
1553 Profiling format. Specific to the ``ls`` instrumenting profiler.
1542 (default: text)
1554 (default: text)
1543
1555
1544 ``text``
1556 ``text``
1545 Generate a profiling report. When saving to a file, it should be
1557 Generate a profiling report. When saving to a file, it should be
1546 noted that only the report is saved, and the profiling data is
1558 noted that only the report is saved, and the profiling data is
1547 not kept.
1559 not kept.
1548 ``kcachegrind``
1560 ``kcachegrind``
1549 Format profiling data for kcachegrind use: when saving to a
1561 Format profiling data for kcachegrind use: when saving to a
1550 file, the generated file can directly be loaded into
1562 file, the generated file can directly be loaded into
1551 kcachegrind.
1563 kcachegrind.
1552
1564
1553 ``statformat``
1565 ``statformat``
1554 Profiling format for the ``stat`` profiler.
1566 Profiling format for the ``stat`` profiler.
1555 (default: hotpath)
1567 (default: hotpath)
1556
1568
1557 ``hotpath``
1569 ``hotpath``
1558 Show a tree-based display containing the hot path of execution (where
1570 Show a tree-based display containing the hot path of execution (where
1559 most time was spent).
1571 most time was spent).
1560 ``bymethod``
1572 ``bymethod``
1561 Show a table of methods ordered by how frequently they are active.
1573 Show a table of methods ordered by how frequently they are active.
1562 ``byline``
1574 ``byline``
1563 Show a table of lines in files ordered by how frequently they are active.
1575 Show a table of lines in files ordered by how frequently they are active.
1564 ``json``
1576 ``json``
1565 Render profiling data as JSON.
1577 Render profiling data as JSON.
1566
1578
1567 ``frequency``
1579 ``frequency``
1568 Sampling frequency. Specific to the ``stat`` sampling profiler.
1580 Sampling frequency. Specific to the ``stat`` sampling profiler.
1569 (default: 1000)
1581 (default: 1000)
1570
1582
1571 ``output``
1583 ``output``
1572 File path where profiling data or report should be saved. If the
1584 File path where profiling data or report should be saved. If the
1573 file exists, it is replaced. (default: None, data is printed on
1585 file exists, it is replaced. (default: None, data is printed on
1574 stderr)
1586 stderr)
1575
1587
1576 ``sort``
1588 ``sort``
1577 Sort field. Specific to the ``ls`` instrumenting profiler.
1589 Sort field. Specific to the ``ls`` instrumenting profiler.
1578 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1590 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1579 ``inlinetime``.
1591 ``inlinetime``.
1580 (default: inlinetime)
1592 (default: inlinetime)
1581
1593
1582 ``limit``
1594 ``limit``
1583 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1595 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1584 (default: 30)
1596 (default: 30)
1585
1597
1586 ``nested``
1598 ``nested``
1587 Show at most this number of lines of drill-down info after each main entry.
1599 Show at most this number of lines of drill-down info after each main entry.
1588 This can help explain the difference between Total and Inline.
1600 This can help explain the difference between Total and Inline.
1589 Specific to the ``ls`` instrumenting profiler.
1601 Specific to the ``ls`` instrumenting profiler.
1590 (default: 5)
1602 (default: 5)
1591
1603
1592 ``showmin``
1604 ``showmin``
1593 Minimum fraction of samples an entry must have for it to be displayed.
1605 Minimum fraction of samples an entry must have for it to be displayed.
1594 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1606 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1595 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1607 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1596
1608
1597 Only used by the ``stat`` profiler.
1609 Only used by the ``stat`` profiler.
1598
1610
1599 For the ``hotpath`` format, default is ``0.05``.
1611 For the ``hotpath`` format, default is ``0.05``.
1600 For the ``chrome`` format, default is ``0.005``.
1612 For the ``chrome`` format, default is ``0.005``.
1601
1613
1602 The option is unused on other formats.
1614 The option is unused on other formats.
1603
1615
1604 ``showmax``
1616 ``showmax``
1605 Maximum fraction of samples an entry can have before it is ignored in
1617 Maximum fraction of samples an entry can have before it is ignored in
1606 display. Values format is the same as ``showmin``.
1618 display. Values format is the same as ``showmin``.
1607
1619
1608 Only used by the ``stat`` profiler.
1620 Only used by the ``stat`` profiler.
1609
1621
1610 For the ``chrome`` format, default is ``0.999``.
1622 For the ``chrome`` format, default is ``0.999``.
1611
1623
1612 The option is unused on other formats.
1624 The option is unused on other formats.
1613
1625
1614 ``progress``
1626 ``progress``
1615 ------------
1627 ------------
1616
1628
1617 Mercurial commands can draw progress bars that are as informative as
1629 Mercurial commands can draw progress bars that are as informative as
1618 possible. Some progress bars only offer indeterminate information, while others
1630 possible. Some progress bars only offer indeterminate information, while others
1619 have a definite end point.
1631 have a definite end point.
1620
1632
1621 ``delay``
1633 ``delay``
1622 Number of seconds (float) before showing the progress bar. (default: 3)
1634 Number of seconds (float) before showing the progress bar. (default: 3)
1623
1635
1624 ``changedelay``
1636 ``changedelay``
1625 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1637 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1626 that value will be used instead. (default: 1)
1638 that value will be used instead. (default: 1)
1627
1639
1628 ``estimateinterval``
1640 ``estimateinterval``
1629 Maximum sampling interval in seconds for speed and estimated time
1641 Maximum sampling interval in seconds for speed and estimated time
1630 calculation. (default: 60)
1642 calculation. (default: 60)
1631
1643
1632 ``refresh``
1644 ``refresh``
1633 Time in seconds between refreshes of the progress bar. (default: 0.1)
1645 Time in seconds between refreshes of the progress bar. (default: 0.1)
1634
1646
1635 ``format``
1647 ``format``
1636 Format of the progress bar.
1648 Format of the progress bar.
1637
1649
1638 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1650 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1639 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1651 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1640 last 20 characters of the item, but this can be changed by adding either
1652 last 20 characters of the item, but this can be changed by adding either
1641 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1653 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1642 first num characters.
1654 first num characters.
1643
1655
1644 (default: topic bar number estimate)
1656 (default: topic bar number estimate)
1645
1657
1646 ``width``
1658 ``width``
1647 If set, the maximum width of the progress information (that is, min(width,
1659 If set, the maximum width of the progress information (that is, min(width,
1648 term width) will be used).
1660 term width) will be used).
1649
1661
1650 ``clear-complete``
1662 ``clear-complete``
1651 Clear the progress bar after it's done. (default: True)
1663 Clear the progress bar after it's done. (default: True)
1652
1664
1653 ``disable``
1665 ``disable``
1654 If true, don't show a progress bar.
1666 If true, don't show a progress bar.
1655
1667
1656 ``assume-tty``
1668 ``assume-tty``
1657 If true, ALWAYS show a progress bar, unless disable is given.
1669 If true, ALWAYS show a progress bar, unless disable is given.
1658
1670
1659 ``rebase``
1671 ``rebase``
1660 ----------
1672 ----------
1661
1673
1662 ``allowdivergence``
1674 ``allowdivergence``
1663 Default to False, when True allow creating divergence when performing
1675 Default to False, when True allow creating divergence when performing
1664 rebase of obsolete changesets.
1676 rebase of obsolete changesets.
1665
1677
1666 ``revsetalias``
1678 ``revsetalias``
1667 ---------------
1679 ---------------
1668
1680
1669 Alias definitions for revsets. See :hg:`help revsets` for details.
1681 Alias definitions for revsets. See :hg:`help revsets` for details.
1670
1682
1671 ``server``
1683 ``server``
1672 ----------
1684 ----------
1673
1685
1674 Controls generic server settings.
1686 Controls generic server settings.
1675
1687
1676 ``compressionengines``
1688 ``compressionengines``
1677 List of compression engines and their relative priority to advertise
1689 List of compression engines and their relative priority to advertise
1678 to clients.
1690 to clients.
1679
1691
1680 The order of compression engines determines their priority, the first
1692 The order of compression engines determines their priority, the first
1681 having the highest priority. If a compression engine is not listed
1693 having the highest priority. If a compression engine is not listed
1682 here, it won't be advertised to clients.
1694 here, it won't be advertised to clients.
1683
1695
1684 If not set (the default), built-in defaults are used. Run
1696 If not set (the default), built-in defaults are used. Run
1685 :hg:`debuginstall` to list available compression engines and their
1697 :hg:`debuginstall` to list available compression engines and their
1686 default wire protocol priority.
1698 default wire protocol priority.
1687
1699
1688 Older Mercurial clients only support zlib compression and this setting
1700 Older Mercurial clients only support zlib compression and this setting
1689 has no effect for legacy clients.
1701 has no effect for legacy clients.
1690
1702
1691 ``uncompressed``
1703 ``uncompressed``
1692 Whether to allow clients to clone a repository using the
1704 Whether to allow clients to clone a repository using the
1693 uncompressed streaming protocol. This transfers about 40% more
1705 uncompressed streaming protocol. This transfers about 40% more
1694 data than a regular clone, but uses less memory and CPU on both
1706 data than a regular clone, but uses less memory and CPU on both
1695 server and client. Over a LAN (100 Mbps or better) or a very fast
1707 server and client. Over a LAN (100 Mbps or better) or a very fast
1696 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1708 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1697 regular clone. Over most WAN connections (anything slower than
1709 regular clone. Over most WAN connections (anything slower than
1698 about 6 Mbps), uncompressed streaming is slower, because of the
1710 about 6 Mbps), uncompressed streaming is slower, because of the
1699 extra data transfer overhead. This mode will also temporarily hold
1711 extra data transfer overhead. This mode will also temporarily hold
1700 the write lock while determining what data to transfer.
1712 the write lock while determining what data to transfer.
1701 (default: True)
1713 (default: True)
1702
1714
1703 ``uncompressedallowsecret``
1715 ``uncompressedallowsecret``
1704 Whether to allow stream clones when the repository contains secret
1716 Whether to allow stream clones when the repository contains secret
1705 changesets. (default: False)
1717 changesets. (default: False)
1706
1718
1707 ``preferuncompressed``
1719 ``preferuncompressed``
1708 When set, clients will try to use the uncompressed streaming
1720 When set, clients will try to use the uncompressed streaming
1709 protocol. (default: False)
1721 protocol. (default: False)
1710
1722
1711 ``disablefullbundle``
1723 ``disablefullbundle``
1712 When set, servers will refuse attempts to do pull-based clones.
1724 When set, servers will refuse attempts to do pull-based clones.
1713 If this option is set, ``preferuncompressed`` and/or clone bundles
1725 If this option is set, ``preferuncompressed`` and/or clone bundles
1714 are highly recommended. Partial clones will still be allowed.
1726 are highly recommended. Partial clones will still be allowed.
1715 (default: False)
1727 (default: False)
1716
1728
1717 ``concurrent-push-mode``
1729 ``concurrent-push-mode``
1718 Level of allowed race condition between two pushing clients.
1730 Level of allowed race condition between two pushing clients.
1719
1731
1720 - 'strict': push is abort if another client touched the repository
1732 - 'strict': push is abort if another client touched the repository
1721 while the push was preparing. (default)
1733 while the push was preparing. (default)
1722 - 'check-related': push is only aborted if it affects head that got also
1734 - 'check-related': push is only aborted if it affects head that got also
1723 affected while the push was preparing.
1735 affected while the push was preparing.
1724
1736
1725 This requires compatible client (version 4.3 and later). Old client will
1737 This requires compatible client (version 4.3 and later). Old client will
1726 use 'strict'.
1738 use 'strict'.
1727
1739
1728 ``validate``
1740 ``validate``
1729 Whether to validate the completeness of pushed changesets by
1741 Whether to validate the completeness of pushed changesets by
1730 checking that all new file revisions specified in manifests are
1742 checking that all new file revisions specified in manifests are
1731 present. (default: False)
1743 present. (default: False)
1732
1744
1733 ``maxhttpheaderlen``
1745 ``maxhttpheaderlen``
1734 Instruct HTTP clients not to send request headers longer than this
1746 Instruct HTTP clients not to send request headers longer than this
1735 many bytes. (default: 1024)
1747 many bytes. (default: 1024)
1736
1748
1737 ``bundle1``
1749 ``bundle1``
1738 Whether to allow clients to push and pull using the legacy bundle1
1750 Whether to allow clients to push and pull using the legacy bundle1
1739 exchange format. (default: True)
1751 exchange format. (default: True)
1740
1752
1741 ``bundle1gd``
1753 ``bundle1gd``
1742 Like ``bundle1`` but only used if the repository is using the
1754 Like ``bundle1`` but only used if the repository is using the
1743 *generaldelta* storage format. (default: True)
1755 *generaldelta* storage format. (default: True)
1744
1756
1745 ``bundle1.push``
1757 ``bundle1.push``
1746 Whether to allow clients to push using the legacy bundle1 exchange
1758 Whether to allow clients to push using the legacy bundle1 exchange
1747 format. (default: True)
1759 format. (default: True)
1748
1760
1749 ``bundle1gd.push``
1761 ``bundle1gd.push``
1750 Like ``bundle1.push`` but only used if the repository is using the
1762 Like ``bundle1.push`` but only used if the repository is using the
1751 *generaldelta* storage format. (default: True)
1763 *generaldelta* storage format. (default: True)
1752
1764
1753 ``bundle1.pull``
1765 ``bundle1.pull``
1754 Whether to allow clients to pull using the legacy bundle1 exchange
1766 Whether to allow clients to pull using the legacy bundle1 exchange
1755 format. (default: True)
1767 format. (default: True)
1756
1768
1757 ``bundle1gd.pull``
1769 ``bundle1gd.pull``
1758 Like ``bundle1.pull`` but only used if the repository is using the
1770 Like ``bundle1.pull`` but only used if the repository is using the
1759 *generaldelta* storage format. (default: True)
1771 *generaldelta* storage format. (default: True)
1760
1772
1761 Large repositories using the *generaldelta* storage format should
1773 Large repositories using the *generaldelta* storage format should
1762 consider setting this option because converting *generaldelta*
1774 consider setting this option because converting *generaldelta*
1763 repositories to the exchange format required by the bundle1 data
1775 repositories to the exchange format required by the bundle1 data
1764 format can consume a lot of CPU.
1776 format can consume a lot of CPU.
1765
1777
1766 ``zliblevel``
1778 ``zliblevel``
1767 Integer between ``-1`` and ``9`` that controls the zlib compression level
1779 Integer between ``-1`` and ``9`` that controls the zlib compression level
1768 for wire protocol commands that send zlib compressed output (notably the
1780 for wire protocol commands that send zlib compressed output (notably the
1769 commands that send repository history data).
1781 commands that send repository history data).
1770
1782
1771 The default (``-1``) uses the default zlib compression level, which is
1783 The default (``-1``) uses the default zlib compression level, which is
1772 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1784 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1773 maximum compression.
1785 maximum compression.
1774
1786
1775 Setting this option allows server operators to make trade-offs between
1787 Setting this option allows server operators to make trade-offs between
1776 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1788 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1777 but sends more bytes to clients.
1789 but sends more bytes to clients.
1778
1790
1779 This option only impacts the HTTP server.
1791 This option only impacts the HTTP server.
1780
1792
1781 ``zstdlevel``
1793 ``zstdlevel``
1782 Integer between ``1`` and ``22`` that controls the zstd compression level
1794 Integer between ``1`` and ``22`` that controls the zstd compression level
1783 for wire protocol commands. ``1`` is the minimal amount of compression and
1795 for wire protocol commands. ``1`` is the minimal amount of compression and
1784 ``22`` is the highest amount of compression.
1796 ``22`` is the highest amount of compression.
1785
1797
1786 The default (``3``) should be significantly faster than zlib while likely
1798 The default (``3``) should be significantly faster than zlib while likely
1787 delivering better compression ratios.
1799 delivering better compression ratios.
1788
1800
1789 This option only impacts the HTTP server.
1801 This option only impacts the HTTP server.
1790
1802
1791 See also ``server.zliblevel``.
1803 See also ``server.zliblevel``.
1792
1804
1793 ``smtp``
1805 ``smtp``
1794 --------
1806 --------
1795
1807
1796 Configuration for extensions that need to send email messages.
1808 Configuration for extensions that need to send email messages.
1797
1809
1798 ``host``
1810 ``host``
1799 Host name of mail server, e.g. "mail.example.com".
1811 Host name of mail server, e.g. "mail.example.com".
1800
1812
1801 ``port``
1813 ``port``
1802 Optional. Port to connect to on mail server. (default: 465 if
1814 Optional. Port to connect to on mail server. (default: 465 if
1803 ``tls`` is smtps; 25 otherwise)
1815 ``tls`` is smtps; 25 otherwise)
1804
1816
1805 ``tls``
1817 ``tls``
1806 Optional. Method to enable TLS when connecting to mail server: starttls,
1818 Optional. Method to enable TLS when connecting to mail server: starttls,
1807 smtps or none. (default: none)
1819 smtps or none. (default: none)
1808
1820
1809 ``username``
1821 ``username``
1810 Optional. User name for authenticating with the SMTP server.
1822 Optional. User name for authenticating with the SMTP server.
1811 (default: None)
1823 (default: None)
1812
1824
1813 ``password``
1825 ``password``
1814 Optional. Password for authenticating with the SMTP server. If not
1826 Optional. Password for authenticating with the SMTP server. If not
1815 specified, interactive sessions will prompt the user for a
1827 specified, interactive sessions will prompt the user for a
1816 password; non-interactive sessions will fail. (default: None)
1828 password; non-interactive sessions will fail. (default: None)
1817
1829
1818 ``local_hostname``
1830 ``local_hostname``
1819 Optional. The hostname that the sender can use to identify
1831 Optional. The hostname that the sender can use to identify
1820 itself to the MTA.
1832 itself to the MTA.
1821
1833
1822
1834
1823 ``subpaths``
1835 ``subpaths``
1824 ------------
1836 ------------
1825
1837
1826 Subrepository source URLs can go stale if a remote server changes name
1838 Subrepository source URLs can go stale if a remote server changes name
1827 or becomes temporarily unavailable. This section lets you define
1839 or becomes temporarily unavailable. This section lets you define
1828 rewrite rules of the form::
1840 rewrite rules of the form::
1829
1841
1830 <pattern> = <replacement>
1842 <pattern> = <replacement>
1831
1843
1832 where ``pattern`` is a regular expression matching a subrepository
1844 where ``pattern`` is a regular expression matching a subrepository
1833 source URL and ``replacement`` is the replacement string used to
1845 source URL and ``replacement`` is the replacement string used to
1834 rewrite it. Groups can be matched in ``pattern`` and referenced in
1846 rewrite it. Groups can be matched in ``pattern`` and referenced in
1835 ``replacements``. For instance::
1847 ``replacements``. For instance::
1836
1848
1837 http://server/(.*)-hg/ = http://hg.server/\1/
1849 http://server/(.*)-hg/ = http://hg.server/\1/
1838
1850
1839 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1851 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1840
1852
1841 Relative subrepository paths are first made absolute, and the
1853 Relative subrepository paths are first made absolute, and the
1842 rewrite rules are then applied on the full (absolute) path. If ``pattern``
1854 rewrite rules are then applied on the full (absolute) path. If ``pattern``
1843 doesn't match the full path, an attempt is made to apply it on the
1855 doesn't match the full path, an attempt is made to apply it on the
1844 relative path alone. The rules are applied in definition order.
1856 relative path alone. The rules are applied in definition order.
1845
1857
1846 ``templatealias``
1858 ``templatealias``
1847 -----------------
1859 -----------------
1848
1860
1849 Alias definitions for templates. See :hg:`help templates` for details.
1861 Alias definitions for templates. See :hg:`help templates` for details.
1850
1862
1851 ``templates``
1863 ``templates``
1852 -------------
1864 -------------
1853
1865
1854 Use the ``[templates]`` section to define template strings.
1866 Use the ``[templates]`` section to define template strings.
1855 See :hg:`help templates` for details.
1867 See :hg:`help templates` for details.
1856
1868
1857 ``trusted``
1869 ``trusted``
1858 -----------
1870 -----------
1859
1871
1860 Mercurial will not use the settings in the
1872 Mercurial will not use the settings in the
1861 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1873 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1862 user or to a trusted group, as various hgrc features allow arbitrary
1874 user or to a trusted group, as various hgrc features allow arbitrary
1863 commands to be run. This issue is often encountered when configuring
1875 commands to be run. This issue is often encountered when configuring
1864 hooks or extensions for shared repositories or servers. However,
1876 hooks or extensions for shared repositories or servers. However,
1865 the web interface will use some safe settings from the ``[web]``
1877 the web interface will use some safe settings from the ``[web]``
1866 section.
1878 section.
1867
1879
1868 This section specifies what users and groups are trusted. The
1880 This section specifies what users and groups are trusted. The
1869 current user is always trusted. To trust everybody, list a user or a
1881 current user is always trusted. To trust everybody, list a user or a
1870 group with name ``*``. These settings must be placed in an
1882 group with name ``*``. These settings must be placed in an
1871 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1883 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1872 user or service running Mercurial.
1884 user or service running Mercurial.
1873
1885
1874 ``users``
1886 ``users``
1875 Comma-separated list of trusted users.
1887 Comma-separated list of trusted users.
1876
1888
1877 ``groups``
1889 ``groups``
1878 Comma-separated list of trusted groups.
1890 Comma-separated list of trusted groups.
1879
1891
1880
1892
1881 ``ui``
1893 ``ui``
1882 ------
1894 ------
1883
1895
1884 User interface controls.
1896 User interface controls.
1885
1897
1886 ``archivemeta``
1898 ``archivemeta``
1887 Whether to include the .hg_archival.txt file containing meta data
1899 Whether to include the .hg_archival.txt file containing meta data
1888 (hashes for the repository base and for tip) in archives created
1900 (hashes for the repository base and for tip) in archives created
1889 by the :hg:`archive` command or downloaded via hgweb.
1901 by the :hg:`archive` command or downloaded via hgweb.
1890 (default: True)
1902 (default: True)
1891
1903
1892 ``askusername``
1904 ``askusername``
1893 Whether to prompt for a username when committing. If True, and
1905 Whether to prompt for a username when committing. If True, and
1894 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1906 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1895 be prompted to enter a username. If no username is entered, the
1907 be prompted to enter a username. If no username is entered, the
1896 default ``USER@HOST`` is used instead.
1908 default ``USER@HOST`` is used instead.
1897 (default: False)
1909 (default: False)
1898
1910
1899 ``clonebundles``
1911 ``clonebundles``
1900 Whether the "clone bundles" feature is enabled.
1912 Whether the "clone bundles" feature is enabled.
1901
1913
1902 When enabled, :hg:`clone` may download and apply a server-advertised
1914 When enabled, :hg:`clone` may download and apply a server-advertised
1903 bundle file from a URL instead of using the normal exchange mechanism.
1915 bundle file from a URL instead of using the normal exchange mechanism.
1904
1916
1905 This can likely result in faster and more reliable clones.
1917 This can likely result in faster and more reliable clones.
1906
1918
1907 (default: True)
1919 (default: True)
1908
1920
1909 ``clonebundlefallback``
1921 ``clonebundlefallback``
1910 Whether failure to apply an advertised "clone bundle" from a server
1922 Whether failure to apply an advertised "clone bundle" from a server
1911 should result in fallback to a regular clone.
1923 should result in fallback to a regular clone.
1912
1924
1913 This is disabled by default because servers advertising "clone
1925 This is disabled by default because servers advertising "clone
1914 bundles" often do so to reduce server load. If advertised bundles
1926 bundles" often do so to reduce server load. If advertised bundles
1915 start mass failing and clients automatically fall back to a regular
1927 start mass failing and clients automatically fall back to a regular
1916 clone, this would add significant and unexpected load to the server
1928 clone, this would add significant and unexpected load to the server
1917 since the server is expecting clone operations to be offloaded to
1929 since the server is expecting clone operations to be offloaded to
1918 pre-generated bundles. Failing fast (the default behavior) ensures
1930 pre-generated bundles. Failing fast (the default behavior) ensures
1919 clients don't overwhelm the server when "clone bundle" application
1931 clients don't overwhelm the server when "clone bundle" application
1920 fails.
1932 fails.
1921
1933
1922 (default: False)
1934 (default: False)
1923
1935
1924 ``clonebundleprefers``
1936 ``clonebundleprefers``
1925 Defines preferences for which "clone bundles" to use.
1937 Defines preferences for which "clone bundles" to use.
1926
1938
1927 Servers advertising "clone bundles" may advertise multiple available
1939 Servers advertising "clone bundles" may advertise multiple available
1928 bundles. Each bundle may have different attributes, such as the bundle
1940 bundles. Each bundle may have different attributes, such as the bundle
1929 type and compression format. This option is used to prefer a particular
1941 type and compression format. This option is used to prefer a particular
1930 bundle over another.
1942 bundle over another.
1931
1943
1932 The following keys are defined by Mercurial:
1944 The following keys are defined by Mercurial:
1933
1945
1934 BUNDLESPEC
1946 BUNDLESPEC
1935 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
1947 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
1936 e.g. ``gzip-v2`` or ``bzip2-v1``.
1948 e.g. ``gzip-v2`` or ``bzip2-v1``.
1937
1949
1938 COMPRESSION
1950 COMPRESSION
1939 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
1951 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
1940
1952
1941 Server operators may define custom keys.
1953 Server operators may define custom keys.
1942
1954
1943 Example values: ``COMPRESSION=bzip2``,
1955 Example values: ``COMPRESSION=bzip2``,
1944 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
1956 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
1945
1957
1946 By default, the first bundle advertised by the server is used.
1958 By default, the first bundle advertised by the server is used.
1947
1959
1948 ``color``
1960 ``color``
1949 When to colorize output. Possible value are Boolean ("yes" or "no"), or
1961 When to colorize output. Possible value are Boolean ("yes" or "no"), or
1950 "debug", or "always". (default: "yes"). "yes" will use color whenever it
1962 "debug", or "always". (default: "yes"). "yes" will use color whenever it
1951 seems possible. See :hg:`help color` for details.
1963 seems possible. See :hg:`help color` for details.
1952
1964
1953 ``commitsubrepos``
1965 ``commitsubrepos``
1954 Whether to commit modified subrepositories when committing the
1966 Whether to commit modified subrepositories when committing the
1955 parent repository. If False and one subrepository has uncommitted
1967 parent repository. If False and one subrepository has uncommitted
1956 changes, abort the commit.
1968 changes, abort the commit.
1957 (default: False)
1969 (default: False)
1958
1970
1959 ``debug``
1971 ``debug``
1960 Print debugging information. (default: False)
1972 Print debugging information. (default: False)
1961
1973
1962 ``editor``
1974 ``editor``
1963 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
1975 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
1964
1976
1965 ``fallbackencoding``
1977 ``fallbackencoding``
1966 Encoding to try if it's not possible to decode the changelog using
1978 Encoding to try if it's not possible to decode the changelog using
1967 UTF-8. (default: ISO-8859-1)
1979 UTF-8. (default: ISO-8859-1)
1968
1980
1969 ``graphnodetemplate``
1981 ``graphnodetemplate``
1970 The template used to print changeset nodes in an ASCII revision graph.
1982 The template used to print changeset nodes in an ASCII revision graph.
1971 (default: ``{graphnode}``)
1983 (default: ``{graphnode}``)
1972
1984
1973 ``ignore``
1985 ``ignore``
1974 A file to read per-user ignore patterns from. This file should be
1986 A file to read per-user ignore patterns from. This file should be
1975 in the same format as a repository-wide .hgignore file. Filenames
1987 in the same format as a repository-wide .hgignore file. Filenames
1976 are relative to the repository root. This option supports hook syntax,
1988 are relative to the repository root. This option supports hook syntax,
1977 so if you want to specify multiple ignore files, you can do so by
1989 so if you want to specify multiple ignore files, you can do so by
1978 setting something like ``ignore.other = ~/.hgignore2``. For details
1990 setting something like ``ignore.other = ~/.hgignore2``. For details
1979 of the ignore file format, see the ``hgignore(5)`` man page.
1991 of the ignore file format, see the ``hgignore(5)`` man page.
1980
1992
1981 ``interactive``
1993 ``interactive``
1982 Allow to prompt the user. (default: True)
1994 Allow to prompt the user. (default: True)
1983
1995
1984 ``interface``
1996 ``interface``
1985 Select the default interface for interactive features (default: text).
1997 Select the default interface for interactive features (default: text).
1986 Possible values are 'text' and 'curses'.
1998 Possible values are 'text' and 'curses'.
1987
1999
1988 ``interface.chunkselector``
2000 ``interface.chunkselector``
1989 Select the interface for change recording (e.g. :hg:`commit -i`).
2001 Select the interface for change recording (e.g. :hg:`commit -i`).
1990 Possible values are 'text' and 'curses'.
2002 Possible values are 'text' and 'curses'.
1991 This config overrides the interface specified by ui.interface.
2003 This config overrides the interface specified by ui.interface.
1992
2004
1993 ``logtemplate``
2005 ``logtemplate``
1994 Template string for commands that print changesets.
2006 Template string for commands that print changesets.
1995
2007
1996 ``merge``
2008 ``merge``
1997 The conflict resolution program to use during a manual merge.
2009 The conflict resolution program to use during a manual merge.
1998 For more information on merge tools see :hg:`help merge-tools`.
2010 For more information on merge tools see :hg:`help merge-tools`.
1999 For configuring merge tools see the ``[merge-tools]`` section.
2011 For configuring merge tools see the ``[merge-tools]`` section.
2000
2012
2001 ``mergemarkers``
2013 ``mergemarkers``
2002 Sets the merge conflict marker label styling. The ``detailed``
2014 Sets the merge conflict marker label styling. The ``detailed``
2003 style uses the ``mergemarkertemplate`` setting to style the labels.
2015 style uses the ``mergemarkertemplate`` setting to style the labels.
2004 The ``basic`` style just uses 'local' and 'other' as the marker label.
2016 The ``basic`` style just uses 'local' and 'other' as the marker label.
2005 One of ``basic`` or ``detailed``.
2017 One of ``basic`` or ``detailed``.
2006 (default: ``basic``)
2018 (default: ``basic``)
2007
2019
2008 ``mergemarkertemplate``
2020 ``mergemarkertemplate``
2009 The template used to print the commit description next to each conflict
2021 The template used to print the commit description next to each conflict
2010 marker during merge conflicts. See :hg:`help templates` for the template
2022 marker during merge conflicts. See :hg:`help templates` for the template
2011 format.
2023 format.
2012
2024
2013 Defaults to showing the hash, tags, branches, bookmarks, author, and
2025 Defaults to showing the hash, tags, branches, bookmarks, author, and
2014 the first line of the commit description.
2026 the first line of the commit description.
2015
2027
2016 If you use non-ASCII characters in names for tags, branches, bookmarks,
2028 If you use non-ASCII characters in names for tags, branches, bookmarks,
2017 authors, and/or commit descriptions, you must pay attention to encodings of
2029 authors, and/or commit descriptions, you must pay attention to encodings of
2018 managed files. At template expansion, non-ASCII characters use the encoding
2030 managed files. At template expansion, non-ASCII characters use the encoding
2019 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2031 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2020 environment variables that govern your locale. If the encoding of the merge
2032 environment variables that govern your locale. If the encoding of the merge
2021 markers is different from the encoding of the merged files,
2033 markers is different from the encoding of the merged files,
2022 serious problems may occur.
2034 serious problems may occur.
2023
2035
2024 ``origbackuppath``
2036 ``origbackuppath``
2025 The path to a directory used to store generated .orig files. If the path is
2037 The path to a directory used to store generated .orig files. If the path is
2026 not a directory, one will be created. If set, files stored in this
2038 not a directory, one will be created. If set, files stored in this
2027 directory have the same name as the original file and do not have a .orig
2039 directory have the same name as the original file and do not have a .orig
2028 suffix.
2040 suffix.
2029
2041
2030 ``paginate``
2042 ``paginate``
2031 Control the pagination of command output (default: True). See :hg:`help pager`
2043 Control the pagination of command output (default: True). See :hg:`help pager`
2032 for details.
2044 for details.
2033
2045
2034 ``patch``
2046 ``patch``
2035 An optional external tool that ``hg import`` and some extensions
2047 An optional external tool that ``hg import`` and some extensions
2036 will use for applying patches. By default Mercurial uses an
2048 will use for applying patches. By default Mercurial uses an
2037 internal patch utility. The external tool must work as the common
2049 internal patch utility. The external tool must work as the common
2038 Unix ``patch`` program. In particular, it must accept a ``-p``
2050 Unix ``patch`` program. In particular, it must accept a ``-p``
2039 argument to strip patch headers, a ``-d`` argument to specify the
2051 argument to strip patch headers, a ``-d`` argument to specify the
2040 current directory, a file name to patch, and a patch file to take
2052 current directory, a file name to patch, and a patch file to take
2041 from stdin.
2053 from stdin.
2042
2054
2043 It is possible to specify a patch tool together with extra
2055 It is possible to specify a patch tool together with extra
2044 arguments. For example, setting this option to ``patch --merge``
2056 arguments. For example, setting this option to ``patch --merge``
2045 will use the ``patch`` program with its 2-way merge option.
2057 will use the ``patch`` program with its 2-way merge option.
2046
2058
2047 ``portablefilenames``
2059 ``portablefilenames``
2048 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2060 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2049 (default: ``warn``)
2061 (default: ``warn``)
2050
2062
2051 ``warn``
2063 ``warn``
2052 Print a warning message on POSIX platforms, if a file with a non-portable
2064 Print a warning message on POSIX platforms, if a file with a non-portable
2053 filename is added (e.g. a file with a name that can't be created on
2065 filename is added (e.g. a file with a name that can't be created on
2054 Windows because it contains reserved parts like ``AUX``, reserved
2066 Windows because it contains reserved parts like ``AUX``, reserved
2055 characters like ``:``, or would cause a case collision with an existing
2067 characters like ``:``, or would cause a case collision with an existing
2056 file).
2068 file).
2057
2069
2058 ``ignore``
2070 ``ignore``
2059 Don't print a warning.
2071 Don't print a warning.
2060
2072
2061 ``abort``
2073 ``abort``
2062 The command is aborted.
2074 The command is aborted.
2063
2075
2064 ``true``
2076 ``true``
2065 Alias for ``warn``.
2077 Alias for ``warn``.
2066
2078
2067 ``false``
2079 ``false``
2068 Alias for ``ignore``.
2080 Alias for ``ignore``.
2069
2081
2070 .. container:: windows
2082 .. container:: windows
2071
2083
2072 On Windows, this configuration option is ignored and the command aborted.
2084 On Windows, this configuration option is ignored and the command aborted.
2073
2085
2074 ``quiet``
2086 ``quiet``
2075 Reduce the amount of output printed.
2087 Reduce the amount of output printed.
2076 (default: False)
2088 (default: False)
2077
2089
2078 ``remotecmd``
2090 ``remotecmd``
2079 Remote command to use for clone/push/pull operations.
2091 Remote command to use for clone/push/pull operations.
2080 (default: ``hg``)
2092 (default: ``hg``)
2081
2093
2082 ``report_untrusted``
2094 ``report_untrusted``
2083 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2095 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2084 trusted user or group.
2096 trusted user or group.
2085 (default: True)
2097 (default: True)
2086
2098
2087 ``slash``
2099 ``slash``
2088 Display paths using a slash (``/``) as the path separator. This
2100 Display paths using a slash (``/``) as the path separator. This
2089 only makes a difference on systems where the default path
2101 only makes a difference on systems where the default path
2090 separator is not the slash character (e.g. Windows uses the
2102 separator is not the slash character (e.g. Windows uses the
2091 backslash character (``\``)).
2103 backslash character (``\``)).
2092 (default: False)
2104 (default: False)
2093
2105
2094 ``statuscopies``
2106 ``statuscopies``
2095 Display copies in the status command.
2107 Display copies in the status command.
2096
2108
2097 ``ssh``
2109 ``ssh``
2098 Command to use for SSH connections. (default: ``ssh``)
2110 Command to use for SSH connections. (default: ``ssh``)
2099
2111
2100 ``strict``
2112 ``strict``
2101 Require exact command names, instead of allowing unambiguous
2113 Require exact command names, instead of allowing unambiguous
2102 abbreviations. (default: False)
2114 abbreviations. (default: False)
2103
2115
2104 ``style``
2116 ``style``
2105 Name of style to use for command output.
2117 Name of style to use for command output.
2106
2118
2107 ``supportcontact``
2119 ``supportcontact``
2108 A URL where users should report a Mercurial traceback. Use this if you are a
2120 A URL where users should report a Mercurial traceback. Use this if you are a
2109 large organisation with its own Mercurial deployment process and crash
2121 large organisation with its own Mercurial deployment process and crash
2110 reports should be addressed to your internal support.
2122 reports should be addressed to your internal support.
2111
2123
2112 ``textwidth``
2124 ``textwidth``
2113 Maximum width of help text. A longer line generated by ``hg help`` or
2125 Maximum width of help text. A longer line generated by ``hg help`` or
2114 ``hg subcommand --help`` will be broken after white space to get this
2126 ``hg subcommand --help`` will be broken after white space to get this
2115 width or the terminal width, whichever comes first.
2127 width or the terminal width, whichever comes first.
2116 A non-positive value will disable this and the terminal width will be
2128 A non-positive value will disable this and the terminal width will be
2117 used. (default: 78)
2129 used. (default: 78)
2118
2130
2119 ``timeout``
2131 ``timeout``
2120 The timeout used when a lock is held (in seconds), a negative value
2132 The timeout used when a lock is held (in seconds), a negative value
2121 means no timeout. (default: 600)
2133 means no timeout. (default: 600)
2122
2134
2123 ``traceback``
2135 ``traceback``
2124 Mercurial always prints a traceback when an unknown exception
2136 Mercurial always prints a traceback when an unknown exception
2125 occurs. Setting this to True will make Mercurial print a traceback
2137 occurs. Setting this to True will make Mercurial print a traceback
2126 on all exceptions, even those recognized by Mercurial (such as
2138 on all exceptions, even those recognized by Mercurial (such as
2127 IOError or MemoryError). (default: False)
2139 IOError or MemoryError). (default: False)
2128
2140
2129 ``tweakdefaults``
2141 ``tweakdefaults``
2130
2142
2131 By default Mercurial's behavior changes very little from release
2143 By default Mercurial's behavior changes very little from release
2132 to release, but over time the recommended config settings
2144 to release, but over time the recommended config settings
2133 shift. Enable this config to opt in to get automatic tweaks to
2145 shift. Enable this config to opt in to get automatic tweaks to
2134 Mercurial's behavior over time. This config setting will have no
2146 Mercurial's behavior over time. This config setting will have no
2135 effet if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2147 effet if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2136 not include ``tweakdefaults``. (default: False)
2148 not include ``tweakdefaults``. (default: False)
2137
2149
2138 ``username``
2150 ``username``
2139 The committer of a changeset created when running "commit".
2151 The committer of a changeset created when running "commit".
2140 Typically a person's name and email address, e.g. ``Fred Widget
2152 Typically a person's name and email address, e.g. ``Fred Widget
2141 <fred@example.com>``. Environment variables in the
2153 <fred@example.com>``. Environment variables in the
2142 username are expanded.
2154 username are expanded.
2143
2155
2144 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2156 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2145 hgrc is empty, e.g. if the system admin set ``username =`` in the
2157 hgrc is empty, e.g. if the system admin set ``username =`` in the
2146 system hgrc, it has to be specified manually or in a different
2158 system hgrc, it has to be specified manually or in a different
2147 hgrc file)
2159 hgrc file)
2148
2160
2149 ``verbose``
2161 ``verbose``
2150 Increase the amount of output printed. (default: False)
2162 Increase the amount of output printed. (default: False)
2151
2163
2152
2164
2153 ``web``
2165 ``web``
2154 -------
2166 -------
2155
2167
2156 Web interface configuration. The settings in this section apply to
2168 Web interface configuration. The settings in this section apply to
2157 both the builtin webserver (started by :hg:`serve`) and the script you
2169 both the builtin webserver (started by :hg:`serve`) and the script you
2158 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2170 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2159 and WSGI).
2171 and WSGI).
2160
2172
2161 The Mercurial webserver does no authentication (it does not prompt for
2173 The Mercurial webserver does no authentication (it does not prompt for
2162 usernames and passwords to validate *who* users are), but it does do
2174 usernames and passwords to validate *who* users are), but it does do
2163 authorization (it grants or denies access for *authenticated users*
2175 authorization (it grants or denies access for *authenticated users*
2164 based on settings in this section). You must either configure your
2176 based on settings in this section). You must either configure your
2165 webserver to do authentication for you, or disable the authorization
2177 webserver to do authentication for you, or disable the authorization
2166 checks.
2178 checks.
2167
2179
2168 For a quick setup in a trusted environment, e.g., a private LAN, where
2180 For a quick setup in a trusted environment, e.g., a private LAN, where
2169 you want it to accept pushes from anybody, you can use the following
2181 you want it to accept pushes from anybody, you can use the following
2170 command line::
2182 command line::
2171
2183
2172 $ hg --config web.allow_push=* --config web.push_ssl=False serve
2184 $ hg --config web.allow_push=* --config web.push_ssl=False serve
2173
2185
2174 Note that this will allow anybody to push anything to the server and
2186 Note that this will allow anybody to push anything to the server and
2175 that this should not be used for public servers.
2187 that this should not be used for public servers.
2176
2188
2177 The full set of options is:
2189 The full set of options is:
2178
2190
2179 ``accesslog``
2191 ``accesslog``
2180 Where to output the access log. (default: stdout)
2192 Where to output the access log. (default: stdout)
2181
2193
2182 ``address``
2194 ``address``
2183 Interface address to bind to. (default: all)
2195 Interface address to bind to. (default: all)
2184
2196
2185 ``allow_archive``
2197 ``allow_archive``
2186 List of archive format (bz2, gz, zip) allowed for downloading.
2198 List of archive format (bz2, gz, zip) allowed for downloading.
2187 (default: empty)
2199 (default: empty)
2188
2200
2189 ``allowbz2``
2201 ``allowbz2``
2190 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2202 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2191 revisions.
2203 revisions.
2192 (default: False)
2204 (default: False)
2193
2205
2194 ``allowgz``
2206 ``allowgz``
2195 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2207 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2196 revisions.
2208 revisions.
2197 (default: False)
2209 (default: False)
2198
2210
2199 ``allowpull``
2211 ``allowpull``
2200 Whether to allow pulling from the repository. (default: True)
2212 Whether to allow pulling from the repository. (default: True)
2201
2213
2202 ``allow_push``
2214 ``allow_push``
2203 Whether to allow pushing to the repository. If empty or not set,
2215 Whether to allow pushing to the repository. If empty or not set,
2204 pushing is not allowed. If the special value ``*``, any remote
2216 pushing is not allowed. If the special value ``*``, any remote
2205 user can push, including unauthenticated users. Otherwise, the
2217 user can push, including unauthenticated users. Otherwise, the
2206 remote user must have been authenticated, and the authenticated
2218 remote user must have been authenticated, and the authenticated
2207 user name must be present in this list. The contents of the
2219 user name must be present in this list. The contents of the
2208 allow_push list are examined after the deny_push list.
2220 allow_push list are examined after the deny_push list.
2209
2221
2210 ``allow_read``
2222 ``allow_read``
2211 If the user has not already been denied repository access due to
2223 If the user has not already been denied repository access due to
2212 the contents of deny_read, this list determines whether to grant
2224 the contents of deny_read, this list determines whether to grant
2213 repository access to the user. If this list is not empty, and the
2225 repository access to the user. If this list is not empty, and the
2214 user is unauthenticated or not present in the list, then access is
2226 user is unauthenticated or not present in the list, then access is
2215 denied for the user. If the list is empty or not set, then access
2227 denied for the user. If the list is empty or not set, then access
2216 is permitted to all users by default. Setting allow_read to the
2228 is permitted to all users by default. Setting allow_read to the
2217 special value ``*`` is equivalent to it not being set (i.e. access
2229 special value ``*`` is equivalent to it not being set (i.e. access
2218 is permitted to all users). The contents of the allow_read list are
2230 is permitted to all users). The contents of the allow_read list are
2219 examined after the deny_read list.
2231 examined after the deny_read list.
2220
2232
2221 ``allowzip``
2233 ``allowzip``
2222 (DEPRECATED) Whether to allow .zip downloading of repository
2234 (DEPRECATED) Whether to allow .zip downloading of repository
2223 revisions. This feature creates temporary files.
2235 revisions. This feature creates temporary files.
2224 (default: False)
2236 (default: False)
2225
2237
2226 ``archivesubrepos``
2238 ``archivesubrepos``
2227 Whether to recurse into subrepositories when archiving.
2239 Whether to recurse into subrepositories when archiving.
2228 (default: False)
2240 (default: False)
2229
2241
2230 ``baseurl``
2242 ``baseurl``
2231 Base URL to use when publishing URLs in other locations, so
2243 Base URL to use when publishing URLs in other locations, so
2232 third-party tools like email notification hooks can construct
2244 third-party tools like email notification hooks can construct
2233 URLs. Example: ``http://hgserver/repos/``.
2245 URLs. Example: ``http://hgserver/repos/``.
2234
2246
2235 ``cacerts``
2247 ``cacerts``
2236 Path to file containing a list of PEM encoded certificate
2248 Path to file containing a list of PEM encoded certificate
2237 authority certificates. Environment variables and ``~user``
2249 authority certificates. Environment variables and ``~user``
2238 constructs are expanded in the filename. If specified on the
2250 constructs are expanded in the filename. If specified on the
2239 client, then it will verify the identity of remote HTTPS servers
2251 client, then it will verify the identity of remote HTTPS servers
2240 with these certificates.
2252 with these certificates.
2241
2253
2242 To disable SSL verification temporarily, specify ``--insecure`` from
2254 To disable SSL verification temporarily, specify ``--insecure`` from
2243 command line.
2255 command line.
2244
2256
2245 You can use OpenSSL's CA certificate file if your platform has
2257 You can use OpenSSL's CA certificate file if your platform has
2246 one. On most Linux systems this will be
2258 one. On most Linux systems this will be
2247 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2259 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2248 generate this file manually. The form must be as follows::
2260 generate this file manually. The form must be as follows::
2249
2261
2250 -----BEGIN CERTIFICATE-----
2262 -----BEGIN CERTIFICATE-----
2251 ... (certificate in base64 PEM encoding) ...
2263 ... (certificate in base64 PEM encoding) ...
2252 -----END CERTIFICATE-----
2264 -----END CERTIFICATE-----
2253 -----BEGIN CERTIFICATE-----
2265 -----BEGIN CERTIFICATE-----
2254 ... (certificate in base64 PEM encoding) ...
2266 ... (certificate in base64 PEM encoding) ...
2255 -----END CERTIFICATE-----
2267 -----END CERTIFICATE-----
2256
2268
2257 ``cache``
2269 ``cache``
2258 Whether to support caching in hgweb. (default: True)
2270 Whether to support caching in hgweb. (default: True)
2259
2271
2260 ``certificate``
2272 ``certificate``
2261 Certificate to use when running :hg:`serve`.
2273 Certificate to use when running :hg:`serve`.
2262
2274
2263 ``collapse``
2275 ``collapse``
2264 With ``descend`` enabled, repositories in subdirectories are shown at
2276 With ``descend`` enabled, repositories in subdirectories are shown at
2265 a single level alongside repositories in the current path. With
2277 a single level alongside repositories in the current path. With
2266 ``collapse`` also enabled, repositories residing at a deeper level than
2278 ``collapse`` also enabled, repositories residing at a deeper level than
2267 the current path are grouped behind navigable directory entries that
2279 the current path are grouped behind navigable directory entries that
2268 lead to the locations of these repositories. In effect, this setting
2280 lead to the locations of these repositories. In effect, this setting
2269 collapses each collection of repositories found within a subdirectory
2281 collapses each collection of repositories found within a subdirectory
2270 into a single entry for that subdirectory. (default: False)
2282 into a single entry for that subdirectory. (default: False)
2271
2283
2272 ``comparisoncontext``
2284 ``comparisoncontext``
2273 Number of lines of context to show in side-by-side file comparison. If
2285 Number of lines of context to show in side-by-side file comparison. If
2274 negative or the value ``full``, whole files are shown. (default: 5)
2286 negative or the value ``full``, whole files are shown. (default: 5)
2275
2287
2276 This setting can be overridden by a ``context`` request parameter to the
2288 This setting can be overridden by a ``context`` request parameter to the
2277 ``comparison`` command, taking the same values.
2289 ``comparison`` command, taking the same values.
2278
2290
2279 ``contact``
2291 ``contact``
2280 Name or email address of the person in charge of the repository.
2292 Name or email address of the person in charge of the repository.
2281 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2293 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2282
2294
2283 ``csp``
2295 ``csp``
2284 Send a ``Content-Security-Policy`` HTTP header with this value.
2296 Send a ``Content-Security-Policy`` HTTP header with this value.
2285
2297
2286 The value may contain a special string ``%nonce%``, which will be replaced
2298 The value may contain a special string ``%nonce%``, which will be replaced
2287 by a randomly-generated one-time use value. If the value contains
2299 by a randomly-generated one-time use value. If the value contains
2288 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2300 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2289 one-time property of the nonce. This nonce will also be inserted into
2301 one-time property of the nonce. This nonce will also be inserted into
2290 ``<script>`` elements containing inline JavaScript.
2302 ``<script>`` elements containing inline JavaScript.
2291
2303
2292 Note: lots of HTML content sent by the server is derived from repository
2304 Note: lots of HTML content sent by the server is derived from repository
2293 data. Please consider the potential for malicious repository data to
2305 data. Please consider the potential for malicious repository data to
2294 "inject" itself into generated HTML content as part of your security
2306 "inject" itself into generated HTML content as part of your security
2295 threat model.
2307 threat model.
2296
2308
2297 ``deny_push``
2309 ``deny_push``
2298 Whether to deny pushing to the repository. If empty or not set,
2310 Whether to deny pushing to the repository. If empty or not set,
2299 push is not denied. If the special value ``*``, all remote users are
2311 push is not denied. If the special value ``*``, all remote users are
2300 denied push. Otherwise, unauthenticated users are all denied, and
2312 denied push. Otherwise, unauthenticated users are all denied, and
2301 any authenticated user name present in this list is also denied. The
2313 any authenticated user name present in this list is also denied. The
2302 contents of the deny_push list are examined before the allow_push list.
2314 contents of the deny_push list are examined before the allow_push list.
2303
2315
2304 ``deny_read``
2316 ``deny_read``
2305 Whether to deny reading/viewing of the repository. If this list is
2317 Whether to deny reading/viewing of the repository. If this list is
2306 not empty, unauthenticated users are all denied, and any
2318 not empty, unauthenticated users are all denied, and any
2307 authenticated user name present in this list is also denied access to
2319 authenticated user name present in this list is also denied access to
2308 the repository. If set to the special value ``*``, all remote users
2320 the repository. If set to the special value ``*``, all remote users
2309 are denied access (rarely needed ;). If deny_read is empty or not set,
2321 are denied access (rarely needed ;). If deny_read is empty or not set,
2310 the determination of repository access depends on the presence and
2322 the determination of repository access depends on the presence and
2311 content of the allow_read list (see description). If both
2323 content of the allow_read list (see description). If both
2312 deny_read and allow_read are empty or not set, then access is
2324 deny_read and allow_read are empty or not set, then access is
2313 permitted to all users by default. If the repository is being
2325 permitted to all users by default. If the repository is being
2314 served via hgwebdir, denied users will not be able to see it in
2326 served via hgwebdir, denied users will not be able to see it in
2315 the list of repositories. The contents of the deny_read list have
2327 the list of repositories. The contents of the deny_read list have
2316 priority over (are examined before) the contents of the allow_read
2328 priority over (are examined before) the contents of the allow_read
2317 list.
2329 list.
2318
2330
2319 ``descend``
2331 ``descend``
2320 hgwebdir indexes will not descend into subdirectories. Only repositories
2332 hgwebdir indexes will not descend into subdirectories. Only repositories
2321 directly in the current path will be shown (other repositories are still
2333 directly in the current path will be shown (other repositories are still
2322 available from the index corresponding to their containing path).
2334 available from the index corresponding to their containing path).
2323
2335
2324 ``description``
2336 ``description``
2325 Textual description of the repository's purpose or contents.
2337 Textual description of the repository's purpose or contents.
2326 (default: "unknown")
2338 (default: "unknown")
2327
2339
2328 ``encoding``
2340 ``encoding``
2329 Character encoding name. (default: the current locale charset)
2341 Character encoding name. (default: the current locale charset)
2330 Example: "UTF-8".
2342 Example: "UTF-8".
2331
2343
2332 ``errorlog``
2344 ``errorlog``
2333 Where to output the error log. (default: stderr)
2345 Where to output the error log. (default: stderr)
2334
2346
2335 ``guessmime``
2347 ``guessmime``
2336 Control MIME types for raw download of file content.
2348 Control MIME types for raw download of file content.
2337 Set to True to let hgweb guess the content type from the file
2349 Set to True to let hgweb guess the content type from the file
2338 extension. This will serve HTML files as ``text/html`` and might
2350 extension. This will serve HTML files as ``text/html`` and might
2339 allow cross-site scripting attacks when serving untrusted
2351 allow cross-site scripting attacks when serving untrusted
2340 repositories. (default: False)
2352 repositories. (default: False)
2341
2353
2342 ``hidden``
2354 ``hidden``
2343 Whether to hide the repository in the hgwebdir index.
2355 Whether to hide the repository in the hgwebdir index.
2344 (default: False)
2356 (default: False)
2345
2357
2346 ``ipv6``
2358 ``ipv6``
2347 Whether to use IPv6. (default: False)
2359 Whether to use IPv6. (default: False)
2348
2360
2349 ``labels``
2361 ``labels``
2350 List of string *labels* associated with the repository.
2362 List of string *labels* associated with the repository.
2351
2363
2352 Labels are exposed as a template keyword and can be used to customize
2364 Labels are exposed as a template keyword and can be used to customize
2353 output. e.g. the ``index`` template can group or filter repositories
2365 output. e.g. the ``index`` template can group or filter repositories
2354 by labels and the ``summary`` template can display additional content
2366 by labels and the ``summary`` template can display additional content
2355 if a specific label is present.
2367 if a specific label is present.
2356
2368
2357 ``logoimg``
2369 ``logoimg``
2358 File name of the logo image that some templates display on each page.
2370 File name of the logo image that some templates display on each page.
2359 The file name is relative to ``staticurl``. That is, the full path to
2371 The file name is relative to ``staticurl``. That is, the full path to
2360 the logo image is "staticurl/logoimg".
2372 the logo image is "staticurl/logoimg".
2361 If unset, ``hglogo.png`` will be used.
2373 If unset, ``hglogo.png`` will be used.
2362
2374
2363 ``logourl``
2375 ``logourl``
2364 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2376 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2365 will be used.
2377 will be used.
2366
2378
2367 ``maxchanges``
2379 ``maxchanges``
2368 Maximum number of changes to list on the changelog. (default: 10)
2380 Maximum number of changes to list on the changelog. (default: 10)
2369
2381
2370 ``maxfiles``
2382 ``maxfiles``
2371 Maximum number of files to list per changeset. (default: 10)
2383 Maximum number of files to list per changeset. (default: 10)
2372
2384
2373 ``maxshortchanges``
2385 ``maxshortchanges``
2374 Maximum number of changes to list on the shortlog, graph or filelog
2386 Maximum number of changes to list on the shortlog, graph or filelog
2375 pages. (default: 60)
2387 pages. (default: 60)
2376
2388
2377 ``name``
2389 ``name``
2378 Repository name to use in the web interface.
2390 Repository name to use in the web interface.
2379 (default: current working directory)
2391 (default: current working directory)
2380
2392
2381 ``port``
2393 ``port``
2382 Port to listen on. (default: 8000)
2394 Port to listen on. (default: 8000)
2383
2395
2384 ``prefix``
2396 ``prefix``
2385 Prefix path to serve from. (default: '' (server root))
2397 Prefix path to serve from. (default: '' (server root))
2386
2398
2387 ``push_ssl``
2399 ``push_ssl``
2388 Whether to require that inbound pushes be transported over SSL to
2400 Whether to require that inbound pushes be transported over SSL to
2389 prevent password sniffing. (default: True)
2401 prevent password sniffing. (default: True)
2390
2402
2391 ``refreshinterval``
2403 ``refreshinterval``
2392 How frequently directory listings re-scan the filesystem for new
2404 How frequently directory listings re-scan the filesystem for new
2393 repositories, in seconds. This is relevant when wildcards are used
2405 repositories, in seconds. This is relevant when wildcards are used
2394 to define paths. Depending on how much filesystem traversal is
2406 to define paths. Depending on how much filesystem traversal is
2395 required, refreshing may negatively impact performance.
2407 required, refreshing may negatively impact performance.
2396
2408
2397 Values less than or equal to 0 always refresh.
2409 Values less than or equal to 0 always refresh.
2398 (default: 20)
2410 (default: 20)
2399
2411
2400 ``staticurl``
2412 ``staticurl``
2401 Base URL to use for static files. If unset, static files (e.g. the
2413 Base URL to use for static files. If unset, static files (e.g. the
2402 hgicon.png favicon) will be served by the CGI script itself. Use
2414 hgicon.png favicon) will be served by the CGI script itself. Use
2403 this setting to serve them directly with the HTTP server.
2415 this setting to serve them directly with the HTTP server.
2404 Example: ``http://hgserver/static/``.
2416 Example: ``http://hgserver/static/``.
2405
2417
2406 ``stripes``
2418 ``stripes``
2407 How many lines a "zebra stripe" should span in multi-line output.
2419 How many lines a "zebra stripe" should span in multi-line output.
2408 Set to 0 to disable. (default: 1)
2420 Set to 0 to disable. (default: 1)
2409
2421
2410 ``style``
2422 ``style``
2411 Which template map style to use. The available options are the names of
2423 Which template map style to use. The available options are the names of
2412 subdirectories in the HTML templates path. (default: ``paper``)
2424 subdirectories in the HTML templates path. (default: ``paper``)
2413 Example: ``monoblue``.
2425 Example: ``monoblue``.
2414
2426
2415 ``templates``
2427 ``templates``
2416 Where to find the HTML templates. The default path to the HTML templates
2428 Where to find the HTML templates. The default path to the HTML templates
2417 can be obtained from ``hg debuginstall``.
2429 can be obtained from ``hg debuginstall``.
2418
2430
2419 ``websub``
2431 ``websub``
2420 ----------
2432 ----------
2421
2433
2422 Web substitution filter definition. You can use this section to
2434 Web substitution filter definition. You can use this section to
2423 define a set of regular expression substitution patterns which
2435 define a set of regular expression substitution patterns which
2424 let you automatically modify the hgweb server output.
2436 let you automatically modify the hgweb server output.
2425
2437
2426 The default hgweb templates only apply these substitution patterns
2438 The default hgweb templates only apply these substitution patterns
2427 on the revision description fields. You can apply them anywhere
2439 on the revision description fields. You can apply them anywhere
2428 you want when you create your own templates by adding calls to the
2440 you want when you create your own templates by adding calls to the
2429 "websub" filter (usually after calling the "escape" filter).
2441 "websub" filter (usually after calling the "escape" filter).
2430
2442
2431 This can be used, for example, to convert issue references to links
2443 This can be used, for example, to convert issue references to links
2432 to your issue tracker, or to convert "markdown-like" syntax into
2444 to your issue tracker, or to convert "markdown-like" syntax into
2433 HTML (see the examples below).
2445 HTML (see the examples below).
2434
2446
2435 Each entry in this section names a substitution filter.
2447 Each entry in this section names a substitution filter.
2436 The value of each entry defines the substitution expression itself.
2448 The value of each entry defines the substitution expression itself.
2437 The websub expressions follow the old interhg extension syntax,
2449 The websub expressions follow the old interhg extension syntax,
2438 which in turn imitates the Unix sed replacement syntax::
2450 which in turn imitates the Unix sed replacement syntax::
2439
2451
2440 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2452 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2441
2453
2442 You can use any separator other than "/". The final "i" is optional
2454 You can use any separator other than "/". The final "i" is optional
2443 and indicates that the search must be case insensitive.
2455 and indicates that the search must be case insensitive.
2444
2456
2445 Examples::
2457 Examples::
2446
2458
2447 [websub]
2459 [websub]
2448 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2460 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2449 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2461 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2450 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2462 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2451
2463
2452 ``worker``
2464 ``worker``
2453 ----------
2465 ----------
2454
2466
2455 Parallel master/worker configuration. We currently perform working
2467 Parallel master/worker configuration. We currently perform working
2456 directory updates in parallel on Unix-like systems, which greatly
2468 directory updates in parallel on Unix-like systems, which greatly
2457 helps performance.
2469 helps performance.
2458
2470
2459 ``numcpus``
2471 ``numcpus``
2460 Number of CPUs to use for parallel operations. A zero or
2472 Number of CPUs to use for parallel operations. A zero or
2461 negative value is treated as ``use the default``.
2473 negative value is treated as ``use the default``.
2462 (default: 4 or the number of CPUs on the system, whichever is larger)
2474 (default: 4 or the number of CPUs on the system, whichever is larger)
2463
2475
2464 ``backgroundclose``
2476 ``backgroundclose``
2465 Whether to enable closing file handles on background threads during certain
2477 Whether to enable closing file handles on background threads during certain
2466 operations. Some platforms aren't very efficient at closing file
2478 operations. Some platforms aren't very efficient at closing file
2467 handles that have been written or appended to. By performing file closing
2479 handles that have been written or appended to. By performing file closing
2468 on background threads, file write rate can increase substantially.
2480 on background threads, file write rate can increase substantially.
2469 (default: true on Windows, false elsewhere)
2481 (default: true on Windows, false elsewhere)
2470
2482
2471 ``backgroundcloseminfilecount``
2483 ``backgroundcloseminfilecount``
2472 Minimum number of files required to trigger background file closing.
2484 Minimum number of files required to trigger background file closing.
2473 Operations not writing this many files won't start background close
2485 Operations not writing this many files won't start background close
2474 threads.
2486 threads.
2475 (default: 2048)
2487 (default: 2048)
2476
2488
2477 ``backgroundclosemaxqueue``
2489 ``backgroundclosemaxqueue``
2478 The maximum number of opened file handles waiting to be closed in the
2490 The maximum number of opened file handles waiting to be closed in the
2479 background. This option only has an effect if ``backgroundclose`` is
2491 background. This option only has an effect if ``backgroundclose`` is
2480 enabled.
2492 enabled.
2481 (default: 384)
2493 (default: 384)
2482
2494
2483 ``backgroundclosethreadcount``
2495 ``backgroundclosethreadcount``
2484 Number of threads to process background file closes. Only relevant if
2496 Number of threads to process background file closes. Only relevant if
2485 ``backgroundclose`` is enabled.
2497 ``backgroundclose`` is enabled.
2486 (default: 4)
2498 (default: 4)
@@ -1,2302 +1,2311 b''
1 # localrepo.py - read/write repository class for mercurial
1 # localrepo.py - read/write repository class for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
10 import errno
11 import hashlib
11 import hashlib
12 import inspect
12 import inspect
13 import os
13 import os
14 import random
14 import random
15 import time
15 import time
16 import weakref
16 import weakref
17
17
18 from .i18n import _
18 from .i18n import _
19 from .node import (
19 from .node import (
20 hex,
20 hex,
21 nullid,
21 nullid,
22 short,
22 short,
23 )
23 )
24 from . import (
24 from . import (
25 bookmarks,
25 bookmarks,
26 branchmap,
26 branchmap,
27 bundle2,
27 bundle2,
28 changegroup,
28 changegroup,
29 changelog,
29 changelog,
30 color,
30 color,
31 context,
31 context,
32 dirstate,
32 dirstate,
33 dirstateguard,
33 dirstateguard,
34 discovery,
34 discovery,
35 encoding,
35 encoding,
36 error,
36 error,
37 exchange,
37 exchange,
38 extensions,
38 extensions,
39 filelog,
39 filelog,
40 hook,
40 hook,
41 lock as lockmod,
41 lock as lockmod,
42 manifest,
42 manifest,
43 match as matchmod,
43 match as matchmod,
44 merge as mergemod,
44 merge as mergemod,
45 mergeutil,
45 mergeutil,
46 namespaces,
46 namespaces,
47 obsolete,
47 obsolete,
48 pathutil,
48 pathutil,
49 peer,
49 peer,
50 phases,
50 phases,
51 pushkey,
51 pushkey,
52 pycompat,
52 pycompat,
53 repository,
53 repository,
54 repoview,
54 repoview,
55 revset,
55 revset,
56 revsetlang,
56 revsetlang,
57 scmutil,
57 scmutil,
58 sparse,
58 sparse,
59 store,
59 store,
60 subrepo,
60 subrepo,
61 tags as tagsmod,
61 tags as tagsmod,
62 transaction,
62 transaction,
63 txnutil,
63 txnutil,
64 util,
64 util,
65 vfs as vfsmod,
65 vfs as vfsmod,
66 )
66 )
67
67
68 release = lockmod.release
68 release = lockmod.release
69 urlerr = util.urlerr
69 urlerr = util.urlerr
70 urlreq = util.urlreq
70 urlreq = util.urlreq
71
71
72 # set of (path, vfs-location) tuples. vfs-location is:
72 # set of (path, vfs-location) tuples. vfs-location is:
73 # - 'plain for vfs relative paths
73 # - 'plain for vfs relative paths
74 # - '' for svfs relative paths
74 # - '' for svfs relative paths
75 _cachedfiles = set()
75 _cachedfiles = set()
76
76
77 class _basefilecache(scmutil.filecache):
77 class _basefilecache(scmutil.filecache):
78 """All filecache usage on repo are done for logic that should be unfiltered
78 """All filecache usage on repo are done for logic that should be unfiltered
79 """
79 """
80 def __get__(self, repo, type=None):
80 def __get__(self, repo, type=None):
81 if repo is None:
81 if repo is None:
82 return self
82 return self
83 return super(_basefilecache, self).__get__(repo.unfiltered(), type)
83 return super(_basefilecache, self).__get__(repo.unfiltered(), type)
84 def __set__(self, repo, value):
84 def __set__(self, repo, value):
85 return super(_basefilecache, self).__set__(repo.unfiltered(), value)
85 return super(_basefilecache, self).__set__(repo.unfiltered(), value)
86 def __delete__(self, repo):
86 def __delete__(self, repo):
87 return super(_basefilecache, self).__delete__(repo.unfiltered())
87 return super(_basefilecache, self).__delete__(repo.unfiltered())
88
88
89 class repofilecache(_basefilecache):
89 class repofilecache(_basefilecache):
90 """filecache for files in .hg but outside of .hg/store"""
90 """filecache for files in .hg but outside of .hg/store"""
91 def __init__(self, *paths):
91 def __init__(self, *paths):
92 super(repofilecache, self).__init__(*paths)
92 super(repofilecache, self).__init__(*paths)
93 for path in paths:
93 for path in paths:
94 _cachedfiles.add((path, 'plain'))
94 _cachedfiles.add((path, 'plain'))
95
95
96 def join(self, obj, fname):
96 def join(self, obj, fname):
97 return obj.vfs.join(fname)
97 return obj.vfs.join(fname)
98
98
99 class storecache(_basefilecache):
99 class storecache(_basefilecache):
100 """filecache for files in the store"""
100 """filecache for files in the store"""
101 def __init__(self, *paths):
101 def __init__(self, *paths):
102 super(storecache, self).__init__(*paths)
102 super(storecache, self).__init__(*paths)
103 for path in paths:
103 for path in paths:
104 _cachedfiles.add((path, ''))
104 _cachedfiles.add((path, ''))
105
105
106 def join(self, obj, fname):
106 def join(self, obj, fname):
107 return obj.sjoin(fname)
107 return obj.sjoin(fname)
108
108
109 def isfilecached(repo, name):
109 def isfilecached(repo, name):
110 """check if a repo has already cached "name" filecache-ed property
110 """check if a repo has already cached "name" filecache-ed property
111
111
112 This returns (cachedobj-or-None, iscached) tuple.
112 This returns (cachedobj-or-None, iscached) tuple.
113 """
113 """
114 cacheentry = repo.unfiltered()._filecache.get(name, None)
114 cacheentry = repo.unfiltered()._filecache.get(name, None)
115 if not cacheentry:
115 if not cacheentry:
116 return None, False
116 return None, False
117 return cacheentry.obj, True
117 return cacheentry.obj, True
118
118
119 class unfilteredpropertycache(util.propertycache):
119 class unfilteredpropertycache(util.propertycache):
120 """propertycache that apply to unfiltered repo only"""
120 """propertycache that apply to unfiltered repo only"""
121
121
122 def __get__(self, repo, type=None):
122 def __get__(self, repo, type=None):
123 unfi = repo.unfiltered()
123 unfi = repo.unfiltered()
124 if unfi is repo:
124 if unfi is repo:
125 return super(unfilteredpropertycache, self).__get__(unfi)
125 return super(unfilteredpropertycache, self).__get__(unfi)
126 return getattr(unfi, self.name)
126 return getattr(unfi, self.name)
127
127
128 class filteredpropertycache(util.propertycache):
128 class filteredpropertycache(util.propertycache):
129 """propertycache that must take filtering in account"""
129 """propertycache that must take filtering in account"""
130
130
131 def cachevalue(self, obj, value):
131 def cachevalue(self, obj, value):
132 object.__setattr__(obj, self.name, value)
132 object.__setattr__(obj, self.name, value)
133
133
134
134
135 def hasunfilteredcache(repo, name):
135 def hasunfilteredcache(repo, name):
136 """check if a repo has an unfilteredpropertycache value for <name>"""
136 """check if a repo has an unfilteredpropertycache value for <name>"""
137 return name in vars(repo.unfiltered())
137 return name in vars(repo.unfiltered())
138
138
139 def unfilteredmethod(orig):
139 def unfilteredmethod(orig):
140 """decorate method that always need to be run on unfiltered version"""
140 """decorate method that always need to be run on unfiltered version"""
141 def wrapper(repo, *args, **kwargs):
141 def wrapper(repo, *args, **kwargs):
142 return orig(repo.unfiltered(), *args, **kwargs)
142 return orig(repo.unfiltered(), *args, **kwargs)
143 return wrapper
143 return wrapper
144
144
145 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
145 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
146 'unbundle'}
146 'unbundle'}
147 legacycaps = moderncaps.union({'changegroupsubset'})
147 legacycaps = moderncaps.union({'changegroupsubset'})
148
148
149 class localpeer(repository.peer):
149 class localpeer(repository.peer):
150 '''peer for a local repo; reflects only the most recent API'''
150 '''peer for a local repo; reflects only the most recent API'''
151
151
152 def __init__(self, repo, caps=None):
152 def __init__(self, repo, caps=None):
153 super(localpeer, self).__init__()
153 super(localpeer, self).__init__()
154
154
155 if caps is None:
155 if caps is None:
156 caps = moderncaps.copy()
156 caps = moderncaps.copy()
157 self._repo = repo.filtered('served')
157 self._repo = repo.filtered('served')
158 self._ui = repo.ui
158 self._ui = repo.ui
159 self._caps = repo._restrictcapabilities(caps)
159 self._caps = repo._restrictcapabilities(caps)
160
160
161 # Begin of _basepeer interface.
161 # Begin of _basepeer interface.
162
162
163 @util.propertycache
163 @util.propertycache
164 def ui(self):
164 def ui(self):
165 return self._ui
165 return self._ui
166
166
167 def url(self):
167 def url(self):
168 return self._repo.url()
168 return self._repo.url()
169
169
170 def local(self):
170 def local(self):
171 return self._repo
171 return self._repo
172
172
173 def peer(self):
173 def peer(self):
174 return self
174 return self
175
175
176 def canpush(self):
176 def canpush(self):
177 return True
177 return True
178
178
179 def close(self):
179 def close(self):
180 self._repo.close()
180 self._repo.close()
181
181
182 # End of _basepeer interface.
182 # End of _basepeer interface.
183
183
184 # Begin of _basewirecommands interface.
184 # Begin of _basewirecommands interface.
185
185
186 def branchmap(self):
186 def branchmap(self):
187 return self._repo.branchmap()
187 return self._repo.branchmap()
188
188
189 def capabilities(self):
189 def capabilities(self):
190 return self._caps
190 return self._caps
191
191
192 def debugwireargs(self, one, two, three=None, four=None, five=None):
192 def debugwireargs(self, one, two, three=None, four=None, five=None):
193 """Used to test argument passing over the wire"""
193 """Used to test argument passing over the wire"""
194 return "%s %s %s %s %s" % (one, two, three, four, five)
194 return "%s %s %s %s %s" % (one, two, three, four, five)
195
195
196 def getbundle(self, source, heads=None, common=None, bundlecaps=None,
196 def getbundle(self, source, heads=None, common=None, bundlecaps=None,
197 **kwargs):
197 **kwargs):
198 chunks = exchange.getbundlechunks(self._repo, source, heads=heads,
198 chunks = exchange.getbundlechunks(self._repo, source, heads=heads,
199 common=common, bundlecaps=bundlecaps,
199 common=common, bundlecaps=bundlecaps,
200 **kwargs)
200 **kwargs)
201 cb = util.chunkbuffer(chunks)
201 cb = util.chunkbuffer(chunks)
202
202
203 if exchange.bundle2requested(bundlecaps):
203 if exchange.bundle2requested(bundlecaps):
204 # When requesting a bundle2, getbundle returns a stream to make the
204 # When requesting a bundle2, getbundle returns a stream to make the
205 # wire level function happier. We need to build a proper object
205 # wire level function happier. We need to build a proper object
206 # from it in local peer.
206 # from it in local peer.
207 return bundle2.getunbundler(self.ui, cb)
207 return bundle2.getunbundler(self.ui, cb)
208 else:
208 else:
209 return changegroup.getunbundler('01', cb, None)
209 return changegroup.getunbundler('01', cb, None)
210
210
211 def heads(self):
211 def heads(self):
212 return self._repo.heads()
212 return self._repo.heads()
213
213
214 def known(self, nodes):
214 def known(self, nodes):
215 return self._repo.known(nodes)
215 return self._repo.known(nodes)
216
216
217 def listkeys(self, namespace):
217 def listkeys(self, namespace):
218 return self._repo.listkeys(namespace)
218 return self._repo.listkeys(namespace)
219
219
220 def lookup(self, key):
220 def lookup(self, key):
221 return self._repo.lookup(key)
221 return self._repo.lookup(key)
222
222
223 def pushkey(self, namespace, key, old, new):
223 def pushkey(self, namespace, key, old, new):
224 return self._repo.pushkey(namespace, key, old, new)
224 return self._repo.pushkey(namespace, key, old, new)
225
225
226 def stream_out(self):
226 def stream_out(self):
227 raise error.Abort(_('cannot perform stream clone against local '
227 raise error.Abort(_('cannot perform stream clone against local '
228 'peer'))
228 'peer'))
229
229
230 def unbundle(self, cg, heads, url):
230 def unbundle(self, cg, heads, url):
231 """apply a bundle on a repo
231 """apply a bundle on a repo
232
232
233 This function handles the repo locking itself."""
233 This function handles the repo locking itself."""
234 try:
234 try:
235 try:
235 try:
236 cg = exchange.readbundle(self.ui, cg, None)
236 cg = exchange.readbundle(self.ui, cg, None)
237 ret = exchange.unbundle(self._repo, cg, heads, 'push', url)
237 ret = exchange.unbundle(self._repo, cg, heads, 'push', url)
238 if util.safehasattr(ret, 'getchunks'):
238 if util.safehasattr(ret, 'getchunks'):
239 # This is a bundle20 object, turn it into an unbundler.
239 # This is a bundle20 object, turn it into an unbundler.
240 # This little dance should be dropped eventually when the
240 # This little dance should be dropped eventually when the
241 # API is finally improved.
241 # API is finally improved.
242 stream = util.chunkbuffer(ret.getchunks())
242 stream = util.chunkbuffer(ret.getchunks())
243 ret = bundle2.getunbundler(self.ui, stream)
243 ret = bundle2.getunbundler(self.ui, stream)
244 return ret
244 return ret
245 except Exception as exc:
245 except Exception as exc:
246 # If the exception contains output salvaged from a bundle2
246 # If the exception contains output salvaged from a bundle2
247 # reply, we need to make sure it is printed before continuing
247 # reply, we need to make sure it is printed before continuing
248 # to fail. So we build a bundle2 with such output and consume
248 # to fail. So we build a bundle2 with such output and consume
249 # it directly.
249 # it directly.
250 #
250 #
251 # This is not very elegant but allows a "simple" solution for
251 # This is not very elegant but allows a "simple" solution for
252 # issue4594
252 # issue4594
253 output = getattr(exc, '_bundle2salvagedoutput', ())
253 output = getattr(exc, '_bundle2salvagedoutput', ())
254 if output:
254 if output:
255 bundler = bundle2.bundle20(self._repo.ui)
255 bundler = bundle2.bundle20(self._repo.ui)
256 for out in output:
256 for out in output:
257 bundler.addpart(out)
257 bundler.addpart(out)
258 stream = util.chunkbuffer(bundler.getchunks())
258 stream = util.chunkbuffer(bundler.getchunks())
259 b = bundle2.getunbundler(self.ui, stream)
259 b = bundle2.getunbundler(self.ui, stream)
260 bundle2.processbundle(self._repo, b)
260 bundle2.processbundle(self._repo, b)
261 raise
261 raise
262 except error.PushRaced as exc:
262 except error.PushRaced as exc:
263 raise error.ResponseError(_('push failed:'), str(exc))
263 raise error.ResponseError(_('push failed:'), str(exc))
264
264
265 # End of _basewirecommands interface.
265 # End of _basewirecommands interface.
266
266
267 # Begin of peer interface.
267 # Begin of peer interface.
268
268
269 def iterbatch(self):
269 def iterbatch(self):
270 return peer.localiterbatcher(self)
270 return peer.localiterbatcher(self)
271
271
272 # End of peer interface.
272 # End of peer interface.
273
273
274 class locallegacypeer(repository.legacypeer, localpeer):
274 class locallegacypeer(repository.legacypeer, localpeer):
275 '''peer extension which implements legacy methods too; used for tests with
275 '''peer extension which implements legacy methods too; used for tests with
276 restricted capabilities'''
276 restricted capabilities'''
277
277
278 def __init__(self, repo):
278 def __init__(self, repo):
279 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
279 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
280
280
281 # Begin of baselegacywirecommands interface.
281 # Begin of baselegacywirecommands interface.
282
282
283 def between(self, pairs):
283 def between(self, pairs):
284 return self._repo.between(pairs)
284 return self._repo.between(pairs)
285
285
286 def branches(self, nodes):
286 def branches(self, nodes):
287 return self._repo.branches(nodes)
287 return self._repo.branches(nodes)
288
288
289 def changegroup(self, basenodes, source):
289 def changegroup(self, basenodes, source):
290 outgoing = discovery.outgoing(self._repo, missingroots=basenodes,
290 outgoing = discovery.outgoing(self._repo, missingroots=basenodes,
291 missingheads=self._repo.heads())
291 missingheads=self._repo.heads())
292 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
292 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
293
293
294 def changegroupsubset(self, bases, heads, source):
294 def changegroupsubset(self, bases, heads, source):
295 outgoing = discovery.outgoing(self._repo, missingroots=bases,
295 outgoing = discovery.outgoing(self._repo, missingroots=bases,
296 missingheads=heads)
296 missingheads=heads)
297 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
297 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
298
298
299 # End of baselegacywirecommands interface.
299 # End of baselegacywirecommands interface.
300
300
301 # Increment the sub-version when the revlog v2 format changes to lock out old
301 # Increment the sub-version when the revlog v2 format changes to lock out old
302 # clients.
302 # clients.
303 REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'
303 REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'
304
304
305 class localrepository(object):
305 class localrepository(object):
306
306
307 supportedformats = {
307 supportedformats = {
308 'revlogv1',
308 'revlogv1',
309 'generaldelta',
309 'generaldelta',
310 'treemanifest',
310 'treemanifest',
311 'manifestv2',
311 'manifestv2',
312 REVLOGV2_REQUIREMENT,
312 REVLOGV2_REQUIREMENT,
313 }
313 }
314 _basesupported = supportedformats | {
314 _basesupported = supportedformats | {
315 'store',
315 'store',
316 'fncache',
316 'fncache',
317 'shared',
317 'shared',
318 'relshared',
318 'relshared',
319 'dotencode',
319 'dotencode',
320 'exp-sparse',
320 'exp-sparse',
321 }
321 }
322 openerreqs = {
322 openerreqs = {
323 'revlogv1',
323 'revlogv1',
324 'generaldelta',
324 'generaldelta',
325 'treemanifest',
325 'treemanifest',
326 'manifestv2',
326 'manifestv2',
327 }
327 }
328
328
329 # a list of (ui, featureset) functions.
329 # a list of (ui, featureset) functions.
330 # only functions defined in module of enabled extensions are invoked
330 # only functions defined in module of enabled extensions are invoked
331 featuresetupfuncs = set()
331 featuresetupfuncs = set()
332
332
333 # list of prefix for file which can be written without 'wlock'
333 # list of prefix for file which can be written without 'wlock'
334 # Extensions should extend this list when needed
334 # Extensions should extend this list when needed
335 _wlockfreeprefix = {
335 _wlockfreeprefix = {
336 # We migh consider requiring 'wlock' for the next
336 # We migh consider requiring 'wlock' for the next
337 # two, but pretty much all the existing code assume
337 # two, but pretty much all the existing code assume
338 # wlock is not needed so we keep them excluded for
338 # wlock is not needed so we keep them excluded for
339 # now.
339 # now.
340 'hgrc',
340 'hgrc',
341 'requires',
341 'requires',
342 # XXX cache is a complicatged business someone
342 # XXX cache is a complicatged business someone
343 # should investigate this in depth at some point
343 # should investigate this in depth at some point
344 'cache/',
344 'cache/',
345 # XXX shouldn't be dirstate covered by the wlock?
345 # XXX shouldn't be dirstate covered by the wlock?
346 'dirstate',
346 'dirstate',
347 # XXX bisect was still a bit too messy at the time
347 # XXX bisect was still a bit too messy at the time
348 # this changeset was introduced. Someone should fix
348 # this changeset was introduced. Someone should fix
349 # the remainig bit and drop this line
349 # the remainig bit and drop this line
350 'bisect.state',
350 'bisect.state',
351 }
351 }
352
352
353 def __init__(self, baseui, path, create=False):
353 def __init__(self, baseui, path, create=False):
354 self.requirements = set()
354 self.requirements = set()
355 self.filtername = None
355 self.filtername = None
356 # wvfs: rooted at the repository root, used to access the working copy
356 # wvfs: rooted at the repository root, used to access the working copy
357 self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
357 self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
358 # vfs: rooted at .hg, used to access repo files outside of .hg/store
358 # vfs: rooted at .hg, used to access repo files outside of .hg/store
359 self.vfs = None
359 self.vfs = None
360 # svfs: usually rooted at .hg/store, used to access repository history
360 # svfs: usually rooted at .hg/store, used to access repository history
361 # If this is a shared repository, this vfs may point to another
361 # If this is a shared repository, this vfs may point to another
362 # repository's .hg/store directory.
362 # repository's .hg/store directory.
363 self.svfs = None
363 self.svfs = None
364 self.root = self.wvfs.base
364 self.root = self.wvfs.base
365 self.path = self.wvfs.join(".hg")
365 self.path = self.wvfs.join(".hg")
366 self.origroot = path
366 self.origroot = path
367 # These auditor are not used by the vfs,
367 # These auditor are not used by the vfs,
368 # only used when writing this comment: basectx.match
368 # only used when writing this comment: basectx.match
369 self.auditor = pathutil.pathauditor(self.root, self._checknested)
369 self.auditor = pathutil.pathauditor(self.root, self._checknested)
370 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
370 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
371 realfs=False, cached=True)
371 realfs=False, cached=True)
372 self.baseui = baseui
372 self.baseui = baseui
373 self.ui = baseui.copy()
373 self.ui = baseui.copy()
374 self.ui.copy = baseui.copy # prevent copying repo configuration
374 self.ui.copy = baseui.copy # prevent copying repo configuration
375 self.vfs = vfsmod.vfs(self.path, cacheaudited=True)
375 self.vfs = vfsmod.vfs(self.path, cacheaudited=True)
376 if (self.ui.configbool('devel', 'all-warnings') or
376 if (self.ui.configbool('devel', 'all-warnings') or
377 self.ui.configbool('devel', 'check-locks')):
377 self.ui.configbool('devel', 'check-locks')):
378 self.vfs.audit = self._getvfsward(self.vfs.audit)
378 self.vfs.audit = self._getvfsward(self.vfs.audit)
379 # A list of callback to shape the phase if no data were found.
379 # A list of callback to shape the phase if no data were found.
380 # Callback are in the form: func(repo, roots) --> processed root.
380 # Callback are in the form: func(repo, roots) --> processed root.
381 # This list it to be filled by extension during repo setup
381 # This list it to be filled by extension during repo setup
382 self._phasedefaults = []
382 self._phasedefaults = []
383 try:
383 try:
384 self.ui.readconfig(self.vfs.join("hgrc"), self.root)
384 self.ui.readconfig(self.vfs.join("hgrc"), self.root)
385 self._loadextensions()
385 self._loadextensions()
386 except IOError:
386 except IOError:
387 pass
387 pass
388
388
389 if self.featuresetupfuncs:
389 if self.featuresetupfuncs:
390 self.supported = set(self._basesupported) # use private copy
390 self.supported = set(self._basesupported) # use private copy
391 extmods = set(m.__name__ for n, m
391 extmods = set(m.__name__ for n, m
392 in extensions.extensions(self.ui))
392 in extensions.extensions(self.ui))
393 for setupfunc in self.featuresetupfuncs:
393 for setupfunc in self.featuresetupfuncs:
394 if setupfunc.__module__ in extmods:
394 if setupfunc.__module__ in extmods:
395 setupfunc(self.ui, self.supported)
395 setupfunc(self.ui, self.supported)
396 else:
396 else:
397 self.supported = self._basesupported
397 self.supported = self._basesupported
398 color.setup(self.ui)
398 color.setup(self.ui)
399
399
400 # Add compression engines.
400 # Add compression engines.
401 for name in util.compengines:
401 for name in util.compengines:
402 engine = util.compengines[name]
402 engine = util.compengines[name]
403 if engine.revlogheader():
403 if engine.revlogheader():
404 self.supported.add('exp-compression-%s' % name)
404 self.supported.add('exp-compression-%s' % name)
405
405
406 if not self.vfs.isdir():
406 if not self.vfs.isdir():
407 if create:
407 if create:
408 self.requirements = newreporequirements(self)
408 self.requirements = newreporequirements(self)
409
409
410 if not self.wvfs.exists():
410 if not self.wvfs.exists():
411 self.wvfs.makedirs()
411 self.wvfs.makedirs()
412 self.vfs.makedir(notindexed=True)
412 self.vfs.makedir(notindexed=True)
413
413
414 if 'store' in self.requirements:
414 if 'store' in self.requirements:
415 self.vfs.mkdir("store")
415 self.vfs.mkdir("store")
416
416
417 # create an invalid changelog
417 # create an invalid changelog
418 self.vfs.append(
418 self.vfs.append(
419 "00changelog.i",
419 "00changelog.i",
420 '\0\0\0\2' # represents revlogv2
420 '\0\0\0\2' # represents revlogv2
421 ' dummy changelog to prevent using the old repo layout'
421 ' dummy changelog to prevent using the old repo layout'
422 )
422 )
423 else:
423 else:
424 raise error.RepoError(_("repository %s not found") % path)
424 raise error.RepoError(_("repository %s not found") % path)
425 elif create:
425 elif create:
426 raise error.RepoError(_("repository %s already exists") % path)
426 raise error.RepoError(_("repository %s already exists") % path)
427 else:
427 else:
428 try:
428 try:
429 self.requirements = scmutil.readrequires(
429 self.requirements = scmutil.readrequires(
430 self.vfs, self.supported)
430 self.vfs, self.supported)
431 except IOError as inst:
431 except IOError as inst:
432 if inst.errno != errno.ENOENT:
432 if inst.errno != errno.ENOENT:
433 raise
433 raise
434
434
435 cachepath = self.vfs.join('cache')
435 cachepath = self.vfs.join('cache')
436 self.sharedpath = self.path
436 self.sharedpath = self.path
437 try:
437 try:
438 sharedpath = self.vfs.read("sharedpath").rstrip('\n')
438 sharedpath = self.vfs.read("sharedpath").rstrip('\n')
439 if 'relshared' in self.requirements:
439 if 'relshared' in self.requirements:
440 sharedpath = self.vfs.join(sharedpath)
440 sharedpath = self.vfs.join(sharedpath)
441 vfs = vfsmod.vfs(sharedpath, realpath=True)
441 vfs = vfsmod.vfs(sharedpath, realpath=True)
442 cachepath = vfs.join('cache')
442 cachepath = vfs.join('cache')
443 s = vfs.base
443 s = vfs.base
444 if not vfs.exists():
444 if not vfs.exists():
445 raise error.RepoError(
445 raise error.RepoError(
446 _('.hg/sharedpath points to nonexistent directory %s') % s)
446 _('.hg/sharedpath points to nonexistent directory %s') % s)
447 self.sharedpath = s
447 self.sharedpath = s
448 except IOError as inst:
448 except IOError as inst:
449 if inst.errno != errno.ENOENT:
449 if inst.errno != errno.ENOENT:
450 raise
450 raise
451
451
452 if 'exp-sparse' in self.requirements and not sparse.enabled:
452 if 'exp-sparse' in self.requirements and not sparse.enabled:
453 raise error.RepoError(_('repository is using sparse feature but '
453 raise error.RepoError(_('repository is using sparse feature but '
454 'sparse is not enabled; enable the '
454 'sparse is not enabled; enable the '
455 '"sparse" extensions to access'))
455 '"sparse" extensions to access'))
456
456
457 self.store = store.store(
457 self.store = store.store(
458 self.requirements, self.sharedpath,
458 self.requirements, self.sharedpath,
459 lambda base: vfsmod.vfs(base, cacheaudited=True))
459 lambda base: vfsmod.vfs(base, cacheaudited=True))
460 self.spath = self.store.path
460 self.spath = self.store.path
461 self.svfs = self.store.vfs
461 self.svfs = self.store.vfs
462 self.sjoin = self.store.join
462 self.sjoin = self.store.join
463 self.vfs.createmode = self.store.createmode
463 self.vfs.createmode = self.store.createmode
464 self.cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
464 self.cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
465 self.cachevfs.createmode = self.store.createmode
465 self.cachevfs.createmode = self.store.createmode
466 if (self.ui.configbool('devel', 'all-warnings') or
466 if (self.ui.configbool('devel', 'all-warnings') or
467 self.ui.configbool('devel', 'check-locks')):
467 self.ui.configbool('devel', 'check-locks')):
468 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs
468 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs
469 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
469 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
470 else: # standard vfs
470 else: # standard vfs
471 self.svfs.audit = self._getsvfsward(self.svfs.audit)
471 self.svfs.audit = self._getsvfsward(self.svfs.audit)
472 self._applyopenerreqs()
472 self._applyopenerreqs()
473 if create:
473 if create:
474 self._writerequirements()
474 self._writerequirements()
475
475
476 self._dirstatevalidatewarned = False
476 self._dirstatevalidatewarned = False
477
477
478 self._branchcaches = {}
478 self._branchcaches = {}
479 self._revbranchcache = None
479 self._revbranchcache = None
480 self.filterpats = {}
480 self.filterpats = {}
481 self._datafilters = {}
481 self._datafilters = {}
482 self._transref = self._lockref = self._wlockref = None
482 self._transref = self._lockref = self._wlockref = None
483
483
484 # A cache for various files under .hg/ that tracks file changes,
484 # A cache for various files under .hg/ that tracks file changes,
485 # (used by the filecache decorator)
485 # (used by the filecache decorator)
486 #
486 #
487 # Maps a property name to its util.filecacheentry
487 # Maps a property name to its util.filecacheentry
488 self._filecache = {}
488 self._filecache = {}
489
489
490 # hold sets of revision to be filtered
490 # hold sets of revision to be filtered
491 # should be cleared when something might have changed the filter value:
491 # should be cleared when something might have changed the filter value:
492 # - new changesets,
492 # - new changesets,
493 # - phase change,
493 # - phase change,
494 # - new obsolescence marker,
494 # - new obsolescence marker,
495 # - working directory parent change,
495 # - working directory parent change,
496 # - bookmark changes
496 # - bookmark changes
497 self.filteredrevcache = {}
497 self.filteredrevcache = {}
498
498
499 # post-dirstate-status hooks
499 # post-dirstate-status hooks
500 self._postdsstatus = []
500 self._postdsstatus = []
501
501
502 # Cache of types representing filtered repos.
502 # Cache of types representing filtered repos.
503 self._filteredrepotypes = weakref.WeakKeyDictionary()
503 self._filteredrepotypes = weakref.WeakKeyDictionary()
504
504
505 # generic mapping between names and nodes
505 # generic mapping between names and nodes
506 self.names = namespaces.namespaces()
506 self.names = namespaces.namespaces()
507
507
508 # Key to signature value.
508 # Key to signature value.
509 self._sparsesignaturecache = {}
509 self._sparsesignaturecache = {}
510 # Signature to cached matcher instance.
510 # Signature to cached matcher instance.
511 self._sparsematchercache = {}
511 self._sparsematchercache = {}
512
512
513 def _getvfsward(self, origfunc):
513 def _getvfsward(self, origfunc):
514 """build a ward for self.vfs"""
514 """build a ward for self.vfs"""
515 rref = weakref.ref(self)
515 rref = weakref.ref(self)
516 def checkvfs(path, mode=None):
516 def checkvfs(path, mode=None):
517 ret = origfunc(path, mode=mode)
517 ret = origfunc(path, mode=mode)
518 repo = rref()
518 repo = rref()
519 if (repo is None
519 if (repo is None
520 or not util.safehasattr(repo, '_wlockref')
520 or not util.safehasattr(repo, '_wlockref')
521 or not util.safehasattr(repo, '_lockref')):
521 or not util.safehasattr(repo, '_lockref')):
522 return
522 return
523 if mode in (None, 'r', 'rb'):
523 if mode in (None, 'r', 'rb'):
524 return
524 return
525 if path.startswith(repo.path):
525 if path.startswith(repo.path):
526 # truncate name relative to the repository (.hg)
526 # truncate name relative to the repository (.hg)
527 path = path[len(repo.path) + 1:]
527 path = path[len(repo.path) + 1:]
528 if path.startswith('cache/'):
528 if path.startswith('cache/'):
529 msg = 'accessing cache with vfs instead of cachevfs: "%s"'
529 msg = 'accessing cache with vfs instead of cachevfs: "%s"'
530 repo.ui.develwarn(msg % path, stacklevel=2, config="cache-vfs")
530 repo.ui.develwarn(msg % path, stacklevel=2, config="cache-vfs")
531 if path.startswith('journal.'):
531 if path.startswith('journal.'):
532 # journal is covered by 'lock'
532 # journal is covered by 'lock'
533 if repo._currentlock(repo._lockref) is None:
533 if repo._currentlock(repo._lockref) is None:
534 repo.ui.develwarn('write with no lock: "%s"' % path,
534 repo.ui.develwarn('write with no lock: "%s"' % path,
535 stacklevel=2, config='check-locks')
535 stacklevel=2, config='check-locks')
536 elif repo._currentlock(repo._wlockref) is None:
536 elif repo._currentlock(repo._wlockref) is None:
537 # rest of vfs files are covered by 'wlock'
537 # rest of vfs files are covered by 'wlock'
538 #
538 #
539 # exclude special files
539 # exclude special files
540 for prefix in self._wlockfreeprefix:
540 for prefix in self._wlockfreeprefix:
541 if path.startswith(prefix):
541 if path.startswith(prefix):
542 return
542 return
543 repo.ui.develwarn('write with no wlock: "%s"' % path,
543 repo.ui.develwarn('write with no wlock: "%s"' % path,
544 stacklevel=2, config='check-locks')
544 stacklevel=2, config='check-locks')
545 return ret
545 return ret
546 return checkvfs
546 return checkvfs
547
547
548 def _getsvfsward(self, origfunc):
548 def _getsvfsward(self, origfunc):
549 """build a ward for self.svfs"""
549 """build a ward for self.svfs"""
550 rref = weakref.ref(self)
550 rref = weakref.ref(self)
551 def checksvfs(path, mode=None):
551 def checksvfs(path, mode=None):
552 ret = origfunc(path, mode=mode)
552 ret = origfunc(path, mode=mode)
553 repo = rref()
553 repo = rref()
554 if repo is None or not util.safehasattr(repo, '_lockref'):
554 if repo is None or not util.safehasattr(repo, '_lockref'):
555 return
555 return
556 if mode in (None, 'r', 'rb'):
556 if mode in (None, 'r', 'rb'):
557 return
557 return
558 if path.startswith(repo.sharedpath):
558 if path.startswith(repo.sharedpath):
559 # truncate name relative to the repository (.hg)
559 # truncate name relative to the repository (.hg)
560 path = path[len(repo.sharedpath) + 1:]
560 path = path[len(repo.sharedpath) + 1:]
561 if repo._currentlock(repo._lockref) is None:
561 if repo._currentlock(repo._lockref) is None:
562 repo.ui.develwarn('write with no lock: "%s"' % path,
562 repo.ui.develwarn('write with no lock: "%s"' % path,
563 stacklevel=3)
563 stacklevel=3)
564 return ret
564 return ret
565 return checksvfs
565 return checksvfs
566
566
567 def close(self):
567 def close(self):
568 self._writecaches()
568 self._writecaches()
569
569
570 def _loadextensions(self):
570 def _loadextensions(self):
571 extensions.loadall(self.ui)
571 extensions.loadall(self.ui)
572
572
573 def _writecaches(self):
573 def _writecaches(self):
574 if self._revbranchcache:
574 if self._revbranchcache:
575 self._revbranchcache.write()
575 self._revbranchcache.write()
576
576
577 def _restrictcapabilities(self, caps):
577 def _restrictcapabilities(self, caps):
578 if self.ui.configbool('experimental', 'bundle2-advertise'):
578 if self.ui.configbool('experimental', 'bundle2-advertise'):
579 caps = set(caps)
579 caps = set(caps)
580 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self))
580 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self))
581 caps.add('bundle2=' + urlreq.quote(capsblob))
581 caps.add('bundle2=' + urlreq.quote(capsblob))
582 return caps
582 return caps
583
583
584 def _applyopenerreqs(self):
584 def _applyopenerreqs(self):
585 self.svfs.options = dict((r, 1) for r in self.requirements
585 self.svfs.options = dict((r, 1) for r in self.requirements
586 if r in self.openerreqs)
586 if r in self.openerreqs)
587 # experimental config: format.chunkcachesize
587 # experimental config: format.chunkcachesize
588 chunkcachesize = self.ui.configint('format', 'chunkcachesize')
588 chunkcachesize = self.ui.configint('format', 'chunkcachesize')
589 if chunkcachesize is not None:
589 if chunkcachesize is not None:
590 self.svfs.options['chunkcachesize'] = chunkcachesize
590 self.svfs.options['chunkcachesize'] = chunkcachesize
591 # experimental config: format.maxchainlen
591 # experimental config: format.maxchainlen
592 maxchainlen = self.ui.configint('format', 'maxchainlen')
592 maxchainlen = self.ui.configint('format', 'maxchainlen')
593 if maxchainlen is not None:
593 if maxchainlen is not None:
594 self.svfs.options['maxchainlen'] = maxchainlen
594 self.svfs.options['maxchainlen'] = maxchainlen
595 # experimental config: format.manifestcachesize
595 # experimental config: format.manifestcachesize
596 manifestcachesize = self.ui.configint('format', 'manifestcachesize')
596 manifestcachesize = self.ui.configint('format', 'manifestcachesize')
597 if manifestcachesize is not None:
597 if manifestcachesize is not None:
598 self.svfs.options['manifestcachesize'] = manifestcachesize
598 self.svfs.options['manifestcachesize'] = manifestcachesize
599 # experimental config: format.aggressivemergedeltas
599 # experimental config: format.aggressivemergedeltas
600 aggressivemergedeltas = self.ui.configbool('format',
600 aggressivemergedeltas = self.ui.configbool('format',
601 'aggressivemergedeltas')
601 'aggressivemergedeltas')
602 self.svfs.options['aggressivemergedeltas'] = aggressivemergedeltas
602 self.svfs.options['aggressivemergedeltas'] = aggressivemergedeltas
603 self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui)
603 self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui)
604 chainspan = self.ui.configbytes('experimental', 'maxdeltachainspan')
604 chainspan = self.ui.configbytes('experimental', 'maxdeltachainspan')
605 if 0 <= chainspan:
605 if 0 <= chainspan:
606 self.svfs.options['maxdeltachainspan'] = chainspan
606 self.svfs.options['maxdeltachainspan'] = chainspan
607 mmapindexthreshold = self.ui.configbytes('experimental',
607 mmapindexthreshold = self.ui.configbytes('experimental',
608 'mmapindexthreshold')
608 'mmapindexthreshold')
609 if mmapindexthreshold is not None:
609 if mmapindexthreshold is not None:
610 self.svfs.options['mmapindexthreshold'] = mmapindexthreshold
610 self.svfs.options['mmapindexthreshold'] = mmapindexthreshold
611
611
612 for r in self.requirements:
612 for r in self.requirements:
613 if r.startswith('exp-compression-'):
613 if r.startswith('exp-compression-'):
614 self.svfs.options['compengine'] = r[len('exp-compression-'):]
614 self.svfs.options['compengine'] = r[len('exp-compression-'):]
615
615
616 # TODO move "revlogv2" to openerreqs once finalized.
616 # TODO move "revlogv2" to openerreqs once finalized.
617 if REVLOGV2_REQUIREMENT in self.requirements:
617 if REVLOGV2_REQUIREMENT in self.requirements:
618 self.svfs.options['revlogv2'] = True
618 self.svfs.options['revlogv2'] = True
619
619
620 def _writerequirements(self):
620 def _writerequirements(self):
621 scmutil.writerequires(self.vfs, self.requirements)
621 scmutil.writerequires(self.vfs, self.requirements)
622
622
623 def _checknested(self, path):
623 def _checknested(self, path):
624 """Determine if path is a legal nested repository."""
624 """Determine if path is a legal nested repository."""
625 if not path.startswith(self.root):
625 if not path.startswith(self.root):
626 return False
626 return False
627 subpath = path[len(self.root) + 1:]
627 subpath = path[len(self.root) + 1:]
628 normsubpath = util.pconvert(subpath)
628 normsubpath = util.pconvert(subpath)
629
629
630 # XXX: Checking against the current working copy is wrong in
630 # XXX: Checking against the current working copy is wrong in
631 # the sense that it can reject things like
631 # the sense that it can reject things like
632 #
632 #
633 # $ hg cat -r 10 sub/x.txt
633 # $ hg cat -r 10 sub/x.txt
634 #
634 #
635 # if sub/ is no longer a subrepository in the working copy
635 # if sub/ is no longer a subrepository in the working copy
636 # parent revision.
636 # parent revision.
637 #
637 #
638 # However, it can of course also allow things that would have
638 # However, it can of course also allow things that would have
639 # been rejected before, such as the above cat command if sub/
639 # been rejected before, such as the above cat command if sub/
640 # is a subrepository now, but was a normal directory before.
640 # is a subrepository now, but was a normal directory before.
641 # The old path auditor would have rejected by mistake since it
641 # The old path auditor would have rejected by mistake since it
642 # panics when it sees sub/.hg/.
642 # panics when it sees sub/.hg/.
643 #
643 #
644 # All in all, checking against the working copy seems sensible
644 # All in all, checking against the working copy seems sensible
645 # since we want to prevent access to nested repositories on
645 # since we want to prevent access to nested repositories on
646 # the filesystem *now*.
646 # the filesystem *now*.
647 ctx = self[None]
647 ctx = self[None]
648 parts = util.splitpath(subpath)
648 parts = util.splitpath(subpath)
649 while parts:
649 while parts:
650 prefix = '/'.join(parts)
650 prefix = '/'.join(parts)
651 if prefix in ctx.substate:
651 if prefix in ctx.substate:
652 if prefix == normsubpath:
652 if prefix == normsubpath:
653 return True
653 return True
654 else:
654 else:
655 sub = ctx.sub(prefix)
655 sub = ctx.sub(prefix)
656 return sub.checknested(subpath[len(prefix) + 1:])
656 return sub.checknested(subpath[len(prefix) + 1:])
657 else:
657 else:
658 parts.pop()
658 parts.pop()
659 return False
659 return False
660
660
661 def peer(self):
661 def peer(self):
662 return localpeer(self) # not cached to avoid reference cycle
662 return localpeer(self) # not cached to avoid reference cycle
663
663
664 def unfiltered(self):
664 def unfiltered(self):
665 """Return unfiltered version of the repository
665 """Return unfiltered version of the repository
666
666
667 Intended to be overwritten by filtered repo."""
667 Intended to be overwritten by filtered repo."""
668 return self
668 return self
669
669
670 def filtered(self, name):
670 def filtered(self, name):
671 """Return a filtered version of a repository"""
671 """Return a filtered version of a repository"""
672 # Python <3.4 easily leaks types via __mro__. See
672 # Python <3.4 easily leaks types via __mro__. See
673 # https://bugs.python.org/issue17950. We cache dynamically
673 # https://bugs.python.org/issue17950. We cache dynamically
674 # created types so this method doesn't leak on every
674 # created types so this method doesn't leak on every
675 # invocation.
675 # invocation.
676
676
677 key = self.unfiltered().__class__
677 key = self.unfiltered().__class__
678 if key not in self._filteredrepotypes:
678 if key not in self._filteredrepotypes:
679 # Build a new type with the repoview mixin and the base
679 # Build a new type with the repoview mixin and the base
680 # class of this repo. Give it a name containing the
680 # class of this repo. Give it a name containing the
681 # filter name to aid debugging.
681 # filter name to aid debugging.
682 bases = (repoview.repoview, key)
682 bases = (repoview.repoview, key)
683 cls = type(r'%sfilteredrepo' % name, bases, {})
683 cls = type(r'%sfilteredrepo' % name, bases, {})
684 self._filteredrepotypes[key] = cls
684 self._filteredrepotypes[key] = cls
685
685
686 return self._filteredrepotypes[key](self, name)
686 return self._filteredrepotypes[key](self, name)
687
687
688 @repofilecache('bookmarks', 'bookmarks.current')
688 @repofilecache('bookmarks', 'bookmarks.current')
689 def _bookmarks(self):
689 def _bookmarks(self):
690 return bookmarks.bmstore(self)
690 return bookmarks.bmstore(self)
691
691
692 @property
692 @property
693 def _activebookmark(self):
693 def _activebookmark(self):
694 return self._bookmarks.active
694 return self._bookmarks.active
695
695
696 # _phaserevs and _phasesets depend on changelog. what we need is to
696 # _phaserevs and _phasesets depend on changelog. what we need is to
697 # call _phasecache.invalidate() if '00changelog.i' was changed, but it
697 # call _phasecache.invalidate() if '00changelog.i' was changed, but it
698 # can't be easily expressed in filecache mechanism.
698 # can't be easily expressed in filecache mechanism.
699 @storecache('phaseroots', '00changelog.i')
699 @storecache('phaseroots', '00changelog.i')
700 def _phasecache(self):
700 def _phasecache(self):
701 return phases.phasecache(self, self._phasedefaults)
701 return phases.phasecache(self, self._phasedefaults)
702
702
703 @storecache('obsstore')
703 @storecache('obsstore')
704 def obsstore(self):
704 def obsstore(self):
705 return obsolete.makestore(self.ui, self)
705 return obsolete.makestore(self.ui, self)
706
706
707 @storecache('00changelog.i')
707 @storecache('00changelog.i')
708 def changelog(self):
708 def changelog(self):
709 return changelog.changelog(self.svfs,
709 return changelog.changelog(self.svfs,
710 trypending=txnutil.mayhavepending(self.root))
710 trypending=txnutil.mayhavepending(self.root))
711
711
712 def _constructmanifest(self):
712 def _constructmanifest(self):
713 # This is a temporary function while we migrate from manifest to
713 # This is a temporary function while we migrate from manifest to
714 # manifestlog. It allows bundlerepo and unionrepo to intercept the
714 # manifestlog. It allows bundlerepo and unionrepo to intercept the
715 # manifest creation.
715 # manifest creation.
716 return manifest.manifestrevlog(self.svfs)
716 return manifest.manifestrevlog(self.svfs)
717
717
718 @storecache('00manifest.i')
718 @storecache('00manifest.i')
719 def manifestlog(self):
719 def manifestlog(self):
720 return manifest.manifestlog(self.svfs, self)
720 return manifest.manifestlog(self.svfs, self)
721
721
722 @repofilecache('dirstate')
722 @repofilecache('dirstate')
723 def dirstate(self):
723 def dirstate(self):
724 sparsematchfn = lambda: sparse.matcher(self)
724 sparsematchfn = lambda: sparse.matcher(self)
725
725
726 return dirstate.dirstate(self.vfs, self.ui, self.root,
726 return dirstate.dirstate(self.vfs, self.ui, self.root,
727 self._dirstatevalidate, sparsematchfn)
727 self._dirstatevalidate, sparsematchfn)
728
728
729 def _dirstatevalidate(self, node):
729 def _dirstatevalidate(self, node):
730 try:
730 try:
731 self.changelog.rev(node)
731 self.changelog.rev(node)
732 return node
732 return node
733 except error.LookupError:
733 except error.LookupError:
734 if not self._dirstatevalidatewarned:
734 if not self._dirstatevalidatewarned:
735 self._dirstatevalidatewarned = True
735 self._dirstatevalidatewarned = True
736 self.ui.warn(_("warning: ignoring unknown"
736 self.ui.warn(_("warning: ignoring unknown"
737 " working parent %s!\n") % short(node))
737 " working parent %s!\n") % short(node))
738 return nullid
738 return nullid
739
739
740 def __getitem__(self, changeid):
740 def __getitem__(self, changeid):
741 if changeid is None:
741 if changeid is None:
742 return context.workingctx(self)
742 return context.workingctx(self)
743 if isinstance(changeid, slice):
743 if isinstance(changeid, slice):
744 # wdirrev isn't contiguous so the slice shouldn't include it
744 # wdirrev isn't contiguous so the slice shouldn't include it
745 return [context.changectx(self, i)
745 return [context.changectx(self, i)
746 for i in xrange(*changeid.indices(len(self)))
746 for i in xrange(*changeid.indices(len(self)))
747 if i not in self.changelog.filteredrevs]
747 if i not in self.changelog.filteredrevs]
748 try:
748 try:
749 return context.changectx(self, changeid)
749 return context.changectx(self, changeid)
750 except error.WdirUnsupported:
750 except error.WdirUnsupported:
751 return context.workingctx(self)
751 return context.workingctx(self)
752
752
753 def __contains__(self, changeid):
753 def __contains__(self, changeid):
754 """True if the given changeid exists
754 """True if the given changeid exists
755
755
756 error.LookupError is raised if an ambiguous node specified.
756 error.LookupError is raised if an ambiguous node specified.
757 """
757 """
758 try:
758 try:
759 self[changeid]
759 self[changeid]
760 return True
760 return True
761 except error.RepoLookupError:
761 except error.RepoLookupError:
762 return False
762 return False
763
763
764 def __nonzero__(self):
764 def __nonzero__(self):
765 return True
765 return True
766
766
767 __bool__ = __nonzero__
767 __bool__ = __nonzero__
768
768
769 def __len__(self):
769 def __len__(self):
770 return len(self.changelog)
770 return len(self.changelog)
771
771
772 def __iter__(self):
772 def __iter__(self):
773 return iter(self.changelog)
773 return iter(self.changelog)
774
774
775 def revs(self, expr, *args):
775 def revs(self, expr, *args):
776 '''Find revisions matching a revset.
776 '''Find revisions matching a revset.
777
777
778 The revset is specified as a string ``expr`` that may contain
778 The revset is specified as a string ``expr`` that may contain
779 %-formatting to escape certain types. See ``revsetlang.formatspec``.
779 %-formatting to escape certain types. See ``revsetlang.formatspec``.
780
780
781 Revset aliases from the configuration are not expanded. To expand
781 Revset aliases from the configuration are not expanded. To expand
782 user aliases, consider calling ``scmutil.revrange()`` or
782 user aliases, consider calling ``scmutil.revrange()`` or
783 ``repo.anyrevs([expr], user=True)``.
783 ``repo.anyrevs([expr], user=True)``.
784
784
785 Returns a revset.abstractsmartset, which is a list-like interface
785 Returns a revset.abstractsmartset, which is a list-like interface
786 that contains integer revisions.
786 that contains integer revisions.
787 '''
787 '''
788 expr = revsetlang.formatspec(expr, *args)
788 expr = revsetlang.formatspec(expr, *args)
789 m = revset.match(None, expr)
789 m = revset.match(None, expr)
790 return m(self)
790 return m(self)
791
791
792 def set(self, expr, *args):
792 def set(self, expr, *args):
793 '''Find revisions matching a revset and emit changectx instances.
793 '''Find revisions matching a revset and emit changectx instances.
794
794
795 This is a convenience wrapper around ``revs()`` that iterates the
795 This is a convenience wrapper around ``revs()`` that iterates the
796 result and is a generator of changectx instances.
796 result and is a generator of changectx instances.
797
797
798 Revset aliases from the configuration are not expanded. To expand
798 Revset aliases from the configuration are not expanded. To expand
799 user aliases, consider calling ``scmutil.revrange()``.
799 user aliases, consider calling ``scmutil.revrange()``.
800 '''
800 '''
801 for r in self.revs(expr, *args):
801 for r in self.revs(expr, *args):
802 yield self[r]
802 yield self[r]
803
803
804 def anyrevs(self, specs, user=False, localalias=None):
804 def anyrevs(self, specs, user=False, localalias=None):
805 '''Find revisions matching one of the given revsets.
805 '''Find revisions matching one of the given revsets.
806
806
807 Revset aliases from the configuration are not expanded by default. To
807 Revset aliases from the configuration are not expanded by default. To
808 expand user aliases, specify ``user=True``. To provide some local
808 expand user aliases, specify ``user=True``. To provide some local
809 definitions overriding user aliases, set ``localalias`` to
809 definitions overriding user aliases, set ``localalias`` to
810 ``{name: definitionstring}``.
810 ``{name: definitionstring}``.
811 '''
811 '''
812 if user:
812 if user:
813 m = revset.matchany(self.ui, specs, repo=self,
813 m = revset.matchany(self.ui, specs, repo=self,
814 localalias=localalias)
814 localalias=localalias)
815 else:
815 else:
816 m = revset.matchany(None, specs, localalias=localalias)
816 m = revset.matchany(None, specs, localalias=localalias)
817 return m(self)
817 return m(self)
818
818
819 def url(self):
819 def url(self):
820 return 'file:' + self.root
820 return 'file:' + self.root
821
821
822 def hook(self, name, throw=False, **args):
822 def hook(self, name, throw=False, **args):
823 """Call a hook, passing this repo instance.
823 """Call a hook, passing this repo instance.
824
824
825 This a convenience method to aid invoking hooks. Extensions likely
825 This a convenience method to aid invoking hooks. Extensions likely
826 won't call this unless they have registered a custom hook or are
826 won't call this unless they have registered a custom hook or are
827 replacing code that is expected to call a hook.
827 replacing code that is expected to call a hook.
828 """
828 """
829 return hook.hook(self.ui, self, name, throw, **args)
829 return hook.hook(self.ui, self, name, throw, **args)
830
830
831 @filteredpropertycache
831 @filteredpropertycache
832 def _tagscache(self):
832 def _tagscache(self):
833 '''Returns a tagscache object that contains various tags related
833 '''Returns a tagscache object that contains various tags related
834 caches.'''
834 caches.'''
835
835
836 # This simplifies its cache management by having one decorated
836 # This simplifies its cache management by having one decorated
837 # function (this one) and the rest simply fetch things from it.
837 # function (this one) and the rest simply fetch things from it.
838 class tagscache(object):
838 class tagscache(object):
839 def __init__(self):
839 def __init__(self):
840 # These two define the set of tags for this repository. tags
840 # These two define the set of tags for this repository. tags
841 # maps tag name to node; tagtypes maps tag name to 'global' or
841 # maps tag name to node; tagtypes maps tag name to 'global' or
842 # 'local'. (Global tags are defined by .hgtags across all
842 # 'local'. (Global tags are defined by .hgtags across all
843 # heads, and local tags are defined in .hg/localtags.)
843 # heads, and local tags are defined in .hg/localtags.)
844 # They constitute the in-memory cache of tags.
844 # They constitute the in-memory cache of tags.
845 self.tags = self.tagtypes = None
845 self.tags = self.tagtypes = None
846
846
847 self.nodetagscache = self.tagslist = None
847 self.nodetagscache = self.tagslist = None
848
848
849 cache = tagscache()
849 cache = tagscache()
850 cache.tags, cache.tagtypes = self._findtags()
850 cache.tags, cache.tagtypes = self._findtags()
851
851
852 return cache
852 return cache
853
853
854 def tags(self):
854 def tags(self):
855 '''return a mapping of tag to node'''
855 '''return a mapping of tag to node'''
856 t = {}
856 t = {}
857 if self.changelog.filteredrevs:
857 if self.changelog.filteredrevs:
858 tags, tt = self._findtags()
858 tags, tt = self._findtags()
859 else:
859 else:
860 tags = self._tagscache.tags
860 tags = self._tagscache.tags
861 for k, v in tags.iteritems():
861 for k, v in tags.iteritems():
862 try:
862 try:
863 # ignore tags to unknown nodes
863 # ignore tags to unknown nodes
864 self.changelog.rev(v)
864 self.changelog.rev(v)
865 t[k] = v
865 t[k] = v
866 except (error.LookupError, ValueError):
866 except (error.LookupError, ValueError):
867 pass
867 pass
868 return t
868 return t
869
869
870 def _findtags(self):
870 def _findtags(self):
871 '''Do the hard work of finding tags. Return a pair of dicts
871 '''Do the hard work of finding tags. Return a pair of dicts
872 (tags, tagtypes) where tags maps tag name to node, and tagtypes
872 (tags, tagtypes) where tags maps tag name to node, and tagtypes
873 maps tag name to a string like \'global\' or \'local\'.
873 maps tag name to a string like \'global\' or \'local\'.
874 Subclasses or extensions are free to add their own tags, but
874 Subclasses or extensions are free to add their own tags, but
875 should be aware that the returned dicts will be retained for the
875 should be aware that the returned dicts will be retained for the
876 duration of the localrepo object.'''
876 duration of the localrepo object.'''
877
877
878 # XXX what tagtype should subclasses/extensions use? Currently
878 # XXX what tagtype should subclasses/extensions use? Currently
879 # mq and bookmarks add tags, but do not set the tagtype at all.
879 # mq and bookmarks add tags, but do not set the tagtype at all.
880 # Should each extension invent its own tag type? Should there
880 # Should each extension invent its own tag type? Should there
881 # be one tagtype for all such "virtual" tags? Or is the status
881 # be one tagtype for all such "virtual" tags? Or is the status
882 # quo fine?
882 # quo fine?
883
883
884
884
885 # map tag name to (node, hist)
885 # map tag name to (node, hist)
886 alltags = tagsmod.findglobaltags(self.ui, self)
886 alltags = tagsmod.findglobaltags(self.ui, self)
887 # map tag name to tag type
887 # map tag name to tag type
888 tagtypes = dict((tag, 'global') for tag in alltags)
888 tagtypes = dict((tag, 'global') for tag in alltags)
889
889
890 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
890 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
891
891
892 # Build the return dicts. Have to re-encode tag names because
892 # Build the return dicts. Have to re-encode tag names because
893 # the tags module always uses UTF-8 (in order not to lose info
893 # the tags module always uses UTF-8 (in order not to lose info
894 # writing to the cache), but the rest of Mercurial wants them in
894 # writing to the cache), but the rest of Mercurial wants them in
895 # local encoding.
895 # local encoding.
896 tags = {}
896 tags = {}
897 for (name, (node, hist)) in alltags.iteritems():
897 for (name, (node, hist)) in alltags.iteritems():
898 if node != nullid:
898 if node != nullid:
899 tags[encoding.tolocal(name)] = node
899 tags[encoding.tolocal(name)] = node
900 tags['tip'] = self.changelog.tip()
900 tags['tip'] = self.changelog.tip()
901 tagtypes = dict([(encoding.tolocal(name), value)
901 tagtypes = dict([(encoding.tolocal(name), value)
902 for (name, value) in tagtypes.iteritems()])
902 for (name, value) in tagtypes.iteritems()])
903 return (tags, tagtypes)
903 return (tags, tagtypes)
904
904
905 def tagtype(self, tagname):
905 def tagtype(self, tagname):
906 '''
906 '''
907 return the type of the given tag. result can be:
907 return the type of the given tag. result can be:
908
908
909 'local' : a local tag
909 'local' : a local tag
910 'global' : a global tag
910 'global' : a global tag
911 None : tag does not exist
911 None : tag does not exist
912 '''
912 '''
913
913
914 return self._tagscache.tagtypes.get(tagname)
914 return self._tagscache.tagtypes.get(tagname)
915
915
916 def tagslist(self):
916 def tagslist(self):
917 '''return a list of tags ordered by revision'''
917 '''return a list of tags ordered by revision'''
918 if not self._tagscache.tagslist:
918 if not self._tagscache.tagslist:
919 l = []
919 l = []
920 for t, n in self.tags().iteritems():
920 for t, n in self.tags().iteritems():
921 l.append((self.changelog.rev(n), t, n))
921 l.append((self.changelog.rev(n), t, n))
922 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
922 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
923
923
924 return self._tagscache.tagslist
924 return self._tagscache.tagslist
925
925
926 def nodetags(self, node):
926 def nodetags(self, node):
927 '''return the tags associated with a node'''
927 '''return the tags associated with a node'''
928 if not self._tagscache.nodetagscache:
928 if not self._tagscache.nodetagscache:
929 nodetagscache = {}
929 nodetagscache = {}
930 for t, n in self._tagscache.tags.iteritems():
930 for t, n in self._tagscache.tags.iteritems():
931 nodetagscache.setdefault(n, []).append(t)
931 nodetagscache.setdefault(n, []).append(t)
932 for tags in nodetagscache.itervalues():
932 for tags in nodetagscache.itervalues():
933 tags.sort()
933 tags.sort()
934 self._tagscache.nodetagscache = nodetagscache
934 self._tagscache.nodetagscache = nodetagscache
935 return self._tagscache.nodetagscache.get(node, [])
935 return self._tagscache.nodetagscache.get(node, [])
936
936
937 def nodebookmarks(self, node):
937 def nodebookmarks(self, node):
938 """return the list of bookmarks pointing to the specified node"""
938 """return the list of bookmarks pointing to the specified node"""
939 marks = []
939 marks = []
940 for bookmark, n in self._bookmarks.iteritems():
940 for bookmark, n in self._bookmarks.iteritems():
941 if n == node:
941 if n == node:
942 marks.append(bookmark)
942 marks.append(bookmark)
943 return sorted(marks)
943 return sorted(marks)
944
944
945 def branchmap(self):
945 def branchmap(self):
946 '''returns a dictionary {branch: [branchheads]} with branchheads
946 '''returns a dictionary {branch: [branchheads]} with branchheads
947 ordered by increasing revision number'''
947 ordered by increasing revision number'''
948 branchmap.updatecache(self)
948 branchmap.updatecache(self)
949 return self._branchcaches[self.filtername]
949 return self._branchcaches[self.filtername]
950
950
951 @unfilteredmethod
951 @unfilteredmethod
952 def revbranchcache(self):
952 def revbranchcache(self):
953 if not self._revbranchcache:
953 if not self._revbranchcache:
954 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
954 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
955 return self._revbranchcache
955 return self._revbranchcache
956
956
957 def branchtip(self, branch, ignoremissing=False):
957 def branchtip(self, branch, ignoremissing=False):
958 '''return the tip node for a given branch
958 '''return the tip node for a given branch
959
959
960 If ignoremissing is True, then this method will not raise an error.
960 If ignoremissing is True, then this method will not raise an error.
961 This is helpful for callers that only expect None for a missing branch
961 This is helpful for callers that only expect None for a missing branch
962 (e.g. namespace).
962 (e.g. namespace).
963
963
964 '''
964 '''
965 try:
965 try:
966 return self.branchmap().branchtip(branch)
966 return self.branchmap().branchtip(branch)
967 except KeyError:
967 except KeyError:
968 if not ignoremissing:
968 if not ignoremissing:
969 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
969 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
970 else:
970 else:
971 pass
971 pass
972
972
973 def lookup(self, key):
973 def lookup(self, key):
974 return self[key].node()
974 return self[key].node()
975
975
976 def lookupbranch(self, key, remote=None):
976 def lookupbranch(self, key, remote=None):
977 repo = remote or self
977 repo = remote or self
978 if key in repo.branchmap():
978 if key in repo.branchmap():
979 return key
979 return key
980
980
981 repo = (remote and remote.local()) and remote or self
981 repo = (remote and remote.local()) and remote or self
982 return repo[key].branch()
982 return repo[key].branch()
983
983
984 def known(self, nodes):
984 def known(self, nodes):
985 cl = self.changelog
985 cl = self.changelog
986 nm = cl.nodemap
986 nm = cl.nodemap
987 filtered = cl.filteredrevs
987 filtered = cl.filteredrevs
988 result = []
988 result = []
989 for n in nodes:
989 for n in nodes:
990 r = nm.get(n)
990 r = nm.get(n)
991 resp = not (r is None or r in filtered)
991 resp = not (r is None or r in filtered)
992 result.append(resp)
992 result.append(resp)
993 return result
993 return result
994
994
995 def local(self):
995 def local(self):
996 return self
996 return self
997
997
998 def publishing(self):
998 def publishing(self):
999 # it's safe (and desirable) to trust the publish flag unconditionally
999 # it's safe (and desirable) to trust the publish flag unconditionally
1000 # so that we don't finalize changes shared between users via ssh or nfs
1000 # so that we don't finalize changes shared between users via ssh or nfs
1001 return self.ui.configbool('phases', 'publish', untrusted=True)
1001 return self.ui.configbool('phases', 'publish', untrusted=True)
1002
1002
1003 def cancopy(self):
1003 def cancopy(self):
1004 # so statichttprepo's override of local() works
1004 # so statichttprepo's override of local() works
1005 if not self.local():
1005 if not self.local():
1006 return False
1006 return False
1007 if not self.publishing():
1007 if not self.publishing():
1008 return True
1008 return True
1009 # if publishing we can't copy if there is filtered content
1009 # if publishing we can't copy if there is filtered content
1010 return not self.filtered('visible').changelog.filteredrevs
1010 return not self.filtered('visible').changelog.filteredrevs
1011
1011
1012 def shared(self):
1012 def shared(self):
1013 '''the type of shared repository (None if not shared)'''
1013 '''the type of shared repository (None if not shared)'''
1014 if self.sharedpath != self.path:
1014 if self.sharedpath != self.path:
1015 return 'store'
1015 return 'store'
1016 return None
1016 return None
1017
1017
1018 def wjoin(self, f, *insidef):
1018 def wjoin(self, f, *insidef):
1019 return self.vfs.reljoin(self.root, f, *insidef)
1019 return self.vfs.reljoin(self.root, f, *insidef)
1020
1020
1021 def file(self, f):
1021 def file(self, f):
1022 if f[0] == '/':
1022 if f[0] == '/':
1023 f = f[1:]
1023 f = f[1:]
1024 return filelog.filelog(self.svfs, f)
1024 return filelog.filelog(self.svfs, f)
1025
1025
1026 def changectx(self, changeid):
1026 def changectx(self, changeid):
1027 return self[changeid]
1027 return self[changeid]
1028
1028
1029 def setparents(self, p1, p2=nullid):
1029 def setparents(self, p1, p2=nullid):
1030 with self.dirstate.parentchange():
1030 with self.dirstate.parentchange():
1031 copies = self.dirstate.setparents(p1, p2)
1031 copies = self.dirstate.setparents(p1, p2)
1032 pctx = self[p1]
1032 pctx = self[p1]
1033 if copies:
1033 if copies:
1034 # Adjust copy records, the dirstate cannot do it, it
1034 # Adjust copy records, the dirstate cannot do it, it
1035 # requires access to parents manifests. Preserve them
1035 # requires access to parents manifests. Preserve them
1036 # only for entries added to first parent.
1036 # only for entries added to first parent.
1037 for f in copies:
1037 for f in copies:
1038 if f not in pctx and copies[f] in pctx:
1038 if f not in pctx and copies[f] in pctx:
1039 self.dirstate.copy(copies[f], f)
1039 self.dirstate.copy(copies[f], f)
1040 if p2 == nullid:
1040 if p2 == nullid:
1041 for f, s in sorted(self.dirstate.copies().items()):
1041 for f, s in sorted(self.dirstate.copies().items()):
1042 if f not in pctx and s not in pctx:
1042 if f not in pctx and s not in pctx:
1043 self.dirstate.copy(None, f)
1043 self.dirstate.copy(None, f)
1044
1044
1045 def filectx(self, path, changeid=None, fileid=None):
1045 def filectx(self, path, changeid=None, fileid=None):
1046 """changeid can be a changeset revision, node, or tag.
1046 """changeid can be a changeset revision, node, or tag.
1047 fileid can be a file revision or node."""
1047 fileid can be a file revision or node."""
1048 return context.filectx(self, path, changeid, fileid)
1048 return context.filectx(self, path, changeid, fileid)
1049
1049
1050 def getcwd(self):
1050 def getcwd(self):
1051 return self.dirstate.getcwd()
1051 return self.dirstate.getcwd()
1052
1052
1053 def pathto(self, f, cwd=None):
1053 def pathto(self, f, cwd=None):
1054 return self.dirstate.pathto(f, cwd)
1054 return self.dirstate.pathto(f, cwd)
1055
1055
1056 def _loadfilter(self, filter):
1056 def _loadfilter(self, filter):
1057 if filter not in self.filterpats:
1057 if filter not in self.filterpats:
1058 l = []
1058 l = []
1059 for pat, cmd in self.ui.configitems(filter):
1059 for pat, cmd in self.ui.configitems(filter):
1060 if cmd == '!':
1060 if cmd == '!':
1061 continue
1061 continue
1062 mf = matchmod.match(self.root, '', [pat])
1062 mf = matchmod.match(self.root, '', [pat])
1063 fn = None
1063 fn = None
1064 params = cmd
1064 params = cmd
1065 for name, filterfn in self._datafilters.iteritems():
1065 for name, filterfn in self._datafilters.iteritems():
1066 if cmd.startswith(name):
1066 if cmd.startswith(name):
1067 fn = filterfn
1067 fn = filterfn
1068 params = cmd[len(name):].lstrip()
1068 params = cmd[len(name):].lstrip()
1069 break
1069 break
1070 if not fn:
1070 if not fn:
1071 fn = lambda s, c, **kwargs: util.filter(s, c)
1071 fn = lambda s, c, **kwargs: util.filter(s, c)
1072 # Wrap old filters not supporting keyword arguments
1072 # Wrap old filters not supporting keyword arguments
1073 if not inspect.getargspec(fn)[2]:
1073 if not inspect.getargspec(fn)[2]:
1074 oldfn = fn
1074 oldfn = fn
1075 fn = lambda s, c, **kwargs: oldfn(s, c)
1075 fn = lambda s, c, **kwargs: oldfn(s, c)
1076 l.append((mf, fn, params))
1076 l.append((mf, fn, params))
1077 self.filterpats[filter] = l
1077 self.filterpats[filter] = l
1078 return self.filterpats[filter]
1078 return self.filterpats[filter]
1079
1079
1080 def _filter(self, filterpats, filename, data):
1080 def _filter(self, filterpats, filename, data):
1081 for mf, fn, cmd in filterpats:
1081 for mf, fn, cmd in filterpats:
1082 if mf(filename):
1082 if mf(filename):
1083 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
1083 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
1084 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
1084 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
1085 break
1085 break
1086
1086
1087 return data
1087 return data
1088
1088
1089 @unfilteredpropertycache
1089 @unfilteredpropertycache
1090 def _encodefilterpats(self):
1090 def _encodefilterpats(self):
1091 return self._loadfilter('encode')
1091 return self._loadfilter('encode')
1092
1092
1093 @unfilteredpropertycache
1093 @unfilteredpropertycache
1094 def _decodefilterpats(self):
1094 def _decodefilterpats(self):
1095 return self._loadfilter('decode')
1095 return self._loadfilter('decode')
1096
1096
1097 def adddatafilter(self, name, filter):
1097 def adddatafilter(self, name, filter):
1098 self._datafilters[name] = filter
1098 self._datafilters[name] = filter
1099
1099
1100 def wread(self, filename):
1100 def wread(self, filename):
1101 if self.wvfs.islink(filename):
1101 if self.wvfs.islink(filename):
1102 data = self.wvfs.readlink(filename)
1102 data = self.wvfs.readlink(filename)
1103 else:
1103 else:
1104 data = self.wvfs.read(filename)
1104 data = self.wvfs.read(filename)
1105 return self._filter(self._encodefilterpats, filename, data)
1105 return self._filter(self._encodefilterpats, filename, data)
1106
1106
1107 def wwrite(self, filename, data, flags, backgroundclose=False):
1107 def wwrite(self, filename, data, flags, backgroundclose=False):
1108 """write ``data`` into ``filename`` in the working directory
1108 """write ``data`` into ``filename`` in the working directory
1109
1109
1110 This returns length of written (maybe decoded) data.
1110 This returns length of written (maybe decoded) data.
1111 """
1111 """
1112 data = self._filter(self._decodefilterpats, filename, data)
1112 data = self._filter(self._decodefilterpats, filename, data)
1113 if 'l' in flags:
1113 if 'l' in flags:
1114 self.wvfs.symlink(data, filename)
1114 self.wvfs.symlink(data, filename)
1115 else:
1115 else:
1116 self.wvfs.write(filename, data, backgroundclose=backgroundclose)
1116 self.wvfs.write(filename, data, backgroundclose=backgroundclose)
1117 if 'x' in flags:
1117 if 'x' in flags:
1118 self.wvfs.setflags(filename, False, True)
1118 self.wvfs.setflags(filename, False, True)
1119 return len(data)
1119 return len(data)
1120
1120
1121 def wwritedata(self, filename, data):
1121 def wwritedata(self, filename, data):
1122 return self._filter(self._decodefilterpats, filename, data)
1122 return self._filter(self._decodefilterpats, filename, data)
1123
1123
1124 def currenttransaction(self):
1124 def currenttransaction(self):
1125 """return the current transaction or None if non exists"""
1125 """return the current transaction or None if non exists"""
1126 if self._transref:
1126 if self._transref:
1127 tr = self._transref()
1127 tr = self._transref()
1128 else:
1128 else:
1129 tr = None
1129 tr = None
1130
1130
1131 if tr and tr.running():
1131 if tr and tr.running():
1132 return tr
1132 return tr
1133 return None
1133 return None
1134
1134
1135 def transaction(self, desc, report=None):
1135 def transaction(self, desc, report=None):
1136 if (self.ui.configbool('devel', 'all-warnings')
1136 if (self.ui.configbool('devel', 'all-warnings')
1137 or self.ui.configbool('devel', 'check-locks')):
1137 or self.ui.configbool('devel', 'check-locks')):
1138 if self._currentlock(self._lockref) is None:
1138 if self._currentlock(self._lockref) is None:
1139 raise error.ProgrammingError('transaction requires locking')
1139 raise error.ProgrammingError('transaction requires locking')
1140 tr = self.currenttransaction()
1140 tr = self.currenttransaction()
1141 if tr is not None:
1141 if tr is not None:
1142 scmutil.registersummarycallback(self, tr, desc)
1142 scmutil.registersummarycallback(self, tr, desc)
1143 return tr.nest()
1143 return tr.nest()
1144
1144
1145 # abort here if the journal already exists
1145 # abort here if the journal already exists
1146 if self.svfs.exists("journal"):
1146 if self.svfs.exists("journal"):
1147 raise error.RepoError(
1147 raise error.RepoError(
1148 _("abandoned transaction found"),
1148 _("abandoned transaction found"),
1149 hint=_("run 'hg recover' to clean up transaction"))
1149 hint=_("run 'hg recover' to clean up transaction"))
1150
1150
1151 idbase = "%.40f#%f" % (random.random(), time.time())
1151 idbase = "%.40f#%f" % (random.random(), time.time())
1152 ha = hex(hashlib.sha1(idbase).digest())
1152 ha = hex(hashlib.sha1(idbase).digest())
1153 txnid = 'TXN:' + ha
1153 txnid = 'TXN:' + ha
1154 self.hook('pretxnopen', throw=True, txnname=desc, txnid=txnid)
1154 self.hook('pretxnopen', throw=True, txnname=desc, txnid=txnid)
1155
1155
1156 self._writejournal(desc)
1156 self._writejournal(desc)
1157 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
1157 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
1158 if report:
1158 if report:
1159 rp = report
1159 rp = report
1160 else:
1160 else:
1161 rp = self.ui.warn
1161 rp = self.ui.warn
1162 vfsmap = {'plain': self.vfs} # root of .hg/
1162 vfsmap = {'plain': self.vfs} # root of .hg/
1163 # we must avoid cyclic reference between repo and transaction.
1163 # we must avoid cyclic reference between repo and transaction.
1164 reporef = weakref.ref(self)
1164 reporef = weakref.ref(self)
1165 # Code to track tag movement
1165 # Code to track tag movement
1166 #
1166 #
1167 # Since tags are all handled as file content, it is actually quite hard
1167 # Since tags are all handled as file content, it is actually quite hard
1168 # to track these movement from a code perspective. So we fallback to a
1168 # to track these movement from a code perspective. So we fallback to a
1169 # tracking at the repository level. One could envision to track changes
1169 # tracking at the repository level. One could envision to track changes
1170 # to the '.hgtags' file through changegroup apply but that fails to
1170 # to the '.hgtags' file through changegroup apply but that fails to
1171 # cope with case where transaction expose new heads without changegroup
1171 # cope with case where transaction expose new heads without changegroup
1172 # being involved (eg: phase movement).
1172 # being involved (eg: phase movement).
1173 #
1173 #
1174 # For now, We gate the feature behind a flag since this likely comes
1174 # For now, We gate the feature behind a flag since this likely comes
1175 # with performance impacts. The current code run more often than needed
1175 # with performance impacts. The current code run more often than needed
1176 # and do not use caches as much as it could. The current focus is on
1176 # and do not use caches as much as it could. The current focus is on
1177 # the behavior of the feature so we disable it by default. The flag
1177 # the behavior of the feature so we disable it by default. The flag
1178 # will be removed when we are happy with the performance impact.
1178 # will be removed when we are happy with the performance impact.
1179 #
1179 #
1180 # Once this feature is no longer experimental move the following
1180 # Once this feature is no longer experimental move the following
1181 # documentation to the appropriate help section:
1181 # documentation to the appropriate help section:
1182 #
1182 #
1183 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
1183 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
1184 # tags (new or changed or deleted tags). In addition the details of
1184 # tags (new or changed or deleted tags). In addition the details of
1185 # these changes are made available in a file at:
1185 # these changes are made available in a file at:
1186 # ``REPOROOT/.hg/changes/tags.changes``.
1186 # ``REPOROOT/.hg/changes/tags.changes``.
1187 # Make sure you check for HG_TAG_MOVED before reading that file as it
1187 # Make sure you check for HG_TAG_MOVED before reading that file as it
1188 # might exist from a previous transaction even if no tag were touched
1188 # might exist from a previous transaction even if no tag were touched
1189 # in this one. Changes are recorded in a line base format::
1189 # in this one. Changes are recorded in a line base format::
1190 #
1190 #
1191 # <action> <hex-node> <tag-name>\n
1191 # <action> <hex-node> <tag-name>\n
1192 #
1192 #
1193 # Actions are defined as follow:
1193 # Actions are defined as follow:
1194 # "-R": tag is removed,
1194 # "-R": tag is removed,
1195 # "+A": tag is added,
1195 # "+A": tag is added,
1196 # "-M": tag is moved (old value),
1196 # "-M": tag is moved (old value),
1197 # "+M": tag is moved (new value),
1197 # "+M": tag is moved (new value),
1198 tracktags = lambda x: None
1198 tracktags = lambda x: None
1199 # experimental config: experimental.hook-track-tags
1199 # experimental config: experimental.hook-track-tags
1200 shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags')
1200 shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags')
1201 if desc != 'strip' and shouldtracktags:
1201 if desc != 'strip' and shouldtracktags:
1202 oldheads = self.changelog.headrevs()
1202 oldheads = self.changelog.headrevs()
1203 def tracktags(tr2):
1203 def tracktags(tr2):
1204 repo = reporef()
1204 repo = reporef()
1205 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
1205 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
1206 newheads = repo.changelog.headrevs()
1206 newheads = repo.changelog.headrevs()
1207 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
1207 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
1208 # notes: we compare lists here.
1208 # notes: we compare lists here.
1209 # As we do it only once buiding set would not be cheaper
1209 # As we do it only once buiding set would not be cheaper
1210 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
1210 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
1211 if changes:
1211 if changes:
1212 tr2.hookargs['tag_moved'] = '1'
1212 tr2.hookargs['tag_moved'] = '1'
1213 with repo.vfs('changes/tags.changes', 'w',
1213 with repo.vfs('changes/tags.changes', 'w',
1214 atomictemp=True) as changesfile:
1214 atomictemp=True) as changesfile:
1215 # note: we do not register the file to the transaction
1215 # note: we do not register the file to the transaction
1216 # because we needs it to still exist on the transaction
1216 # because we needs it to still exist on the transaction
1217 # is close (for txnclose hooks)
1217 # is close (for txnclose hooks)
1218 tagsmod.writediff(changesfile, changes)
1218 tagsmod.writediff(changesfile, changes)
1219 def validate(tr2):
1219 def validate(tr2):
1220 """will run pre-closing hooks"""
1220 """will run pre-closing hooks"""
1221 # XXX the transaction API is a bit lacking here so we take a hacky
1221 # XXX the transaction API is a bit lacking here so we take a hacky
1222 # path for now
1222 # path for now
1223 #
1223 #
1224 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
1224 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
1225 # dict is copied before these run. In addition we needs the data
1225 # dict is copied before these run. In addition we needs the data
1226 # available to in memory hooks too.
1226 # available to in memory hooks too.
1227 #
1227 #
1228 # Moreover, we also need to make sure this runs before txnclose
1228 # Moreover, we also need to make sure this runs before txnclose
1229 # hooks and there is no "pending" mechanism that would execute
1229 # hooks and there is no "pending" mechanism that would execute
1230 # logic only if hooks are about to run.
1230 # logic only if hooks are about to run.
1231 #
1231 #
1232 # Fixing this limitation of the transaction is also needed to track
1232 # Fixing this limitation of the transaction is also needed to track
1233 # other families of changes (bookmarks, phases, obsolescence).
1233 # other families of changes (bookmarks, phases, obsolescence).
1234 #
1234 #
1235 # This will have to be fixed before we remove the experimental
1235 # This will have to be fixed before we remove the experimental
1236 # gating.
1236 # gating.
1237 tracktags(tr2)
1237 tracktags(tr2)
1238 reporef().hook('pretxnclose', throw=True,
1238 reporef().hook('pretxnclose', throw=True,
1239 txnname=desc, **pycompat.strkwargs(tr.hookargs))
1239 txnname=desc, **pycompat.strkwargs(tr.hookargs))
1240 def releasefn(tr, success):
1240 def releasefn(tr, success):
1241 repo = reporef()
1241 repo = reporef()
1242 if success:
1242 if success:
1243 # this should be explicitly invoked here, because
1243 # this should be explicitly invoked here, because
1244 # in-memory changes aren't written out at closing
1244 # in-memory changes aren't written out at closing
1245 # transaction, if tr.addfilegenerator (via
1245 # transaction, if tr.addfilegenerator (via
1246 # dirstate.write or so) isn't invoked while
1246 # dirstate.write or so) isn't invoked while
1247 # transaction running
1247 # transaction running
1248 repo.dirstate.write(None)
1248 repo.dirstate.write(None)
1249 else:
1249 else:
1250 # discard all changes (including ones already written
1250 # discard all changes (including ones already written
1251 # out) in this transaction
1251 # out) in this transaction
1252 repo.dirstate.restorebackup(None, 'journal.dirstate')
1252 repo.dirstate.restorebackup(None, 'journal.dirstate')
1253
1253
1254 repo.invalidate(clearfilecache=True)
1254 repo.invalidate(clearfilecache=True)
1255
1255
1256 tr = transaction.transaction(rp, self.svfs, vfsmap,
1256 tr = transaction.transaction(rp, self.svfs, vfsmap,
1257 "journal",
1257 "journal",
1258 "undo",
1258 "undo",
1259 aftertrans(renames),
1259 aftertrans(renames),
1260 self.store.createmode,
1260 self.store.createmode,
1261 validator=validate,
1261 validator=validate,
1262 releasefn=releasefn,
1262 releasefn=releasefn,
1263 checkambigfiles=_cachedfiles)
1263 checkambigfiles=_cachedfiles)
1264 tr.changes['revs'] = set()
1264 tr.changes['revs'] = set()
1265 tr.changes['obsmarkers'] = set()
1265 tr.changes['obsmarkers'] = set()
1266 tr.changes['phases'] = {}
1266 tr.changes['phases'] = {}
1267 tr.changes['bookmarks'] = {}
1267 tr.changes['bookmarks'] = {}
1268
1268
1269 tr.hookargs['txnid'] = txnid
1269 tr.hookargs['txnid'] = txnid
1270 # note: writing the fncache only during finalize mean that the file is
1270 # note: writing the fncache only during finalize mean that the file is
1271 # outdated when running hooks. As fncache is used for streaming clone,
1271 # outdated when running hooks. As fncache is used for streaming clone,
1272 # this is not expected to break anything that happen during the hooks.
1272 # this is not expected to break anything that happen during the hooks.
1273 tr.addfinalize('flush-fncache', self.store.write)
1273 tr.addfinalize('flush-fncache', self.store.write)
1274 def txnclosehook(tr2):
1274 def txnclosehook(tr2):
1275 """To be run if transaction is successful, will schedule a hook run
1275 """To be run if transaction is successful, will schedule a hook run
1276 """
1276 """
1277 # Don't reference tr2 in hook() so we don't hold a reference.
1277 # Don't reference tr2 in hook() so we don't hold a reference.
1278 # This reduces memory consumption when there are multiple
1278 # This reduces memory consumption when there are multiple
1279 # transactions per lock. This can likely go away if issue5045
1279 # transactions per lock. This can likely go away if issue5045
1280 # fixes the function accumulation.
1280 # fixes the function accumulation.
1281 hookargs = tr2.hookargs
1281 hookargs = tr2.hookargs
1282
1282
1283 def hook():
1283 def hookfunc():
1284 reporef().hook('txnclose', throw=False, txnname=desc,
1284 repo = reporef()
1285 **pycompat.strkwargs(hookargs))
1285 if hook.hashook(repo.ui, 'txnclose-bookmark'):
1286 reporef()._afterlock(hook)
1286 bmchanges = sorted(tr.changes['bookmarks'].items())
1287 for name, (old, new) in bmchanges:
1288 args = tr.hookargs.copy()
1289 args.update(bookmarks.preparehookargs(name, old, new))
1290 repo.hook('txnclose-bookmark', throw=False,
1291 txnname=desc, **pycompat.strkwargs(args))
1292
1293 repo.hook('txnclose', throw=False, txnname=desc,
1294 **pycompat.strkwargs(hookargs))
1295 reporef()._afterlock(hookfunc)
1287 tr.addfinalize('txnclose-hook', txnclosehook)
1296 tr.addfinalize('txnclose-hook', txnclosehook)
1288 tr.addpostclose('warms-cache', self._buildcacheupdater(tr))
1297 tr.addpostclose('warms-cache', self._buildcacheupdater(tr))
1289 def txnaborthook(tr2):
1298 def txnaborthook(tr2):
1290 """To be run if transaction is aborted
1299 """To be run if transaction is aborted
1291 """
1300 """
1292 reporef().hook('txnabort', throw=False, txnname=desc,
1301 reporef().hook('txnabort', throw=False, txnname=desc,
1293 **tr2.hookargs)
1302 **tr2.hookargs)
1294 tr.addabort('txnabort-hook', txnaborthook)
1303 tr.addabort('txnabort-hook', txnaborthook)
1295 # avoid eager cache invalidation. in-memory data should be identical
1304 # avoid eager cache invalidation. in-memory data should be identical
1296 # to stored data if transaction has no error.
1305 # to stored data if transaction has no error.
1297 tr.addpostclose('refresh-filecachestats', self._refreshfilecachestats)
1306 tr.addpostclose('refresh-filecachestats', self._refreshfilecachestats)
1298 self._transref = weakref.ref(tr)
1307 self._transref = weakref.ref(tr)
1299 scmutil.registersummarycallback(self, tr, desc)
1308 scmutil.registersummarycallback(self, tr, desc)
1300 return tr
1309 return tr
1301
1310
1302 def _journalfiles(self):
1311 def _journalfiles(self):
1303 return ((self.svfs, 'journal'),
1312 return ((self.svfs, 'journal'),
1304 (self.vfs, 'journal.dirstate'),
1313 (self.vfs, 'journal.dirstate'),
1305 (self.vfs, 'journal.branch'),
1314 (self.vfs, 'journal.branch'),
1306 (self.vfs, 'journal.desc'),
1315 (self.vfs, 'journal.desc'),
1307 (self.vfs, 'journal.bookmarks'),
1316 (self.vfs, 'journal.bookmarks'),
1308 (self.svfs, 'journal.phaseroots'))
1317 (self.svfs, 'journal.phaseroots'))
1309
1318
1310 def undofiles(self):
1319 def undofiles(self):
1311 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
1320 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
1312
1321
1313 @unfilteredmethod
1322 @unfilteredmethod
1314 def _writejournal(self, desc):
1323 def _writejournal(self, desc):
1315 self.dirstate.savebackup(None, 'journal.dirstate')
1324 self.dirstate.savebackup(None, 'journal.dirstate')
1316 self.vfs.write("journal.branch",
1325 self.vfs.write("journal.branch",
1317 encoding.fromlocal(self.dirstate.branch()))
1326 encoding.fromlocal(self.dirstate.branch()))
1318 self.vfs.write("journal.desc",
1327 self.vfs.write("journal.desc",
1319 "%d\n%s\n" % (len(self), desc))
1328 "%d\n%s\n" % (len(self), desc))
1320 self.vfs.write("journal.bookmarks",
1329 self.vfs.write("journal.bookmarks",
1321 self.vfs.tryread("bookmarks"))
1330 self.vfs.tryread("bookmarks"))
1322 self.svfs.write("journal.phaseroots",
1331 self.svfs.write("journal.phaseroots",
1323 self.svfs.tryread("phaseroots"))
1332 self.svfs.tryread("phaseroots"))
1324
1333
1325 def recover(self):
1334 def recover(self):
1326 with self.lock():
1335 with self.lock():
1327 if self.svfs.exists("journal"):
1336 if self.svfs.exists("journal"):
1328 self.ui.status(_("rolling back interrupted transaction\n"))
1337 self.ui.status(_("rolling back interrupted transaction\n"))
1329 vfsmap = {'': self.svfs,
1338 vfsmap = {'': self.svfs,
1330 'plain': self.vfs,}
1339 'plain': self.vfs,}
1331 transaction.rollback(self.svfs, vfsmap, "journal",
1340 transaction.rollback(self.svfs, vfsmap, "journal",
1332 self.ui.warn,
1341 self.ui.warn,
1333 checkambigfiles=_cachedfiles)
1342 checkambigfiles=_cachedfiles)
1334 self.invalidate()
1343 self.invalidate()
1335 return True
1344 return True
1336 else:
1345 else:
1337 self.ui.warn(_("no interrupted transaction available\n"))
1346 self.ui.warn(_("no interrupted transaction available\n"))
1338 return False
1347 return False
1339
1348
1340 def rollback(self, dryrun=False, force=False):
1349 def rollback(self, dryrun=False, force=False):
1341 wlock = lock = dsguard = None
1350 wlock = lock = dsguard = None
1342 try:
1351 try:
1343 wlock = self.wlock()
1352 wlock = self.wlock()
1344 lock = self.lock()
1353 lock = self.lock()
1345 if self.svfs.exists("undo"):
1354 if self.svfs.exists("undo"):
1346 dsguard = dirstateguard.dirstateguard(self, 'rollback')
1355 dsguard = dirstateguard.dirstateguard(self, 'rollback')
1347
1356
1348 return self._rollback(dryrun, force, dsguard)
1357 return self._rollback(dryrun, force, dsguard)
1349 else:
1358 else:
1350 self.ui.warn(_("no rollback information available\n"))
1359 self.ui.warn(_("no rollback information available\n"))
1351 return 1
1360 return 1
1352 finally:
1361 finally:
1353 release(dsguard, lock, wlock)
1362 release(dsguard, lock, wlock)
1354
1363
1355 @unfilteredmethod # Until we get smarter cache management
1364 @unfilteredmethod # Until we get smarter cache management
1356 def _rollback(self, dryrun, force, dsguard):
1365 def _rollback(self, dryrun, force, dsguard):
1357 ui = self.ui
1366 ui = self.ui
1358 try:
1367 try:
1359 args = self.vfs.read('undo.desc').splitlines()
1368 args = self.vfs.read('undo.desc').splitlines()
1360 (oldlen, desc, detail) = (int(args[0]), args[1], None)
1369 (oldlen, desc, detail) = (int(args[0]), args[1], None)
1361 if len(args) >= 3:
1370 if len(args) >= 3:
1362 detail = args[2]
1371 detail = args[2]
1363 oldtip = oldlen - 1
1372 oldtip = oldlen - 1
1364
1373
1365 if detail and ui.verbose:
1374 if detail and ui.verbose:
1366 msg = (_('repository tip rolled back to revision %d'
1375 msg = (_('repository tip rolled back to revision %d'
1367 ' (undo %s: %s)\n')
1376 ' (undo %s: %s)\n')
1368 % (oldtip, desc, detail))
1377 % (oldtip, desc, detail))
1369 else:
1378 else:
1370 msg = (_('repository tip rolled back to revision %d'
1379 msg = (_('repository tip rolled back to revision %d'
1371 ' (undo %s)\n')
1380 ' (undo %s)\n')
1372 % (oldtip, desc))
1381 % (oldtip, desc))
1373 except IOError:
1382 except IOError:
1374 msg = _('rolling back unknown transaction\n')
1383 msg = _('rolling back unknown transaction\n')
1375 desc = None
1384 desc = None
1376
1385
1377 if not force and self['.'] != self['tip'] and desc == 'commit':
1386 if not force and self['.'] != self['tip'] and desc == 'commit':
1378 raise error.Abort(
1387 raise error.Abort(
1379 _('rollback of last commit while not checked out '
1388 _('rollback of last commit while not checked out '
1380 'may lose data'), hint=_('use -f to force'))
1389 'may lose data'), hint=_('use -f to force'))
1381
1390
1382 ui.status(msg)
1391 ui.status(msg)
1383 if dryrun:
1392 if dryrun:
1384 return 0
1393 return 0
1385
1394
1386 parents = self.dirstate.parents()
1395 parents = self.dirstate.parents()
1387 self.destroying()
1396 self.destroying()
1388 vfsmap = {'plain': self.vfs, '': self.svfs}
1397 vfsmap = {'plain': self.vfs, '': self.svfs}
1389 transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn,
1398 transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn,
1390 checkambigfiles=_cachedfiles)
1399 checkambigfiles=_cachedfiles)
1391 if self.vfs.exists('undo.bookmarks'):
1400 if self.vfs.exists('undo.bookmarks'):
1392 self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
1401 self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
1393 if self.svfs.exists('undo.phaseroots'):
1402 if self.svfs.exists('undo.phaseroots'):
1394 self.svfs.rename('undo.phaseroots', 'phaseroots', checkambig=True)
1403 self.svfs.rename('undo.phaseroots', 'phaseroots', checkambig=True)
1395 self.invalidate()
1404 self.invalidate()
1396
1405
1397 parentgone = (parents[0] not in self.changelog.nodemap or
1406 parentgone = (parents[0] not in self.changelog.nodemap or
1398 parents[1] not in self.changelog.nodemap)
1407 parents[1] not in self.changelog.nodemap)
1399 if parentgone:
1408 if parentgone:
1400 # prevent dirstateguard from overwriting already restored one
1409 # prevent dirstateguard from overwriting already restored one
1401 dsguard.close()
1410 dsguard.close()
1402
1411
1403 self.dirstate.restorebackup(None, 'undo.dirstate')
1412 self.dirstate.restorebackup(None, 'undo.dirstate')
1404 try:
1413 try:
1405 branch = self.vfs.read('undo.branch')
1414 branch = self.vfs.read('undo.branch')
1406 self.dirstate.setbranch(encoding.tolocal(branch))
1415 self.dirstate.setbranch(encoding.tolocal(branch))
1407 except IOError:
1416 except IOError:
1408 ui.warn(_('named branch could not be reset: '
1417 ui.warn(_('named branch could not be reset: '
1409 'current branch is still \'%s\'\n')
1418 'current branch is still \'%s\'\n')
1410 % self.dirstate.branch())
1419 % self.dirstate.branch())
1411
1420
1412 parents = tuple([p.rev() for p in self[None].parents()])
1421 parents = tuple([p.rev() for p in self[None].parents()])
1413 if len(parents) > 1:
1422 if len(parents) > 1:
1414 ui.status(_('working directory now based on '
1423 ui.status(_('working directory now based on '
1415 'revisions %d and %d\n') % parents)
1424 'revisions %d and %d\n') % parents)
1416 else:
1425 else:
1417 ui.status(_('working directory now based on '
1426 ui.status(_('working directory now based on '
1418 'revision %d\n') % parents)
1427 'revision %d\n') % parents)
1419 mergemod.mergestate.clean(self, self['.'].node())
1428 mergemod.mergestate.clean(self, self['.'].node())
1420
1429
1421 # TODO: if we know which new heads may result from this rollback, pass
1430 # TODO: if we know which new heads may result from this rollback, pass
1422 # them to destroy(), which will prevent the branchhead cache from being
1431 # them to destroy(), which will prevent the branchhead cache from being
1423 # invalidated.
1432 # invalidated.
1424 self.destroyed()
1433 self.destroyed()
1425 return 0
1434 return 0
1426
1435
1427 def _buildcacheupdater(self, newtransaction):
1436 def _buildcacheupdater(self, newtransaction):
1428 """called during transaction to build the callback updating cache
1437 """called during transaction to build the callback updating cache
1429
1438
1430 Lives on the repository to help extension who might want to augment
1439 Lives on the repository to help extension who might want to augment
1431 this logic. For this purpose, the created transaction is passed to the
1440 this logic. For this purpose, the created transaction is passed to the
1432 method.
1441 method.
1433 """
1442 """
1434 # we must avoid cyclic reference between repo and transaction.
1443 # we must avoid cyclic reference between repo and transaction.
1435 reporef = weakref.ref(self)
1444 reporef = weakref.ref(self)
1436 def updater(tr):
1445 def updater(tr):
1437 repo = reporef()
1446 repo = reporef()
1438 repo.updatecaches(tr)
1447 repo.updatecaches(tr)
1439 return updater
1448 return updater
1440
1449
1441 @unfilteredmethod
1450 @unfilteredmethod
1442 def updatecaches(self, tr=None):
1451 def updatecaches(self, tr=None):
1443 """warm appropriate caches
1452 """warm appropriate caches
1444
1453
1445 If this function is called after a transaction closed. The transaction
1454 If this function is called after a transaction closed. The transaction
1446 will be available in the 'tr' argument. This can be used to selectively
1455 will be available in the 'tr' argument. This can be used to selectively
1447 update caches relevant to the changes in that transaction.
1456 update caches relevant to the changes in that transaction.
1448 """
1457 """
1449 if tr is not None and tr.hookargs.get('source') == 'strip':
1458 if tr is not None and tr.hookargs.get('source') == 'strip':
1450 # During strip, many caches are invalid but
1459 # During strip, many caches are invalid but
1451 # later call to `destroyed` will refresh them.
1460 # later call to `destroyed` will refresh them.
1452 return
1461 return
1453
1462
1454 if tr is None or tr.changes['revs']:
1463 if tr is None or tr.changes['revs']:
1455 # updating the unfiltered branchmap should refresh all the others,
1464 # updating the unfiltered branchmap should refresh all the others,
1456 self.ui.debug('updating the branch cache\n')
1465 self.ui.debug('updating the branch cache\n')
1457 branchmap.updatecache(self.filtered('served'))
1466 branchmap.updatecache(self.filtered('served'))
1458
1467
1459 def invalidatecaches(self):
1468 def invalidatecaches(self):
1460
1469
1461 if '_tagscache' in vars(self):
1470 if '_tagscache' in vars(self):
1462 # can't use delattr on proxy
1471 # can't use delattr on proxy
1463 del self.__dict__['_tagscache']
1472 del self.__dict__['_tagscache']
1464
1473
1465 self.unfiltered()._branchcaches.clear()
1474 self.unfiltered()._branchcaches.clear()
1466 self.invalidatevolatilesets()
1475 self.invalidatevolatilesets()
1467 self._sparsesignaturecache.clear()
1476 self._sparsesignaturecache.clear()
1468
1477
1469 def invalidatevolatilesets(self):
1478 def invalidatevolatilesets(self):
1470 self.filteredrevcache.clear()
1479 self.filteredrevcache.clear()
1471 obsolete.clearobscaches(self)
1480 obsolete.clearobscaches(self)
1472
1481
1473 def invalidatedirstate(self):
1482 def invalidatedirstate(self):
1474 '''Invalidates the dirstate, causing the next call to dirstate
1483 '''Invalidates the dirstate, causing the next call to dirstate
1475 to check if it was modified since the last time it was read,
1484 to check if it was modified since the last time it was read,
1476 rereading it if it has.
1485 rereading it if it has.
1477
1486
1478 This is different to dirstate.invalidate() that it doesn't always
1487 This is different to dirstate.invalidate() that it doesn't always
1479 rereads the dirstate. Use dirstate.invalidate() if you want to
1488 rereads the dirstate. Use dirstate.invalidate() if you want to
1480 explicitly read the dirstate again (i.e. restoring it to a previous
1489 explicitly read the dirstate again (i.e. restoring it to a previous
1481 known good state).'''
1490 known good state).'''
1482 if hasunfilteredcache(self, 'dirstate'):
1491 if hasunfilteredcache(self, 'dirstate'):
1483 for k in self.dirstate._filecache:
1492 for k in self.dirstate._filecache:
1484 try:
1493 try:
1485 delattr(self.dirstate, k)
1494 delattr(self.dirstate, k)
1486 except AttributeError:
1495 except AttributeError:
1487 pass
1496 pass
1488 delattr(self.unfiltered(), 'dirstate')
1497 delattr(self.unfiltered(), 'dirstate')
1489
1498
1490 def invalidate(self, clearfilecache=False):
1499 def invalidate(self, clearfilecache=False):
1491 '''Invalidates both store and non-store parts other than dirstate
1500 '''Invalidates both store and non-store parts other than dirstate
1492
1501
1493 If a transaction is running, invalidation of store is omitted,
1502 If a transaction is running, invalidation of store is omitted,
1494 because discarding in-memory changes might cause inconsistency
1503 because discarding in-memory changes might cause inconsistency
1495 (e.g. incomplete fncache causes unintentional failure, but
1504 (e.g. incomplete fncache causes unintentional failure, but
1496 redundant one doesn't).
1505 redundant one doesn't).
1497 '''
1506 '''
1498 unfiltered = self.unfiltered() # all file caches are stored unfiltered
1507 unfiltered = self.unfiltered() # all file caches are stored unfiltered
1499 for k in list(self._filecache.keys()):
1508 for k in list(self._filecache.keys()):
1500 # dirstate is invalidated separately in invalidatedirstate()
1509 # dirstate is invalidated separately in invalidatedirstate()
1501 if k == 'dirstate':
1510 if k == 'dirstate':
1502 continue
1511 continue
1503 if (k == 'changelog' and
1512 if (k == 'changelog' and
1504 self.currenttransaction() and
1513 self.currenttransaction() and
1505 self.changelog._delayed):
1514 self.changelog._delayed):
1506 # The changelog object may store unwritten revisions. We don't
1515 # The changelog object may store unwritten revisions. We don't
1507 # want to lose them.
1516 # want to lose them.
1508 # TODO: Solve the problem instead of working around it.
1517 # TODO: Solve the problem instead of working around it.
1509 continue
1518 continue
1510
1519
1511 if clearfilecache:
1520 if clearfilecache:
1512 del self._filecache[k]
1521 del self._filecache[k]
1513 try:
1522 try:
1514 delattr(unfiltered, k)
1523 delattr(unfiltered, k)
1515 except AttributeError:
1524 except AttributeError:
1516 pass
1525 pass
1517 self.invalidatecaches()
1526 self.invalidatecaches()
1518 if not self.currenttransaction():
1527 if not self.currenttransaction():
1519 # TODO: Changing contents of store outside transaction
1528 # TODO: Changing contents of store outside transaction
1520 # causes inconsistency. We should make in-memory store
1529 # causes inconsistency. We should make in-memory store
1521 # changes detectable, and abort if changed.
1530 # changes detectable, and abort if changed.
1522 self.store.invalidatecaches()
1531 self.store.invalidatecaches()
1523
1532
1524 def invalidateall(self):
1533 def invalidateall(self):
1525 '''Fully invalidates both store and non-store parts, causing the
1534 '''Fully invalidates both store and non-store parts, causing the
1526 subsequent operation to reread any outside changes.'''
1535 subsequent operation to reread any outside changes.'''
1527 # extension should hook this to invalidate its caches
1536 # extension should hook this to invalidate its caches
1528 self.invalidate()
1537 self.invalidate()
1529 self.invalidatedirstate()
1538 self.invalidatedirstate()
1530
1539
1531 @unfilteredmethod
1540 @unfilteredmethod
1532 def _refreshfilecachestats(self, tr):
1541 def _refreshfilecachestats(self, tr):
1533 """Reload stats of cached files so that they are flagged as valid"""
1542 """Reload stats of cached files so that they are flagged as valid"""
1534 for k, ce in self._filecache.items():
1543 for k, ce in self._filecache.items():
1535 if k == 'dirstate' or k not in self.__dict__:
1544 if k == 'dirstate' or k not in self.__dict__:
1536 continue
1545 continue
1537 ce.refresh()
1546 ce.refresh()
1538
1547
1539 def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc,
1548 def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc,
1540 inheritchecker=None, parentenvvar=None):
1549 inheritchecker=None, parentenvvar=None):
1541 parentlock = None
1550 parentlock = None
1542 # the contents of parentenvvar are used by the underlying lock to
1551 # the contents of parentenvvar are used by the underlying lock to
1543 # determine whether it can be inherited
1552 # determine whether it can be inherited
1544 if parentenvvar is not None:
1553 if parentenvvar is not None:
1545 parentlock = encoding.environ.get(parentenvvar)
1554 parentlock = encoding.environ.get(parentenvvar)
1546 try:
1555 try:
1547 l = lockmod.lock(vfs, lockname, 0, releasefn=releasefn,
1556 l = lockmod.lock(vfs, lockname, 0, releasefn=releasefn,
1548 acquirefn=acquirefn, desc=desc,
1557 acquirefn=acquirefn, desc=desc,
1549 inheritchecker=inheritchecker,
1558 inheritchecker=inheritchecker,
1550 parentlock=parentlock)
1559 parentlock=parentlock)
1551 except error.LockHeld as inst:
1560 except error.LockHeld as inst:
1552 if not wait:
1561 if not wait:
1553 raise
1562 raise
1554 # show more details for new-style locks
1563 # show more details for new-style locks
1555 if ':' in inst.locker:
1564 if ':' in inst.locker:
1556 host, pid = inst.locker.split(":", 1)
1565 host, pid = inst.locker.split(":", 1)
1557 self.ui.warn(
1566 self.ui.warn(
1558 _("waiting for lock on %s held by process %r "
1567 _("waiting for lock on %s held by process %r "
1559 "on host %r\n") % (desc, pid, host))
1568 "on host %r\n") % (desc, pid, host))
1560 else:
1569 else:
1561 self.ui.warn(_("waiting for lock on %s held by %r\n") %
1570 self.ui.warn(_("waiting for lock on %s held by %r\n") %
1562 (desc, inst.locker))
1571 (desc, inst.locker))
1563 # default to 600 seconds timeout
1572 # default to 600 seconds timeout
1564 l = lockmod.lock(vfs, lockname,
1573 l = lockmod.lock(vfs, lockname,
1565 int(self.ui.config("ui", "timeout")),
1574 int(self.ui.config("ui", "timeout")),
1566 releasefn=releasefn, acquirefn=acquirefn,
1575 releasefn=releasefn, acquirefn=acquirefn,
1567 desc=desc)
1576 desc=desc)
1568 self.ui.warn(_("got lock after %s seconds\n") % l.delay)
1577 self.ui.warn(_("got lock after %s seconds\n") % l.delay)
1569 return l
1578 return l
1570
1579
1571 def _afterlock(self, callback):
1580 def _afterlock(self, callback):
1572 """add a callback to be run when the repository is fully unlocked
1581 """add a callback to be run when the repository is fully unlocked
1573
1582
1574 The callback will be executed when the outermost lock is released
1583 The callback will be executed when the outermost lock is released
1575 (with wlock being higher level than 'lock')."""
1584 (with wlock being higher level than 'lock')."""
1576 for ref in (self._wlockref, self._lockref):
1585 for ref in (self._wlockref, self._lockref):
1577 l = ref and ref()
1586 l = ref and ref()
1578 if l and l.held:
1587 if l and l.held:
1579 l.postrelease.append(callback)
1588 l.postrelease.append(callback)
1580 break
1589 break
1581 else: # no lock have been found.
1590 else: # no lock have been found.
1582 callback()
1591 callback()
1583
1592
1584 def lock(self, wait=True):
1593 def lock(self, wait=True):
1585 '''Lock the repository store (.hg/store) and return a weak reference
1594 '''Lock the repository store (.hg/store) and return a weak reference
1586 to the lock. Use this before modifying the store (e.g. committing or
1595 to the lock. Use this before modifying the store (e.g. committing or
1587 stripping). If you are opening a transaction, get a lock as well.)
1596 stripping). If you are opening a transaction, get a lock as well.)
1588
1597
1589 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
1598 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
1590 'wlock' first to avoid a dead-lock hazard.'''
1599 'wlock' first to avoid a dead-lock hazard.'''
1591 l = self._currentlock(self._lockref)
1600 l = self._currentlock(self._lockref)
1592 if l is not None:
1601 if l is not None:
1593 l.lock()
1602 l.lock()
1594 return l
1603 return l
1595
1604
1596 l = self._lock(self.svfs, "lock", wait, None,
1605 l = self._lock(self.svfs, "lock", wait, None,
1597 self.invalidate, _('repository %s') % self.origroot)
1606 self.invalidate, _('repository %s') % self.origroot)
1598 self._lockref = weakref.ref(l)
1607 self._lockref = weakref.ref(l)
1599 return l
1608 return l
1600
1609
1601 def _wlockchecktransaction(self):
1610 def _wlockchecktransaction(self):
1602 if self.currenttransaction() is not None:
1611 if self.currenttransaction() is not None:
1603 raise error.LockInheritanceContractViolation(
1612 raise error.LockInheritanceContractViolation(
1604 'wlock cannot be inherited in the middle of a transaction')
1613 'wlock cannot be inherited in the middle of a transaction')
1605
1614
1606 def wlock(self, wait=True):
1615 def wlock(self, wait=True):
1607 '''Lock the non-store parts of the repository (everything under
1616 '''Lock the non-store parts of the repository (everything under
1608 .hg except .hg/store) and return a weak reference to the lock.
1617 .hg except .hg/store) and return a weak reference to the lock.
1609
1618
1610 Use this before modifying files in .hg.
1619 Use this before modifying files in .hg.
1611
1620
1612 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
1621 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
1613 'wlock' first to avoid a dead-lock hazard.'''
1622 'wlock' first to avoid a dead-lock hazard.'''
1614 l = self._wlockref and self._wlockref()
1623 l = self._wlockref and self._wlockref()
1615 if l is not None and l.held:
1624 if l is not None and l.held:
1616 l.lock()
1625 l.lock()
1617 return l
1626 return l
1618
1627
1619 # We do not need to check for non-waiting lock acquisition. Such
1628 # We do not need to check for non-waiting lock acquisition. Such
1620 # acquisition would not cause dead-lock as they would just fail.
1629 # acquisition would not cause dead-lock as they would just fail.
1621 if wait and (self.ui.configbool('devel', 'all-warnings')
1630 if wait and (self.ui.configbool('devel', 'all-warnings')
1622 or self.ui.configbool('devel', 'check-locks')):
1631 or self.ui.configbool('devel', 'check-locks')):
1623 if self._currentlock(self._lockref) is not None:
1632 if self._currentlock(self._lockref) is not None:
1624 self.ui.develwarn('"wlock" acquired after "lock"')
1633 self.ui.develwarn('"wlock" acquired after "lock"')
1625
1634
1626 def unlock():
1635 def unlock():
1627 if self.dirstate.pendingparentchange():
1636 if self.dirstate.pendingparentchange():
1628 self.dirstate.invalidate()
1637 self.dirstate.invalidate()
1629 else:
1638 else:
1630 self.dirstate.write(None)
1639 self.dirstate.write(None)
1631
1640
1632 self._filecache['dirstate'].refresh()
1641 self._filecache['dirstate'].refresh()
1633
1642
1634 l = self._lock(self.vfs, "wlock", wait, unlock,
1643 l = self._lock(self.vfs, "wlock", wait, unlock,
1635 self.invalidatedirstate, _('working directory of %s') %
1644 self.invalidatedirstate, _('working directory of %s') %
1636 self.origroot,
1645 self.origroot,
1637 inheritchecker=self._wlockchecktransaction,
1646 inheritchecker=self._wlockchecktransaction,
1638 parentenvvar='HG_WLOCK_LOCKER')
1647 parentenvvar='HG_WLOCK_LOCKER')
1639 self._wlockref = weakref.ref(l)
1648 self._wlockref = weakref.ref(l)
1640 return l
1649 return l
1641
1650
1642 def _currentlock(self, lockref):
1651 def _currentlock(self, lockref):
1643 """Returns the lock if it's held, or None if it's not."""
1652 """Returns the lock if it's held, or None if it's not."""
1644 if lockref is None:
1653 if lockref is None:
1645 return None
1654 return None
1646 l = lockref()
1655 l = lockref()
1647 if l is None or not l.held:
1656 if l is None or not l.held:
1648 return None
1657 return None
1649 return l
1658 return l
1650
1659
1651 def currentwlock(self):
1660 def currentwlock(self):
1652 """Returns the wlock if it's held, or None if it's not."""
1661 """Returns the wlock if it's held, or None if it's not."""
1653 return self._currentlock(self._wlockref)
1662 return self._currentlock(self._wlockref)
1654
1663
1655 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
1664 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
1656 """
1665 """
1657 commit an individual file as part of a larger transaction
1666 commit an individual file as part of a larger transaction
1658 """
1667 """
1659
1668
1660 fname = fctx.path()
1669 fname = fctx.path()
1661 fparent1 = manifest1.get(fname, nullid)
1670 fparent1 = manifest1.get(fname, nullid)
1662 fparent2 = manifest2.get(fname, nullid)
1671 fparent2 = manifest2.get(fname, nullid)
1663 if isinstance(fctx, context.filectx):
1672 if isinstance(fctx, context.filectx):
1664 node = fctx.filenode()
1673 node = fctx.filenode()
1665 if node in [fparent1, fparent2]:
1674 if node in [fparent1, fparent2]:
1666 self.ui.debug('reusing %s filelog entry\n' % fname)
1675 self.ui.debug('reusing %s filelog entry\n' % fname)
1667 if manifest1.flags(fname) != fctx.flags():
1676 if manifest1.flags(fname) != fctx.flags():
1668 changelist.append(fname)
1677 changelist.append(fname)
1669 return node
1678 return node
1670
1679
1671 flog = self.file(fname)
1680 flog = self.file(fname)
1672 meta = {}
1681 meta = {}
1673 copy = fctx.renamed()
1682 copy = fctx.renamed()
1674 if copy and copy[0] != fname:
1683 if copy and copy[0] != fname:
1675 # Mark the new revision of this file as a copy of another
1684 # Mark the new revision of this file as a copy of another
1676 # file. This copy data will effectively act as a parent
1685 # file. This copy data will effectively act as a parent
1677 # of this new revision. If this is a merge, the first
1686 # of this new revision. If this is a merge, the first
1678 # parent will be the nullid (meaning "look up the copy data")
1687 # parent will be the nullid (meaning "look up the copy data")
1679 # and the second one will be the other parent. For example:
1688 # and the second one will be the other parent. For example:
1680 #
1689 #
1681 # 0 --- 1 --- 3 rev1 changes file foo
1690 # 0 --- 1 --- 3 rev1 changes file foo
1682 # \ / rev2 renames foo to bar and changes it
1691 # \ / rev2 renames foo to bar and changes it
1683 # \- 2 -/ rev3 should have bar with all changes and
1692 # \- 2 -/ rev3 should have bar with all changes and
1684 # should record that bar descends from
1693 # should record that bar descends from
1685 # bar in rev2 and foo in rev1
1694 # bar in rev2 and foo in rev1
1686 #
1695 #
1687 # this allows this merge to succeed:
1696 # this allows this merge to succeed:
1688 #
1697 #
1689 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
1698 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
1690 # \ / merging rev3 and rev4 should use bar@rev2
1699 # \ / merging rev3 and rev4 should use bar@rev2
1691 # \- 2 --- 4 as the merge base
1700 # \- 2 --- 4 as the merge base
1692 #
1701 #
1693
1702
1694 cfname = copy[0]
1703 cfname = copy[0]
1695 crev = manifest1.get(cfname)
1704 crev = manifest1.get(cfname)
1696 newfparent = fparent2
1705 newfparent = fparent2
1697
1706
1698 if manifest2: # branch merge
1707 if manifest2: # branch merge
1699 if fparent2 == nullid or crev is None: # copied on remote side
1708 if fparent2 == nullid or crev is None: # copied on remote side
1700 if cfname in manifest2:
1709 if cfname in manifest2:
1701 crev = manifest2[cfname]
1710 crev = manifest2[cfname]
1702 newfparent = fparent1
1711 newfparent = fparent1
1703
1712
1704 # Here, we used to search backwards through history to try to find
1713 # Here, we used to search backwards through history to try to find
1705 # where the file copy came from if the source of a copy was not in
1714 # where the file copy came from if the source of a copy was not in
1706 # the parent directory. However, this doesn't actually make sense to
1715 # the parent directory. However, this doesn't actually make sense to
1707 # do (what does a copy from something not in your working copy even
1716 # do (what does a copy from something not in your working copy even
1708 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
1717 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
1709 # the user that copy information was dropped, so if they didn't
1718 # the user that copy information was dropped, so if they didn't
1710 # expect this outcome it can be fixed, but this is the correct
1719 # expect this outcome it can be fixed, but this is the correct
1711 # behavior in this circumstance.
1720 # behavior in this circumstance.
1712
1721
1713 if crev:
1722 if crev:
1714 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
1723 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
1715 meta["copy"] = cfname
1724 meta["copy"] = cfname
1716 meta["copyrev"] = hex(crev)
1725 meta["copyrev"] = hex(crev)
1717 fparent1, fparent2 = nullid, newfparent
1726 fparent1, fparent2 = nullid, newfparent
1718 else:
1727 else:
1719 self.ui.warn(_("warning: can't find ancestor for '%s' "
1728 self.ui.warn(_("warning: can't find ancestor for '%s' "
1720 "copied from '%s'!\n") % (fname, cfname))
1729 "copied from '%s'!\n") % (fname, cfname))
1721
1730
1722 elif fparent1 == nullid:
1731 elif fparent1 == nullid:
1723 fparent1, fparent2 = fparent2, nullid
1732 fparent1, fparent2 = fparent2, nullid
1724 elif fparent2 != nullid:
1733 elif fparent2 != nullid:
1725 # is one parent an ancestor of the other?
1734 # is one parent an ancestor of the other?
1726 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
1735 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
1727 if fparent1 in fparentancestors:
1736 if fparent1 in fparentancestors:
1728 fparent1, fparent2 = fparent2, nullid
1737 fparent1, fparent2 = fparent2, nullid
1729 elif fparent2 in fparentancestors:
1738 elif fparent2 in fparentancestors:
1730 fparent2 = nullid
1739 fparent2 = nullid
1731
1740
1732 # is the file changed?
1741 # is the file changed?
1733 text = fctx.data()
1742 text = fctx.data()
1734 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
1743 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
1735 changelist.append(fname)
1744 changelist.append(fname)
1736 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
1745 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
1737 # are just the flags changed during merge?
1746 # are just the flags changed during merge?
1738 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
1747 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
1739 changelist.append(fname)
1748 changelist.append(fname)
1740
1749
1741 return fparent1
1750 return fparent1
1742
1751
1743 def checkcommitpatterns(self, wctx, vdirs, match, status, fail):
1752 def checkcommitpatterns(self, wctx, vdirs, match, status, fail):
1744 """check for commit arguments that aren't committable"""
1753 """check for commit arguments that aren't committable"""
1745 if match.isexact() or match.prefix():
1754 if match.isexact() or match.prefix():
1746 matched = set(status.modified + status.added + status.removed)
1755 matched = set(status.modified + status.added + status.removed)
1747
1756
1748 for f in match.files():
1757 for f in match.files():
1749 f = self.dirstate.normalize(f)
1758 f = self.dirstate.normalize(f)
1750 if f == '.' or f in matched or f in wctx.substate:
1759 if f == '.' or f in matched or f in wctx.substate:
1751 continue
1760 continue
1752 if f in status.deleted:
1761 if f in status.deleted:
1753 fail(f, _('file not found!'))
1762 fail(f, _('file not found!'))
1754 if f in vdirs: # visited directory
1763 if f in vdirs: # visited directory
1755 d = f + '/'
1764 d = f + '/'
1756 for mf in matched:
1765 for mf in matched:
1757 if mf.startswith(d):
1766 if mf.startswith(d):
1758 break
1767 break
1759 else:
1768 else:
1760 fail(f, _("no match under directory!"))
1769 fail(f, _("no match under directory!"))
1761 elif f not in self.dirstate:
1770 elif f not in self.dirstate:
1762 fail(f, _("file not tracked!"))
1771 fail(f, _("file not tracked!"))
1763
1772
1764 @unfilteredmethod
1773 @unfilteredmethod
1765 def commit(self, text="", user=None, date=None, match=None, force=False,
1774 def commit(self, text="", user=None, date=None, match=None, force=False,
1766 editor=False, extra=None):
1775 editor=False, extra=None):
1767 """Add a new revision to current repository.
1776 """Add a new revision to current repository.
1768
1777
1769 Revision information is gathered from the working directory,
1778 Revision information is gathered from the working directory,
1770 match can be used to filter the committed files. If editor is
1779 match can be used to filter the committed files. If editor is
1771 supplied, it is called to get a commit message.
1780 supplied, it is called to get a commit message.
1772 """
1781 """
1773 if extra is None:
1782 if extra is None:
1774 extra = {}
1783 extra = {}
1775
1784
1776 def fail(f, msg):
1785 def fail(f, msg):
1777 raise error.Abort('%s: %s' % (f, msg))
1786 raise error.Abort('%s: %s' % (f, msg))
1778
1787
1779 if not match:
1788 if not match:
1780 match = matchmod.always(self.root, '')
1789 match = matchmod.always(self.root, '')
1781
1790
1782 if not force:
1791 if not force:
1783 vdirs = []
1792 vdirs = []
1784 match.explicitdir = vdirs.append
1793 match.explicitdir = vdirs.append
1785 match.bad = fail
1794 match.bad = fail
1786
1795
1787 wlock = lock = tr = None
1796 wlock = lock = tr = None
1788 try:
1797 try:
1789 wlock = self.wlock()
1798 wlock = self.wlock()
1790 lock = self.lock() # for recent changelog (see issue4368)
1799 lock = self.lock() # for recent changelog (see issue4368)
1791
1800
1792 wctx = self[None]
1801 wctx = self[None]
1793 merge = len(wctx.parents()) > 1
1802 merge = len(wctx.parents()) > 1
1794
1803
1795 if not force and merge and not match.always():
1804 if not force and merge and not match.always():
1796 raise error.Abort(_('cannot partially commit a merge '
1805 raise error.Abort(_('cannot partially commit a merge '
1797 '(do not specify files or patterns)'))
1806 '(do not specify files or patterns)'))
1798
1807
1799 status = self.status(match=match, clean=force)
1808 status = self.status(match=match, clean=force)
1800 if force:
1809 if force:
1801 status.modified.extend(status.clean) # mq may commit clean files
1810 status.modified.extend(status.clean) # mq may commit clean files
1802
1811
1803 # check subrepos
1812 # check subrepos
1804 subs = []
1813 subs = []
1805 commitsubs = set()
1814 commitsubs = set()
1806 newstate = wctx.substate.copy()
1815 newstate = wctx.substate.copy()
1807 # only manage subrepos and .hgsubstate if .hgsub is present
1816 # only manage subrepos and .hgsubstate if .hgsub is present
1808 if '.hgsub' in wctx:
1817 if '.hgsub' in wctx:
1809 # we'll decide whether to track this ourselves, thanks
1818 # we'll decide whether to track this ourselves, thanks
1810 for c in status.modified, status.added, status.removed:
1819 for c in status.modified, status.added, status.removed:
1811 if '.hgsubstate' in c:
1820 if '.hgsubstate' in c:
1812 c.remove('.hgsubstate')
1821 c.remove('.hgsubstate')
1813
1822
1814 # compare current state to last committed state
1823 # compare current state to last committed state
1815 # build new substate based on last committed state
1824 # build new substate based on last committed state
1816 oldstate = wctx.p1().substate
1825 oldstate = wctx.p1().substate
1817 for s in sorted(newstate.keys()):
1826 for s in sorted(newstate.keys()):
1818 if not match(s):
1827 if not match(s):
1819 # ignore working copy, use old state if present
1828 # ignore working copy, use old state if present
1820 if s in oldstate:
1829 if s in oldstate:
1821 newstate[s] = oldstate[s]
1830 newstate[s] = oldstate[s]
1822 continue
1831 continue
1823 if not force:
1832 if not force:
1824 raise error.Abort(
1833 raise error.Abort(
1825 _("commit with new subrepo %s excluded") % s)
1834 _("commit with new subrepo %s excluded") % s)
1826 dirtyreason = wctx.sub(s).dirtyreason(True)
1835 dirtyreason = wctx.sub(s).dirtyreason(True)
1827 if dirtyreason:
1836 if dirtyreason:
1828 if not self.ui.configbool('ui', 'commitsubrepos'):
1837 if not self.ui.configbool('ui', 'commitsubrepos'):
1829 raise error.Abort(dirtyreason,
1838 raise error.Abort(dirtyreason,
1830 hint=_("use --subrepos for recursive commit"))
1839 hint=_("use --subrepos for recursive commit"))
1831 subs.append(s)
1840 subs.append(s)
1832 commitsubs.add(s)
1841 commitsubs.add(s)
1833 else:
1842 else:
1834 bs = wctx.sub(s).basestate()
1843 bs = wctx.sub(s).basestate()
1835 newstate[s] = (newstate[s][0], bs, newstate[s][2])
1844 newstate[s] = (newstate[s][0], bs, newstate[s][2])
1836 if oldstate.get(s, (None, None, None))[1] != bs:
1845 if oldstate.get(s, (None, None, None))[1] != bs:
1837 subs.append(s)
1846 subs.append(s)
1838
1847
1839 # check for removed subrepos
1848 # check for removed subrepos
1840 for p in wctx.parents():
1849 for p in wctx.parents():
1841 r = [s for s in p.substate if s not in newstate]
1850 r = [s for s in p.substate if s not in newstate]
1842 subs += [s for s in r if match(s)]
1851 subs += [s for s in r if match(s)]
1843 if subs:
1852 if subs:
1844 if (not match('.hgsub') and
1853 if (not match('.hgsub') and
1845 '.hgsub' in (wctx.modified() + wctx.added())):
1854 '.hgsub' in (wctx.modified() + wctx.added())):
1846 raise error.Abort(
1855 raise error.Abort(
1847 _("can't commit subrepos without .hgsub"))
1856 _("can't commit subrepos without .hgsub"))
1848 status.modified.insert(0, '.hgsubstate')
1857 status.modified.insert(0, '.hgsubstate')
1849
1858
1850 elif '.hgsub' in status.removed:
1859 elif '.hgsub' in status.removed:
1851 # clean up .hgsubstate when .hgsub is removed
1860 # clean up .hgsubstate when .hgsub is removed
1852 if ('.hgsubstate' in wctx and
1861 if ('.hgsubstate' in wctx and
1853 '.hgsubstate' not in (status.modified + status.added +
1862 '.hgsubstate' not in (status.modified + status.added +
1854 status.removed)):
1863 status.removed)):
1855 status.removed.insert(0, '.hgsubstate')
1864 status.removed.insert(0, '.hgsubstate')
1856
1865
1857 # make sure all explicit patterns are matched
1866 # make sure all explicit patterns are matched
1858 if not force:
1867 if not force:
1859 self.checkcommitpatterns(wctx, vdirs, match, status, fail)
1868 self.checkcommitpatterns(wctx, vdirs, match, status, fail)
1860
1869
1861 cctx = context.workingcommitctx(self, status,
1870 cctx = context.workingcommitctx(self, status,
1862 text, user, date, extra)
1871 text, user, date, extra)
1863
1872
1864 # internal config: ui.allowemptycommit
1873 # internal config: ui.allowemptycommit
1865 allowemptycommit = (wctx.branch() != wctx.p1().branch()
1874 allowemptycommit = (wctx.branch() != wctx.p1().branch()
1866 or extra.get('close') or merge or cctx.files()
1875 or extra.get('close') or merge or cctx.files()
1867 or self.ui.configbool('ui', 'allowemptycommit'))
1876 or self.ui.configbool('ui', 'allowemptycommit'))
1868 if not allowemptycommit:
1877 if not allowemptycommit:
1869 return None
1878 return None
1870
1879
1871 if merge and cctx.deleted():
1880 if merge and cctx.deleted():
1872 raise error.Abort(_("cannot commit merge with missing files"))
1881 raise error.Abort(_("cannot commit merge with missing files"))
1873
1882
1874 ms = mergemod.mergestate.read(self)
1883 ms = mergemod.mergestate.read(self)
1875 mergeutil.checkunresolved(ms)
1884 mergeutil.checkunresolved(ms)
1876
1885
1877 if editor:
1886 if editor:
1878 cctx._text = editor(self, cctx, subs)
1887 cctx._text = editor(self, cctx, subs)
1879 edited = (text != cctx._text)
1888 edited = (text != cctx._text)
1880
1889
1881 # Save commit message in case this transaction gets rolled back
1890 # Save commit message in case this transaction gets rolled back
1882 # (e.g. by a pretxncommit hook). Leave the content alone on
1891 # (e.g. by a pretxncommit hook). Leave the content alone on
1883 # the assumption that the user will use the same editor again.
1892 # the assumption that the user will use the same editor again.
1884 msgfn = self.savecommitmessage(cctx._text)
1893 msgfn = self.savecommitmessage(cctx._text)
1885
1894
1886 # commit subs and write new state
1895 # commit subs and write new state
1887 if subs:
1896 if subs:
1888 for s in sorted(commitsubs):
1897 for s in sorted(commitsubs):
1889 sub = wctx.sub(s)
1898 sub = wctx.sub(s)
1890 self.ui.status(_('committing subrepository %s\n') %
1899 self.ui.status(_('committing subrepository %s\n') %
1891 subrepo.subrelpath(sub))
1900 subrepo.subrelpath(sub))
1892 sr = sub.commit(cctx._text, user, date)
1901 sr = sub.commit(cctx._text, user, date)
1893 newstate[s] = (newstate[s][0], sr)
1902 newstate[s] = (newstate[s][0], sr)
1894 subrepo.writestate(self, newstate)
1903 subrepo.writestate(self, newstate)
1895
1904
1896 p1, p2 = self.dirstate.parents()
1905 p1, p2 = self.dirstate.parents()
1897 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
1906 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
1898 try:
1907 try:
1899 self.hook("precommit", throw=True, parent1=hookp1,
1908 self.hook("precommit", throw=True, parent1=hookp1,
1900 parent2=hookp2)
1909 parent2=hookp2)
1901 tr = self.transaction('commit')
1910 tr = self.transaction('commit')
1902 ret = self.commitctx(cctx, True)
1911 ret = self.commitctx(cctx, True)
1903 except: # re-raises
1912 except: # re-raises
1904 if edited:
1913 if edited:
1905 self.ui.write(
1914 self.ui.write(
1906 _('note: commit message saved in %s\n') % msgfn)
1915 _('note: commit message saved in %s\n') % msgfn)
1907 raise
1916 raise
1908 # update bookmarks, dirstate and mergestate
1917 # update bookmarks, dirstate and mergestate
1909 bookmarks.update(self, [p1, p2], ret)
1918 bookmarks.update(self, [p1, p2], ret)
1910 cctx.markcommitted(ret)
1919 cctx.markcommitted(ret)
1911 ms.reset()
1920 ms.reset()
1912 tr.close()
1921 tr.close()
1913
1922
1914 finally:
1923 finally:
1915 lockmod.release(tr, lock, wlock)
1924 lockmod.release(tr, lock, wlock)
1916
1925
1917 def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
1926 def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
1918 # hack for command that use a temporary commit (eg: histedit)
1927 # hack for command that use a temporary commit (eg: histedit)
1919 # temporary commit got stripped before hook release
1928 # temporary commit got stripped before hook release
1920 if self.changelog.hasnode(ret):
1929 if self.changelog.hasnode(ret):
1921 self.hook("commit", node=node, parent1=parent1,
1930 self.hook("commit", node=node, parent1=parent1,
1922 parent2=parent2)
1931 parent2=parent2)
1923 self._afterlock(commithook)
1932 self._afterlock(commithook)
1924 return ret
1933 return ret
1925
1934
1926 @unfilteredmethod
1935 @unfilteredmethod
1927 def commitctx(self, ctx, error=False):
1936 def commitctx(self, ctx, error=False):
1928 """Add a new revision to current repository.
1937 """Add a new revision to current repository.
1929 Revision information is passed via the context argument.
1938 Revision information is passed via the context argument.
1930 """
1939 """
1931
1940
1932 tr = None
1941 tr = None
1933 p1, p2 = ctx.p1(), ctx.p2()
1942 p1, p2 = ctx.p1(), ctx.p2()
1934 user = ctx.user()
1943 user = ctx.user()
1935
1944
1936 lock = self.lock()
1945 lock = self.lock()
1937 try:
1946 try:
1938 tr = self.transaction("commit")
1947 tr = self.transaction("commit")
1939 trp = weakref.proxy(tr)
1948 trp = weakref.proxy(tr)
1940
1949
1941 if ctx.manifestnode():
1950 if ctx.manifestnode():
1942 # reuse an existing manifest revision
1951 # reuse an existing manifest revision
1943 mn = ctx.manifestnode()
1952 mn = ctx.manifestnode()
1944 files = ctx.files()
1953 files = ctx.files()
1945 elif ctx.files():
1954 elif ctx.files():
1946 m1ctx = p1.manifestctx()
1955 m1ctx = p1.manifestctx()
1947 m2ctx = p2.manifestctx()
1956 m2ctx = p2.manifestctx()
1948 mctx = m1ctx.copy()
1957 mctx = m1ctx.copy()
1949
1958
1950 m = mctx.read()
1959 m = mctx.read()
1951 m1 = m1ctx.read()
1960 m1 = m1ctx.read()
1952 m2 = m2ctx.read()
1961 m2 = m2ctx.read()
1953
1962
1954 # check in files
1963 # check in files
1955 added = []
1964 added = []
1956 changed = []
1965 changed = []
1957 removed = list(ctx.removed())
1966 removed = list(ctx.removed())
1958 linkrev = len(self)
1967 linkrev = len(self)
1959 self.ui.note(_("committing files:\n"))
1968 self.ui.note(_("committing files:\n"))
1960 for f in sorted(ctx.modified() + ctx.added()):
1969 for f in sorted(ctx.modified() + ctx.added()):
1961 self.ui.note(f + "\n")
1970 self.ui.note(f + "\n")
1962 try:
1971 try:
1963 fctx = ctx[f]
1972 fctx = ctx[f]
1964 if fctx is None:
1973 if fctx is None:
1965 removed.append(f)
1974 removed.append(f)
1966 else:
1975 else:
1967 added.append(f)
1976 added.append(f)
1968 m[f] = self._filecommit(fctx, m1, m2, linkrev,
1977 m[f] = self._filecommit(fctx, m1, m2, linkrev,
1969 trp, changed)
1978 trp, changed)
1970 m.setflag(f, fctx.flags())
1979 m.setflag(f, fctx.flags())
1971 except OSError as inst:
1980 except OSError as inst:
1972 self.ui.warn(_("trouble committing %s!\n") % f)
1981 self.ui.warn(_("trouble committing %s!\n") % f)
1973 raise
1982 raise
1974 except IOError as inst:
1983 except IOError as inst:
1975 errcode = getattr(inst, 'errno', errno.ENOENT)
1984 errcode = getattr(inst, 'errno', errno.ENOENT)
1976 if error or errcode and errcode != errno.ENOENT:
1985 if error or errcode and errcode != errno.ENOENT:
1977 self.ui.warn(_("trouble committing %s!\n") % f)
1986 self.ui.warn(_("trouble committing %s!\n") % f)
1978 raise
1987 raise
1979
1988
1980 # update manifest
1989 # update manifest
1981 self.ui.note(_("committing manifest\n"))
1990 self.ui.note(_("committing manifest\n"))
1982 removed = [f for f in sorted(removed) if f in m1 or f in m2]
1991 removed = [f for f in sorted(removed) if f in m1 or f in m2]
1983 drop = [f for f in removed if f in m]
1992 drop = [f for f in removed if f in m]
1984 for f in drop:
1993 for f in drop:
1985 del m[f]
1994 del m[f]
1986 mn = mctx.write(trp, linkrev,
1995 mn = mctx.write(trp, linkrev,
1987 p1.manifestnode(), p2.manifestnode(),
1996 p1.manifestnode(), p2.manifestnode(),
1988 added, drop)
1997 added, drop)
1989 files = changed + removed
1998 files = changed + removed
1990 else:
1999 else:
1991 mn = p1.manifestnode()
2000 mn = p1.manifestnode()
1992 files = []
2001 files = []
1993
2002
1994 # update changelog
2003 # update changelog
1995 self.ui.note(_("committing changelog\n"))
2004 self.ui.note(_("committing changelog\n"))
1996 self.changelog.delayupdate(tr)
2005 self.changelog.delayupdate(tr)
1997 n = self.changelog.add(mn, files, ctx.description(),
2006 n = self.changelog.add(mn, files, ctx.description(),
1998 trp, p1.node(), p2.node(),
2007 trp, p1.node(), p2.node(),
1999 user, ctx.date(), ctx.extra().copy())
2008 user, ctx.date(), ctx.extra().copy())
2000 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
2009 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
2001 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
2010 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
2002 parent2=xp2)
2011 parent2=xp2)
2003 # set the new commit is proper phase
2012 # set the new commit is proper phase
2004 targetphase = subrepo.newcommitphase(self.ui, ctx)
2013 targetphase = subrepo.newcommitphase(self.ui, ctx)
2005 if targetphase:
2014 if targetphase:
2006 # retract boundary do not alter parent changeset.
2015 # retract boundary do not alter parent changeset.
2007 # if a parent have higher the resulting phase will
2016 # if a parent have higher the resulting phase will
2008 # be compliant anyway
2017 # be compliant anyway
2009 #
2018 #
2010 # if minimal phase was 0 we don't need to retract anything
2019 # if minimal phase was 0 we don't need to retract anything
2011 phases.registernew(self, tr, targetphase, [n])
2020 phases.registernew(self, tr, targetphase, [n])
2012 tr.close()
2021 tr.close()
2013 return n
2022 return n
2014 finally:
2023 finally:
2015 if tr:
2024 if tr:
2016 tr.release()
2025 tr.release()
2017 lock.release()
2026 lock.release()
2018
2027
2019 @unfilteredmethod
2028 @unfilteredmethod
2020 def destroying(self):
2029 def destroying(self):
2021 '''Inform the repository that nodes are about to be destroyed.
2030 '''Inform the repository that nodes are about to be destroyed.
2022 Intended for use by strip and rollback, so there's a common
2031 Intended for use by strip and rollback, so there's a common
2023 place for anything that has to be done before destroying history.
2032 place for anything that has to be done before destroying history.
2024
2033
2025 This is mostly useful for saving state that is in memory and waiting
2034 This is mostly useful for saving state that is in memory and waiting
2026 to be flushed when the current lock is released. Because a call to
2035 to be flushed when the current lock is released. Because a call to
2027 destroyed is imminent, the repo will be invalidated causing those
2036 destroyed is imminent, the repo will be invalidated causing those
2028 changes to stay in memory (waiting for the next unlock), or vanish
2037 changes to stay in memory (waiting for the next unlock), or vanish
2029 completely.
2038 completely.
2030 '''
2039 '''
2031 # When using the same lock to commit and strip, the phasecache is left
2040 # When using the same lock to commit and strip, the phasecache is left
2032 # dirty after committing. Then when we strip, the repo is invalidated,
2041 # dirty after committing. Then when we strip, the repo is invalidated,
2033 # causing those changes to disappear.
2042 # causing those changes to disappear.
2034 if '_phasecache' in vars(self):
2043 if '_phasecache' in vars(self):
2035 self._phasecache.write()
2044 self._phasecache.write()
2036
2045
2037 @unfilteredmethod
2046 @unfilteredmethod
2038 def destroyed(self):
2047 def destroyed(self):
2039 '''Inform the repository that nodes have been destroyed.
2048 '''Inform the repository that nodes have been destroyed.
2040 Intended for use by strip and rollback, so there's a common
2049 Intended for use by strip and rollback, so there's a common
2041 place for anything that has to be done after destroying history.
2050 place for anything that has to be done after destroying history.
2042 '''
2051 '''
2043 # When one tries to:
2052 # When one tries to:
2044 # 1) destroy nodes thus calling this method (e.g. strip)
2053 # 1) destroy nodes thus calling this method (e.g. strip)
2045 # 2) use phasecache somewhere (e.g. commit)
2054 # 2) use phasecache somewhere (e.g. commit)
2046 #
2055 #
2047 # then 2) will fail because the phasecache contains nodes that were
2056 # then 2) will fail because the phasecache contains nodes that were
2048 # removed. We can either remove phasecache from the filecache,
2057 # removed. We can either remove phasecache from the filecache,
2049 # causing it to reload next time it is accessed, or simply filter
2058 # causing it to reload next time it is accessed, or simply filter
2050 # the removed nodes now and write the updated cache.
2059 # the removed nodes now and write the updated cache.
2051 self._phasecache.filterunknown(self)
2060 self._phasecache.filterunknown(self)
2052 self._phasecache.write()
2061 self._phasecache.write()
2053
2062
2054 # refresh all repository caches
2063 # refresh all repository caches
2055 self.updatecaches()
2064 self.updatecaches()
2056
2065
2057 # Ensure the persistent tag cache is updated. Doing it now
2066 # Ensure the persistent tag cache is updated. Doing it now
2058 # means that the tag cache only has to worry about destroyed
2067 # means that the tag cache only has to worry about destroyed
2059 # heads immediately after a strip/rollback. That in turn
2068 # heads immediately after a strip/rollback. That in turn
2060 # guarantees that "cachetip == currenttip" (comparing both rev
2069 # guarantees that "cachetip == currenttip" (comparing both rev
2061 # and node) always means no nodes have been added or destroyed.
2070 # and node) always means no nodes have been added or destroyed.
2062
2071
2063 # XXX this is suboptimal when qrefresh'ing: we strip the current
2072 # XXX this is suboptimal when qrefresh'ing: we strip the current
2064 # head, refresh the tag cache, then immediately add a new head.
2073 # head, refresh the tag cache, then immediately add a new head.
2065 # But I think doing it this way is necessary for the "instant
2074 # But I think doing it this way is necessary for the "instant
2066 # tag cache retrieval" case to work.
2075 # tag cache retrieval" case to work.
2067 self.invalidate()
2076 self.invalidate()
2068
2077
2069 def walk(self, match, node=None):
2078 def walk(self, match, node=None):
2070 '''
2079 '''
2071 walk recursively through the directory tree or a given
2080 walk recursively through the directory tree or a given
2072 changeset, finding all files matched by the match
2081 changeset, finding all files matched by the match
2073 function
2082 function
2074 '''
2083 '''
2075 self.ui.deprecwarn('use repo[node].walk instead of repo.walk', '4.3')
2084 self.ui.deprecwarn('use repo[node].walk instead of repo.walk', '4.3')
2076 return self[node].walk(match)
2085 return self[node].walk(match)
2077
2086
2078 def status(self, node1='.', node2=None, match=None,
2087 def status(self, node1='.', node2=None, match=None,
2079 ignored=False, clean=False, unknown=False,
2088 ignored=False, clean=False, unknown=False,
2080 listsubrepos=False):
2089 listsubrepos=False):
2081 '''a convenience method that calls node1.status(node2)'''
2090 '''a convenience method that calls node1.status(node2)'''
2082 return self[node1].status(node2, match, ignored, clean, unknown,
2091 return self[node1].status(node2, match, ignored, clean, unknown,
2083 listsubrepos)
2092 listsubrepos)
2084
2093
2085 def addpostdsstatus(self, ps):
2094 def addpostdsstatus(self, ps):
2086 """Add a callback to run within the wlock, at the point at which status
2095 """Add a callback to run within the wlock, at the point at which status
2087 fixups happen.
2096 fixups happen.
2088
2097
2089 On status completion, callback(wctx, status) will be called with the
2098 On status completion, callback(wctx, status) will be called with the
2090 wlock held, unless the dirstate has changed from underneath or the wlock
2099 wlock held, unless the dirstate has changed from underneath or the wlock
2091 couldn't be grabbed.
2100 couldn't be grabbed.
2092
2101
2093 Callbacks should not capture and use a cached copy of the dirstate --
2102 Callbacks should not capture and use a cached copy of the dirstate --
2094 it might change in the meanwhile. Instead, they should access the
2103 it might change in the meanwhile. Instead, they should access the
2095 dirstate via wctx.repo().dirstate.
2104 dirstate via wctx.repo().dirstate.
2096
2105
2097 This list is emptied out after each status run -- extensions should
2106 This list is emptied out after each status run -- extensions should
2098 make sure it adds to this list each time dirstate.status is called.
2107 make sure it adds to this list each time dirstate.status is called.
2099 Extensions should also make sure they don't call this for statuses
2108 Extensions should also make sure they don't call this for statuses
2100 that don't involve the dirstate.
2109 that don't involve the dirstate.
2101 """
2110 """
2102
2111
2103 # The list is located here for uniqueness reasons -- it is actually
2112 # The list is located here for uniqueness reasons -- it is actually
2104 # managed by the workingctx, but that isn't unique per-repo.
2113 # managed by the workingctx, but that isn't unique per-repo.
2105 self._postdsstatus.append(ps)
2114 self._postdsstatus.append(ps)
2106
2115
2107 def postdsstatus(self):
2116 def postdsstatus(self):
2108 """Used by workingctx to get the list of post-dirstate-status hooks."""
2117 """Used by workingctx to get the list of post-dirstate-status hooks."""
2109 return self._postdsstatus
2118 return self._postdsstatus
2110
2119
2111 def clearpostdsstatus(self):
2120 def clearpostdsstatus(self):
2112 """Used by workingctx to clear post-dirstate-status hooks."""
2121 """Used by workingctx to clear post-dirstate-status hooks."""
2113 del self._postdsstatus[:]
2122 del self._postdsstatus[:]
2114
2123
2115 def heads(self, start=None):
2124 def heads(self, start=None):
2116 if start is None:
2125 if start is None:
2117 cl = self.changelog
2126 cl = self.changelog
2118 headrevs = reversed(cl.headrevs())
2127 headrevs = reversed(cl.headrevs())
2119 return [cl.node(rev) for rev in headrevs]
2128 return [cl.node(rev) for rev in headrevs]
2120
2129
2121 heads = self.changelog.heads(start)
2130 heads = self.changelog.heads(start)
2122 # sort the output in rev descending order
2131 # sort the output in rev descending order
2123 return sorted(heads, key=self.changelog.rev, reverse=True)
2132 return sorted(heads, key=self.changelog.rev, reverse=True)
2124
2133
2125 def branchheads(self, branch=None, start=None, closed=False):
2134 def branchheads(self, branch=None, start=None, closed=False):
2126 '''return a (possibly filtered) list of heads for the given branch
2135 '''return a (possibly filtered) list of heads for the given branch
2127
2136
2128 Heads are returned in topological order, from newest to oldest.
2137 Heads are returned in topological order, from newest to oldest.
2129 If branch is None, use the dirstate branch.
2138 If branch is None, use the dirstate branch.
2130 If start is not None, return only heads reachable from start.
2139 If start is not None, return only heads reachable from start.
2131 If closed is True, return heads that are marked as closed as well.
2140 If closed is True, return heads that are marked as closed as well.
2132 '''
2141 '''
2133 if branch is None:
2142 if branch is None:
2134 branch = self[None].branch()
2143 branch = self[None].branch()
2135 branches = self.branchmap()
2144 branches = self.branchmap()
2136 if branch not in branches:
2145 if branch not in branches:
2137 return []
2146 return []
2138 # the cache returns heads ordered lowest to highest
2147 # the cache returns heads ordered lowest to highest
2139 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
2148 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
2140 if start is not None:
2149 if start is not None:
2141 # filter out the heads that cannot be reached from startrev
2150 # filter out the heads that cannot be reached from startrev
2142 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
2151 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
2143 bheads = [h for h in bheads if h in fbheads]
2152 bheads = [h for h in bheads if h in fbheads]
2144 return bheads
2153 return bheads
2145
2154
2146 def branches(self, nodes):
2155 def branches(self, nodes):
2147 if not nodes:
2156 if not nodes:
2148 nodes = [self.changelog.tip()]
2157 nodes = [self.changelog.tip()]
2149 b = []
2158 b = []
2150 for n in nodes:
2159 for n in nodes:
2151 t = n
2160 t = n
2152 while True:
2161 while True:
2153 p = self.changelog.parents(n)
2162 p = self.changelog.parents(n)
2154 if p[1] != nullid or p[0] == nullid:
2163 if p[1] != nullid or p[0] == nullid:
2155 b.append((t, n, p[0], p[1]))
2164 b.append((t, n, p[0], p[1]))
2156 break
2165 break
2157 n = p[0]
2166 n = p[0]
2158 return b
2167 return b
2159
2168
2160 def between(self, pairs):
2169 def between(self, pairs):
2161 r = []
2170 r = []
2162
2171
2163 for top, bottom in pairs:
2172 for top, bottom in pairs:
2164 n, l, i = top, [], 0
2173 n, l, i = top, [], 0
2165 f = 1
2174 f = 1
2166
2175
2167 while n != bottom and n != nullid:
2176 while n != bottom and n != nullid:
2168 p = self.changelog.parents(n)[0]
2177 p = self.changelog.parents(n)[0]
2169 if i == f:
2178 if i == f:
2170 l.append(n)
2179 l.append(n)
2171 f = f * 2
2180 f = f * 2
2172 n = p
2181 n = p
2173 i += 1
2182 i += 1
2174
2183
2175 r.append(l)
2184 r.append(l)
2176
2185
2177 return r
2186 return r
2178
2187
2179 def checkpush(self, pushop):
2188 def checkpush(self, pushop):
2180 """Extensions can override this function if additional checks have
2189 """Extensions can override this function if additional checks have
2181 to be performed before pushing, or call it if they override push
2190 to be performed before pushing, or call it if they override push
2182 command.
2191 command.
2183 """
2192 """
2184
2193
2185 @unfilteredpropertycache
2194 @unfilteredpropertycache
2186 def prepushoutgoinghooks(self):
2195 def prepushoutgoinghooks(self):
2187 """Return util.hooks consists of a pushop with repo, remote, outgoing
2196 """Return util.hooks consists of a pushop with repo, remote, outgoing
2188 methods, which are called before pushing changesets.
2197 methods, which are called before pushing changesets.
2189 """
2198 """
2190 return util.hooks()
2199 return util.hooks()
2191
2200
2192 def pushkey(self, namespace, key, old, new):
2201 def pushkey(self, namespace, key, old, new):
2193 try:
2202 try:
2194 tr = self.currenttransaction()
2203 tr = self.currenttransaction()
2195 hookargs = {}
2204 hookargs = {}
2196 if tr is not None:
2205 if tr is not None:
2197 hookargs.update(tr.hookargs)
2206 hookargs.update(tr.hookargs)
2198 hookargs['namespace'] = namespace
2207 hookargs['namespace'] = namespace
2199 hookargs['key'] = key
2208 hookargs['key'] = key
2200 hookargs['old'] = old
2209 hookargs['old'] = old
2201 hookargs['new'] = new
2210 hookargs['new'] = new
2202 self.hook('prepushkey', throw=True, **hookargs)
2211 self.hook('prepushkey', throw=True, **hookargs)
2203 except error.HookAbort as exc:
2212 except error.HookAbort as exc:
2204 self.ui.write_err(_("pushkey-abort: %s\n") % exc)
2213 self.ui.write_err(_("pushkey-abort: %s\n") % exc)
2205 if exc.hint:
2214 if exc.hint:
2206 self.ui.write_err(_("(%s)\n") % exc.hint)
2215 self.ui.write_err(_("(%s)\n") % exc.hint)
2207 return False
2216 return False
2208 self.ui.debug('pushing key for "%s:%s"\n' % (namespace, key))
2217 self.ui.debug('pushing key for "%s:%s"\n' % (namespace, key))
2209 ret = pushkey.push(self, namespace, key, old, new)
2218 ret = pushkey.push(self, namespace, key, old, new)
2210 def runhook():
2219 def runhook():
2211 self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
2220 self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
2212 ret=ret)
2221 ret=ret)
2213 self._afterlock(runhook)
2222 self._afterlock(runhook)
2214 return ret
2223 return ret
2215
2224
2216 def listkeys(self, namespace):
2225 def listkeys(self, namespace):
2217 self.hook('prelistkeys', throw=True, namespace=namespace)
2226 self.hook('prelistkeys', throw=True, namespace=namespace)
2218 self.ui.debug('listing keys for "%s"\n' % namespace)
2227 self.ui.debug('listing keys for "%s"\n' % namespace)
2219 values = pushkey.list(self, namespace)
2228 values = pushkey.list(self, namespace)
2220 self.hook('listkeys', namespace=namespace, values=values)
2229 self.hook('listkeys', namespace=namespace, values=values)
2221 return values
2230 return values
2222
2231
2223 def debugwireargs(self, one, two, three=None, four=None, five=None):
2232 def debugwireargs(self, one, two, three=None, four=None, five=None):
2224 '''used to test argument passing over the wire'''
2233 '''used to test argument passing over the wire'''
2225 return "%s %s %s %s %s" % (one, two, three, four, five)
2234 return "%s %s %s %s %s" % (one, two, three, four, five)
2226
2235
2227 def savecommitmessage(self, text):
2236 def savecommitmessage(self, text):
2228 fp = self.vfs('last-message.txt', 'wb')
2237 fp = self.vfs('last-message.txt', 'wb')
2229 try:
2238 try:
2230 fp.write(text)
2239 fp.write(text)
2231 finally:
2240 finally:
2232 fp.close()
2241 fp.close()
2233 return self.pathto(fp.name[len(self.root) + 1:])
2242 return self.pathto(fp.name[len(self.root) + 1:])
2234
2243
2235 # used to avoid circular references so destructors work
2244 # used to avoid circular references so destructors work
2236 def aftertrans(files):
2245 def aftertrans(files):
2237 renamefiles = [tuple(t) for t in files]
2246 renamefiles = [tuple(t) for t in files]
2238 def a():
2247 def a():
2239 for vfs, src, dest in renamefiles:
2248 for vfs, src, dest in renamefiles:
2240 # if src and dest refer to a same file, vfs.rename is a no-op,
2249 # if src and dest refer to a same file, vfs.rename is a no-op,
2241 # leaving both src and dest on disk. delete dest to make sure
2250 # leaving both src and dest on disk. delete dest to make sure
2242 # the rename couldn't be such a no-op.
2251 # the rename couldn't be such a no-op.
2243 vfs.tryunlink(dest)
2252 vfs.tryunlink(dest)
2244 try:
2253 try:
2245 vfs.rename(src, dest)
2254 vfs.rename(src, dest)
2246 except OSError: # journal file does not yet exist
2255 except OSError: # journal file does not yet exist
2247 pass
2256 pass
2248 return a
2257 return a
2249
2258
2250 def undoname(fn):
2259 def undoname(fn):
2251 base, name = os.path.split(fn)
2260 base, name = os.path.split(fn)
2252 assert name.startswith('journal')
2261 assert name.startswith('journal')
2253 return os.path.join(base, name.replace('journal', 'undo', 1))
2262 return os.path.join(base, name.replace('journal', 'undo', 1))
2254
2263
2255 def instance(ui, path, create):
2264 def instance(ui, path, create):
2256 return localrepository(ui, util.urllocalpath(path), create)
2265 return localrepository(ui, util.urllocalpath(path), create)
2257
2266
2258 def islocal(path):
2267 def islocal(path):
2259 return True
2268 return True
2260
2269
2261 def newreporequirements(repo):
2270 def newreporequirements(repo):
2262 """Determine the set of requirements for a new local repository.
2271 """Determine the set of requirements for a new local repository.
2263
2272
2264 Extensions can wrap this function to specify custom requirements for
2273 Extensions can wrap this function to specify custom requirements for
2265 new repositories.
2274 new repositories.
2266 """
2275 """
2267 ui = repo.ui
2276 ui = repo.ui
2268 requirements = {'revlogv1'}
2277 requirements = {'revlogv1'}
2269 if ui.configbool('format', 'usestore'):
2278 if ui.configbool('format', 'usestore'):
2270 requirements.add('store')
2279 requirements.add('store')
2271 if ui.configbool('format', 'usefncache'):
2280 if ui.configbool('format', 'usefncache'):
2272 requirements.add('fncache')
2281 requirements.add('fncache')
2273 if ui.configbool('format', 'dotencode'):
2282 if ui.configbool('format', 'dotencode'):
2274 requirements.add('dotencode')
2283 requirements.add('dotencode')
2275
2284
2276 compengine = ui.config('experimental', 'format.compression')
2285 compengine = ui.config('experimental', 'format.compression')
2277 if compengine not in util.compengines:
2286 if compengine not in util.compengines:
2278 raise error.Abort(_('compression engine %s defined by '
2287 raise error.Abort(_('compression engine %s defined by '
2279 'experimental.format.compression not available') %
2288 'experimental.format.compression not available') %
2280 compengine,
2289 compengine,
2281 hint=_('run "hg debuginstall" to list available '
2290 hint=_('run "hg debuginstall" to list available '
2282 'compression engines'))
2291 'compression engines'))
2283
2292
2284 # zlib is the historical default and doesn't need an explicit requirement.
2293 # zlib is the historical default and doesn't need an explicit requirement.
2285 if compengine != 'zlib':
2294 if compengine != 'zlib':
2286 requirements.add('exp-compression-%s' % compengine)
2295 requirements.add('exp-compression-%s' % compengine)
2287
2296
2288 if scmutil.gdinitconfig(ui):
2297 if scmutil.gdinitconfig(ui):
2289 requirements.add('generaldelta')
2298 requirements.add('generaldelta')
2290 if ui.configbool('experimental', 'treemanifest'):
2299 if ui.configbool('experimental', 'treemanifest'):
2291 requirements.add('treemanifest')
2300 requirements.add('treemanifest')
2292 if ui.configbool('experimental', 'manifestv2'):
2301 if ui.configbool('experimental', 'manifestv2'):
2293 requirements.add('manifestv2')
2302 requirements.add('manifestv2')
2294
2303
2295 revlogv2 = ui.config('experimental', 'revlogv2')
2304 revlogv2 = ui.config('experimental', 'revlogv2')
2296 if revlogv2 == 'enable-unstable-format-and-corrupt-my-data':
2305 if revlogv2 == 'enable-unstable-format-and-corrupt-my-data':
2297 requirements.remove('revlogv1')
2306 requirements.remove('revlogv1')
2298 # generaldelta is implied by revlogv2.
2307 # generaldelta is implied by revlogv2.
2299 requirements.discard('generaldelta')
2308 requirements.discard('generaldelta')
2300 requirements.add(REVLOGV2_REQUIREMENT)
2309 requirements.add(REVLOGV2_REQUIREMENT)
2301
2310
2302 return requirements
2311 return requirements
@@ -1,889 +1,905 b''
1 #require serve
1 #require serve
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [ui]
4 > [ui]
5 > logtemplate={rev}:{node|short} {desc|firstline}
5 > logtemplate={rev}:{node|short} {desc|firstline}
6 > [phases]
6 > [phases]
7 > publish=False
7 > publish=False
8 > [experimental]
8 > [experimental]
9 > stabilization=createmarkers,exchange
9 > stabilization=createmarkers,exchange
10 > EOF
10 > EOF
11
11
12 $ TESTHOOK='hooks.txnclose-bookmark.test=echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"'
13
12 initialize
14 initialize
13
15
14 $ hg init a
16 $ hg init a
15 $ cd a
17 $ cd a
16 $ echo 'test' > test
18 $ echo 'test' > test
17 $ hg commit -Am'test'
19 $ hg commit -Am'test'
18 adding test
20 adding test
19
21
20 set bookmarks
22 set bookmarks
21
23
22 $ hg bookmark X
24 $ hg bookmark X
23 $ hg bookmark Y
25 $ hg bookmark Y
24 $ hg bookmark Z
26 $ hg bookmark Z
25
27
26 import bookmark by name
28 import bookmark by name
27
29
28 $ hg init ../b
30 $ hg init ../b
29 $ cd ../b
31 $ cd ../b
30 $ hg book Y
32 $ hg book Y
31 $ hg book
33 $ hg book
32 * Y -1:000000000000
34 * Y -1:000000000000
33 $ hg pull ../a
35 $ hg pull ../a --config "$TESTHOOK"
34 pulling from ../a
36 pulling from ../a
35 requesting all changes
37 requesting all changes
36 adding changesets
38 adding changesets
37 adding manifests
39 adding manifests
38 adding file changes
40 adding file changes
39 added 1 changesets with 1 changes to 1 files
41 added 1 changesets with 1 changes to 1 files
40 adding remote bookmark X
42 adding remote bookmark X
41 updating bookmark Y
43 updating bookmark Y
42 adding remote bookmark Z
44 adding remote bookmark Z
43 new changesets 4e3505fd9583
45 new changesets 4e3505fd9583
46 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
47 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
48 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
44 (run 'hg update' to get a working copy)
49 (run 'hg update' to get a working copy)
45 $ hg bookmarks
50 $ hg bookmarks
46 X 0:4e3505fd9583
51 X 0:4e3505fd9583
47 * Y 0:4e3505fd9583
52 * Y 0:4e3505fd9583
48 Z 0:4e3505fd9583
53 Z 0:4e3505fd9583
49 $ hg debugpushkey ../a namespaces
54 $ hg debugpushkey ../a namespaces
50 bookmarks
55 bookmarks
51 namespaces
56 namespaces
52 obsolete
57 obsolete
53 phases
58 phases
54 $ hg debugpushkey ../a bookmarks
59 $ hg debugpushkey ../a bookmarks
55 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
60 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
56 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
61 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
57 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
62 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
58
63
59 delete the bookmark to re-pull it
64 delete the bookmark to re-pull it
60
65
61 $ hg book -d X
66 $ hg book -d X
62 $ hg pull -B X ../a
67 $ hg pull -B X ../a
63 pulling from ../a
68 pulling from ../a
64 no changes found
69 no changes found
65 adding remote bookmark X
70 adding remote bookmark X
66
71
67 finally no-op pull
72 finally no-op pull
68
73
69 $ hg pull -B X ../a
74 $ hg pull -B X ../a
70 pulling from ../a
75 pulling from ../a
71 no changes found
76 no changes found
72 $ hg bookmark
77 $ hg bookmark
73 X 0:4e3505fd9583
78 X 0:4e3505fd9583
74 * Y 0:4e3505fd9583
79 * Y 0:4e3505fd9583
75 Z 0:4e3505fd9583
80 Z 0:4e3505fd9583
76
81
77 export bookmark by name
82 export bookmark by name
78
83
79 $ hg bookmark W
84 $ hg bookmark W
80 $ hg bookmark foo
85 $ hg bookmark foo
81 $ hg bookmark foobar
86 $ hg bookmark foobar
82 $ hg push -B W ../a
87 $ hg push -B W ../a
83 pushing to ../a
88 pushing to ../a
84 searching for changes
89 searching for changes
85 no changes found
90 no changes found
86 exporting bookmark W
91 exporting bookmark W
87 [1]
92 [1]
88 $ hg -R ../a bookmarks
93 $ hg -R ../a bookmarks
89 W -1:000000000000
94 W -1:000000000000
90 X 0:4e3505fd9583
95 X 0:4e3505fd9583
91 Y 0:4e3505fd9583
96 Y 0:4e3505fd9583
92 * Z 0:4e3505fd9583
97 * Z 0:4e3505fd9583
93
98
94 delete a remote bookmark
99 delete a remote bookmark
95
100
96 $ hg book -d W
101 $ hg book -d W
97 $ hg push -B W ../a
102 $ hg push -B W ../a --config "$TESTHOOK"
98 pushing to ../a
103 pushing to ../a
99 searching for changes
104 searching for changes
100 no changes found
105 no changes found
106 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
101 deleting remote bookmark W
107 deleting remote bookmark W
102 [1]
108 [1]
103
109
104 export the active bookmark
110 export the active bookmark
105
111
106 $ hg bookmark V
112 $ hg bookmark V
107 $ hg push -B . ../a
113 $ hg push -B . ../a
108 pushing to ../a
114 pushing to ../a
109 searching for changes
115 searching for changes
110 no changes found
116 no changes found
111 exporting bookmark V
117 exporting bookmark V
112 [1]
118 [1]
113
119
114 exporting the active bookmark with 'push -B .'
120 exporting the active bookmark with 'push -B .'
115 demand that one of the bookmarks is activated
121 demand that one of the bookmarks is activated
116
122
117 $ hg update -r default
123 $ hg update -r default
118 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 (leaving bookmark V)
125 (leaving bookmark V)
120 $ hg push -B . ../a
126 $ hg push -B . ../a
121 abort: no active bookmark
127 abort: no active bookmark
122 [255]
128 [255]
123 $ hg update -r V
129 $ hg update -r V
124 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
130 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
125 (activating bookmark V)
131 (activating bookmark V)
126
132
127 delete the bookmark
133 delete the bookmark
128
134
129 $ hg book -d V
135 $ hg book -d V
130 $ hg push -B V ../a
136 $ hg push -B V ../a
131 pushing to ../a
137 pushing to ../a
132 searching for changes
138 searching for changes
133 no changes found
139 no changes found
134 deleting remote bookmark V
140 deleting remote bookmark V
135 [1]
141 [1]
136 $ hg up foobar
142 $ hg up foobar
137 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 (activating bookmark foobar)
144 (activating bookmark foobar)
139
145
140 push/pull name that doesn't exist
146 push/pull name that doesn't exist
141
147
142 $ hg push -B badname ../a
148 $ hg push -B badname ../a
143 pushing to ../a
149 pushing to ../a
144 searching for changes
150 searching for changes
145 bookmark badname does not exist on the local or remote repository!
151 bookmark badname does not exist on the local or remote repository!
146 no changes found
152 no changes found
147 [2]
153 [2]
148 $ hg pull -B anotherbadname ../a
154 $ hg pull -B anotherbadname ../a
149 pulling from ../a
155 pulling from ../a
150 abort: remote bookmark anotherbadname not found!
156 abort: remote bookmark anotherbadname not found!
151 [255]
157 [255]
152
158
153 divergent bookmarks
159 divergent bookmarks
154
160
155 $ cd ../a
161 $ cd ../a
156 $ echo c1 > f1
162 $ echo c1 > f1
157 $ hg ci -Am1
163 $ hg ci -Am1
158 adding f1
164 adding f1
159 $ hg book -f @
165 $ hg book -f @
160 $ hg book -f X
166 $ hg book -f X
161 $ hg book
167 $ hg book
162 @ 1:0d2164f0ce0d
168 @ 1:0d2164f0ce0d
163 * X 1:0d2164f0ce0d
169 * X 1:0d2164f0ce0d
164 Y 0:4e3505fd9583
170 Y 0:4e3505fd9583
165 Z 1:0d2164f0ce0d
171 Z 1:0d2164f0ce0d
166
172
167 $ cd ../b
173 $ cd ../b
168 $ hg up
174 $ hg up --config
169 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 updating bookmark foobar
176 updating bookmark foobar
171 $ echo c2 > f2
177 $ echo c2 > f2
172 $ hg ci -Am2
178 $ hg ci -Am2
173 adding f2
179 adding f2
174 $ hg book -if @
180 $ hg book -if @
175 $ hg book -if X
181 $ hg book -if X
176 $ hg book
182 $ hg book
177 @ 1:9b140be10808
183 @ 1:9b140be10808
178 X 1:9b140be10808
184 X 1:9b140be10808
179 Y 0:4e3505fd9583
185 Y 0:4e3505fd9583
180 Z 0:4e3505fd9583
186 Z 0:4e3505fd9583
181 foo -1:000000000000
187 foo -1:000000000000
182 * foobar 1:9b140be10808
188 * foobar 1:9b140be10808
183
189
184 $ hg pull --config paths.foo=../a foo
190 $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
185 pulling from $TESTTMP/a (glob)
191 pulling from $TESTTMP/a (glob)
186 searching for changes
192 searching for changes
187 adding changesets
193 adding changesets
188 adding manifests
194 adding manifests
189 adding file changes
195 adding file changes
190 added 1 changesets with 1 changes to 1 files (+1 heads)
196 added 1 changesets with 1 changes to 1 files (+1 heads)
191 divergent bookmark @ stored as @foo
197 divergent bookmark @ stored as @foo
192 divergent bookmark X stored as X@foo
198 divergent bookmark X stored as X@foo
193 updating bookmark Z
199 updating bookmark Z
194 new changesets 0d2164f0ce0d
200 new changesets 0d2164f0ce0d
201 test-hook-bookmark: @foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
202 test-hook-bookmark: X@foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
203 test-hook-bookmark: Z: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
195 (run 'hg heads' to see heads, 'hg merge' to merge)
204 (run 'hg heads' to see heads, 'hg merge' to merge)
196 $ hg book
205 $ hg book
197 @ 1:9b140be10808
206 @ 1:9b140be10808
198 @foo 2:0d2164f0ce0d
207 @foo 2:0d2164f0ce0d
199 X 1:9b140be10808
208 X 1:9b140be10808
200 X@foo 2:0d2164f0ce0d
209 X@foo 2:0d2164f0ce0d
201 Y 0:4e3505fd9583
210 Y 0:4e3505fd9583
202 Z 2:0d2164f0ce0d
211 Z 2:0d2164f0ce0d
203 foo -1:000000000000
212 foo -1:000000000000
204 * foobar 1:9b140be10808
213 * foobar 1:9b140be10808
205
214
206 (test that too many divergence of bookmark)
215 (test that too many divergence of bookmark)
207
216
208 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
217 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
209 $ hg pull ../a
218 $ hg pull ../a
210 pulling from ../a
219 pulling from ../a
211 searching for changes
220 searching for changes
212 no changes found
221 no changes found
213 warning: failed to assign numbered name to divergent bookmark X
222 warning: failed to assign numbered name to divergent bookmark X
214 divergent bookmark @ stored as @1
223 divergent bookmark @ stored as @1
215 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
224 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
216 X 1:9b140be10808
225 X 1:9b140be10808
217 X@foo 2:0d2164f0ce0d
226 X@foo 2:0d2164f0ce0d
218
227
219 (test that remotely diverged bookmarks are reused if they aren't changed)
228 (test that remotely diverged bookmarks are reused if they aren't changed)
220
229
221 $ hg bookmarks | grep '^ @'
230 $ hg bookmarks | grep '^ @'
222 @ 1:9b140be10808
231 @ 1:9b140be10808
223 @1 2:0d2164f0ce0d
232 @1 2:0d2164f0ce0d
224 @foo 2:0d2164f0ce0d
233 @foo 2:0d2164f0ce0d
225 $ hg pull ../a
234 $ hg pull ../a
226 pulling from ../a
235 pulling from ../a
227 searching for changes
236 searching for changes
228 no changes found
237 no changes found
229 warning: failed to assign numbered name to divergent bookmark X
238 warning: failed to assign numbered name to divergent bookmark X
230 divergent bookmark @ stored as @1
239 divergent bookmark @ stored as @1
231 $ hg bookmarks | grep '^ @'
240 $ hg bookmarks | grep '^ @'
232 @ 1:9b140be10808
241 @ 1:9b140be10808
233 @1 2:0d2164f0ce0d
242 @1 2:0d2164f0ce0d
234 @foo 2:0d2164f0ce0d
243 @foo 2:0d2164f0ce0d
235
244
236 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
245 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
237 $ hg bookmarks -d "@1"
246 $ hg bookmarks -d "@1"
238
247
239 $ hg push -f ../a
248 $ hg push -f ../a
240 pushing to ../a
249 pushing to ../a
241 searching for changes
250 searching for changes
242 adding changesets
251 adding changesets
243 adding manifests
252 adding manifests
244 adding file changes
253 adding file changes
245 added 1 changesets with 1 changes to 1 files (+1 heads)
254 added 1 changesets with 1 changes to 1 files (+1 heads)
246 $ hg -R ../a book
255 $ hg -R ../a book
247 @ 1:0d2164f0ce0d
256 @ 1:0d2164f0ce0d
248 * X 1:0d2164f0ce0d
257 * X 1:0d2164f0ce0d
249 Y 0:4e3505fd9583
258 Y 0:4e3505fd9583
250 Z 1:0d2164f0ce0d
259 Z 1:0d2164f0ce0d
251
260
252 explicit pull should overwrite the local version (issue4439)
261 explicit pull should overwrite the local version (issue4439)
253
262
254 $ hg update -r X
263 $ hg update -r X
255 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
264 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 (activating bookmark X)
265 (activating bookmark X)
257 $ hg pull --config paths.foo=../a foo -B .
266 $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
258 pulling from $TESTTMP/a (glob)
267 pulling from $TESTTMP/a (glob)
259 no changes found
268 no changes found
260 divergent bookmark @ stored as @foo
269 divergent bookmark @ stored as @foo
261 importing bookmark X
270 importing bookmark X
271 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
272 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
262
273
263 reinstall state for further testing:
274 reinstall state for further testing:
264
275
265 $ hg book -fr 9b140be10808 X
276 $ hg book -fr 9b140be10808 X
266
277
267 revsets should not ignore divergent bookmarks
278 revsets should not ignore divergent bookmarks
268
279
269 $ hg bookmark -fr 1 Z
280 $ hg bookmark -fr 1 Z
270 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
281 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
271 0:4e3505fd9583 Y
282 0:4e3505fd9583 Y
272 1:9b140be10808 @ X Z foobar
283 1:9b140be10808 @ X Z foobar
273 2:0d2164f0ce0d @foo X@foo
284 2:0d2164f0ce0d @foo X@foo
274 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
285 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
275 2:0d2164f0ce0d @foo X@foo
286 2:0d2164f0ce0d @foo X@foo
276 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
287 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
277 2:0d2164f0ce0d @foo X@foo
288 2:0d2164f0ce0d @foo X@foo
278
289
279 update a remote bookmark from a non-head to a head
290 update a remote bookmark from a non-head to a head
280
291
281 $ hg up -q Y
292 $ hg up -q Y
282 $ echo c3 > f2
293 $ echo c3 > f2
283 $ hg ci -Am3
294 $ hg ci -Am3
284 adding f2
295 adding f2
285 created new head
296 created new head
286 $ hg push ../a
297 $ hg push ../a --config "$TESTHOOK"
287 pushing to ../a
298 pushing to ../a
288 searching for changes
299 searching for changes
289 adding changesets
300 adding changesets
290 adding manifests
301 adding manifests
291 adding file changes
302 adding file changes
292 added 1 changesets with 1 changes to 1 files (+1 heads)
303 added 1 changesets with 1 changes to 1 files (+1 heads)
304 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
293 updating bookmark Y
305 updating bookmark Y
294 $ hg -R ../a book
306 $ hg -R ../a book
295 @ 1:0d2164f0ce0d
307 @ 1:0d2164f0ce0d
296 * X 1:0d2164f0ce0d
308 * X 1:0d2164f0ce0d
297 Y 3:f6fc62dde3c0
309 Y 3:f6fc62dde3c0
298 Z 1:0d2164f0ce0d
310 Z 1:0d2164f0ce0d
299
311
300 update a bookmark in the middle of a client pulling changes
312 update a bookmark in the middle of a client pulling changes
301
313
302 $ cd ..
314 $ cd ..
303 $ hg clone -q a pull-race
315 $ hg clone -q a pull-race
304
316
305 We want to use http because it is stateless and therefore more susceptible to
317 We want to use http because it is stateless and therefore more susceptible to
306 race conditions
318 race conditions
307
319
308 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
320 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
309 $ cat pull-race.pid >> $DAEMON_PIDS
321 $ cat pull-race.pid >> $DAEMON_PIDS
310
322
311 $ cat <<EOF > $TESTTMP/out_makecommit.sh
323 $ cat <<EOF > $TESTTMP/out_makecommit.sh
312 > #!/bin/sh
324 > #!/bin/sh
313 > hg ci -Am5
325 > hg ci -Am5
314 > echo committed in pull-race
326 > echo committed in pull-race
315 > EOF
327 > EOF
316
328
317 $ hg clone -q http://localhost:$HGPORT/ pull-race2
329 $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
330 test-hook-bookmark: @: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
331 test-hook-bookmark: X: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
332 test-hook-bookmark: Y: -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
333 test-hook-bookmark: Z: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
318 $ cd pull-race
334 $ cd pull-race
319 $ hg up -q Y
335 $ hg up -q Y
320 $ echo c4 > f2
336 $ echo c4 > f2
321 $ hg ci -Am4
337 $ hg ci -Am4
322 $ echo c5 > f3
338 $ echo c5 > f3
323 $ cat <<EOF > .hg/hgrc
339 $ cat <<EOF > .hg/hgrc
324 > [hooks]
340 > [hooks]
325 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
341 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
326 > EOF
342 > EOF
327
343
328 (new config needs a server restart)
344 (new config needs a server restart)
329
345
330 $ cd ..
346 $ cd ..
331 $ killdaemons.py
347 $ killdaemons.py
332 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
348 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
333 $ cat pull-race.pid >> $DAEMON_PIDS
349 $ cat pull-race.pid >> $DAEMON_PIDS
334 $ cd pull-race2
350 $ cd pull-race2
335 $ hg -R $TESTTMP/pull-race book
351 $ hg -R $TESTTMP/pull-race book
336 @ 1:0d2164f0ce0d
352 @ 1:0d2164f0ce0d
337 X 1:0d2164f0ce0d
353 X 1:0d2164f0ce0d
338 * Y 4:b0a5eff05604
354 * Y 4:b0a5eff05604
339 Z 1:0d2164f0ce0d
355 Z 1:0d2164f0ce0d
340 $ hg pull
356 $ hg pull
341 pulling from http://localhost:$HGPORT/
357 pulling from http://localhost:$HGPORT/
342 searching for changes
358 searching for changes
343 adding changesets
359 adding changesets
344 adding manifests
360 adding manifests
345 adding file changes
361 adding file changes
346 added 1 changesets with 1 changes to 1 files
362 added 1 changesets with 1 changes to 1 files
347 updating bookmark Y
363 updating bookmark Y
348 new changesets b0a5eff05604
364 new changesets b0a5eff05604
349 (run 'hg update' to get a working copy)
365 (run 'hg update' to get a working copy)
350 $ hg book
366 $ hg book
351 * @ 1:0d2164f0ce0d
367 * @ 1:0d2164f0ce0d
352 X 1:0d2164f0ce0d
368 X 1:0d2164f0ce0d
353 Y 4:b0a5eff05604
369 Y 4:b0a5eff05604
354 Z 1:0d2164f0ce0d
370 Z 1:0d2164f0ce0d
355
371
356 Update a bookmark right after the initial lookup -B (issue4689)
372 Update a bookmark right after the initial lookup -B (issue4689)
357
373
358 $ echo c6 > ../pull-race/f3 # to be committed during the race
374 $ echo c6 > ../pull-race/f3 # to be committed during the race
359 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
375 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
360 > #!/bin/sh
376 > #!/bin/sh
361 > if hg st | grep -q M; then
377 > if hg st | grep -q M; then
362 > hg commit -m race
378 > hg commit -m race
363 > echo committed in pull-race
379 > echo committed in pull-race
364 > else
380 > else
365 > exit 0
381 > exit 0
366 > fi
382 > fi
367 > EOF
383 > EOF
368 $ cat <<EOF > ../pull-race/.hg/hgrc
384 $ cat <<EOF > ../pull-race/.hg/hgrc
369 > [hooks]
385 > [hooks]
370 > # If anything to commit, commit it right after the first key listing used
386 > # If anything to commit, commit it right after the first key listing used
371 > # during lookup. This makes the commit appear before the actual getbundle
387 > # during lookup. This makes the commit appear before the actual getbundle
372 > # call.
388 > # call.
373 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
389 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
374 > EOF
390 > EOF
375
391
376 (new config need server restart)
392 (new config need server restart)
377
393
378 $ killdaemons.py
394 $ killdaemons.py
379 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
395 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
380 $ cat ../pull-race.pid >> $DAEMON_PIDS
396 $ cat ../pull-race.pid >> $DAEMON_PIDS
381
397
382 $ hg -R $TESTTMP/pull-race book
398 $ hg -R $TESTTMP/pull-race book
383 @ 1:0d2164f0ce0d
399 @ 1:0d2164f0ce0d
384 X 1:0d2164f0ce0d
400 X 1:0d2164f0ce0d
385 * Y 5:35d1ef0a8d1b
401 * Y 5:35d1ef0a8d1b
386 Z 1:0d2164f0ce0d
402 Z 1:0d2164f0ce0d
387 $ hg update -r Y
403 $ hg update -r Y
388 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
389 (activating bookmark Y)
405 (activating bookmark Y)
390 $ hg pull -B .
406 $ hg pull -B .
391 pulling from http://localhost:$HGPORT/
407 pulling from http://localhost:$HGPORT/
392 searching for changes
408 searching for changes
393 adding changesets
409 adding changesets
394 adding manifests
410 adding manifests
395 adding file changes
411 adding file changes
396 added 1 changesets with 1 changes to 1 files
412 added 1 changesets with 1 changes to 1 files
397 updating bookmark Y
413 updating bookmark Y
398 new changesets 35d1ef0a8d1b
414 new changesets 35d1ef0a8d1b
399 (run 'hg update' to get a working copy)
415 (run 'hg update' to get a working copy)
400 $ hg book
416 $ hg book
401 @ 1:0d2164f0ce0d
417 @ 1:0d2164f0ce0d
402 X 1:0d2164f0ce0d
418 X 1:0d2164f0ce0d
403 * Y 5:35d1ef0a8d1b
419 * Y 5:35d1ef0a8d1b
404 Z 1:0d2164f0ce0d
420 Z 1:0d2164f0ce0d
405
421
406 (done with this section of the test)
422 (done with this section of the test)
407
423
408 $ killdaemons.py
424 $ killdaemons.py
409 $ cd ../b
425 $ cd ../b
410
426
411 diverging a remote bookmark fails
427 diverging a remote bookmark fails
412
428
413 $ hg up -q 4e3505fd9583
429 $ hg up -q 4e3505fd9583
414 $ echo c4 > f2
430 $ echo c4 > f2
415 $ hg ci -Am4
431 $ hg ci -Am4
416 adding f2
432 adding f2
417 created new head
433 created new head
418 $ echo c5 > f2
434 $ echo c5 > f2
419 $ hg ci -Am5
435 $ hg ci -Am5
420 $ hg log -G
436 $ hg log -G
421 @ 5:c922c0139ca0 5
437 @ 5:c922c0139ca0 5
422 |
438 |
423 o 4:4efff6d98829 4
439 o 4:4efff6d98829 4
424 |
440 |
425 | o 3:f6fc62dde3c0 3
441 | o 3:f6fc62dde3c0 3
426 |/
442 |/
427 | o 2:0d2164f0ce0d 1
443 | o 2:0d2164f0ce0d 1
428 |/
444 |/
429 | o 1:9b140be10808 2
445 | o 1:9b140be10808 2
430 |/
446 |/
431 o 0:4e3505fd9583 test
447 o 0:4e3505fd9583 test
432
448
433
449
434 $ hg book -f Y
450 $ hg book -f Y
435
451
436 $ cat <<EOF > ../a/.hg/hgrc
452 $ cat <<EOF > ../a/.hg/hgrc
437 > [web]
453 > [web]
438 > push_ssl = false
454 > push_ssl = false
439 > allow_push = *
455 > allow_push = *
440 > EOF
456 > EOF
441
457
442 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
458 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
443 $ cat ../hg2.pid >> $DAEMON_PIDS
459 $ cat ../hg2.pid >> $DAEMON_PIDS
444
460
445 $ hg push http://localhost:$HGPORT2/
461 $ hg push http://localhost:$HGPORT2/
446 pushing to http://localhost:$HGPORT2/
462 pushing to http://localhost:$HGPORT2/
447 searching for changes
463 searching for changes
448 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
464 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
449 (merge or see 'hg help push' for details about pushing new heads)
465 (merge or see 'hg help push' for details about pushing new heads)
450 [255]
466 [255]
451 $ hg -R ../a book
467 $ hg -R ../a book
452 @ 1:0d2164f0ce0d
468 @ 1:0d2164f0ce0d
453 * X 1:0d2164f0ce0d
469 * X 1:0d2164f0ce0d
454 Y 3:f6fc62dde3c0
470 Y 3:f6fc62dde3c0
455 Z 1:0d2164f0ce0d
471 Z 1:0d2164f0ce0d
456
472
457
473
458 Unrelated marker does not alter the decision
474 Unrelated marker does not alter the decision
459
475
460 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
476 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
461 $ hg push http://localhost:$HGPORT2/
477 $ hg push http://localhost:$HGPORT2/
462 pushing to http://localhost:$HGPORT2/
478 pushing to http://localhost:$HGPORT2/
463 searching for changes
479 searching for changes
464 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
480 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
465 (merge or see 'hg help push' for details about pushing new heads)
481 (merge or see 'hg help push' for details about pushing new heads)
466 [255]
482 [255]
467 $ hg -R ../a book
483 $ hg -R ../a book
468 @ 1:0d2164f0ce0d
484 @ 1:0d2164f0ce0d
469 * X 1:0d2164f0ce0d
485 * X 1:0d2164f0ce0d
470 Y 3:f6fc62dde3c0
486 Y 3:f6fc62dde3c0
471 Z 1:0d2164f0ce0d
487 Z 1:0d2164f0ce0d
472
488
473 Update to a successor works
489 Update to a successor works
474
490
475 $ hg id --debug -r 3
491 $ hg id --debug -r 3
476 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
492 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
477 $ hg id --debug -r 4
493 $ hg id --debug -r 4
478 4efff6d98829d9c824c621afd6e3f01865f5439f
494 4efff6d98829d9c824c621afd6e3f01865f5439f
479 $ hg id --debug -r 5
495 $ hg id --debug -r 5
480 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
496 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
481 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
497 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
482 obsoleted 1 changesets
498 obsoleted 1 changesets
483 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
499 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
484 $ hg push http://localhost:$HGPORT2/
500 $ hg push http://localhost:$HGPORT2/
485 pushing to http://localhost:$HGPORT2/
501 pushing to http://localhost:$HGPORT2/
486 searching for changes
502 searching for changes
487 remote: adding changesets
503 remote: adding changesets
488 remote: adding manifests
504 remote: adding manifests
489 remote: adding file changes
505 remote: adding file changes
490 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
506 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
491 remote: 2 new obsolescence markers
507 remote: 2 new obsolescence markers
492 remote: obsoleted 1 changesets
508 remote: obsoleted 1 changesets
493 updating bookmark Y
509 updating bookmark Y
494 $ hg -R ../a book
510 $ hg -R ../a book
495 @ 1:0d2164f0ce0d
511 @ 1:0d2164f0ce0d
496 * X 1:0d2164f0ce0d
512 * X 1:0d2164f0ce0d
497 Y 5:c922c0139ca0
513 Y 5:c922c0139ca0
498 Z 1:0d2164f0ce0d
514 Z 1:0d2164f0ce0d
499
515
500 hgweb
516 hgweb
501
517
502 $ cat <<EOF > .hg/hgrc
518 $ cat <<EOF > .hg/hgrc
503 > [web]
519 > [web]
504 > push_ssl = false
520 > push_ssl = false
505 > allow_push = *
521 > allow_push = *
506 > EOF
522 > EOF
507
523
508 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
524 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
509 $ cat ../hg.pid >> $DAEMON_PIDS
525 $ cat ../hg.pid >> $DAEMON_PIDS
510 $ cd ../a
526 $ cd ../a
511
527
512 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
528 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
513 bookmarks
529 bookmarks
514 namespaces
530 namespaces
515 obsolete
531 obsolete
516 phases
532 phases
517 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
533 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
518 @ 9b140be1080824d768c5a4691a564088eede71f9
534 @ 9b140be1080824d768c5a4691a564088eede71f9
519 X 9b140be1080824d768c5a4691a564088eede71f9
535 X 9b140be1080824d768c5a4691a564088eede71f9
520 Y c922c0139ca03858f655e4a2af4dd02796a63969
536 Y c922c0139ca03858f655e4a2af4dd02796a63969
521 Z 9b140be1080824d768c5a4691a564088eede71f9
537 Z 9b140be1080824d768c5a4691a564088eede71f9
522 foo 0000000000000000000000000000000000000000
538 foo 0000000000000000000000000000000000000000
523 foobar 9b140be1080824d768c5a4691a564088eede71f9
539 foobar 9b140be1080824d768c5a4691a564088eede71f9
524 $ hg out -B http://localhost:$HGPORT/
540 $ hg out -B http://localhost:$HGPORT/
525 comparing with http://localhost:$HGPORT/
541 comparing with http://localhost:$HGPORT/
526 searching for changed bookmarks
542 searching for changed bookmarks
527 @ 0d2164f0ce0d
543 @ 0d2164f0ce0d
528 X 0d2164f0ce0d
544 X 0d2164f0ce0d
529 Z 0d2164f0ce0d
545 Z 0d2164f0ce0d
530 foo
546 foo
531 foobar
547 foobar
532 $ hg push -B Z http://localhost:$HGPORT/
548 $ hg push -B Z http://localhost:$HGPORT/
533 pushing to http://localhost:$HGPORT/
549 pushing to http://localhost:$HGPORT/
534 searching for changes
550 searching for changes
535 no changes found
551 no changes found
536 updating bookmark Z
552 updating bookmark Z
537 [1]
553 [1]
538 $ hg book -d Z
554 $ hg book -d Z
539 $ hg in -B http://localhost:$HGPORT/
555 $ hg in -B http://localhost:$HGPORT/
540 comparing with http://localhost:$HGPORT/
556 comparing with http://localhost:$HGPORT/
541 searching for changed bookmarks
557 searching for changed bookmarks
542 @ 9b140be10808
558 @ 9b140be10808
543 X 9b140be10808
559 X 9b140be10808
544 Z 0d2164f0ce0d
560 Z 0d2164f0ce0d
545 foo 000000000000
561 foo 000000000000
546 foobar 9b140be10808
562 foobar 9b140be10808
547 $ hg pull -B Z http://localhost:$HGPORT/
563 $ hg pull -B Z http://localhost:$HGPORT/
548 pulling from http://localhost:$HGPORT/
564 pulling from http://localhost:$HGPORT/
549 no changes found
565 no changes found
550 divergent bookmark @ stored as @1
566 divergent bookmark @ stored as @1
551 divergent bookmark X stored as X@1
567 divergent bookmark X stored as X@1
552 adding remote bookmark Z
568 adding remote bookmark Z
553 adding remote bookmark foo
569 adding remote bookmark foo
554 adding remote bookmark foobar
570 adding remote bookmark foobar
555 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
571 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
556 requesting all changes
572 requesting all changes
557 adding changesets
573 adding changesets
558 adding manifests
574 adding manifests
559 adding file changes
575 adding file changes
560 added 5 changesets with 5 changes to 3 files (+2 heads)
576 added 5 changesets with 5 changes to 3 files (+2 heads)
561 2 new obsolescence markers
577 2 new obsolescence markers
562 new changesets 4e3505fd9583:c922c0139ca0
578 new changesets 4e3505fd9583:c922c0139ca0
563 updating to bookmark @
579 updating to bookmark @
564 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
580 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
565 $ hg -R cloned-bookmarks bookmarks
581 $ hg -R cloned-bookmarks bookmarks
566 * @ 1:9b140be10808
582 * @ 1:9b140be10808
567 X 1:9b140be10808
583 X 1:9b140be10808
568 Y 4:c922c0139ca0
584 Y 4:c922c0139ca0
569 Z 2:0d2164f0ce0d
585 Z 2:0d2164f0ce0d
570 foo -1:000000000000
586 foo -1:000000000000
571 foobar 1:9b140be10808
587 foobar 1:9b140be10808
572
588
573 $ cd ..
589 $ cd ..
574
590
575 Test to show result of bookmarks comparison
591 Test to show result of bookmarks comparison
576
592
577 $ mkdir bmcomparison
593 $ mkdir bmcomparison
578 $ cd bmcomparison
594 $ cd bmcomparison
579
595
580 $ hg init source
596 $ hg init source
581 $ hg -R source debugbuilddag '+2*2*3*4'
597 $ hg -R source debugbuilddag '+2*2*3*4'
582 $ hg -R source log -G --template '{rev}:{node|short}'
598 $ hg -R source log -G --template '{rev}:{node|short}'
583 o 4:e7bd5218ca15
599 o 4:e7bd5218ca15
584 |
600 |
585 | o 3:6100d3090acf
601 | o 3:6100d3090acf
586 |/
602 |/
587 | o 2:fa942426a6fd
603 | o 2:fa942426a6fd
588 |/
604 |/
589 | o 1:66f7d451a68b
605 | o 1:66f7d451a68b
590 |/
606 |/
591 o 0:1ea73414a91b
607 o 0:1ea73414a91b
592
608
593 $ hg -R source bookmarks -r 0 SAME
609 $ hg -R source bookmarks -r 0 SAME
594 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
610 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
595 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
611 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
596 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
612 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
597 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
613 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
598 $ hg -R source bookmarks -r 1 DIVERGED
614 $ hg -R source bookmarks -r 1 DIVERGED
599
615
600 $ hg clone -U source repo1
616 $ hg clone -U source repo1
601
617
602 (test that incoming/outgoing exit with 1, if there is no bookmark to
618 (test that incoming/outgoing exit with 1, if there is no bookmark to
603 be exchanged)
619 be exchanged)
604
620
605 $ hg -R repo1 incoming -B
621 $ hg -R repo1 incoming -B
606 comparing with $TESTTMP/bmcomparison/source (glob)
622 comparing with $TESTTMP/bmcomparison/source (glob)
607 searching for changed bookmarks
623 searching for changed bookmarks
608 no changed bookmarks found
624 no changed bookmarks found
609 [1]
625 [1]
610 $ hg -R repo1 outgoing -B
626 $ hg -R repo1 outgoing -B
611 comparing with $TESTTMP/bmcomparison/source (glob)
627 comparing with $TESTTMP/bmcomparison/source (glob)
612 searching for changed bookmarks
628 searching for changed bookmarks
613 no changed bookmarks found
629 no changed bookmarks found
614 [1]
630 [1]
615
631
616 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
632 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
617 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
633 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
618 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
634 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
619 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
635 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
620 $ hg -R repo1 -q --config extensions.mq= strip 4
636 $ hg -R repo1 -q --config extensions.mq= strip 4
621 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
637 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
622 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
638 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
623 |
639 |
624 | o fa942426a6fd (ADV_ON_REPO1)
640 | o fa942426a6fd (ADV_ON_REPO1)
625 |/
641 |/
626 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
642 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
627 |/
643 |/
628 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
644 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
629
645
630
646
631 $ hg clone -U source repo2
647 $ hg clone -U source repo2
632 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
648 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
633 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
649 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
634 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
650 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
635 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
651 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
636 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
652 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
637 $ hg -R repo2 -q --config extensions.mq= strip 3
653 $ hg -R repo2 -q --config extensions.mq= strip 3
638 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
654 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
639 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
655 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
640 |
656 |
641 | o fa942426a6fd (DIVERGED)
657 | o fa942426a6fd (DIVERGED)
642 |/
658 |/
643 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
659 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
644 |/
660 |/
645 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
661 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
646
662
647
663
648 (test that difference of bookmarks between repositories are fully shown)
664 (test that difference of bookmarks between repositories are fully shown)
649
665
650 $ hg -R repo1 incoming -B repo2 -v
666 $ hg -R repo1 incoming -B repo2 -v
651 comparing with repo2
667 comparing with repo2
652 searching for changed bookmarks
668 searching for changed bookmarks
653 ADD_ON_REPO2 66f7d451a68b added
669 ADD_ON_REPO2 66f7d451a68b added
654 ADV_ON_REPO2 66f7d451a68b advanced
670 ADV_ON_REPO2 66f7d451a68b advanced
655 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
671 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
656 DIFF_DIVERGED e7bd5218ca15 changed
672 DIFF_DIVERGED e7bd5218ca15 changed
657 DIVERGED fa942426a6fd diverged
673 DIVERGED fa942426a6fd diverged
658 $ hg -R repo1 outgoing -B repo2 -v
674 $ hg -R repo1 outgoing -B repo2 -v
659 comparing with repo2
675 comparing with repo2
660 searching for changed bookmarks
676 searching for changed bookmarks
661 ADD_ON_REPO1 66f7d451a68b added
677 ADD_ON_REPO1 66f7d451a68b added
662 ADD_ON_REPO2 deleted
678 ADD_ON_REPO2 deleted
663 ADV_ON_REPO1 fa942426a6fd advanced
679 ADV_ON_REPO1 fa942426a6fd advanced
664 DIFF_ADV_ON_REPO1 6100d3090acf advanced
680 DIFF_ADV_ON_REPO1 6100d3090acf advanced
665 DIFF_ADV_ON_REPO2 1ea73414a91b changed
681 DIFF_ADV_ON_REPO2 1ea73414a91b changed
666 DIFF_DIVERGED 6100d3090acf changed
682 DIFF_DIVERGED 6100d3090acf changed
667 DIVERGED 66f7d451a68b diverged
683 DIVERGED 66f7d451a68b diverged
668
684
669 $ hg -R repo2 incoming -B repo1 -v
685 $ hg -R repo2 incoming -B repo1 -v
670 comparing with repo1
686 comparing with repo1
671 searching for changed bookmarks
687 searching for changed bookmarks
672 ADD_ON_REPO1 66f7d451a68b added
688 ADD_ON_REPO1 66f7d451a68b added
673 ADV_ON_REPO1 fa942426a6fd advanced
689 ADV_ON_REPO1 fa942426a6fd advanced
674 DIFF_ADV_ON_REPO1 6100d3090acf changed
690 DIFF_ADV_ON_REPO1 6100d3090acf changed
675 DIFF_DIVERGED 6100d3090acf changed
691 DIFF_DIVERGED 6100d3090acf changed
676 DIVERGED 66f7d451a68b diverged
692 DIVERGED 66f7d451a68b diverged
677 $ hg -R repo2 outgoing -B repo1 -v
693 $ hg -R repo2 outgoing -B repo1 -v
678 comparing with repo1
694 comparing with repo1
679 searching for changed bookmarks
695 searching for changed bookmarks
680 ADD_ON_REPO1 deleted
696 ADD_ON_REPO1 deleted
681 ADD_ON_REPO2 66f7d451a68b added
697 ADD_ON_REPO2 66f7d451a68b added
682 ADV_ON_REPO2 66f7d451a68b advanced
698 ADV_ON_REPO2 66f7d451a68b advanced
683 DIFF_ADV_ON_REPO1 1ea73414a91b changed
699 DIFF_ADV_ON_REPO1 1ea73414a91b changed
684 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
700 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
685 DIFF_DIVERGED e7bd5218ca15 changed
701 DIFF_DIVERGED e7bd5218ca15 changed
686 DIVERGED fa942426a6fd diverged
702 DIVERGED fa942426a6fd diverged
687
703
688 $ cd ..
704 $ cd ..
689
705
690 Pushing a bookmark should only push the changes required by that
706 Pushing a bookmark should only push the changes required by that
691 bookmark, not all outgoing changes:
707 bookmark, not all outgoing changes:
692 $ hg clone http://localhost:$HGPORT/ addmarks
708 $ hg clone http://localhost:$HGPORT/ addmarks
693 requesting all changes
709 requesting all changes
694 adding changesets
710 adding changesets
695 adding manifests
711 adding manifests
696 adding file changes
712 adding file changes
697 added 5 changesets with 5 changes to 3 files (+2 heads)
713 added 5 changesets with 5 changes to 3 files (+2 heads)
698 2 new obsolescence markers
714 2 new obsolescence markers
699 new changesets 4e3505fd9583:c922c0139ca0
715 new changesets 4e3505fd9583:c922c0139ca0
700 updating to bookmark @
716 updating to bookmark @
701 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
717 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
702 $ cd addmarks
718 $ cd addmarks
703 $ echo foo > foo
719 $ echo foo > foo
704 $ hg add foo
720 $ hg add foo
705 $ hg commit -m 'add foo'
721 $ hg commit -m 'add foo'
706 $ echo bar > bar
722 $ echo bar > bar
707 $ hg add bar
723 $ hg add bar
708 $ hg commit -m 'add bar'
724 $ hg commit -m 'add bar'
709 $ hg co "tip^"
725 $ hg co "tip^"
710 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
726 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
711 (leaving bookmark @)
727 (leaving bookmark @)
712 $ hg book add-foo
728 $ hg book add-foo
713 $ hg book -r tip add-bar
729 $ hg book -r tip add-bar
714 Note: this push *must* push only a single changeset, as that's the point
730 Note: this push *must* push only a single changeset, as that's the point
715 of this test.
731 of this test.
716 $ hg push -B add-foo --traceback
732 $ hg push -B add-foo --traceback
717 pushing to http://localhost:$HGPORT/
733 pushing to http://localhost:$HGPORT/
718 searching for changes
734 searching for changes
719 remote: adding changesets
735 remote: adding changesets
720 remote: adding manifests
736 remote: adding manifests
721 remote: adding file changes
737 remote: adding file changes
722 remote: added 1 changesets with 1 changes to 1 files
738 remote: added 1 changesets with 1 changes to 1 files
723 exporting bookmark add-foo
739 exporting bookmark add-foo
724
740
725 pushing a new bookmark on a new head does not require -f if -B is specified
741 pushing a new bookmark on a new head does not require -f if -B is specified
726
742
727 $ hg up -q X
743 $ hg up -q X
728 $ hg book W
744 $ hg book W
729 $ echo c5 > f2
745 $ echo c5 > f2
730 $ hg ci -Am5
746 $ hg ci -Am5
731 created new head
747 created new head
732 $ hg push -B .
748 $ hg push -B .
733 pushing to http://localhost:$HGPORT/
749 pushing to http://localhost:$HGPORT/
734 searching for changes
750 searching for changes
735 remote: adding changesets
751 remote: adding changesets
736 remote: adding manifests
752 remote: adding manifests
737 remote: adding file changes
753 remote: adding file changes
738 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
754 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
739 exporting bookmark W
755 exporting bookmark W
740 $ hg -R ../b id -r W
756 $ hg -R ../b id -r W
741 cc978a373a53 tip W
757 cc978a373a53 tip W
742
758
743 pushing an existing but divergent bookmark with -B still requires -f
759 pushing an existing but divergent bookmark with -B still requires -f
744
760
745 $ hg clone -q . ../r
761 $ hg clone -q . ../r
746 $ hg up -q X
762 $ hg up -q X
747 $ echo 1 > f2
763 $ echo 1 > f2
748 $ hg ci -qAml
764 $ hg ci -qAml
749
765
750 $ cd ../r
766 $ cd ../r
751 $ hg up -q X
767 $ hg up -q X
752 $ echo 2 > f2
768 $ echo 2 > f2
753 $ hg ci -qAmr
769 $ hg ci -qAmr
754 $ hg push -B X
770 $ hg push -B X
755 pushing to $TESTTMP/addmarks (glob)
771 pushing to $TESTTMP/addmarks (glob)
756 searching for changes
772 searching for changes
757 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
773 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
758 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
774 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
759 (pull and merge or see 'hg help push' for details about pushing new heads)
775 (pull and merge or see 'hg help push' for details about pushing new heads)
760 [255]
776 [255]
761 $ cd ../addmarks
777 $ cd ../addmarks
762
778
763 Check summary output for incoming/outgoing bookmarks
779 Check summary output for incoming/outgoing bookmarks
764
780
765 $ hg bookmarks -d X
781 $ hg bookmarks -d X
766 $ hg bookmarks -d Y
782 $ hg bookmarks -d Y
767 $ hg summary --remote | grep '^remote:'
783 $ hg summary --remote | grep '^remote:'
768 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
784 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
769
785
770 $ cd ..
786 $ cd ..
771
787
772 pushing an unchanged bookmark should result in no changes
788 pushing an unchanged bookmark should result in no changes
773
789
774 $ hg init unchanged-a
790 $ hg init unchanged-a
775 $ hg init unchanged-b
791 $ hg init unchanged-b
776 $ cd unchanged-a
792 $ cd unchanged-a
777 $ echo initial > foo
793 $ echo initial > foo
778 $ hg commit -A -m initial
794 $ hg commit -A -m initial
779 adding foo
795 adding foo
780 $ hg bookmark @
796 $ hg bookmark @
781 $ hg push -B @ ../unchanged-b
797 $ hg push -B @ ../unchanged-b
782 pushing to ../unchanged-b
798 pushing to ../unchanged-b
783 searching for changes
799 searching for changes
784 adding changesets
800 adding changesets
785 adding manifests
801 adding manifests
786 adding file changes
802 adding file changes
787 added 1 changesets with 1 changes to 1 files
803 added 1 changesets with 1 changes to 1 files
788 exporting bookmark @
804 exporting bookmark @
789
805
790 $ hg push -B @ ../unchanged-b
806 $ hg push -B @ ../unchanged-b
791 pushing to ../unchanged-b
807 pushing to ../unchanged-b
792 searching for changes
808 searching for changes
793 no changes found
809 no changes found
794 [1]
810 [1]
795
811
796
812
797 Check hook preventing push (issue4455)
813 Check hook preventing push (issue4455)
798 ======================================
814 ======================================
799
815
800 $ hg bookmarks
816 $ hg bookmarks
801 * @ 0:55482a6fb4b1
817 * @ 0:55482a6fb4b1
802 $ hg log -G
818 $ hg log -G
803 @ 0:55482a6fb4b1 initial
819 @ 0:55482a6fb4b1 initial
804
820
805 $ hg init ../issue4455-dest
821 $ hg init ../issue4455-dest
806 $ hg push ../issue4455-dest # changesets only
822 $ hg push ../issue4455-dest # changesets only
807 pushing to ../issue4455-dest
823 pushing to ../issue4455-dest
808 searching for changes
824 searching for changes
809 adding changesets
825 adding changesets
810 adding manifests
826 adding manifests
811 adding file changes
827 adding file changes
812 added 1 changesets with 1 changes to 1 files
828 added 1 changesets with 1 changes to 1 files
813 $ cat >> .hg/hgrc << EOF
829 $ cat >> .hg/hgrc << EOF
814 > [paths]
830 > [paths]
815 > local=../issue4455-dest/
831 > local=../issue4455-dest/
816 > ssh=ssh://user@dummy/issue4455-dest
832 > ssh=ssh://user@dummy/issue4455-dest
817 > http=http://localhost:$HGPORT/
833 > http=http://localhost:$HGPORT/
818 > [ui]
834 > [ui]
819 > ssh=$PYTHON "$TESTDIR/dummyssh"
835 > ssh=$PYTHON "$TESTDIR/dummyssh"
820 > EOF
836 > EOF
821 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
837 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
822 > [hooks]
838 > [hooks]
823 > prepushkey=false
839 > prepushkey=false
824 > [web]
840 > [web]
825 > push_ssl = false
841 > push_ssl = false
826 > allow_push = *
842 > allow_push = *
827 > EOF
843 > EOF
828 $ killdaemons.py
844 $ killdaemons.py
829 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
845 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
830 $ cat ../issue4455.pid >> $DAEMON_PIDS
846 $ cat ../issue4455.pid >> $DAEMON_PIDS
831
847
832 Local push
848 Local push
833 ----------
849 ----------
834
850
835 $ hg push -B @ local
851 $ hg push -B @ local
836 pushing to $TESTTMP/issue4455-dest (glob)
852 pushing to $TESTTMP/issue4455-dest (glob)
837 searching for changes
853 searching for changes
838 no changes found
854 no changes found
839 pushkey-abort: prepushkey hook exited with status 1
855 pushkey-abort: prepushkey hook exited with status 1
840 abort: exporting bookmark @ failed!
856 abort: exporting bookmark @ failed!
841 [255]
857 [255]
842 $ hg -R ../issue4455-dest/ bookmarks
858 $ hg -R ../issue4455-dest/ bookmarks
843 no bookmarks set
859 no bookmarks set
844
860
845 Using ssh
861 Using ssh
846 ---------
862 ---------
847
863
848 $ hg push -B @ ssh # bundle2+
864 $ hg push -B @ ssh # bundle2+
849 pushing to ssh://user@dummy/issue4455-dest
865 pushing to ssh://user@dummy/issue4455-dest
850 searching for changes
866 searching for changes
851 no changes found
867 no changes found
852 remote: pushkey-abort: prepushkey hook exited with status 1
868 remote: pushkey-abort: prepushkey hook exited with status 1
853 abort: exporting bookmark @ failed!
869 abort: exporting bookmark @ failed!
854 [255]
870 [255]
855 $ hg -R ../issue4455-dest/ bookmarks
871 $ hg -R ../issue4455-dest/ bookmarks
856 no bookmarks set
872 no bookmarks set
857
873
858 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
874 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
859 pushing to ssh://user@dummy/issue4455-dest
875 pushing to ssh://user@dummy/issue4455-dest
860 searching for changes
876 searching for changes
861 no changes found
877 no changes found
862 remote: pushkey-abort: prepushkey hook exited with status 1
878 remote: pushkey-abort: prepushkey hook exited with status 1
863 exporting bookmark @ failed!
879 exporting bookmark @ failed!
864 [1]
880 [1]
865 $ hg -R ../issue4455-dest/ bookmarks
881 $ hg -R ../issue4455-dest/ bookmarks
866 no bookmarks set
882 no bookmarks set
867
883
868 Using http
884 Using http
869 ----------
885 ----------
870
886
871 $ hg push -B @ http # bundle2+
887 $ hg push -B @ http # bundle2+
872 pushing to http://localhost:$HGPORT/
888 pushing to http://localhost:$HGPORT/
873 searching for changes
889 searching for changes
874 no changes found
890 no changes found
875 remote: pushkey-abort: prepushkey hook exited with status 1
891 remote: pushkey-abort: prepushkey hook exited with status 1
876 abort: exporting bookmark @ failed!
892 abort: exporting bookmark @ failed!
877 [255]
893 [255]
878 $ hg -R ../issue4455-dest/ bookmarks
894 $ hg -R ../issue4455-dest/ bookmarks
879 no bookmarks set
895 no bookmarks set
880
896
881 $ hg push -B @ http --config devel.legacy.exchange=bundle1
897 $ hg push -B @ http --config devel.legacy.exchange=bundle1
882 pushing to http://localhost:$HGPORT/
898 pushing to http://localhost:$HGPORT/
883 searching for changes
899 searching for changes
884 no changes found
900 no changes found
885 remote: pushkey-abort: prepushkey hook exited with status 1
901 remote: pushkey-abort: prepushkey hook exited with status 1
886 exporting bookmark @ failed!
902 exporting bookmark @ failed!
887 [1]
903 [1]
888 $ hg -R ../issue4455-dest/ bookmarks
904 $ hg -R ../issue4455-dest/ bookmarks
889 no bookmarks set
905 no bookmarks set
@@ -1,1052 +1,1065 b''
1
1 $ hg init repo
2 $ hg init repo
2 $ cd repo
3 $ cd repo
3
4
5 $ TESTHOOK='hooks.txnclose-bookmark.test=echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"'
6
4 no bookmarks
7 no bookmarks
5
8
6 $ hg bookmarks
9 $ hg bookmarks
7 no bookmarks set
10 no bookmarks set
8
11
9 $ hg bookmarks -Tjson
12 $ hg bookmarks -Tjson
10 [
13 [
11 ]
14 ]
12
15
13 bookmark rev -1
16 bookmark rev -1
14
17
15 $ hg bookmark X
18 $ hg bookmark X --config "$TESTHOOK"
19 test-hook-bookmark: X: -> 0000000000000000000000000000000000000000
16
20
17 list bookmarks
21 list bookmarks
18
22
19 $ hg bookmarks
23 $ hg bookmarks
20 * X -1:000000000000
24 * X -1:000000000000
21
25
22 list bookmarks with color
26 list bookmarks with color
23
27
24 $ hg --config extensions.color= --config color.mode=ansi \
28 $ hg --config extensions.color= --config color.mode=ansi \
25 > bookmarks --color=always
29 > bookmarks --color=always
26 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
30 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
27
31
28 $ echo a > a
32 $ echo a > a
29 $ hg add a
33 $ hg add a
30 $ hg commit -m 0
34 $ hg commit -m 0 --config "$TESTHOOK"
35 test-hook-bookmark: X: 0000000000000000000000000000000000000000 -> f7b1eb17ad24730a1651fccd46c43826d1bbc2ac
31
36
32 bookmark X moved to rev 0
37 bookmark X moved to rev 0
33
38
34 $ hg bookmarks
39 $ hg bookmarks
35 * X 0:f7b1eb17ad24
40 * X 0:f7b1eb17ad24
36
41
37 look up bookmark
42 look up bookmark
38
43
39 $ hg log -r X
44 $ hg log -r X
40 changeset: 0:f7b1eb17ad24
45 changeset: 0:f7b1eb17ad24
41 bookmark: X
46 bookmark: X
42 tag: tip
47 tag: tip
43 user: test
48 user: test
44 date: Thu Jan 01 00:00:00 1970 +0000
49 date: Thu Jan 01 00:00:00 1970 +0000
45 summary: 0
50 summary: 0
46
51
47
52
48 second bookmark for rev 0, command should work even with ui.strict on
53 second bookmark for rev 0, command should work even with ui.strict on
49
54
50 $ hg --config ui.strict=1 bookmark X2
55 $ hg --config ui.strict=1 bookmark X2 --config "$TESTHOOK"
56 test-hook-bookmark: X2: -> f7b1eb17ad24730a1651fccd46c43826d1bbc2ac
51
57
52 bookmark rev -1 again
58 bookmark rev -1 again
53
59
54 $ hg bookmark -r null Y
60 $ hg bookmark -r null Y
55
61
56 list bookmarks
62 list bookmarks
57
63
58 $ hg bookmarks
64 $ hg bookmarks
59 X 0:f7b1eb17ad24
65 X 0:f7b1eb17ad24
60 * X2 0:f7b1eb17ad24
66 * X2 0:f7b1eb17ad24
61 Y -1:000000000000
67 Y -1:000000000000
62
68
63 $ echo b > b
69 $ echo b > b
64 $ hg add b
70 $ hg add b
65 $ hg commit -m 1
71 $ hg commit -m 1 --config "$TESTHOOK"
72 test-hook-bookmark: X2: f7b1eb17ad24730a1651fccd46c43826d1bbc2ac -> 925d80f479bb026b0fb3deb27503780b13f74123
66
73
67 $ hg bookmarks -Tjson
74 $ hg bookmarks -Tjson
68 [
75 [
69 {
76 {
70 "active": false,
77 "active": false,
71 "bookmark": "X",
78 "bookmark": "X",
72 "node": "f7b1eb17ad24730a1651fccd46c43826d1bbc2ac",
79 "node": "f7b1eb17ad24730a1651fccd46c43826d1bbc2ac",
73 "rev": 0
80 "rev": 0
74 },
81 },
75 {
82 {
76 "active": true,
83 "active": true,
77 "bookmark": "X2",
84 "bookmark": "X2",
78 "node": "925d80f479bb026b0fb3deb27503780b13f74123",
85 "node": "925d80f479bb026b0fb3deb27503780b13f74123",
79 "rev": 1
86 "rev": 1
80 },
87 },
81 {
88 {
82 "active": false,
89 "active": false,
83 "bookmark": "Y",
90 "bookmark": "Y",
84 "node": "0000000000000000000000000000000000000000",
91 "node": "0000000000000000000000000000000000000000",
85 "rev": -1
92 "rev": -1
86 }
93 }
87 ]
94 ]
88
95
89 bookmarks revset
96 bookmarks revset
90
97
91 $ hg log -r 'bookmark()'
98 $ hg log -r 'bookmark()'
92 changeset: 0:f7b1eb17ad24
99 changeset: 0:f7b1eb17ad24
93 bookmark: X
100 bookmark: X
94 user: test
101 user: test
95 date: Thu Jan 01 00:00:00 1970 +0000
102 date: Thu Jan 01 00:00:00 1970 +0000
96 summary: 0
103 summary: 0
97
104
98 changeset: 1:925d80f479bb
105 changeset: 1:925d80f479bb
99 bookmark: X2
106 bookmark: X2
100 tag: tip
107 tag: tip
101 user: test
108 user: test
102 date: Thu Jan 01 00:00:00 1970 +0000
109 date: Thu Jan 01 00:00:00 1970 +0000
103 summary: 1
110 summary: 1
104
111
105 $ hg log -r 'bookmark(Y)'
112 $ hg log -r 'bookmark(Y)'
106 $ hg log -r 'bookmark(X2)'
113 $ hg log -r 'bookmark(X2)'
107 changeset: 1:925d80f479bb
114 changeset: 1:925d80f479bb
108 bookmark: X2
115 bookmark: X2
109 tag: tip
116 tag: tip
110 user: test
117 user: test
111 date: Thu Jan 01 00:00:00 1970 +0000
118 date: Thu Jan 01 00:00:00 1970 +0000
112 summary: 1
119 summary: 1
113
120
114 $ hg log -r 'bookmark("re:X")'
121 $ hg log -r 'bookmark("re:X")'
115 changeset: 0:f7b1eb17ad24
122 changeset: 0:f7b1eb17ad24
116 bookmark: X
123 bookmark: X
117 user: test
124 user: test
118 date: Thu Jan 01 00:00:00 1970 +0000
125 date: Thu Jan 01 00:00:00 1970 +0000
119 summary: 0
126 summary: 0
120
127
121 changeset: 1:925d80f479bb
128 changeset: 1:925d80f479bb
122 bookmark: X2
129 bookmark: X2
123 tag: tip
130 tag: tip
124 user: test
131 user: test
125 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
126 summary: 1
133 summary: 1
127
134
128 $ hg log -r 'bookmark("literal:X")'
135 $ hg log -r 'bookmark("literal:X")'
129 changeset: 0:f7b1eb17ad24
136 changeset: 0:f7b1eb17ad24
130 bookmark: X
137 bookmark: X
131 user: test
138 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
139 date: Thu Jan 01 00:00:00 1970 +0000
133 summary: 0
140 summary: 0
134
141
135
142
136 $ hg log -r 'bookmark(unknown)'
143 $ hg log -r 'bookmark(unknown)'
137 abort: bookmark 'unknown' does not exist!
144 abort: bookmark 'unknown' does not exist!
138 [255]
145 [255]
139 $ hg log -r 'bookmark("literal:unknown")'
146 $ hg log -r 'bookmark("literal:unknown")'
140 abort: bookmark 'unknown' does not exist!
147 abort: bookmark 'unknown' does not exist!
141 [255]
148 [255]
142 $ hg log -r 'bookmark("re:unknown")'
149 $ hg log -r 'bookmark("re:unknown")'
143 abort: no bookmarks exist that match 'unknown'!
150 abort: no bookmarks exist that match 'unknown'!
144 [255]
151 [255]
145 $ hg log -r 'present(bookmark("literal:unknown"))'
152 $ hg log -r 'present(bookmark("literal:unknown"))'
146 $ hg log -r 'present(bookmark("re:unknown"))'
153 $ hg log -r 'present(bookmark("re:unknown"))'
147
154
148 $ hg help revsets | grep 'bookmark('
155 $ hg help revsets | grep 'bookmark('
149 "bookmark([name])"
156 "bookmark([name])"
150
157
151 bookmarks X and X2 moved to rev 1, Y at rev -1
158 bookmarks X and X2 moved to rev 1, Y at rev -1
152
159
153 $ hg bookmarks
160 $ hg bookmarks
154 X 0:f7b1eb17ad24
161 X 0:f7b1eb17ad24
155 * X2 1:925d80f479bb
162 * X2 1:925d80f479bb
156 Y -1:000000000000
163 Y -1:000000000000
157
164
158 bookmark rev 0 again
165 bookmark rev 0 again
159
166
160 $ hg bookmark -r 0 Z
167 $ hg bookmark -r 0 Z
161
168
162 $ hg update X
169 $ hg update X
163 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
170 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
164 (activating bookmark X)
171 (activating bookmark X)
165 $ echo c > c
172 $ echo c > c
166 $ hg add c
173 $ hg add c
167 $ hg commit -m 2
174 $ hg commit -m 2
168 created new head
175 created new head
169
176
170 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
177 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
171
178
172 $ hg bookmarks
179 $ hg bookmarks
173 * X 2:db815d6d32e6
180 * X 2:db815d6d32e6
174 X2 1:925d80f479bb
181 X2 1:925d80f479bb
175 Y -1:000000000000
182 Y -1:000000000000
176 Z 0:f7b1eb17ad24
183 Z 0:f7b1eb17ad24
177
184
178 rename nonexistent bookmark
185 rename nonexistent bookmark
179
186
180 $ hg bookmark -m A B
187 $ hg bookmark -m A B
181 abort: bookmark 'A' does not exist
188 abort: bookmark 'A' does not exist
182 [255]
189 [255]
183
190
184 rename to existent bookmark
191 rename to existent bookmark
185
192
186 $ hg bookmark -m X Y
193 $ hg bookmark -m X Y
187 abort: bookmark 'Y' already exists (use -f to force)
194 abort: bookmark 'Y' already exists (use -f to force)
188 [255]
195 [255]
189
196
190 force rename to existent bookmark
197 force rename to existent bookmark
191
198
192 $ hg bookmark -f -m X Y
199 $ hg bookmark -f -m X Y
193
200
194 rename bookmark using .
201 rename bookmark using .
195
202
196 $ hg book rename-me
203 $ hg book rename-me
197 $ hg book -m . renamed
204 $ hg book -m . renamed --config "$TESTHOOK"
205 test-hook-bookmark: rename-me: db815d6d32e69058eadefc8cffbad37675707975 ->
206 test-hook-bookmark: renamed: -> db815d6d32e69058eadefc8cffbad37675707975
198 $ hg bookmark
207 $ hg bookmark
199 X2 1:925d80f479bb
208 X2 1:925d80f479bb
200 Y 2:db815d6d32e6
209 Y 2:db815d6d32e6
201 Z 0:f7b1eb17ad24
210 Z 0:f7b1eb17ad24
202 * renamed 2:db815d6d32e6
211 * renamed 2:db815d6d32e6
203 $ hg up -q Y
212 $ hg up -q Y
204 $ hg book -d renamed
213 $ hg book -d renamed --config "$TESTHOOK"
214 test-hook-bookmark: renamed: db815d6d32e69058eadefc8cffbad37675707975 ->
205
215
206 rename bookmark using . with no active bookmark
216 rename bookmark using . with no active bookmark
207
217
208 $ hg book rename-me
218 $ hg book rename-me
209 $ hg book -i rename-me
219 $ hg book -i rename-me
210 $ hg book -m . renamed
220 $ hg book -m . renamed
211 abort: no active bookmark
221 abort: no active bookmark
212 [255]
222 [255]
213 $ hg up -q Y
223 $ hg up -q Y
214 $ hg book -d rename-me
224 $ hg book -d rename-me
215
225
216 delete bookmark using .
226 delete bookmark using .
217
227
218 $ hg book delete-me
228 $ hg book delete-me
219 $ hg book -d .
229 $ hg book -d .
220 $ hg bookmark
230 $ hg bookmark
221 X2 1:925d80f479bb
231 X2 1:925d80f479bb
222 Y 2:db815d6d32e6
232 Y 2:db815d6d32e6
223 Z 0:f7b1eb17ad24
233 Z 0:f7b1eb17ad24
224 $ hg up -q Y
234 $ hg up -q Y
225
235
226 delete bookmark using . with no active bookmark
236 delete bookmark using . with no active bookmark
227
237
228 $ hg book delete-me
238 $ hg book delete-me
229 $ hg book -i delete-me
239 $ hg book -i delete-me
230 $ hg book -d .
240 $ hg book -d .
231 abort: no active bookmark
241 abort: no active bookmark
232 [255]
242 [255]
233 $ hg up -q Y
243 $ hg up -q Y
234 $ hg book -d delete-me
244 $ hg book -d delete-me
235
245
236 list bookmarks
246 list bookmarks
237
247
238 $ hg bookmark
248 $ hg bookmark
239 X2 1:925d80f479bb
249 X2 1:925d80f479bb
240 * Y 2:db815d6d32e6
250 * Y 2:db815d6d32e6
241 Z 0:f7b1eb17ad24
251 Z 0:f7b1eb17ad24
242
252
243 bookmarks from a revset
253 bookmarks from a revset
244 $ hg bookmark -r '.^1' REVSET
254 $ hg bookmark -r '.^1' REVSET
245 $ hg bookmark -r ':tip' TIP
255 $ hg bookmark -r ':tip' TIP
246 $ hg up -q TIP
256 $ hg up -q TIP
247 $ hg bookmarks
257 $ hg bookmarks
248 REVSET 0:f7b1eb17ad24
258 REVSET 0:f7b1eb17ad24
249 * TIP 2:db815d6d32e6
259 * TIP 2:db815d6d32e6
250 X2 1:925d80f479bb
260 X2 1:925d80f479bb
251 Y 2:db815d6d32e6
261 Y 2:db815d6d32e6
252 Z 0:f7b1eb17ad24
262 Z 0:f7b1eb17ad24
253
263
254 $ hg bookmark -d REVSET
264 $ hg bookmark -d REVSET
255 $ hg bookmark -d TIP
265 $ hg bookmark -d TIP
256
266
257 rename without new name or multiple names
267 rename without new name or multiple names
258
268
259 $ hg bookmark -m Y
269 $ hg bookmark -m Y
260 abort: new bookmark name required
270 abort: new bookmark name required
261 [255]
271 [255]
262 $ hg bookmark -m Y Y2 Y3
272 $ hg bookmark -m Y Y2 Y3
263 abort: only one new bookmark name allowed
273 abort: only one new bookmark name allowed
264 [255]
274 [255]
265
275
266 delete without name
276 delete without name
267
277
268 $ hg bookmark -d
278 $ hg bookmark -d
269 abort: bookmark name required
279 abort: bookmark name required
270 [255]
280 [255]
271
281
272 delete nonexistent bookmark
282 delete nonexistent bookmark
273
283
274 $ hg bookmark -d A
284 $ hg bookmark -d A
275 abort: bookmark 'A' does not exist
285 abort: bookmark 'A' does not exist
276 [255]
286 [255]
277
287
278 bookmark name with spaces should be stripped
288 bookmark name with spaces should be stripped
279
289
280 $ hg bookmark ' x y '
290 $ hg bookmark ' x y '
281
291
282 list bookmarks
292 list bookmarks
283
293
284 $ hg bookmarks
294 $ hg bookmarks
285 X2 1:925d80f479bb
295 X2 1:925d80f479bb
286 Y 2:db815d6d32e6
296 Y 2:db815d6d32e6
287 Z 0:f7b1eb17ad24
297 Z 0:f7b1eb17ad24
288 * x y 2:db815d6d32e6
298 * x y 2:db815d6d32e6
289
299
290 look up stripped bookmark name
300 look up stripped bookmark name
291
301
292 $ hg log -r '"x y"'
302 $ hg log -r '"x y"'
293 changeset: 2:db815d6d32e6
303 changeset: 2:db815d6d32e6
294 bookmark: Y
304 bookmark: Y
295 bookmark: x y
305 bookmark: x y
296 tag: tip
306 tag: tip
297 parent: 0:f7b1eb17ad24
307 parent: 0:f7b1eb17ad24
298 user: test
308 user: test
299 date: Thu Jan 01 00:00:00 1970 +0000
309 date: Thu Jan 01 00:00:00 1970 +0000
300 summary: 2
310 summary: 2
301
311
302
312
303 reject bookmark name with newline
313 reject bookmark name with newline
304
314
305 $ hg bookmark '
315 $ hg bookmark '
306 > '
316 > '
307 abort: bookmark names cannot consist entirely of whitespace
317 abort: bookmark names cannot consist entirely of whitespace
308 [255]
318 [255]
309
319
310 $ hg bookmark -m Z '
320 $ hg bookmark -m Z '
311 > '
321 > '
312 abort: bookmark names cannot consist entirely of whitespace
322 abort: bookmark names cannot consist entirely of whitespace
313 [255]
323 [255]
314
324
315 bookmark with reserved name
325 bookmark with reserved name
316
326
317 $ hg bookmark tip
327 $ hg bookmark tip
318 abort: the name 'tip' is reserved
328 abort: the name 'tip' is reserved
319 [255]
329 [255]
320
330
321 $ hg bookmark .
331 $ hg bookmark .
322 abort: the name '.' is reserved
332 abort: the name '.' is reserved
323 [255]
333 [255]
324
334
325 $ hg bookmark null
335 $ hg bookmark null
326 abort: the name 'null' is reserved
336 abort: the name 'null' is reserved
327 [255]
337 [255]
328
338
329
339
330 bookmark with existing name
340 bookmark with existing name
331
341
332 $ hg bookmark X2
342 $ hg bookmark X2
333 abort: bookmark 'X2' already exists (use -f to force)
343 abort: bookmark 'X2' already exists (use -f to force)
334 [255]
344 [255]
335
345
336 $ hg bookmark -m Y Z
346 $ hg bookmark -m Y Z
337 abort: bookmark 'Z' already exists (use -f to force)
347 abort: bookmark 'Z' already exists (use -f to force)
338 [255]
348 [255]
339
349
340 bookmark with name of branch
350 bookmark with name of branch
341
351
342 $ hg bookmark default
352 $ hg bookmark default
343 abort: a bookmark cannot have the name of an existing branch
353 abort: a bookmark cannot have the name of an existing branch
344 [255]
354 [255]
345
355
346 $ hg bookmark -m Y default
356 $ hg bookmark -m Y default
347 abort: a bookmark cannot have the name of an existing branch
357 abort: a bookmark cannot have the name of an existing branch
348 [255]
358 [255]
349
359
350 bookmark with integer name
360 bookmark with integer name
351
361
352 $ hg bookmark 10
362 $ hg bookmark 10
353 abort: cannot use an integer as a name
363 abort: cannot use an integer as a name
354 [255]
364 [255]
355
365
356 bookmark with a name that matches a node id
366 bookmark with a name that matches a node id
357 $ hg bookmark 925d80f479bb db815d6d32e6
367 $ hg bookmark 925d80f479bb db815d6d32e6 --config "$TESTHOOK"
358 bookmark 925d80f479bb matches a changeset hash
368 bookmark 925d80f479bb matches a changeset hash
359 (did you leave a -r out of an 'hg bookmark' command?)
369 (did you leave a -r out of an 'hg bookmark' command?)
360 bookmark db815d6d32e6 matches a changeset hash
370 bookmark db815d6d32e6 matches a changeset hash
361 (did you leave a -r out of an 'hg bookmark' command?)
371 (did you leave a -r out of an 'hg bookmark' command?)
372 test-hook-bookmark: 925d80f479bb: -> db815d6d32e69058eadefc8cffbad37675707975
373 test-hook-bookmark: db815d6d32e6: -> db815d6d32e69058eadefc8cffbad37675707975
362 $ hg bookmark -d 925d80f479bb
374 $ hg bookmark -d 925d80f479bb
363 $ hg bookmark -d db815d6d32e6
375 $ hg bookmark -d db815d6d32e6
364
376
365 $ cd ..
377 $ cd ..
366
378
367 bookmark with a name that matches an ambiguous node id
379 bookmark with a name that matches an ambiguous node id
368
380
369 $ hg init ambiguous
381 $ hg init ambiguous
370 $ cd ambiguous
382 $ cd ambiguous
371 $ echo 0 > a
383 $ echo 0 > a
372 $ hg ci -qAm 0
384 $ hg ci -qAm 0
373 $ for i in 1057 2857 4025; do
385 $ for i in 1057 2857 4025; do
374 > hg up -q 0
386 > hg up -q 0
375 > echo $i > a
387 > echo $i > a
376 > hg ci -qm $i
388 > hg ci -qm $i
377 > done
389 > done
378 $ hg up -q null
390 $ hg up -q null
379 $ hg log -r0: -T '{rev}:{node}\n'
391 $ hg log -r0: -T '{rev}:{node}\n'
380 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
392 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
381 1:c56256a09cd28e5764f32e8e2810d0f01e2e357a
393 1:c56256a09cd28e5764f32e8e2810d0f01e2e357a
382 2:c5623987d205cd6d9d8389bfc40fff9dbb670b48
394 2:c5623987d205cd6d9d8389bfc40fff9dbb670b48
383 3:c562ddd9c94164376c20b86b0b4991636a3bf84f
395 3:c562ddd9c94164376c20b86b0b4991636a3bf84f
384
396
385 $ hg bookmark -r0 c562
397 $ hg bookmark -r0 c562
386 $ hg bookmarks
398 $ hg bookmarks
387 c562 0:b4e73ffab476
399 c562 0:b4e73ffab476
388
400
389 $ cd ..
401 $ cd ..
390
402
391 incompatible options
403 incompatible options
392
404
393 $ cd repo
405 $ cd repo
394
406
395 $ hg bookmark -m Y -d Z
407 $ hg bookmark -m Y -d Z
396 abort: --delete and --rename are incompatible
408 abort: --delete and --rename are incompatible
397 [255]
409 [255]
398
410
399 $ hg bookmark -r 1 -d Z
411 $ hg bookmark -r 1 -d Z
400 abort: --rev is incompatible with --delete
412 abort: --rev is incompatible with --delete
401 [255]
413 [255]
402
414
403 $ hg bookmark -r 1 -m Z Y
415 $ hg bookmark -r 1 -m Z Y
404 abort: --rev is incompatible with --rename
416 abort: --rev is incompatible with --rename
405 [255]
417 [255]
406
418
407 force bookmark with existing name
419 force bookmark with existing name
408
420
409 $ hg bookmark -f X2
421 $ hg bookmark -f X2 --config "$TESTHOOK"
422 test-hook-bookmark: X2: 925d80f479bb026b0fb3deb27503780b13f74123 -> db815d6d32e69058eadefc8cffbad37675707975
410
423
411 force bookmark back to where it was, should deactivate it
424 force bookmark back to where it was, should deactivate it
412
425
413 $ hg bookmark -fr1 X2
426 $ hg bookmark -fr1 X2
414 $ hg bookmarks
427 $ hg bookmarks
415 X2 1:925d80f479bb
428 X2 1:925d80f479bb
416 Y 2:db815d6d32e6
429 Y 2:db815d6d32e6
417 Z 0:f7b1eb17ad24
430 Z 0:f7b1eb17ad24
418 x y 2:db815d6d32e6
431 x y 2:db815d6d32e6
419
432
420 forward bookmark to descendant without --force
433 forward bookmark to descendant without --force
421
434
422 $ hg bookmark Z
435 $ hg bookmark Z
423 moving bookmark 'Z' forward from f7b1eb17ad24
436 moving bookmark 'Z' forward from f7b1eb17ad24
424
437
425 list bookmarks
438 list bookmarks
426
439
427 $ hg bookmark
440 $ hg bookmark
428 X2 1:925d80f479bb
441 X2 1:925d80f479bb
429 Y 2:db815d6d32e6
442 Y 2:db815d6d32e6
430 * Z 2:db815d6d32e6
443 * Z 2:db815d6d32e6
431 x y 2:db815d6d32e6
444 x y 2:db815d6d32e6
432
445
433 revision but no bookmark name
446 revision but no bookmark name
434
447
435 $ hg bookmark -r .
448 $ hg bookmark -r .
436 abort: bookmark name required
449 abort: bookmark name required
437 [255]
450 [255]
438
451
439 bookmark name with whitespace only
452 bookmark name with whitespace only
440
453
441 $ hg bookmark ' '
454 $ hg bookmark ' '
442 abort: bookmark names cannot consist entirely of whitespace
455 abort: bookmark names cannot consist entirely of whitespace
443 [255]
456 [255]
444
457
445 $ hg bookmark -m Y ' '
458 $ hg bookmark -m Y ' '
446 abort: bookmark names cannot consist entirely of whitespace
459 abort: bookmark names cannot consist entirely of whitespace
447 [255]
460 [255]
448
461
449 invalid bookmark
462 invalid bookmark
450
463
451 $ hg bookmark 'foo:bar'
464 $ hg bookmark 'foo:bar'
452 abort: ':' cannot be used in a name
465 abort: ':' cannot be used in a name
453 [255]
466 [255]
454
467
455 $ hg bookmark 'foo
468 $ hg bookmark 'foo
456 > bar'
469 > bar'
457 abort: '\n' cannot be used in a name
470 abort: '\n' cannot be used in a name
458 [255]
471 [255]
459
472
460 the bookmark extension should be ignored now that it is part of core
473 the bookmark extension should be ignored now that it is part of core
461
474
462 $ echo "[extensions]" >> $HGRCPATH
475 $ echo "[extensions]" >> $HGRCPATH
463 $ echo "bookmarks=" >> $HGRCPATH
476 $ echo "bookmarks=" >> $HGRCPATH
464 $ hg bookmarks
477 $ hg bookmarks
465 X2 1:925d80f479bb
478 X2 1:925d80f479bb
466 Y 2:db815d6d32e6
479 Y 2:db815d6d32e6
467 * Z 2:db815d6d32e6
480 * Z 2:db815d6d32e6
468 x y 2:db815d6d32e6
481 x y 2:db815d6d32e6
469
482
470 test summary
483 test summary
471
484
472 $ hg summary
485 $ hg summary
473 parent: 2:db815d6d32e6 tip
486 parent: 2:db815d6d32e6 tip
474 2
487 2
475 branch: default
488 branch: default
476 bookmarks: *Z Y x y
489 bookmarks: *Z Y x y
477 commit: (clean)
490 commit: (clean)
478 update: 1 new changesets, 2 branch heads (merge)
491 update: 1 new changesets, 2 branch heads (merge)
479 phases: 3 draft
492 phases: 3 draft
480
493
481 test id
494 test id
482
495
483 $ hg id
496 $ hg id
484 db815d6d32e6 tip Y/Z/x y
497 db815d6d32e6 tip Y/Z/x y
485
498
486 test rollback
499 test rollback
487
500
488 $ echo foo > f1
501 $ echo foo > f1
489 $ hg bookmark tmp-rollback
502 $ hg bookmark tmp-rollback
490 $ hg ci -Amr
503 $ hg ci -Amr
491 adding f1
504 adding f1
492 $ hg bookmarks
505 $ hg bookmarks
493 X2 1:925d80f479bb
506 X2 1:925d80f479bb
494 Y 2:db815d6d32e6
507 Y 2:db815d6d32e6
495 Z 2:db815d6d32e6
508 Z 2:db815d6d32e6
496 * tmp-rollback 3:2bf5cfec5864
509 * tmp-rollback 3:2bf5cfec5864
497 x y 2:db815d6d32e6
510 x y 2:db815d6d32e6
498 $ hg rollback
511 $ hg rollback
499 repository tip rolled back to revision 2 (undo commit)
512 repository tip rolled back to revision 2 (undo commit)
500 working directory now based on revision 2
513 working directory now based on revision 2
501 $ hg bookmarks
514 $ hg bookmarks
502 X2 1:925d80f479bb
515 X2 1:925d80f479bb
503 Y 2:db815d6d32e6
516 Y 2:db815d6d32e6
504 Z 2:db815d6d32e6
517 Z 2:db815d6d32e6
505 * tmp-rollback 2:db815d6d32e6
518 * tmp-rollback 2:db815d6d32e6
506 x y 2:db815d6d32e6
519 x y 2:db815d6d32e6
507 $ hg bookmark -f Z -r 1
520 $ hg bookmark -f Z -r 1
508 $ hg rollback
521 $ hg rollback
509 repository tip rolled back to revision 2 (undo bookmark)
522 repository tip rolled back to revision 2 (undo bookmark)
510 $ hg bookmarks
523 $ hg bookmarks
511 X2 1:925d80f479bb
524 X2 1:925d80f479bb
512 Y 2:db815d6d32e6
525 Y 2:db815d6d32e6
513 Z 2:db815d6d32e6
526 Z 2:db815d6d32e6
514 * tmp-rollback 2:db815d6d32e6
527 * tmp-rollback 2:db815d6d32e6
515 x y 2:db815d6d32e6
528 x y 2:db815d6d32e6
516 $ hg bookmark -d tmp-rollback
529 $ hg bookmark -d tmp-rollback
517
530
518 activate bookmark on working dir parent without --force
531 activate bookmark on working dir parent without --force
519
532
520 $ hg bookmark --inactive Z
533 $ hg bookmark --inactive Z
521 $ hg bookmark Z
534 $ hg bookmark Z
522
535
523 test clone
536 test clone
524
537
525 $ hg bookmark -r 2 -i @
538 $ hg bookmark -r 2 -i @
526 $ hg bookmark -r 2 -i a@
539 $ hg bookmark -r 2 -i a@
527 $ hg bookmarks
540 $ hg bookmarks
528 @ 2:db815d6d32e6
541 @ 2:db815d6d32e6
529 X2 1:925d80f479bb
542 X2 1:925d80f479bb
530 Y 2:db815d6d32e6
543 Y 2:db815d6d32e6
531 * Z 2:db815d6d32e6
544 * Z 2:db815d6d32e6
532 a@ 2:db815d6d32e6
545 a@ 2:db815d6d32e6
533 x y 2:db815d6d32e6
546 x y 2:db815d6d32e6
534 $ hg clone . cloned-bookmarks
547 $ hg clone . cloned-bookmarks
535 updating to bookmark @
548 updating to bookmark @
536 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
549 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
537 $ hg -R cloned-bookmarks bookmarks
550 $ hg -R cloned-bookmarks bookmarks
538 * @ 2:db815d6d32e6
551 * @ 2:db815d6d32e6
539 X2 1:925d80f479bb
552 X2 1:925d80f479bb
540 Y 2:db815d6d32e6
553 Y 2:db815d6d32e6
541 Z 2:db815d6d32e6
554 Z 2:db815d6d32e6
542 a@ 2:db815d6d32e6
555 a@ 2:db815d6d32e6
543 x y 2:db815d6d32e6
556 x y 2:db815d6d32e6
544
557
545 test clone with pull protocol
558 test clone with pull protocol
546
559
547 $ hg clone --pull . cloned-bookmarks-pull
560 $ hg clone --pull . cloned-bookmarks-pull
548 requesting all changes
561 requesting all changes
549 adding changesets
562 adding changesets
550 adding manifests
563 adding manifests
551 adding file changes
564 adding file changes
552 added 3 changesets with 3 changes to 3 files (+1 heads)
565 added 3 changesets with 3 changes to 3 files (+1 heads)
553 new changesets f7b1eb17ad24:db815d6d32e6
566 new changesets f7b1eb17ad24:db815d6d32e6
554 updating to bookmark @
567 updating to bookmark @
555 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
568 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 $ hg -R cloned-bookmarks-pull bookmarks
569 $ hg -R cloned-bookmarks-pull bookmarks
557 * @ 2:db815d6d32e6
570 * @ 2:db815d6d32e6
558 X2 1:925d80f479bb
571 X2 1:925d80f479bb
559 Y 2:db815d6d32e6
572 Y 2:db815d6d32e6
560 Z 2:db815d6d32e6
573 Z 2:db815d6d32e6
561 a@ 2:db815d6d32e6
574 a@ 2:db815d6d32e6
562 x y 2:db815d6d32e6
575 x y 2:db815d6d32e6
563
576
564 delete multiple bookmarks at once
577 delete multiple bookmarks at once
565
578
566 $ hg bookmark -d @ a@
579 $ hg bookmark -d @ a@
567
580
568 test clone with a bookmark named "default" (issue3677)
581 test clone with a bookmark named "default" (issue3677)
569
582
570 $ hg bookmark -r 1 -f -i default
583 $ hg bookmark -r 1 -f -i default
571 $ hg clone . cloned-bookmark-default
584 $ hg clone . cloned-bookmark-default
572 updating to branch default
585 updating to branch default
573 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
574 $ hg -R cloned-bookmark-default bookmarks
587 $ hg -R cloned-bookmark-default bookmarks
575 X2 1:925d80f479bb
588 X2 1:925d80f479bb
576 Y 2:db815d6d32e6
589 Y 2:db815d6d32e6
577 Z 2:db815d6d32e6
590 Z 2:db815d6d32e6
578 default 1:925d80f479bb
591 default 1:925d80f479bb
579 x y 2:db815d6d32e6
592 x y 2:db815d6d32e6
580 $ hg -R cloned-bookmark-default parents -q
593 $ hg -R cloned-bookmark-default parents -q
581 2:db815d6d32e6
594 2:db815d6d32e6
582 $ hg bookmark -d default
595 $ hg bookmark -d default
583
596
584 test clone with a specific revision
597 test clone with a specific revision
585
598
586 $ hg clone -r 925d80 . cloned-bookmarks-rev
599 $ hg clone -r 925d80 . cloned-bookmarks-rev
587 adding changesets
600 adding changesets
588 adding manifests
601 adding manifests
589 adding file changes
602 adding file changes
590 added 2 changesets with 2 changes to 2 files
603 added 2 changesets with 2 changes to 2 files
591 new changesets f7b1eb17ad24:925d80f479bb
604 new changesets f7b1eb17ad24:925d80f479bb
592 updating to branch default
605 updating to branch default
593 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 $ hg -R cloned-bookmarks-rev bookmarks
607 $ hg -R cloned-bookmarks-rev bookmarks
595 X2 1:925d80f479bb
608 X2 1:925d80f479bb
596
609
597 test clone with update to a bookmark
610 test clone with update to a bookmark
598
611
599 $ hg clone -u Z . ../cloned-bookmarks-update
612 $ hg clone -u Z . ../cloned-bookmarks-update
600 updating to branch default
613 updating to branch default
601 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
614 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
602 $ hg -R ../cloned-bookmarks-update bookmarks
615 $ hg -R ../cloned-bookmarks-update bookmarks
603 X2 1:925d80f479bb
616 X2 1:925d80f479bb
604 Y 2:db815d6d32e6
617 Y 2:db815d6d32e6
605 * Z 2:db815d6d32e6
618 * Z 2:db815d6d32e6
606 x y 2:db815d6d32e6
619 x y 2:db815d6d32e6
607
620
608 create bundle with two heads
621 create bundle with two heads
609
622
610 $ hg clone . tobundle
623 $ hg clone . tobundle
611 updating to branch default
624 updating to branch default
612 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
625 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
613 $ echo x > tobundle/x
626 $ echo x > tobundle/x
614 $ hg -R tobundle add tobundle/x
627 $ hg -R tobundle add tobundle/x
615 $ hg -R tobundle commit -m'x'
628 $ hg -R tobundle commit -m'x'
616 $ hg -R tobundle update -r -2
629 $ hg -R tobundle update -r -2
617 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
630 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
618 $ echo y > tobundle/y
631 $ echo y > tobundle/y
619 $ hg -R tobundle branch test
632 $ hg -R tobundle branch test
620 marked working directory as branch test
633 marked working directory as branch test
621 (branches are permanent and global, did you want a bookmark?)
634 (branches are permanent and global, did you want a bookmark?)
622 $ hg -R tobundle add tobundle/y
635 $ hg -R tobundle add tobundle/y
623 $ hg -R tobundle commit -m'y'
636 $ hg -R tobundle commit -m'y'
624 $ hg -R tobundle bundle tobundle.hg
637 $ hg -R tobundle bundle tobundle.hg
625 searching for changes
638 searching for changes
626 2 changesets found
639 2 changesets found
627 $ hg unbundle tobundle.hg
640 $ hg unbundle tobundle.hg
628 adding changesets
641 adding changesets
629 adding manifests
642 adding manifests
630 adding file changes
643 adding file changes
631 added 2 changesets with 2 changes to 2 files (+1 heads)
644 added 2 changesets with 2 changes to 2 files (+1 heads)
632 new changesets 125c9a1d6df6:9ba5f110a0b3
645 new changesets 125c9a1d6df6:9ba5f110a0b3
633 (run 'hg heads' to see heads, 'hg merge' to merge)
646 (run 'hg heads' to see heads, 'hg merge' to merge)
634
647
635 update to active bookmark if it's not the parent
648 update to active bookmark if it's not the parent
636
649
637 (it is known issue that fsmonitor can't handle nested repositories. In
650 (it is known issue that fsmonitor can't handle nested repositories. In
638 this test scenario, cloned-bookmark-default and tobundle exist in the
651 this test scenario, cloned-bookmark-default and tobundle exist in the
639 working directory of current repository)
652 working directory of current repository)
640
653
641 $ hg summary
654 $ hg summary
642 parent: 2:db815d6d32e6
655 parent: 2:db815d6d32e6
643 2
656 2
644 branch: default
657 branch: default
645 bookmarks: *Z Y x y
658 bookmarks: *Z Y x y
646 commit: 1 added, 1 unknown (new branch head) (no-fsmonitor !)
659 commit: 1 added, 1 unknown (new branch head) (no-fsmonitor !)
647 commit: 1 added, * unknown (new branch head) (glob) (fsmonitor !)
660 commit: 1 added, * unknown (new branch head) (glob) (fsmonitor !)
648 update: 2 new changesets (update)
661 update: 2 new changesets (update)
649 phases: 5 draft
662 phases: 5 draft
650 $ hg update
663 $ hg update
651 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
664 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
652 updating bookmark Z
665 updating bookmark Z
653 $ hg bookmarks
666 $ hg bookmarks
654 X2 1:925d80f479bb
667 X2 1:925d80f479bb
655 Y 2:db815d6d32e6
668 Y 2:db815d6d32e6
656 * Z 3:125c9a1d6df6
669 * Z 3:125c9a1d6df6
657 x y 2:db815d6d32e6
670 x y 2:db815d6d32e6
658
671
659 pull --update works the same as pull && update
672 pull --update works the same as pull && update
660
673
661 $ hg bookmark -r3 Y
674 $ hg bookmark -r3 Y
662 moving bookmark 'Y' forward from db815d6d32e6
675 moving bookmark 'Y' forward from db815d6d32e6
663 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update
676 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update
664 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update-with-divergence
677 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update-with-divergence
665
678
666 (manual version)
679 (manual version)
667
680
668 $ hg -R ../cloned-bookmarks-manual-update update Y
681 $ hg -R ../cloned-bookmarks-manual-update update Y
669 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
682 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
670 (activating bookmark Y)
683 (activating bookmark Y)
671 $ hg -R ../cloned-bookmarks-manual-update pull .
684 $ hg -R ../cloned-bookmarks-manual-update pull .
672 pulling from .
685 pulling from .
673 searching for changes
686 searching for changes
674 adding changesets
687 adding changesets
675 adding manifests
688 adding manifests
676 adding file changes
689 adding file changes
677 added 2 changesets with 2 changes to 2 files (+1 heads)
690 added 2 changesets with 2 changes to 2 files (+1 heads)
678 updating bookmark Y
691 updating bookmark Y
679 updating bookmark Z
692 updating bookmark Z
680 new changesets 125c9a1d6df6:9ba5f110a0b3
693 new changesets 125c9a1d6df6:9ba5f110a0b3
681 (run 'hg heads' to see heads, 'hg merge' to merge)
694 (run 'hg heads' to see heads, 'hg merge' to merge)
682
695
683 (# tests strange but with --date crashing when bookmark have to move)
696 (# tests strange but with --date crashing when bookmark have to move)
684
697
685 $ hg -R ../cloned-bookmarks-manual-update update -d 1986
698 $ hg -R ../cloned-bookmarks-manual-update update -d 1986
686 abort: revision matching date not found
699 abort: revision matching date not found
687 [255]
700 [255]
688 $ hg -R ../cloned-bookmarks-manual-update update
701 $ hg -R ../cloned-bookmarks-manual-update update
689 updating to active bookmark Y
702 updating to active bookmark Y
690 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
703 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
691
704
692 (all in one version)
705 (all in one version)
693
706
694 $ hg -R ../cloned-bookmarks-update update Y
707 $ hg -R ../cloned-bookmarks-update update Y
695 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
708 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
696 (activating bookmark Y)
709 (activating bookmark Y)
697 $ hg -R ../cloned-bookmarks-update pull --update .
710 $ hg -R ../cloned-bookmarks-update pull --update .
698 pulling from .
711 pulling from .
699 searching for changes
712 searching for changes
700 adding changesets
713 adding changesets
701 adding manifests
714 adding manifests
702 adding file changes
715 adding file changes
703 added 2 changesets with 2 changes to 2 files (+1 heads)
716 added 2 changesets with 2 changes to 2 files (+1 heads)
704 updating bookmark Y
717 updating bookmark Y
705 updating bookmark Z
718 updating bookmark Z
706 new changesets 125c9a1d6df6:9ba5f110a0b3
719 new changesets 125c9a1d6df6:9ba5f110a0b3
707 updating to active bookmark Y
720 updating to active bookmark Y
708 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
721 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
709
722
710 We warn about divergent during bare update to the active bookmark
723 We warn about divergent during bare update to the active bookmark
711
724
712 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update Y
725 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update Y
713 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
726 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
714 (activating bookmark Y)
727 (activating bookmark Y)
715 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks -r X2 Y@1
728 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks -r X2 Y@1
716 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks
729 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks
717 X2 1:925d80f479bb
730 X2 1:925d80f479bb
718 * Y 2:db815d6d32e6
731 * Y 2:db815d6d32e6
719 Y@1 1:925d80f479bb
732 Y@1 1:925d80f479bb
720 Z 2:db815d6d32e6
733 Z 2:db815d6d32e6
721 x y 2:db815d6d32e6
734 x y 2:db815d6d32e6
722 $ hg -R ../cloned-bookmarks-manual-update-with-divergence pull
735 $ hg -R ../cloned-bookmarks-manual-update-with-divergence pull
723 pulling from $TESTTMP/repo (glob)
736 pulling from $TESTTMP/repo (glob)
724 searching for changes
737 searching for changes
725 adding changesets
738 adding changesets
726 adding manifests
739 adding manifests
727 adding file changes
740 adding file changes
728 added 2 changesets with 2 changes to 2 files (+1 heads)
741 added 2 changesets with 2 changes to 2 files (+1 heads)
729 updating bookmark Y
742 updating bookmark Y
730 updating bookmark Z
743 updating bookmark Z
731 new changesets 125c9a1d6df6:9ba5f110a0b3
744 new changesets 125c9a1d6df6:9ba5f110a0b3
732 (run 'hg heads' to see heads, 'hg merge' to merge)
745 (run 'hg heads' to see heads, 'hg merge' to merge)
733 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update
746 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update
734 updating to active bookmark Y
747 updating to active bookmark Y
735 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
748 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
736 1 other divergent bookmarks for "Y"
749 1 other divergent bookmarks for "Y"
737
750
738 test wrongly formated bookmark
751 test wrongly formated bookmark
739
752
740 $ echo '' >> .hg/bookmarks
753 $ echo '' >> .hg/bookmarks
741 $ hg bookmarks
754 $ hg bookmarks
742 X2 1:925d80f479bb
755 X2 1:925d80f479bb
743 Y 3:125c9a1d6df6
756 Y 3:125c9a1d6df6
744 * Z 3:125c9a1d6df6
757 * Z 3:125c9a1d6df6
745 x y 2:db815d6d32e6
758 x y 2:db815d6d32e6
746 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
759 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
747 $ hg bookmarks
760 $ hg bookmarks
748 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
761 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
749 X2 1:925d80f479bb
762 X2 1:925d80f479bb
750 Y 3:125c9a1d6df6
763 Y 3:125c9a1d6df6
751 * Z 3:125c9a1d6df6
764 * Z 3:125c9a1d6df6
752 x y 2:db815d6d32e6
765 x y 2:db815d6d32e6
753
766
754 test missing revisions
767 test missing revisions
755
768
756 $ echo "925d80f479b925d80f479bc925d80f479bccabab z" > .hg/bookmarks
769 $ echo "925d80f479b925d80f479bc925d80f479bccabab z" > .hg/bookmarks
757 $ hg book
770 $ hg book
758 no bookmarks set
771 no bookmarks set
759
772
760 test stripping a non-checked-out but bookmarked revision
773 test stripping a non-checked-out but bookmarked revision
761
774
762 $ hg log --graph
775 $ hg log --graph
763 o changeset: 4:9ba5f110a0b3
776 o changeset: 4:9ba5f110a0b3
764 | branch: test
777 | branch: test
765 | tag: tip
778 | tag: tip
766 | parent: 2:db815d6d32e6
779 | parent: 2:db815d6d32e6
767 | user: test
780 | user: test
768 | date: Thu Jan 01 00:00:00 1970 +0000
781 | date: Thu Jan 01 00:00:00 1970 +0000
769 | summary: y
782 | summary: y
770 |
783 |
771 | @ changeset: 3:125c9a1d6df6
784 | @ changeset: 3:125c9a1d6df6
772 |/ user: test
785 |/ user: test
773 | date: Thu Jan 01 00:00:00 1970 +0000
786 | date: Thu Jan 01 00:00:00 1970 +0000
774 | summary: x
787 | summary: x
775 |
788 |
776 o changeset: 2:db815d6d32e6
789 o changeset: 2:db815d6d32e6
777 | parent: 0:f7b1eb17ad24
790 | parent: 0:f7b1eb17ad24
778 | user: test
791 | user: test
779 | date: Thu Jan 01 00:00:00 1970 +0000
792 | date: Thu Jan 01 00:00:00 1970 +0000
780 | summary: 2
793 | summary: 2
781 |
794 |
782 | o changeset: 1:925d80f479bb
795 | o changeset: 1:925d80f479bb
783 |/ user: test
796 |/ user: test
784 | date: Thu Jan 01 00:00:00 1970 +0000
797 | date: Thu Jan 01 00:00:00 1970 +0000
785 | summary: 1
798 | summary: 1
786 |
799 |
787 o changeset: 0:f7b1eb17ad24
800 o changeset: 0:f7b1eb17ad24
788 user: test
801 user: test
789 date: Thu Jan 01 00:00:00 1970 +0000
802 date: Thu Jan 01 00:00:00 1970 +0000
790 summary: 0
803 summary: 0
791
804
792 $ hg book should-end-on-two
805 $ hg book should-end-on-two
793 $ hg co --clean 4
806 $ hg co --clean 4
794 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
807 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
795 (leaving bookmark should-end-on-two)
808 (leaving bookmark should-end-on-two)
796 $ hg book four
809 $ hg book four
797 $ hg --config extensions.mq= strip 3
810 $ hg --config extensions.mq= strip 3
798 saved backup bundle to * (glob)
811 saved backup bundle to * (glob)
799 should-end-on-two should end up pointing to revision 2, as that's the
812 should-end-on-two should end up pointing to revision 2, as that's the
800 tipmost surviving ancestor of the stripped revision.
813 tipmost surviving ancestor of the stripped revision.
801 $ hg log --graph
814 $ hg log --graph
802 @ changeset: 3:9ba5f110a0b3
815 @ changeset: 3:9ba5f110a0b3
803 | branch: test
816 | branch: test
804 | bookmark: four
817 | bookmark: four
805 | tag: tip
818 | tag: tip
806 | user: test
819 | user: test
807 | date: Thu Jan 01 00:00:00 1970 +0000
820 | date: Thu Jan 01 00:00:00 1970 +0000
808 | summary: y
821 | summary: y
809 |
822 |
810 o changeset: 2:db815d6d32e6
823 o changeset: 2:db815d6d32e6
811 | bookmark: should-end-on-two
824 | bookmark: should-end-on-two
812 | parent: 0:f7b1eb17ad24
825 | parent: 0:f7b1eb17ad24
813 | user: test
826 | user: test
814 | date: Thu Jan 01 00:00:00 1970 +0000
827 | date: Thu Jan 01 00:00:00 1970 +0000
815 | summary: 2
828 | summary: 2
816 |
829 |
817 | o changeset: 1:925d80f479bb
830 | o changeset: 1:925d80f479bb
818 |/ user: test
831 |/ user: test
819 | date: Thu Jan 01 00:00:00 1970 +0000
832 | date: Thu Jan 01 00:00:00 1970 +0000
820 | summary: 1
833 | summary: 1
821 |
834 |
822 o changeset: 0:f7b1eb17ad24
835 o changeset: 0:f7b1eb17ad24
823 user: test
836 user: test
824 date: Thu Jan 01 00:00:00 1970 +0000
837 date: Thu Jan 01 00:00:00 1970 +0000
825 summary: 0
838 summary: 0
826
839
827
840
828 no-op update doesn't deactivate bookmarks
841 no-op update doesn't deactivate bookmarks
829
842
830 (it is known issue that fsmonitor can't handle nested repositories. In
843 (it is known issue that fsmonitor can't handle nested repositories. In
831 this test scenario, cloned-bookmark-default and tobundle exist in the
844 this test scenario, cloned-bookmark-default and tobundle exist in the
832 working directory of current repository)
845 working directory of current repository)
833
846
834 $ hg bookmarks
847 $ hg bookmarks
835 * four 3:9ba5f110a0b3
848 * four 3:9ba5f110a0b3
836 should-end-on-two 2:db815d6d32e6
849 should-end-on-two 2:db815d6d32e6
837 $ hg up four
850 $ hg up four
838 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
851 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
839 $ hg up
852 $ hg up
840 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
853 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
841 $ hg sum
854 $ hg sum
842 parent: 3:9ba5f110a0b3 tip
855 parent: 3:9ba5f110a0b3 tip
843 y
856 y
844 branch: test
857 branch: test
845 bookmarks: *four
858 bookmarks: *four
846 commit: 2 unknown (clean) (no-fsmonitor !)
859 commit: 2 unknown (clean) (no-fsmonitor !)
847 commit: * unknown (clean) (glob) (fsmonitor !)
860 commit: * unknown (clean) (glob) (fsmonitor !)
848 update: (current)
861 update: (current)
849 phases: 4 draft
862 phases: 4 draft
850
863
851 test clearing divergent bookmarks of linear ancestors
864 test clearing divergent bookmarks of linear ancestors
852
865
853 $ hg bookmark Z -r 0
866 $ hg bookmark Z -r 0
854 $ hg bookmark Z@1 -r 1
867 $ hg bookmark Z@1 -r 1
855 $ hg bookmark Z@2 -r 2
868 $ hg bookmark Z@2 -r 2
856 $ hg bookmark Z@3 -r 3
869 $ hg bookmark Z@3 -r 3
857 $ hg book
870 $ hg book
858 Z 0:f7b1eb17ad24
871 Z 0:f7b1eb17ad24
859 Z@1 1:925d80f479bb
872 Z@1 1:925d80f479bb
860 Z@2 2:db815d6d32e6
873 Z@2 2:db815d6d32e6
861 Z@3 3:9ba5f110a0b3
874 Z@3 3:9ba5f110a0b3
862 * four 3:9ba5f110a0b3
875 * four 3:9ba5f110a0b3
863 should-end-on-two 2:db815d6d32e6
876 should-end-on-two 2:db815d6d32e6
864 $ hg bookmark Z
877 $ hg bookmark Z
865 moving bookmark 'Z' forward from f7b1eb17ad24
878 moving bookmark 'Z' forward from f7b1eb17ad24
866 $ hg book
879 $ hg book
867 * Z 3:9ba5f110a0b3
880 * Z 3:9ba5f110a0b3
868 Z@1 1:925d80f479bb
881 Z@1 1:925d80f479bb
869 four 3:9ba5f110a0b3
882 four 3:9ba5f110a0b3
870 should-end-on-two 2:db815d6d32e6
883 should-end-on-two 2:db815d6d32e6
871
884
872 test clearing only a single divergent bookmark across branches
885 test clearing only a single divergent bookmark across branches
873
886
874 $ hg book foo -r 1
887 $ hg book foo -r 1
875 $ hg book foo@1 -r 0
888 $ hg book foo@1 -r 0
876 $ hg book foo@2 -r 2
889 $ hg book foo@2 -r 2
877 $ hg book foo@3 -r 3
890 $ hg book foo@3 -r 3
878 $ hg book foo -r foo@3
891 $ hg book foo -r foo@3
879 $ hg book
892 $ hg book
880 * Z 3:9ba5f110a0b3
893 * Z 3:9ba5f110a0b3
881 Z@1 1:925d80f479bb
894 Z@1 1:925d80f479bb
882 foo 3:9ba5f110a0b3
895 foo 3:9ba5f110a0b3
883 foo@1 0:f7b1eb17ad24
896 foo@1 0:f7b1eb17ad24
884 foo@2 2:db815d6d32e6
897 foo@2 2:db815d6d32e6
885 four 3:9ba5f110a0b3
898 four 3:9ba5f110a0b3
886 should-end-on-two 2:db815d6d32e6
899 should-end-on-two 2:db815d6d32e6
887
900
888 pull --update works the same as pull && update (case #2)
901 pull --update works the same as pull && update (case #2)
889
902
890 It is assumed that "hg pull" itself doesn't update current active
903 It is assumed that "hg pull" itself doesn't update current active
891 bookmark ('Y' in tests below).
904 bookmark ('Y' in tests below).
892
905
893 $ hg pull -q ../cloned-bookmarks-update
906 $ hg pull -q ../cloned-bookmarks-update
894 divergent bookmark Z stored as Z@2
907 divergent bookmark Z stored as Z@2
895
908
896 (pulling revision on another named branch with --update updates
909 (pulling revision on another named branch with --update updates
897 neither the working directory nor current active bookmark: "no-op"
910 neither the working directory nor current active bookmark: "no-op"
898 case)
911 case)
899
912
900 $ echo yy >> y
913 $ echo yy >> y
901 $ hg commit -m yy
914 $ hg commit -m yy
902
915
903 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
916 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
904 * Y 3:125c9a1d6df6
917 * Y 3:125c9a1d6df6
905 $ hg -R ../cloned-bookmarks-update pull . --update
918 $ hg -R ../cloned-bookmarks-update pull . --update
906 pulling from .
919 pulling from .
907 searching for changes
920 searching for changes
908 adding changesets
921 adding changesets
909 adding manifests
922 adding manifests
910 adding file changes
923 adding file changes
911 added 1 changesets with 1 changes to 1 files
924 added 1 changesets with 1 changes to 1 files
912 divergent bookmark Z stored as Z@default
925 divergent bookmark Z stored as Z@default
913 adding remote bookmark foo
926 adding remote bookmark foo
914 adding remote bookmark four
927 adding remote bookmark four
915 adding remote bookmark should-end-on-two
928 adding remote bookmark should-end-on-two
916 new changesets 5fb12f0f2d51
929 new changesets 5fb12f0f2d51
917 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
930 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
918 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
931 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
919 3:125c9a1d6df6
932 3:125c9a1d6df6
920 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
933 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
921 * Y 3:125c9a1d6df6
934 * Y 3:125c9a1d6df6
922
935
923 (pulling revision on current named/topological branch with --update
936 (pulling revision on current named/topological branch with --update
924 updates the working directory and current active bookmark)
937 updates the working directory and current active bookmark)
925
938
926 $ hg update -C -q 125c9a1d6df6
939 $ hg update -C -q 125c9a1d6df6
927 $ echo xx >> x
940 $ echo xx >> x
928 $ hg commit -m xx
941 $ hg commit -m xx
929
942
930 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
943 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
931 * Y 3:125c9a1d6df6
944 * Y 3:125c9a1d6df6
932 $ hg -R ../cloned-bookmarks-update pull . --update
945 $ hg -R ../cloned-bookmarks-update pull . --update
933 pulling from .
946 pulling from .
934 searching for changes
947 searching for changes
935 adding changesets
948 adding changesets
936 adding manifests
949 adding manifests
937 adding file changes
950 adding file changes
938 added 1 changesets with 1 changes to 1 files
951 added 1 changesets with 1 changes to 1 files
939 divergent bookmark Z stored as Z@default
952 divergent bookmark Z stored as Z@default
940 new changesets 81dcce76aa0b
953 new changesets 81dcce76aa0b
941 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
954 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
942 updating bookmark Y
955 updating bookmark Y
943 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
956 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
944 6:81dcce76aa0b
957 6:81dcce76aa0b
945 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
958 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
946 * Y 6:81dcce76aa0b
959 * Y 6:81dcce76aa0b
947
960
948 $ cd ..
961 $ cd ..
949
962
950 ensure changelog is written before bookmarks
963 ensure changelog is written before bookmarks
951 $ hg init orderrepo
964 $ hg init orderrepo
952 $ cd orderrepo
965 $ cd orderrepo
953 $ touch a
966 $ touch a
954 $ hg commit -Aqm one
967 $ hg commit -Aqm one
955 $ hg book mybook
968 $ hg book mybook
956 $ echo a > a
969 $ echo a > a
957
970
958 $ cat > $TESTTMP/pausefinalize.py <<EOF
971 $ cat > $TESTTMP/pausefinalize.py <<EOF
959 > from __future__ import absolute_import
972 > from __future__ import absolute_import
960 > import os
973 > import os
961 > import time
974 > import time
962 > from mercurial import extensions, localrepo
975 > from mercurial import extensions, localrepo
963 > def transaction(orig, self, desc, report=None):
976 > def transaction(orig, self, desc, report=None):
964 > tr = orig(self, desc, report)
977 > tr = orig(self, desc, report)
965 > def sleep(*args, **kwargs):
978 > def sleep(*args, **kwargs):
966 > retry = 20
979 > retry = 20
967 > while retry > 0 and not os.path.exists("$TESTTMP/unpause"):
980 > while retry > 0 and not os.path.exists("$TESTTMP/unpause"):
968 > retry -= 1
981 > retry -= 1
969 > time.sleep(0.5)
982 > time.sleep(0.5)
970 > if os.path.exists("$TESTTMP/unpause"):
983 > if os.path.exists("$TESTTMP/unpause"):
971 > os.remove("$TESTTMP/unpause")
984 > os.remove("$TESTTMP/unpause")
972 > # It is important that this finalizer start with 'a', so it runs before
985 > # It is important that this finalizer start with 'a', so it runs before
973 > # the changelog finalizer appends to the changelog.
986 > # the changelog finalizer appends to the changelog.
974 > tr.addfinalize('a-sleep', sleep)
987 > tr.addfinalize('a-sleep', sleep)
975 > return tr
988 > return tr
976 >
989 >
977 > def extsetup(ui):
990 > def extsetup(ui):
978 > # This extension inserts an artifical pause during the transaction
991 > # This extension inserts an artifical pause during the transaction
979 > # finalizer, so we can run commands mid-transaction-close.
992 > # finalizer, so we can run commands mid-transaction-close.
980 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
993 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
981 > transaction)
994 > transaction)
982 > EOF
995 > EOF
983 $ hg commit -qm two --config extensions.pausefinalize=$TESTTMP/pausefinalize.py &
996 $ hg commit -qm two --config extensions.pausefinalize=$TESTTMP/pausefinalize.py &
984 $ sleep 2
997 $ sleep 2
985 $ hg log -r .
998 $ hg log -r .
986 changeset: 0:867bc5792c8c
999 changeset: 0:867bc5792c8c
987 bookmark: mybook
1000 bookmark: mybook
988 tag: tip
1001 tag: tip
989 user: test
1002 user: test
990 date: Thu Jan 01 00:00:00 1970 +0000
1003 date: Thu Jan 01 00:00:00 1970 +0000
991 summary: one
1004 summary: one
992
1005
993 $ hg bookmarks
1006 $ hg bookmarks
994 * mybook 0:867bc5792c8c
1007 * mybook 0:867bc5792c8c
995 $ touch $TESTTMP/unpause
1008 $ touch $TESTTMP/unpause
996
1009
997 $ cd ..
1010 $ cd ..
998
1011
999 check whether HG_PENDING makes pending changes only in related
1012 check whether HG_PENDING makes pending changes only in related
1000 repositories visible to an external hook.
1013 repositories visible to an external hook.
1001
1014
1002 (emulate a transaction running concurrently by copied
1015 (emulate a transaction running concurrently by copied
1003 .hg/bookmarks.pending in subsequent test)
1016 .hg/bookmarks.pending in subsequent test)
1004
1017
1005 $ cat > $TESTTMP/savepending.sh <<EOF
1018 $ cat > $TESTTMP/savepending.sh <<EOF
1006 > cp .hg/bookmarks.pending .hg/bookmarks.pending.saved
1019 > cp .hg/bookmarks.pending .hg/bookmarks.pending.saved
1007 > exit 1 # to avoid adding new bookmark for subsequent tests
1020 > exit 1 # to avoid adding new bookmark for subsequent tests
1008 > EOF
1021 > EOF
1009
1022
1010 $ hg init unrelated
1023 $ hg init unrelated
1011 $ cd unrelated
1024 $ cd unrelated
1012 $ echo a > a
1025 $ echo a > a
1013 $ hg add a
1026 $ hg add a
1014 $ hg commit -m '#0'
1027 $ hg commit -m '#0'
1015 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" bookmarks INVISIBLE
1028 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" bookmarks INVISIBLE
1016 transaction abort!
1029 transaction abort!
1017 rollback completed
1030 rollback completed
1018 abort: pretxnclose hook exited with status 1
1031 abort: pretxnclose hook exited with status 1
1019 [255]
1032 [255]
1020 $ cp .hg/bookmarks.pending.saved .hg/bookmarks.pending
1033 $ cp .hg/bookmarks.pending.saved .hg/bookmarks.pending
1021
1034
1022 (check visible bookmarks while transaction running in repo)
1035 (check visible bookmarks while transaction running in repo)
1023
1036
1024 $ cat > $TESTTMP/checkpending.sh <<EOF
1037 $ cat > $TESTTMP/checkpending.sh <<EOF
1025 > echo "@repo"
1038 > echo "@repo"
1026 > hg -R "$TESTTMP/repo" bookmarks
1039 > hg -R "$TESTTMP/repo" bookmarks
1027 > echo "@unrelated"
1040 > echo "@unrelated"
1028 > hg -R "$TESTTMP/unrelated" bookmarks
1041 > hg -R "$TESTTMP/unrelated" bookmarks
1029 > exit 1 # to avoid adding new bookmark for subsequent tests
1042 > exit 1 # to avoid adding new bookmark for subsequent tests
1030 > EOF
1043 > EOF
1031
1044
1032 $ cd ../repo
1045 $ cd ../repo
1033 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" bookmarks NEW
1046 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" bookmarks NEW
1034 @repo
1047 @repo
1035 * NEW 6:81dcce76aa0b
1048 * NEW 6:81dcce76aa0b
1036 X2 1:925d80f479bb
1049 X2 1:925d80f479bb
1037 Y 4:125c9a1d6df6
1050 Y 4:125c9a1d6df6
1038 Z 5:5fb12f0f2d51
1051 Z 5:5fb12f0f2d51
1039 Z@1 1:925d80f479bb
1052 Z@1 1:925d80f479bb
1040 Z@2 4:125c9a1d6df6
1053 Z@2 4:125c9a1d6df6
1041 foo 3:9ba5f110a0b3
1054 foo 3:9ba5f110a0b3
1042 foo@1 0:f7b1eb17ad24
1055 foo@1 0:f7b1eb17ad24
1043 foo@2 2:db815d6d32e6
1056 foo@2 2:db815d6d32e6
1044 four 3:9ba5f110a0b3
1057 four 3:9ba5f110a0b3
1045 should-end-on-two 2:db815d6d32e6
1058 should-end-on-two 2:db815d6d32e6
1046 x y 2:db815d6d32e6
1059 x y 2:db815d6d32e6
1047 @unrelated
1060 @unrelated
1048 no bookmarks set
1061 no bookmarks set
1049 transaction abort!
1062 transaction abort!
1050 rollback completed
1063 rollback completed
1051 abort: pretxnclose hook exited with status 1
1064 abort: pretxnclose hook exited with status 1
1052 [255]
1065 [255]
General Comments 0
You need to be logged in to leave comments. Login now