##// 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 1 # Mercurial bookmark support code
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11
12 12 from .i18n import _
13 13 from .node import (
14 14 bin,
15 15 hex,
16 16 short,
17 17 )
18 18 from . import (
19 19 encoding,
20 20 error,
21 21 lock as lockmod,
22 22 obsutil,
23 23 pycompat,
24 24 scmutil,
25 25 txnutil,
26 26 util,
27 27 )
28 28
29 29 # label constants
30 30 # until 3.5, bookmarks.current was the advertised name, not
31 31 # bookmarks.active, so we must use both to avoid breaking old
32 32 # custom styles
33 33 activebookmarklabel = 'bookmarks.active bookmarks.current'
34 34
35 35 def _getbkfile(repo):
36 36 """Hook so that extensions that mess with the store can hook bm storage.
37 37
38 38 For core, this just handles wether we should see pending
39 39 bookmarks or the committed ones. Other extensions (like share)
40 40 may need to tweak this behavior further.
41 41 """
42 42 fp, pending = txnutil.trypending(repo.root, repo.vfs, 'bookmarks')
43 43 return fp
44 44
45 45 class bmstore(dict):
46 46 """Storage for bookmarks.
47 47
48 48 This object should do all bookmark-related reads and writes, so
49 49 that it's fairly simple to replace the storage underlying
50 50 bookmarks without having to clone the logic surrounding
51 51 bookmarks. This type also should manage the active bookmark, if
52 52 any.
53 53
54 54 This particular bmstore implementation stores bookmarks as
55 55 {hash}\s{name}\n (the same format as localtags) in
56 56 .hg/bookmarks. The mapping is stored as {name: nodeid}.
57 57 """
58 58
59 59 def __init__(self, repo):
60 60 dict.__init__(self)
61 61 self._repo = repo
62 62 self._clean = True
63 63 self._aclean = True
64 64 nm = repo.changelog.nodemap
65 65 tonode = bin # force local lookup
66 66 setitem = dict.__setitem__
67 67 try:
68 68 with _getbkfile(repo) as bkfile:
69 69 for line in bkfile:
70 70 line = line.strip()
71 71 if not line:
72 72 continue
73 73 try:
74 74 sha, refspec = line.split(' ', 1)
75 75 node = tonode(sha)
76 76 if node in nm:
77 77 refspec = encoding.tolocal(refspec)
78 78 setitem(self, refspec, node)
79 79 except (TypeError, ValueError):
80 80 # TypeError:
81 81 # - bin(...)
82 82 # ValueError:
83 83 # - node in nm, for non-20-bytes entry
84 84 # - split(...), for string without ' '
85 85 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
86 86 % line)
87 87 except IOError as inst:
88 88 if inst.errno != errno.ENOENT:
89 89 raise
90 90 self._active = _readactive(repo, self)
91 91
92 92 @property
93 93 def active(self):
94 94 return self._active
95 95
96 96 @active.setter
97 97 def active(self, mark):
98 98 if mark is not None and mark not in self:
99 99 raise AssertionError('bookmark %s does not exist!' % mark)
100 100
101 101 self._active = mark
102 102 self._aclean = False
103 103
104 104 def __setitem__(self, *args, **kwargs):
105 105 msg = ("'bookmarks[name] = node' is deprecated, "
106 106 "use 'bookmarks.applychanges'")
107 107 self._repo.ui.deprecwarn(msg, '4.3')
108 108 self._set(*args, **kwargs)
109 109
110 110 def _set(self, key, value):
111 111 self._clean = False
112 112 return dict.__setitem__(self, key, value)
113 113
114 114 def __delitem__(self, key):
115 115 msg = ("'del bookmarks[name]' is deprecated, "
116 116 "use 'bookmarks.applychanges'")
117 117 self._repo.ui.deprecwarn(msg, '4.3')
118 118 self._del(key)
119 119
120 120 def _del(self, key):
121 121 self._clean = False
122 122 return dict.__delitem__(self, key)
123 123
124 124 def applychanges(self, repo, tr, changes):
125 125 """Apply a list of changes to bookmarks
126 126 """
127 127 bmchanges = tr.changes.get('bookmarks')
128 128 for name, node in changes:
129 129 old = self.get(name)
130 130 if node is None:
131 131 self._del(name)
132 132 else:
133 133 self._set(name, node)
134 134 if bmchanges is not None:
135 135 # if a previous value exist preserve the "initial" value
136 136 previous = bmchanges.get(name)
137 137 if previous is not None:
138 138 old = previous[0]
139 139 bmchanges[name] = (old, node)
140 140 self._recordchange(tr)
141 141
142 142 def recordchange(self, tr):
143 143 msg = ("'bookmarks.recorchange' is deprecated, "
144 144 "use 'bookmarks.applychanges'")
145 145 self._repo.ui.deprecwarn(msg, '4.3')
146 146 return self._recordchange(tr)
147 147
148 148 def _recordchange(self, tr):
149 149 """record that bookmarks have been changed in a transaction
150 150
151 151 The transaction is then responsible for updating the file content."""
152 152 tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
153 153 location='plain')
154 154 tr.hookargs['bookmark_moved'] = '1'
155 155
156 156 def _writerepo(self, repo):
157 157 """Factored out for extensibility"""
158 158 rbm = repo._bookmarks
159 159 if rbm.active not in self:
160 160 rbm.active = None
161 161 rbm._writeactive()
162 162
163 163 with repo.wlock():
164 164 file_ = repo.vfs('bookmarks', 'w', atomictemp=True,
165 165 checkambig=True)
166 166 try:
167 167 self._write(file_)
168 168 except: # re-raises
169 169 file_.discard()
170 170 raise
171 171 finally:
172 172 file_.close()
173 173
174 174 def _writeactive(self):
175 175 if self._aclean:
176 176 return
177 177 with self._repo.wlock():
178 178 if self._active is not None:
179 179 f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True,
180 180 checkambig=True)
181 181 try:
182 182 f.write(encoding.fromlocal(self._active))
183 183 finally:
184 184 f.close()
185 185 else:
186 186 self._repo.vfs.tryunlink('bookmarks.current')
187 187 self._aclean = True
188 188
189 189 def _write(self, fp):
190 190 for name, node in self.iteritems():
191 191 fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
192 192 self._clean = True
193 193 self._repo.invalidatevolatilesets()
194 194
195 195 def expandname(self, bname):
196 196 if bname == '.':
197 197 if self.active:
198 198 return self.active
199 199 else:
200 200 raise error.Abort(_("no active bookmark"))
201 201 return bname
202 202
203 203 def checkconflict(self, mark, force=False, target=None):
204 204 """check repo for a potential clash of mark with an existing bookmark,
205 205 branch, or hash
206 206
207 207 If target is supplied, then check that we are moving the bookmark
208 208 forward.
209 209
210 210 If force is supplied, then forcibly move the bookmark to a new commit
211 211 regardless if it is a move forward.
212 212
213 213 If divergent bookmark are to be deleted, they will be returned as list.
214 214 """
215 215 cur = self._repo.changectx('.').node()
216 216 if mark in self and not force:
217 217 if target:
218 218 if self[mark] == target and target == cur:
219 219 # re-activating a bookmark
220 220 return []
221 221 rev = self._repo[target].rev()
222 222 anc = self._repo.changelog.ancestors([rev])
223 223 bmctx = self._repo[self[mark]]
224 224 divs = [self._repo[b].node() for b in self
225 225 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
226 226
227 227 # allow resolving a single divergent bookmark even if moving
228 228 # the bookmark across branches when a revision is specified
229 229 # that contains a divergent bookmark
230 230 if bmctx.rev() not in anc and target in divs:
231 231 return divergent2delete(self._repo, [target], mark)
232 232
233 233 deletefrom = [b for b in divs
234 234 if self._repo[b].rev() in anc or b == target]
235 235 delbms = divergent2delete(self._repo, deletefrom, mark)
236 236 if validdest(self._repo, bmctx, self._repo[target]):
237 237 self._repo.ui.status(
238 238 _("moving bookmark '%s' forward from %s\n") %
239 239 (mark, short(bmctx.node())))
240 240 return delbms
241 241 raise error.Abort(_("bookmark '%s' already exists "
242 242 "(use -f to force)") % mark)
243 243 if ((mark in self._repo.branchmap() or
244 244 mark == self._repo.dirstate.branch()) and not force):
245 245 raise error.Abort(
246 246 _("a bookmark cannot have the name of an existing branch"))
247 247 if len(mark) > 3 and not force:
248 248 try:
249 249 shadowhash = (mark in self._repo)
250 250 except error.LookupError: # ambiguous identifier
251 251 shadowhash = False
252 252 if shadowhash:
253 253 self._repo.ui.warn(
254 254 _("bookmark %s matches a changeset hash\n"
255 255 "(did you leave a -r out of an 'hg bookmark' "
256 256 "command?)\n")
257 257 % mark)
258 258 return []
259 259
260 260 def _readactive(repo, marks):
261 261 """
262 262 Get the active bookmark. We can have an active bookmark that updates
263 263 itself as we commit. This function returns the name of that bookmark.
264 264 It is stored in .hg/bookmarks.current
265 265 """
266 266 mark = None
267 267 try:
268 268 file = repo.vfs('bookmarks.current')
269 269 except IOError as inst:
270 270 if inst.errno != errno.ENOENT:
271 271 raise
272 272 return None
273 273 try:
274 274 # No readline() in osutil.posixfile, reading everything is
275 275 # cheap.
276 276 # Note that it's possible for readlines() here to raise
277 277 # IOError, since we might be reading the active mark over
278 278 # static-http which only tries to load the file when we try
279 279 # to read from it.
280 280 mark = encoding.tolocal((file.readlines() or [''])[0])
281 281 if mark == '' or mark not in marks:
282 282 mark = None
283 283 except IOError as inst:
284 284 if inst.errno != errno.ENOENT:
285 285 raise
286 286 return None
287 287 finally:
288 288 file.close()
289 289 return mark
290 290
291 291 def activate(repo, mark):
292 292 """
293 293 Set the given bookmark to be 'active', meaning that this bookmark will
294 294 follow new commits that are made.
295 295 The name is recorded in .hg/bookmarks.current
296 296 """
297 297 repo._bookmarks.active = mark
298 298 repo._bookmarks._writeactive()
299 299
300 300 def deactivate(repo):
301 301 """
302 302 Unset the active bookmark in this repository.
303 303 """
304 304 repo._bookmarks.active = None
305 305 repo._bookmarks._writeactive()
306 306
307 307 def isactivewdirparent(repo):
308 308 """
309 309 Tell whether the 'active' bookmark (the one that follows new commits)
310 310 points to one of the parents of the current working directory (wdir).
311 311
312 312 While this is normally the case, it can on occasion be false; for example,
313 313 immediately after a pull, the active bookmark can be moved to point
314 314 to a place different than the wdir. This is solved by running `hg update`.
315 315 """
316 316 mark = repo._activebookmark
317 317 marks = repo._bookmarks
318 318 parents = [p.node() for p in repo[None].parents()]
319 319 return (mark in marks and marks[mark] in parents)
320 320
321 321 def divergent2delete(repo, deletefrom, bm):
322 322 """find divergent versions of bm on nodes in deletefrom.
323 323
324 324 the list of bookmark to delete."""
325 325 todelete = []
326 326 marks = repo._bookmarks
327 327 divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
328 328 for mark in divergent:
329 329 if mark == '@' or '@' not in mark:
330 330 # can't be divergent by definition
331 331 continue
332 332 if mark and marks[mark] in deletefrom:
333 333 if mark != bm:
334 334 todelete.append(mark)
335 335 return todelete
336 336
337 337 def headsforactive(repo):
338 338 """Given a repo with an active bookmark, return divergent bookmark nodes.
339 339
340 340 Args:
341 341 repo: A repository with an active bookmark.
342 342
343 343 Returns:
344 344 A list of binary node ids that is the full list of other
345 345 revisions with bookmarks divergent from the active bookmark. If
346 346 there were no divergent bookmarks, then this list will contain
347 347 only one entry.
348 348 """
349 349 if not repo._activebookmark:
350 350 raise ValueError(
351 351 'headsforactive() only makes sense with an active bookmark')
352 352 name = repo._activebookmark.split('@', 1)[0]
353 353 heads = []
354 354 for mark, n in repo._bookmarks.iteritems():
355 355 if mark.split('@', 1)[0] == name:
356 356 heads.append(n)
357 357 return heads
358 358
359 359 def calculateupdate(ui, repo, checkout):
360 360 '''Return a tuple (targetrev, movemarkfrom) indicating the rev to
361 361 check out and where to move the active bookmark from, if needed.'''
362 362 movemarkfrom = None
363 363 if checkout is None:
364 364 activemark = repo._activebookmark
365 365 if isactivewdirparent(repo):
366 366 movemarkfrom = repo['.'].node()
367 367 elif activemark:
368 368 ui.status(_("updating to active bookmark %s\n") % activemark)
369 369 checkout = activemark
370 370 return (checkout, movemarkfrom)
371 371
372 372 def update(repo, parents, node):
373 373 deletefrom = parents
374 374 marks = repo._bookmarks
375 375 active = marks.active
376 376 if not active:
377 377 return False
378 378
379 379 bmchanges = []
380 380 if marks[active] in parents:
381 381 new = repo[node]
382 382 divs = [repo[b] for b in marks
383 383 if b.split('@', 1)[0] == active.split('@', 1)[0]]
384 384 anc = repo.changelog.ancestors([new.rev()])
385 385 deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
386 386 if validdest(repo, repo[marks[active]], new):
387 387 bmchanges.append((active, new.node()))
388 388
389 389 for bm in divergent2delete(repo, deletefrom, active):
390 390 bmchanges.append((bm, None))
391 391
392 392 if bmchanges:
393 393 lock = tr = None
394 394 try:
395 395 lock = repo.lock()
396 396 tr = repo.transaction('bookmark')
397 397 marks.applychanges(repo, tr, bmchanges)
398 398 tr.close()
399 399 finally:
400 400 lockmod.release(tr, lock)
401 401 return bool(bmchanges)
402 402
403 403 def listbinbookmarks(repo):
404 404 # We may try to list bookmarks on a repo type that does not
405 405 # support it (e.g., statichttprepository).
406 406 marks = getattr(repo, '_bookmarks', {})
407 407
408 408 hasnode = repo.changelog.hasnode
409 409 for k, v in marks.iteritems():
410 410 # don't expose local divergent bookmarks
411 411 if hasnode(v) and ('@' not in k or k.endswith('@')):
412 412 yield k, v
413 413
414 414 def listbookmarks(repo):
415 415 d = {}
416 416 for book, node in listbinbookmarks(repo):
417 417 d[book] = hex(node)
418 418 return d
419 419
420 420 def pushbookmark(repo, key, old, new):
421 421 w = l = tr = None
422 422 try:
423 423 w = repo.wlock()
424 424 l = repo.lock()
425 425 tr = repo.transaction('bookmarks')
426 426 marks = repo._bookmarks
427 427 existing = hex(marks.get(key, ''))
428 428 if existing != old and existing != new:
429 429 return False
430 430 if new == '':
431 431 changes = [(key, None)]
432 432 else:
433 433 if new not in repo:
434 434 return False
435 435 changes = [(key, repo[new].node())]
436 436 marks.applychanges(repo, tr, changes)
437 437 tr.close()
438 438 return True
439 439 finally:
440 440 lockmod.release(tr, l, w)
441 441
442 442 def comparebookmarks(repo, srcmarks, dstmarks, targets=None):
443 443 '''Compare bookmarks between srcmarks and dstmarks
444 444
445 445 This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
446 446 differ, invalid)", each are list of bookmarks below:
447 447
448 448 :addsrc: added on src side (removed on dst side, perhaps)
449 449 :adddst: added on dst side (removed on src side, perhaps)
450 450 :advsrc: advanced on src side
451 451 :advdst: advanced on dst side
452 452 :diverge: diverge
453 453 :differ: changed, but changeset referred on src is unknown on dst
454 454 :invalid: unknown on both side
455 455 :same: same on both side
456 456
457 457 Each elements of lists in result tuple is tuple "(bookmark name,
458 458 changeset ID on source side, changeset ID on destination
459 459 side)". Each changeset IDs are 40 hexadecimal digit string or
460 460 None.
461 461
462 462 Changeset IDs of tuples in "addsrc", "adddst", "differ" or
463 463 "invalid" list may be unknown for repo.
464 464
465 465 If "targets" is specified, only bookmarks listed in it are
466 466 examined.
467 467 '''
468 468
469 469 if targets:
470 470 bset = set(targets)
471 471 else:
472 472 srcmarkset = set(srcmarks)
473 473 dstmarkset = set(dstmarks)
474 474 bset = srcmarkset | dstmarkset
475 475
476 476 results = ([], [], [], [], [], [], [], [])
477 477 addsrc = results[0].append
478 478 adddst = results[1].append
479 479 advsrc = results[2].append
480 480 advdst = results[3].append
481 481 diverge = results[4].append
482 482 differ = results[5].append
483 483 invalid = results[6].append
484 484 same = results[7].append
485 485
486 486 for b in sorted(bset):
487 487 if b not in srcmarks:
488 488 if b in dstmarks:
489 489 adddst((b, None, dstmarks[b]))
490 490 else:
491 491 invalid((b, None, None))
492 492 elif b not in dstmarks:
493 493 addsrc((b, srcmarks[b], None))
494 494 else:
495 495 scid = srcmarks[b]
496 496 dcid = dstmarks[b]
497 497 if scid == dcid:
498 498 same((b, scid, dcid))
499 499 elif scid in repo and dcid in repo:
500 500 sctx = repo[scid]
501 501 dctx = repo[dcid]
502 502 if sctx.rev() < dctx.rev():
503 503 if validdest(repo, sctx, dctx):
504 504 advdst((b, scid, dcid))
505 505 else:
506 506 diverge((b, scid, dcid))
507 507 else:
508 508 if validdest(repo, dctx, sctx):
509 509 advsrc((b, scid, dcid))
510 510 else:
511 511 diverge((b, scid, dcid))
512 512 else:
513 513 # it is too expensive to examine in detail, in this case
514 514 differ((b, scid, dcid))
515 515
516 516 return results
517 517
518 518 def _diverge(ui, b, path, localmarks, remotenode):
519 519 '''Return appropriate diverged bookmark for specified ``path``
520 520
521 521 This returns None, if it is failed to assign any divergent
522 522 bookmark name.
523 523
524 524 This reuses already existing one with "@number" suffix, if it
525 525 refers ``remotenode``.
526 526 '''
527 527 if b == '@':
528 528 b = ''
529 529 # try to use an @pathalias suffix
530 530 # if an @pathalias already exists, we overwrite (update) it
531 531 if path.startswith("file:"):
532 532 path = util.url(path).path
533 533 for p, u in ui.configitems("paths"):
534 534 if u.startswith("file:"):
535 535 u = util.url(u).path
536 536 if path == u:
537 537 return '%s@%s' % (b, p)
538 538
539 539 # assign a unique "@number" suffix newly
540 540 for x in range(1, 100):
541 541 n = '%s@%d' % (b, x)
542 542 if n not in localmarks or localmarks[n] == remotenode:
543 543 return n
544 544
545 545 return None
546 546
547 547 def unhexlifybookmarks(marks):
548 548 binremotemarks = {}
549 549 for name, node in marks.items():
550 550 binremotemarks[name] = bin(node)
551 551 return binremotemarks
552 552
553 553 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
554 554 ui.debug("checking for updated bookmarks\n")
555 555 localmarks = repo._bookmarks
556 556 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
557 557 ) = comparebookmarks(repo, remotemarks, localmarks)
558 558
559 559 status = ui.status
560 560 warn = ui.warn
561 561 if ui.configbool('ui', 'quietbookmarkmove'):
562 562 status = warn = ui.debug
563 563
564 564 explicit = set(explicit)
565 565 changed = []
566 566 for b, scid, dcid in addsrc:
567 567 if scid in repo: # add remote bookmarks for changes we already have
568 568 changed.append((b, scid, status,
569 569 _("adding remote bookmark %s\n") % (b)))
570 570 elif b in explicit:
571 571 explicit.remove(b)
572 572 ui.warn(_("remote bookmark %s points to locally missing %s\n")
573 573 % (b, hex(scid)[:12]))
574 574
575 575 for b, scid, dcid in advsrc:
576 576 changed.append((b, scid, status,
577 577 _("updating bookmark %s\n") % (b)))
578 578 # remove normal movement from explicit set
579 579 explicit.difference_update(d[0] for d in changed)
580 580
581 581 for b, scid, dcid in diverge:
582 582 if b in explicit:
583 583 explicit.discard(b)
584 584 changed.append((b, scid, status,
585 585 _("importing bookmark %s\n") % (b)))
586 586 else:
587 587 db = _diverge(ui, b, path, localmarks, scid)
588 588 if db:
589 589 changed.append((db, scid, warn,
590 590 _("divergent bookmark %s stored as %s\n") %
591 591 (b, db)))
592 592 else:
593 593 warn(_("warning: failed to assign numbered name "
594 594 "to divergent bookmark %s\n") % (b))
595 595 for b, scid, dcid in adddst + advdst:
596 596 if b in explicit:
597 597 explicit.discard(b)
598 598 changed.append((b, scid, status,
599 599 _("importing bookmark %s\n") % (b)))
600 600 for b, scid, dcid in differ:
601 601 if b in explicit:
602 602 explicit.remove(b)
603 603 ui.warn(_("remote bookmark %s points to locally missing %s\n")
604 604 % (b, hex(scid)[:12]))
605 605
606 606 if changed:
607 607 tr = trfunc()
608 608 changes = []
609 609 for b, node, writer, msg in sorted(changed):
610 610 changes.append((b, node))
611 611 writer(msg)
612 612 localmarks.applychanges(repo, tr, changes)
613 613
614 614 def incoming(ui, repo, other):
615 615 '''Show bookmarks incoming from other to repo
616 616 '''
617 617 ui.status(_("searching for changed bookmarks\n"))
618 618
619 619 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
620 620 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
621 621 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
622 622
623 623 incomings = []
624 624 if ui.debugflag:
625 625 getid = lambda id: id
626 626 else:
627 627 getid = lambda id: id[:12]
628 628 if ui.verbose:
629 629 def add(b, id, st):
630 630 incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
631 631 else:
632 632 def add(b, id, st):
633 633 incomings.append(" %-25s %s\n" % (b, getid(id)))
634 634 for b, scid, dcid in addsrc:
635 635 # i18n: "added" refers to a bookmark
636 636 add(b, hex(scid), _('added'))
637 637 for b, scid, dcid in advsrc:
638 638 # i18n: "advanced" refers to a bookmark
639 639 add(b, hex(scid), _('advanced'))
640 640 for b, scid, dcid in diverge:
641 641 # i18n: "diverged" refers to a bookmark
642 642 add(b, hex(scid), _('diverged'))
643 643 for b, scid, dcid in differ:
644 644 # i18n: "changed" refers to a bookmark
645 645 add(b, hex(scid), _('changed'))
646 646
647 647 if not incomings:
648 648 ui.status(_("no changed bookmarks found\n"))
649 649 return 1
650 650
651 651 for s in sorted(incomings):
652 652 ui.write(s)
653 653
654 654 return 0
655 655
656 656 def outgoing(ui, repo, other):
657 657 '''Show bookmarks outgoing from repo to other
658 658 '''
659 659 ui.status(_("searching for changed bookmarks\n"))
660 660
661 661 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
662 662 r = comparebookmarks(repo, repo._bookmarks, remotemarks)
663 663 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
664 664
665 665 outgoings = []
666 666 if ui.debugflag:
667 667 getid = lambda id: id
668 668 else:
669 669 getid = lambda id: id[:12]
670 670 if ui.verbose:
671 671 def add(b, id, st):
672 672 outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
673 673 else:
674 674 def add(b, id, st):
675 675 outgoings.append(" %-25s %s\n" % (b, getid(id)))
676 676 for b, scid, dcid in addsrc:
677 677 # i18n: "added refers to a bookmark
678 678 add(b, hex(scid), _('added'))
679 679 for b, scid, dcid in adddst:
680 680 # i18n: "deleted" refers to a bookmark
681 681 add(b, ' ' * 40, _('deleted'))
682 682 for b, scid, dcid in advsrc:
683 683 # i18n: "advanced" refers to a bookmark
684 684 add(b, hex(scid), _('advanced'))
685 685 for b, scid, dcid in diverge:
686 686 # i18n: "diverged" refers to a bookmark
687 687 add(b, hex(scid), _('diverged'))
688 688 for b, scid, dcid in differ:
689 689 # i18n: "changed" refers to a bookmark
690 690 add(b, hex(scid), _('changed'))
691 691
692 692 if not outgoings:
693 693 ui.status(_("no changed bookmarks found\n"))
694 694 return 1
695 695
696 696 for s in sorted(outgoings):
697 697 ui.write(s)
698 698
699 699 return 0
700 700
701 701 def summary(repo, other):
702 702 '''Compare bookmarks between repo and other for "hg summary" output
703 703
704 704 This returns "(# of incoming, # of outgoing)" tuple.
705 705 '''
706 706 remotemarks = unhexlifybookmarks(other.listkeys('bookmarks'))
707 707 r = comparebookmarks(repo, remotemarks, repo._bookmarks)
708 708 addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
709 709 return (len(addsrc), len(adddst))
710 710
711 711 def validdest(repo, old, new):
712 712 """Is the new bookmark destination a valid update from the old one"""
713 713 repo = repo.unfiltered()
714 714 if old == new:
715 715 # Old == new -> nothing to update.
716 716 return False
717 717 elif not old:
718 718 # old is nullrev, anything is valid.
719 719 # (new != nullrev has been excluded by the previous check)
720 720 return True
721 721 elif repo.obsstore:
722 722 return new.node() in obsutil.foreground(repo, [old.node()])
723 723 else:
724 724 # still an independent clause as it is lazier (and therefore faster)
725 725 return old.descendant(new)
726 726
727 727 def checkformat(repo, mark):
728 728 """return a valid version of a potential bookmark name
729 729
730 730 Raises an abort error if the bookmark name is not valid.
731 731 """
732 732 mark = mark.strip()
733 733 if not mark:
734 734 raise error.Abort(_("bookmark names cannot consist entirely of "
735 735 "whitespace"))
736 736 scmutil.checknewlabel(repo, mark, 'bookmark')
737 737 return mark
738 738
739 739 def delete(repo, tr, names):
740 740 """remove a mark from the bookmark store
741 741
742 742 Raises an abort error if mark does not exist.
743 743 """
744 744 marks = repo._bookmarks
745 745 changes = []
746 746 for mark in names:
747 747 if mark not in marks:
748 748 raise error.Abort(_("bookmark '%s' does not exist") % mark)
749 749 if mark == repo._activebookmark:
750 750 deactivate(repo)
751 751 changes.append((mark, None))
752 752 marks.applychanges(repo, tr, changes)
753 753
754 754 def rename(repo, tr, old, new, force=False, inactive=False):
755 755 """rename a bookmark from old to new
756 756
757 757 If force is specified, then the new name can overwrite an existing
758 758 bookmark.
759 759
760 760 If inactive is specified, then do not activate the new bookmark.
761 761
762 762 Raises an abort error if old is not in the bookmark store.
763 763 """
764 764 marks = repo._bookmarks
765 765 mark = checkformat(repo, new)
766 766 if old not in marks:
767 767 raise error.Abort(_("bookmark '%s' does not exist") % old)
768 768 changes = []
769 769 for bm in marks.checkconflict(mark, force):
770 770 changes.append((bm, None))
771 771 changes.extend([(mark, marks[old]), (old, None)])
772 772 marks.applychanges(repo, tr, changes)
773 773 if repo._activebookmark == old and not inactive:
774 774 activate(repo, mark)
775 775
776 776 def addbookmarks(repo, tr, names, rev=None, force=False, inactive=False):
777 777 """add a list of bookmarks
778 778
779 779 If force is specified, then the new name can overwrite an existing
780 780 bookmark.
781 781
782 782 If inactive is specified, then do not activate any bookmark. Otherwise, the
783 783 first bookmark is activated.
784 784
785 785 Raises an abort error if old is not in the bookmark store.
786 786 """
787 787 marks = repo._bookmarks
788 788 cur = repo.changectx('.').node()
789 789 newact = None
790 790 changes = []
791 791 for mark in names:
792 792 mark = checkformat(repo, mark)
793 793 if newact is None:
794 794 newact = mark
795 795 if inactive and mark == repo._activebookmark:
796 796 deactivate(repo)
797 797 return
798 798 tgt = cur
799 799 if rev:
800 800 tgt = scmutil.revsingle(repo, rev).node()
801 801 for bm in marks.checkconflict(mark, force, tgt):
802 802 changes.append((bm, None))
803 803 changes.append((mark, tgt))
804 804 marks.applychanges(repo, tr, changes)
805 805 if not inactive and cur == marks[newact] and not rev:
806 806 activate(repo, newact)
807 807 elif cur != tgt and newact == repo._activebookmark:
808 808 deactivate(repo)
809 809
810 810 def _printbookmarks(ui, repo, bmarks, **opts):
811 811 """private method to print bookmarks
812 812
813 813 Provides a way for extensions to control how bookmarks are printed (e.g.
814 814 prepend or postpend names)
815 815 """
816 816 opts = pycompat.byteskwargs(opts)
817 817 fm = ui.formatter('bookmarks', opts)
818 818 hexfn = fm.hexfunc
819 819 if len(bmarks) == 0 and fm.isplain():
820 820 ui.status(_("no bookmarks set\n"))
821 821 for bmark, (n, prefix, label) in sorted(bmarks.iteritems()):
822 822 fm.startitem()
823 823 if not ui.quiet:
824 824 fm.plain(' %s ' % prefix, label=label)
825 825 fm.write('bookmark', '%s', bmark, label=label)
826 826 pad = " " * (25 - encoding.colwidth(bmark))
827 827 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
828 828 repo.changelog.rev(n), hexfn(n), label=label)
829 829 fm.data(active=(activebookmarklabel in label))
830 830 fm.plain('\n')
831 831 fm.end()
832 832
833 833 def printbookmarks(ui, repo, **opts):
834 834 """print bookmarks to a formatter
835 835
836 836 Provides a way for extensions to control how bookmarks are printed.
837 837 """
838 838 marks = repo._bookmarks
839 839 bmarks = {}
840 840 for bmark, n in sorted(marks.iteritems()):
841 841 active = repo._activebookmark
842 842 if bmark == active:
843 843 prefix, label = '*', activebookmarklabel
844 844 else:
845 845 prefix, label = ' ', ''
846 846
847 847 bmarks[bmark] = (n, prefix, label)
848 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 1 The Mercurial system uses a set of configuration files to control
2 2 aspects of its behavior.
3 3
4 4 Troubleshooting
5 5 ===============
6 6
7 7 If you're having problems with your configuration,
8 8 :hg:`config --debug` can help you understand what is introducing
9 9 a setting into your environment.
10 10
11 11 See :hg:`help config.syntax` and :hg:`help config.files`
12 12 for information about how and where to override things.
13 13
14 14 Structure
15 15 =========
16 16
17 17 The configuration files use a simple ini-file format. A configuration
18 18 file consists of sections, led by a ``[section]`` header and followed
19 19 by ``name = value`` entries::
20 20
21 21 [ui]
22 22 username = Firstname Lastname <firstname.lastname@example.net>
23 23 verbose = True
24 24
25 25 The above entries will be referred to as ``ui.username`` and
26 26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
27 27
28 28 Files
29 29 =====
30 30
31 31 Mercurial reads configuration data from several files, if they exist.
32 32 These files do not exist by default and you will have to create the
33 33 appropriate configuration files yourself:
34 34
35 35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
36 36
37 37 Global configuration like the username setting is typically put into:
38 38
39 39 .. container:: windows
40 40
41 41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
42 42
43 43 .. container:: unix.plan9
44 44
45 45 - ``$HOME/.hgrc`` (on Unix, Plan9)
46 46
47 47 The names of these files depend on the system on which Mercurial is
48 48 installed. ``*.rc`` files from a single directory are read in
49 49 alphabetical order, later ones overriding earlier ones. Where multiple
50 50 paths are given below, settings from earlier paths override later
51 51 ones.
52 52
53 53 .. container:: verbose.unix
54 54
55 55 On Unix, the following files are consulted:
56 56
57 57 - ``<repo>/.hg/hgrc`` (per-repository)
58 58 - ``$HOME/.hgrc`` (per-user)
59 59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
60 60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
61 61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
62 62 - ``/etc/mercurial/hgrc`` (per-system)
63 63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
64 64 - ``<internal>/default.d/*.rc`` (defaults)
65 65
66 66 .. container:: verbose.windows
67 67
68 68 On Windows, the following files are consulted:
69 69
70 70 - ``<repo>/.hg/hgrc`` (per-repository)
71 71 - ``%USERPROFILE%\.hgrc`` (per-user)
72 72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
73 73 - ``%HOME%\.hgrc`` (per-user)
74 74 - ``%HOME%\Mercurial.ini`` (per-user)
75 75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
76 76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
77 77 - ``<install-dir>\Mercurial.ini`` (per-installation)
78 78 - ``<internal>/default.d/*.rc`` (defaults)
79 79
80 80 .. note::
81 81
82 82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
83 83 is used when running 32-bit Python on 64-bit Windows.
84 84
85 85 .. container:: windows
86 86
87 87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
88 88
89 89 .. container:: verbose.plan9
90 90
91 91 On Plan9, the following files are consulted:
92 92
93 93 - ``<repo>/.hg/hgrc`` (per-repository)
94 94 - ``$home/lib/hgrc`` (per-user)
95 95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
96 96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
97 97 - ``/lib/mercurial/hgrc`` (per-system)
98 98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
99 99 - ``<internal>/default.d/*.rc`` (defaults)
100 100
101 101 Per-repository configuration options only apply in a
102 102 particular repository. This file is not version-controlled, and
103 103 will not get transferred during a "clone" operation. Options in
104 104 this file override options in all other configuration files.
105 105
106 106 .. container:: unix.plan9
107 107
108 108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
109 109 belong to a trusted user or to a trusted group. See
110 110 :hg:`help config.trusted` for more details.
111 111
112 112 Per-user configuration file(s) are for the user running Mercurial. Options
113 113 in these files apply to all Mercurial commands executed by this user in any
114 114 directory. Options in these files override per-system and per-installation
115 115 options.
116 116
117 117 Per-installation configuration files are searched for in the
118 118 directory where Mercurial is installed. ``<install-root>`` is the
119 119 parent directory of the **hg** executable (or symlink) being run.
120 120
121 121 .. container:: unix.plan9
122 122
123 123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
124 124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
125 125 files apply to all Mercurial commands executed by any user in any
126 126 directory.
127 127
128 128 Per-installation configuration files are for the system on
129 129 which Mercurial is running. Options in these files apply to all
130 130 Mercurial commands executed by any user in any directory. Registry
131 131 keys contain PATH-like strings, every part of which must reference
132 132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
133 133 be read. Mercurial checks each of these locations in the specified
134 134 order until one or more configuration files are detected.
135 135
136 136 Per-system configuration files are for the system on which Mercurial
137 137 is running. Options in these files apply to all Mercurial commands
138 138 executed by any user in any directory. Options in these files
139 139 override per-installation options.
140 140
141 141 Mercurial comes with some default configuration. The default configuration
142 142 files are installed with Mercurial and will be overwritten on upgrades. Default
143 143 configuration files should never be edited by users or administrators but can
144 144 be overridden in other configuration files. So far the directory only contains
145 145 merge tool configuration but packagers can also put other default configuration
146 146 there.
147 147
148 148 Syntax
149 149 ======
150 150
151 151 A configuration file consists of sections, led by a ``[section]`` header
152 152 and followed by ``name = value`` entries (sometimes called
153 153 ``configuration keys``)::
154 154
155 155 [spam]
156 156 eggs=ham
157 157 green=
158 158 eggs
159 159
160 160 Each line contains one entry. If the lines that follow are indented,
161 161 they are treated as continuations of that entry. Leading whitespace is
162 162 removed from values. Empty lines are skipped. Lines beginning with
163 163 ``#`` or ``;`` are ignored and may be used to provide comments.
164 164
165 165 Configuration keys can be set multiple times, in which case Mercurial
166 166 will use the value that was configured last. As an example::
167 167
168 168 [spam]
169 169 eggs=large
170 170 ham=serrano
171 171 eggs=small
172 172
173 173 This would set the configuration key named ``eggs`` to ``small``.
174 174
175 175 It is also possible to define a section multiple times. A section can
176 176 be redefined on the same and/or on different configuration files. For
177 177 example::
178 178
179 179 [foo]
180 180 eggs=large
181 181 ham=serrano
182 182 eggs=small
183 183
184 184 [bar]
185 185 eggs=ham
186 186 green=
187 187 eggs
188 188
189 189 [foo]
190 190 ham=prosciutto
191 191 eggs=medium
192 192 bread=toasted
193 193
194 194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
195 195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
196 196 respectively. As you can see there only thing that matters is the last
197 197 value that was set for each of the configuration keys.
198 198
199 199 If a configuration key is set multiple times in different
200 200 configuration files the final value will depend on the order in which
201 201 the different configuration files are read, with settings from earlier
202 202 paths overriding later ones as described on the ``Files`` section
203 203 above.
204 204
205 205 A line of the form ``%include file`` will include ``file`` into the
206 206 current configuration file. The inclusion is recursive, which means
207 207 that included files can include other files. Filenames are relative to
208 208 the configuration file in which the ``%include`` directive is found.
209 209 Environment variables and ``~user`` constructs are expanded in
210 210 ``file``. This lets you do something like::
211 211
212 212 %include ~/.hgrc.d/$HOST.rc
213 213
214 214 to include a different configuration file on each computer you use.
215 215
216 216 A line with ``%unset name`` will remove ``name`` from the current
217 217 section, if it has been set previously.
218 218
219 219 The values are either free-form text strings, lists of text strings,
220 220 or Boolean values. Boolean values can be set to true using any of "1",
221 221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
222 222 (all case insensitive).
223 223
224 224 List values are separated by whitespace or comma, except when values are
225 225 placed in double quotation marks::
226 226
227 227 allow_read = "John Doe, PhD", brian, betty
228 228
229 229 Quotation marks can be escaped by prefixing them with a backslash. Only
230 230 quotation marks at the beginning of a word is counted as a quotation
231 231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
232 232
233 233 Sections
234 234 ========
235 235
236 236 This section describes the different sections that may appear in a
237 237 Mercurial configuration file, the purpose of each section, its possible
238 238 keys, and their possible values.
239 239
240 240 ``alias``
241 241 ---------
242 242
243 243 Defines command aliases.
244 244
245 245 Aliases allow you to define your own commands in terms of other
246 246 commands (or aliases), optionally including arguments. Positional
247 247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
248 248 are expanded by Mercurial before execution. Positional arguments not
249 249 already used by ``$N`` in the definition are put at the end of the
250 250 command to be executed.
251 251
252 252 Alias definitions consist of lines of the form::
253 253
254 254 <alias> = <command> [<argument>]...
255 255
256 256 For example, this definition::
257 257
258 258 latest = log --limit 5
259 259
260 260 creates a new command ``latest`` that shows only the five most recent
261 261 changesets. You can define subsequent aliases using earlier ones::
262 262
263 263 stable5 = latest -b stable
264 264
265 265 .. note::
266 266
267 267 It is possible to create aliases with the same names as
268 268 existing commands, which will then override the original
269 269 definitions. This is almost always a bad idea!
270 270
271 271 An alias can start with an exclamation point (``!``) to make it a
272 272 shell alias. A shell alias is executed with the shell and will let you
273 273 run arbitrary commands. As an example, ::
274 274
275 275 echo = !echo $@
276 276
277 277 will let you do ``hg echo foo`` to have ``foo`` printed in your
278 278 terminal. A better example might be::
279 279
280 280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
281 281
282 282 which will make ``hg purge`` delete all unknown files in the
283 283 repository in the same manner as the purge extension.
284 284
285 285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
286 286 expand to the command arguments. Unmatched arguments are
287 287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
288 288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
289 289 arguments quoted individually and separated by a space. These expansions
290 290 happen before the command is passed to the shell.
291 291
292 292 Shell aliases are executed in an environment where ``$HG`` expands to
293 293 the path of the Mercurial that was used to execute the alias. This is
294 294 useful when you want to call further Mercurial commands in a shell
295 295 alias, as was done above for the purge alias. In addition,
296 296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
297 297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
298 298
299 299 .. note::
300 300
301 301 Some global configuration options such as ``-R`` are
302 302 processed before shell aliases and will thus not be passed to
303 303 aliases.
304 304
305 305
306 306 ``annotate``
307 307 ------------
308 308
309 309 Settings used when displaying file annotations. All values are
310 310 Booleans and default to False. See :hg:`help config.diff` for
311 311 related options for the diff command.
312 312
313 313 ``ignorews``
314 314 Ignore white space when comparing lines.
315 315
316 316 ``ignorewseol``
317 317 Ignore white space at the end of a line when comparing lines.
318 318
319 319 ``ignorewsamount``
320 320 Ignore changes in the amount of white space.
321 321
322 322 ``ignoreblanklines``
323 323 Ignore changes whose lines are all blank.
324 324
325 325
326 326 ``auth``
327 327 --------
328 328
329 329 Authentication credentials and other authentication-like configuration
330 330 for HTTP connections. This section allows you to store usernames and
331 331 passwords for use when logging *into* HTTP servers. See
332 332 :hg:`help config.web` if you want to configure *who* can login to
333 333 your HTTP server.
334 334
335 335 The following options apply to all hosts.
336 336
337 337 ``cookiefile``
338 338 Path to a file containing HTTP cookie lines. Cookies matching a
339 339 host will be sent automatically.
340 340
341 341 The file format uses the Mozilla cookies.txt format, which defines cookies
342 342 on their own lines. Each line contains 7 fields delimited by the tab
343 343 character (domain, is_domain_cookie, path, is_secure, expires, name,
344 344 value). For more info, do an Internet search for "Netscape cookies.txt
345 345 format."
346 346
347 347 Note: the cookies parser does not handle port numbers on domains. You
348 348 will need to remove ports from the domain for the cookie to be recognized.
349 349 This could result in a cookie being disclosed to an unwanted server.
350 350
351 351 The cookies file is read-only.
352 352
353 353 Other options in this section are grouped by name and have the following
354 354 format::
355 355
356 356 <name>.<argument> = <value>
357 357
358 358 where ``<name>`` is used to group arguments into authentication
359 359 entries. Example::
360 360
361 361 foo.prefix = hg.intevation.de/mercurial
362 362 foo.username = foo
363 363 foo.password = bar
364 364 foo.schemes = http https
365 365
366 366 bar.prefix = secure.example.org
367 367 bar.key = path/to/file.key
368 368 bar.cert = path/to/file.cert
369 369 bar.schemes = https
370 370
371 371 Supported arguments:
372 372
373 373 ``prefix``
374 374 Either ``*`` or a URI prefix with or without the scheme part.
375 375 The authentication entry with the longest matching prefix is used
376 376 (where ``*`` matches everything and counts as a match of length
377 377 1). If the prefix doesn't include a scheme, the match is performed
378 378 against the URI with its scheme stripped as well, and the schemes
379 379 argument, q.v., is then subsequently consulted.
380 380
381 381 ``username``
382 382 Optional. Username to authenticate with. If not given, and the
383 383 remote site requires basic or digest authentication, the user will
384 384 be prompted for it. Environment variables are expanded in the
385 385 username letting you do ``foo.username = $USER``. If the URI
386 386 includes a username, only ``[auth]`` entries with a matching
387 387 username or without a username will be considered.
388 388
389 389 ``password``
390 390 Optional. Password to authenticate with. If not given, and the
391 391 remote site requires basic or digest authentication, the user
392 392 will be prompted for it.
393 393
394 394 ``key``
395 395 Optional. PEM encoded client certificate key file. Environment
396 396 variables are expanded in the filename.
397 397
398 398 ``cert``
399 399 Optional. PEM encoded client certificate chain file. Environment
400 400 variables are expanded in the filename.
401 401
402 402 ``schemes``
403 403 Optional. Space separated list of URI schemes to use this
404 404 authentication entry with. Only used if the prefix doesn't include
405 405 a scheme. Supported schemes are http and https. They will match
406 406 static-http and static-https respectively, as well.
407 407 (default: https)
408 408
409 409 If no suitable authentication entry is found, the user is prompted
410 410 for credentials as usual if required by the remote.
411 411
412 412 ``color``
413 413 ---------
414 414
415 415 Configure the Mercurial color mode. For details about how to define your custom
416 416 effect and style see :hg:`help color`.
417 417
418 418 ``mode``
419 419 String: control the method used to output color. One of ``auto``, ``ansi``,
420 420 ``win32``, ``terminfo`` or ``debug``. In auto mode, Mercurial will
421 421 use ANSI mode by default (or win32 mode prior to Windows 10) if it detects a
422 422 terminal. Any invalid value will disable color.
423 423
424 424 ``pagermode``
425 425 String: optional override of ``color.mode`` used with pager.
426 426
427 427 On some systems, terminfo mode may cause problems when using
428 428 color with ``less -R`` as a pager program. less with the -R option
429 429 will only display ECMA-48 color codes, and terminfo mode may sometimes
430 430 emit codes that less doesn't understand. You can work around this by
431 431 either using ansi mode (or auto mode), or by using less -r (which will
432 432 pass through all terminal control codes, not just color control
433 433 codes).
434 434
435 435 On some systems (such as MSYS in Windows), the terminal may support
436 436 a different color mode than the pager program.
437 437
438 438 ``commands``
439 439 ------------
440 440
441 441 ``status.relative``
442 442 Make paths in :hg:`status` output relative to the current directory.
443 443 (default: False)
444 444
445 445 ``update.check``
446 446 Determines what level of checking :hg:`update` will perform before moving
447 447 to a destination revision. Valid values are ``abort``, ``none``,
448 448 ``linear``, and ``noconflict``. ``abort`` always fails if the working
449 449 directory has uncommitted changes. ``none`` performs no checking, and may
450 450 result in a merge with uncommitted changes. ``linear`` allows any update
451 451 as long as it follows a straight line in the revision history, and may
452 452 trigger a merge with uncommitted changes. ``noconflict`` will allow any
453 453 update which would not trigger a merge with uncommitted changes, if any
454 454 are present.
455 455 (default: ``linear``)
456 456
457 457 ``update.requiredest``
458 458 Require that the user pass a destination when running :hg:`update`.
459 459 For example, :hg:`update .::` will be allowed, but a plain :hg:`update`
460 460 will be disallowed.
461 461 (default: False)
462 462
463 463 ``committemplate``
464 464 ------------------
465 465
466 466 ``changeset``
467 467 String: configuration in this section is used as the template to
468 468 customize the text shown in the editor when committing.
469 469
470 470 In addition to pre-defined template keywords, commit log specific one
471 471 below can be used for customization:
472 472
473 473 ``extramsg``
474 474 String: Extra message (typically 'Leave message empty to abort
475 475 commit.'). This may be changed by some commands or extensions.
476 476
477 477 For example, the template configuration below shows as same text as
478 478 one shown by default::
479 479
480 480 [committemplate]
481 481 changeset = {desc}\n\n
482 482 HG: Enter commit message. Lines beginning with 'HG:' are removed.
483 483 HG: {extramsg}
484 484 HG: --
485 485 HG: user: {author}\n{ifeq(p2rev, "-1", "",
486 486 "HG: branch merge\n")
487 487 }HG: branch '{branch}'\n{if(activebookmark,
488 488 "HG: bookmark '{activebookmark}'\n") }{subrepos %
489 489 "HG: subrepo {subrepo}\n" }{file_adds %
490 490 "HG: added {file}\n" }{file_mods %
491 491 "HG: changed {file}\n" }{file_dels %
492 492 "HG: removed {file}\n" }{if(files, "",
493 493 "HG: no files changed\n")}
494 494
495 495 ``diff()``
496 496 String: show the diff (see :hg:`help templates` for detail)
497 497
498 498 Sometimes it is helpful to show the diff of the changeset in the editor without
499 499 having to prefix 'HG: ' to each line so that highlighting works correctly. For
500 500 this, Mercurial provides a special string which will ignore everything below
501 501 it::
502 502
503 503 HG: ------------------------ >8 ------------------------
504 504
505 505 For example, the template configuration below will show the diff below the
506 506 extra message::
507 507
508 508 [committemplate]
509 509 changeset = {desc}\n\n
510 510 HG: Enter commit message. Lines beginning with 'HG:' are removed.
511 511 HG: {extramsg}
512 512 HG: ------------------------ >8 ------------------------
513 513 HG: Do not touch the line above.
514 514 HG: Everything below will be removed.
515 515 {diff()}
516 516
517 517 .. note::
518 518
519 519 For some problematic encodings (see :hg:`help win32mbcs` for
520 520 detail), this customization should be configured carefully, to
521 521 avoid showing broken characters.
522 522
523 523 For example, if a multibyte character ending with backslash (0x5c) is
524 524 followed by the ASCII character 'n' in the customized template,
525 525 the sequence of backslash and 'n' is treated as line-feed unexpectedly
526 526 (and the multibyte character is broken, too).
527 527
528 528 Customized template is used for commands below (``--edit`` may be
529 529 required):
530 530
531 531 - :hg:`backout`
532 532 - :hg:`commit`
533 533 - :hg:`fetch` (for merge commit only)
534 534 - :hg:`graft`
535 535 - :hg:`histedit`
536 536 - :hg:`import`
537 537 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
538 538 - :hg:`rebase`
539 539 - :hg:`shelve`
540 540 - :hg:`sign`
541 541 - :hg:`tag`
542 542 - :hg:`transplant`
543 543
544 544 Configuring items below instead of ``changeset`` allows showing
545 545 customized message only for specific actions, or showing different
546 546 messages for each action.
547 547
548 548 - ``changeset.backout`` for :hg:`backout`
549 549 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
550 550 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
551 551 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
552 552 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
553 553 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
554 554 - ``changeset.gpg.sign`` for :hg:`sign`
555 555 - ``changeset.graft`` for :hg:`graft`
556 556 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
557 557 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
558 558 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
559 559 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
560 560 - ``changeset.import.bypass`` for :hg:`import --bypass`
561 561 - ``changeset.import.normal.merge`` for :hg:`import` on merges
562 562 - ``changeset.import.normal.normal`` for :hg:`import` on other
563 563 - ``changeset.mq.qnew`` for :hg:`qnew`
564 564 - ``changeset.mq.qfold`` for :hg:`qfold`
565 565 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
566 566 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
567 567 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
568 568 - ``changeset.rebase.normal`` for :hg:`rebase` on other
569 569 - ``changeset.shelve.shelve`` for :hg:`shelve`
570 570 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
571 571 - ``changeset.tag.remove`` for :hg:`tag --remove`
572 572 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
573 573 - ``changeset.transplant.normal`` for :hg:`transplant` on other
574 574
575 575 These dot-separated lists of names are treated as hierarchical ones.
576 576 For example, ``changeset.tag.remove`` customizes the commit message
577 577 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
578 578 commit message for :hg:`tag` regardless of ``--remove`` option.
579 579
580 580 When the external editor is invoked for a commit, the corresponding
581 581 dot-separated list of names without the ``changeset.`` prefix
582 582 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
583 583 variable.
584 584
585 585 In this section, items other than ``changeset`` can be referred from
586 586 others. For example, the configuration to list committed files up
587 587 below can be referred as ``{listupfiles}``::
588 588
589 589 [committemplate]
590 590 listupfiles = {file_adds %
591 591 "HG: added {file}\n" }{file_mods %
592 592 "HG: changed {file}\n" }{file_dels %
593 593 "HG: removed {file}\n" }{if(files, "",
594 594 "HG: no files changed\n")}
595 595
596 596 ``decode/encode``
597 597 -----------------
598 598
599 599 Filters for transforming files on checkout/checkin. This would
600 600 typically be used for newline processing or other
601 601 localization/canonicalization of files.
602 602
603 603 Filters consist of a filter pattern followed by a filter command.
604 604 Filter patterns are globs by default, rooted at the repository root.
605 605 For example, to match any file ending in ``.txt`` in the root
606 606 directory only, use the pattern ``*.txt``. To match any file ending
607 607 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
608 608 For each file only the first matching filter applies.
609 609
610 610 The filter command can start with a specifier, either ``pipe:`` or
611 611 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
612 612
613 613 A ``pipe:`` command must accept data on stdin and return the transformed
614 614 data on stdout.
615 615
616 616 Pipe example::
617 617
618 618 [encode]
619 619 # uncompress gzip files on checkin to improve delta compression
620 620 # note: not necessarily a good idea, just an example
621 621 *.gz = pipe: gunzip
622 622
623 623 [decode]
624 624 # recompress gzip files when writing them to the working dir (we
625 625 # can safely omit "pipe:", because it's the default)
626 626 *.gz = gzip
627 627
628 628 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
629 629 with the name of a temporary file that contains the data to be
630 630 filtered by the command. The string ``OUTFILE`` is replaced with the name
631 631 of an empty temporary file, where the filtered data must be written by
632 632 the command.
633 633
634 634 .. container:: windows
635 635
636 636 .. note::
637 637
638 638 The tempfile mechanism is recommended for Windows systems,
639 639 where the standard shell I/O redirection operators often have
640 640 strange effects and may corrupt the contents of your files.
641 641
642 642 This filter mechanism is used internally by the ``eol`` extension to
643 643 translate line ending characters between Windows (CRLF) and Unix (LF)
644 644 format. We suggest you use the ``eol`` extension for convenience.
645 645
646 646
647 647 ``defaults``
648 648 ------------
649 649
650 650 (defaults are deprecated. Don't use them. Use aliases instead.)
651 651
652 652 Use the ``[defaults]`` section to define command defaults, i.e. the
653 653 default options/arguments to pass to the specified commands.
654 654
655 655 The following example makes :hg:`log` run in verbose mode, and
656 656 :hg:`status` show only the modified files, by default::
657 657
658 658 [defaults]
659 659 log = -v
660 660 status = -m
661 661
662 662 The actual commands, instead of their aliases, must be used when
663 663 defining command defaults. The command defaults will also be applied
664 664 to the aliases of the commands defined.
665 665
666 666
667 667 ``diff``
668 668 --------
669 669
670 670 Settings used when displaying diffs. Everything except for ``unified``
671 671 is a Boolean and defaults to False. See :hg:`help config.annotate`
672 672 for related options for the annotate command.
673 673
674 674 ``git``
675 675 Use git extended diff format.
676 676
677 677 ``nobinary``
678 678 Omit git binary patches.
679 679
680 680 ``nodates``
681 681 Don't include dates in diff headers.
682 682
683 683 ``noprefix``
684 684 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
685 685
686 686 ``showfunc``
687 687 Show which function each change is in.
688 688
689 689 ``ignorews``
690 690 Ignore white space when comparing lines.
691 691
692 692 ``ignorewsamount``
693 693 Ignore changes in the amount of white space.
694 694
695 695 ``ignoreblanklines``
696 696 Ignore changes whose lines are all blank.
697 697
698 698 ``unified``
699 699 Number of lines of context to show.
700 700
701 701 ``email``
702 702 ---------
703 703
704 704 Settings for extensions that send email messages.
705 705
706 706 ``from``
707 707 Optional. Email address to use in "From" header and SMTP envelope
708 708 of outgoing messages.
709 709
710 710 ``to``
711 711 Optional. Comma-separated list of recipients' email addresses.
712 712
713 713 ``cc``
714 714 Optional. Comma-separated list of carbon copy recipients'
715 715 email addresses.
716 716
717 717 ``bcc``
718 718 Optional. Comma-separated list of blind carbon copy recipients'
719 719 email addresses.
720 720
721 721 ``method``
722 722 Optional. Method to use to send email messages. If value is ``smtp``
723 723 (default), use SMTP (see the ``[smtp]`` section for configuration).
724 724 Otherwise, use as name of program to run that acts like sendmail
725 725 (takes ``-f`` option for sender, list of recipients on command line,
726 726 message on stdin). Normally, setting this to ``sendmail`` or
727 727 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
728 728
729 729 ``charsets``
730 730 Optional. Comma-separated list of character sets considered
731 731 convenient for recipients. Addresses, headers, and parts not
732 732 containing patches of outgoing messages will be encoded in the
733 733 first character set to which conversion from local encoding
734 734 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
735 735 conversion fails, the text in question is sent as is.
736 736 (default: '')
737 737
738 738 Order of outgoing email character sets:
739 739
740 740 1. ``us-ascii``: always first, regardless of settings
741 741 2. ``email.charsets``: in order given by user
742 742 3. ``ui.fallbackencoding``: if not in email.charsets
743 743 4. ``$HGENCODING``: if not in email.charsets
744 744 5. ``utf-8``: always last, regardless of settings
745 745
746 746 Email example::
747 747
748 748 [email]
749 749 from = Joseph User <joe.user@example.com>
750 750 method = /usr/sbin/sendmail
751 751 # charsets for western Europeans
752 752 # us-ascii, utf-8 omitted, as they are tried first and last
753 753 charsets = iso-8859-1, iso-8859-15, windows-1252
754 754
755 755
756 756 ``extensions``
757 757 --------------
758 758
759 759 Mercurial has an extension mechanism for adding new features. To
760 760 enable an extension, create an entry for it in this section.
761 761
762 762 If you know that the extension is already in Python's search path,
763 763 you can give the name of the module, followed by ``=``, with nothing
764 764 after the ``=``.
765 765
766 766 Otherwise, give a name that you choose, followed by ``=``, followed by
767 767 the path to the ``.py`` file (including the file name extension) that
768 768 defines the extension.
769 769
770 770 To explicitly disable an extension that is enabled in an hgrc of
771 771 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
772 772 or ``foo = !`` when path is not supplied.
773 773
774 774 Example for ``~/.hgrc``::
775 775
776 776 [extensions]
777 777 # (the churn extension will get loaded from Mercurial's path)
778 778 churn =
779 779 # (this extension will get loaded from the file specified)
780 780 myfeature = ~/.hgext/myfeature.py
781 781
782 782
783 783 ``format``
784 784 ----------
785 785
786 786 ``usegeneraldelta``
787 787 Enable or disable the "generaldelta" repository format which improves
788 788 repository compression by allowing "revlog" to store delta against arbitrary
789 789 revision instead of the previous stored one. This provides significant
790 790 improvement for repositories with branches.
791 791
792 792 Repositories with this on-disk format require Mercurial version 1.9.
793 793
794 794 Enabled by default.
795 795
796 796 ``dotencode``
797 797 Enable or disable the "dotencode" repository format which enhances
798 798 the "fncache" repository format (which has to be enabled to use
799 799 dotencode) to avoid issues with filenames starting with ._ on
800 800 Mac OS X and spaces on Windows.
801 801
802 802 Repositories with this on-disk format require Mercurial version 1.7.
803 803
804 804 Enabled by default.
805 805
806 806 ``usefncache``
807 807 Enable or disable the "fncache" repository format which enhances
808 808 the "store" repository format (which has to be enabled to use
809 809 fncache) to allow longer filenames and avoids using Windows
810 810 reserved names, e.g. "nul".
811 811
812 812 Repositories with this on-disk format require Mercurial version 1.1.
813 813
814 814 Enabled by default.
815 815
816 816 ``usestore``
817 817 Enable or disable the "store" repository format which improves
818 818 compatibility with systems that fold case or otherwise mangle
819 819 filenames. Disabling this option will allow you to store longer filenames
820 820 in some situations at the expense of compatibility.
821 821
822 822 Repositories with this on-disk format require Mercurial version 0.9.4.
823 823
824 824 Enabled by default.
825 825
826 826 ``graph``
827 827 ---------
828 828
829 829 Web graph view configuration. This section let you change graph
830 830 elements display properties by branches, for instance to make the
831 831 ``default`` branch stand out.
832 832
833 833 Each line has the following format::
834 834
835 835 <branch>.<argument> = <value>
836 836
837 837 where ``<branch>`` is the name of the branch being
838 838 customized. Example::
839 839
840 840 [graph]
841 841 # 2px width
842 842 default.width = 2
843 843 # red color
844 844 default.color = FF0000
845 845
846 846 Supported arguments:
847 847
848 848 ``width``
849 849 Set branch edges width in pixels.
850 850
851 851 ``color``
852 852 Set branch edges color in hexadecimal RGB notation.
853 853
854 854 ``hooks``
855 855 ---------
856 856
857 857 Commands or Python functions that get automatically executed by
858 858 various actions such as starting or finishing a commit. Multiple
859 859 hooks can be run for the same action by appending a suffix to the
860 860 action. Overriding a site-wide hook can be done by changing its
861 861 value or setting it to an empty string. Hooks can be prioritized
862 862 by adding a prefix of ``priority.`` to the hook name on a new line
863 863 and setting the priority. The default priority is 0.
864 864
865 865 Example ``.hg/hgrc``::
866 866
867 867 [hooks]
868 868 # update working directory after adding changesets
869 869 changegroup.update = hg update
870 870 # do not use the site-wide hook
871 871 incoming =
872 872 incoming.email = /my/email/hook
873 873 incoming.autobuild = /my/build/hook
874 874 # force autobuild hook to run before other incoming hooks
875 875 priority.incoming.autobuild = 1
876 876
877 877 Most hooks are run with environment variables set that give useful
878 878 additional information. For each hook below, the environment variables
879 879 it is passed are listed with names in the form ``$HG_foo``. The
880 880 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
881 881 They contain the type of hook which triggered the run and the full name
882 882 of the hook in the config, respectively. In the example above, this will
883 883 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
884 884
885 885 ``changegroup``
886 886 Run after a changegroup has been added via push, pull or unbundle. The ID of
887 887 the first new changeset is in ``$HG_NODE`` and last is in ``$HG_NODE_LAST``.
888 888 The URL from which changes came is in ``$HG_URL``.
889 889
890 890 ``commit``
891 891 Run after a changeset has been created in the local repository. The ID
892 892 of the newly created changeset is in ``$HG_NODE``. Parent changeset
893 893 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
894 894
895 895 ``incoming``
896 896 Run after a changeset has been pulled, pushed, or unbundled into
897 897 the local repository. The ID of the newly arrived changeset is in
898 898 ``$HG_NODE``. The URL that was source of the changes is in ``$HG_URL``.
899 899
900 900 ``outgoing``
901 901 Run after sending changes from the local repository to another. The ID of
902 902 first changeset sent is in ``$HG_NODE``. The source of operation is in
903 903 ``$HG_SOURCE``. Also see :hg:`help config.hooks.preoutgoing`.
904 904
905 905 ``post-<command>``
906 906 Run after successful invocations of the associated command. The
907 907 contents of the command line are passed as ``$HG_ARGS`` and the result
908 908 code in ``$HG_RESULT``. Parsed command line arguments are passed as
909 909 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
910 910 the python data internally passed to <command>. ``$HG_OPTS`` is a
911 911 dictionary of options (with unspecified options set to their defaults).
912 912 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
913 913
914 914 ``fail-<command>``
915 915 Run after a failed invocation of an associated command. The contents
916 916 of the command line are passed as ``$HG_ARGS``. Parsed command line
917 917 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
918 918 string representations of the python data internally passed to
919 919 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
920 920 options set to their defaults). ``$HG_PATS`` is a list of arguments.
921 921 Hook failure is ignored.
922 922
923 923 ``pre-<command>``
924 924 Run before executing the associated command. The contents of the
925 925 command line are passed as ``$HG_ARGS``. Parsed command line arguments
926 926 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
927 927 representations of the data internally passed to <command>. ``$HG_OPTS``
928 928 is a dictionary of options (with unspecified options set to their
929 929 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
930 930 failure, the command doesn't execute and Mercurial returns the failure
931 931 code.
932 932
933 933 ``prechangegroup``
934 934 Run before a changegroup is added via push, pull or unbundle. Exit
935 935 status 0 allows the changegroup to proceed. A non-zero status will
936 936 cause the push, pull or unbundle to fail. The URL from which changes
937 937 will come is in ``$HG_URL``.
938 938
939 939 ``precommit``
940 940 Run before starting a local commit. Exit status 0 allows the
941 941 commit to proceed. A non-zero status will cause the commit to fail.
942 942 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
943 943
944 944 ``prelistkeys``
945 945 Run before listing pushkeys (like bookmarks) in the
946 946 repository. A non-zero status will cause failure. The key namespace is
947 947 in ``$HG_NAMESPACE``.
948 948
949 949 ``preoutgoing``
950 950 Run before collecting changes to send from the local repository to
951 951 another. A non-zero status will cause failure. This lets you prevent
952 952 pull over HTTP or SSH. It can also prevent propagating commits (via
953 953 local pull, push (outbound) or bundle commands), but not completely,
954 954 since you can just copy files instead. The source of operation is in
955 955 ``$HG_SOURCE``. If "serve", the operation is happening on behalf of a remote
956 956 SSH or HTTP repository. If "push", "pull" or "bundle", the operation
957 957 is happening on behalf of a repository on same system.
958 958
959 959 ``prepushkey``
960 960 Run before a pushkey (like a bookmark) is added to the
961 961 repository. A non-zero status will cause the key to be rejected. The
962 962 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
963 963 the old value (if any) is in ``$HG_OLD``, and the new value is in
964 964 ``$HG_NEW``.
965 965
966 966 ``pretag``
967 967 Run before creating a tag. Exit status 0 allows the tag to be
968 968 created. A non-zero status will cause the tag to fail. The ID of the
969 969 changeset to tag is in ``$HG_NODE``. The name of tag is in ``$HG_TAG``. The
970 970 tag is local if ``$HG_LOCAL=1``, or in the repository if ``$HG_LOCAL=0``.
971 971
972 972 ``pretxnopen``
973 973 Run before any new repository transaction is open. The reason for the
974 974 transaction will be in ``$HG_TXNNAME``, and a unique identifier for the
975 975 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
976 976 transaction from being opened.
977 977
978 978 ``pretxnclose``
979 979 Run right before the transaction is actually finalized. Any repository change
980 980 will be visible to the hook program. This lets you validate the transaction
981 981 content or change it. Exit status 0 allows the commit to proceed. A non-zero
982 982 status will cause the transaction to be rolled back. The reason for the
983 983 transaction opening will be in ``$HG_TXNNAME``, and a unique identifier for
984 984 the transaction will be in ``HG_TXNID``. The rest of the available data will
985 985 vary according the transaction type. New changesets will add ``$HG_NODE``
986 986 (the ID of the first added changeset), ``$HG_NODE_LAST`` (the ID of the last
987 987 added changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables. Bookmark and
988 988 phase changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``
989 989 respectively, etc.
990 990
991 991 ``txnclose``
992 992 Run after any repository transaction has been committed. At this
993 993 point, the transaction can no longer be rolled back. The hook will run
994 994 after the lock is released. See :hg:`help config.hooks.pretxnclose` for
995 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 1009 ``txnabort``
998 1010 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
999 1011 for details about available variables.
1000 1012
1001 1013 ``pretxnchangegroup``
1002 1014 Run after a changegroup has been added via push, pull or unbundle, but before
1003 1015 the transaction has been committed. The changegroup is visible to the hook
1004 1016 program. This allows validation of incoming changes before accepting them.
1005 1017 The ID of the first new changeset is in ``$HG_NODE`` and last is in
1006 1018 ``$HG_NODE_LAST``. Exit status 0 allows the transaction to commit. A non-zero
1007 1019 status will cause the transaction to be rolled back, and the push, pull or
1008 1020 unbundle will fail. The URL that was the source of changes is in ``$HG_URL``.
1009 1021
1010 1022 ``pretxncommit``
1011 1023 Run after a changeset has been created, but before the transaction is
1012 1024 committed. The changeset is visible to the hook program. This allows
1013 1025 validation of the commit message and changes. Exit status 0 allows the
1014 1026 commit to proceed. A non-zero status will cause the transaction to
1015 1027 be rolled back. The ID of the new changeset is in ``$HG_NODE``. The parent
1016 1028 changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
1017 1029
1018 1030 ``preupdate``
1019 1031 Run before updating the working directory. Exit status 0 allows
1020 1032 the update to proceed. A non-zero status will prevent the update.
1021 1033 The changeset ID of first new parent is in ``$HG_PARENT1``. If updating to a
1022 1034 merge, the ID of second new parent is in ``$HG_PARENT2``.
1023 1035
1024 1036 ``listkeys``
1025 1037 Run after listing pushkeys (like bookmarks) in the repository. The
1026 1038 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
1027 1039 dictionary containing the keys and values.
1028 1040
1029 1041 ``pushkey``
1030 1042 Run after a pushkey (like a bookmark) is added to the
1031 1043 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
1032 1044 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
1033 1045 value is in ``$HG_NEW``.
1034 1046
1035 1047 ``tag``
1036 1048 Run after a tag is created. The ID of the tagged changeset is in ``$HG_NODE``.
1037 1049 The name of tag is in ``$HG_TAG``. The tag is local if ``$HG_LOCAL=1``, or in
1038 1050 the repository if ``$HG_LOCAL=0``.
1039 1051
1040 1052 ``update``
1041 1053 Run after updating the working directory. The changeset ID of first
1042 1054 new parent is in ``$HG_PARENT1``. If updating to a merge, the ID of second new
1043 1055 parent is in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1044 1056 update failed (e.g. because conflicts were not resolved), ``$HG_ERROR=1``.
1045 1057
1046 1058 .. note::
1047 1059
1048 1060 It is generally better to use standard hooks rather than the
1049 1061 generic pre- and post- command hooks, as they are guaranteed to be
1050 1062 called in the appropriate contexts for influencing transactions.
1051 1063 Also, hooks like "commit" will be called in all contexts that
1052 1064 generate a commit (e.g. tag) and not just the commit command.
1053 1065
1054 1066 .. note::
1055 1067
1056 1068 Environment variables with empty values may not be passed to
1057 1069 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1058 1070 will have an empty value under Unix-like platforms for non-merge
1059 1071 changesets, while it will not be available at all under Windows.
1060 1072
1061 1073 The syntax for Python hooks is as follows::
1062 1074
1063 1075 hookname = python:modulename.submodule.callable
1064 1076 hookname = python:/path/to/python/module.py:callable
1065 1077
1066 1078 Python hooks are run within the Mercurial process. Each hook is
1067 1079 called with at least three keyword arguments: a ui object (keyword
1068 1080 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1069 1081 keyword that tells what kind of hook is used. Arguments listed as
1070 1082 environment variables above are passed as keyword arguments, with no
1071 1083 ``HG_`` prefix, and names in lower case.
1072 1084
1073 1085 If a Python hook returns a "true" value or raises an exception, this
1074 1086 is treated as a failure.
1075 1087
1076 1088
1077 1089 ``hostfingerprints``
1078 1090 --------------------
1079 1091
1080 1092 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1081 1093
1082 1094 Fingerprints of the certificates of known HTTPS servers.
1083 1095
1084 1096 A HTTPS connection to a server with a fingerprint configured here will
1085 1097 only succeed if the servers certificate matches the fingerprint.
1086 1098 This is very similar to how ssh known hosts works.
1087 1099
1088 1100 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1089 1101 Multiple values can be specified (separated by spaces or commas). This can
1090 1102 be used to define both old and new fingerprints while a host transitions
1091 1103 to a new certificate.
1092 1104
1093 1105 The CA chain and web.cacerts is not used for servers with a fingerprint.
1094 1106
1095 1107 For example::
1096 1108
1097 1109 [hostfingerprints]
1098 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 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 1113 ``hostsecurity``
1102 1114 ----------------
1103 1115
1104 1116 Used to specify global and per-host security settings for connecting to
1105 1117 other machines.
1106 1118
1107 1119 The following options control default behavior for all hosts.
1108 1120
1109 1121 ``ciphers``
1110 1122 Defines the cryptographic ciphers to use for connections.
1111 1123
1112 1124 Value must be a valid OpenSSL Cipher List Format as documented at
1113 1125 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1114 1126
1115 1127 This setting is for advanced users only. Setting to incorrect values
1116 1128 can significantly lower connection security or decrease performance.
1117 1129 You have been warned.
1118 1130
1119 1131 This option requires Python 2.7.
1120 1132
1121 1133 ``minimumprotocol``
1122 1134 Defines the minimum channel encryption protocol to use.
1123 1135
1124 1136 By default, the highest version of TLS supported by both client and server
1125 1137 is used.
1126 1138
1127 1139 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1128 1140
1129 1141 When running on an old Python version, only ``tls1.0`` is allowed since
1130 1142 old versions of Python only support up to TLS 1.0.
1131 1143
1132 1144 When running a Python that supports modern TLS versions, the default is
1133 1145 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1134 1146 weakens security and should only be used as a feature of last resort if
1135 1147 a server does not support TLS 1.1+.
1136 1148
1137 1149 Options in the ``[hostsecurity]`` section can have the form
1138 1150 ``hostname``:``setting``. This allows multiple settings to be defined on a
1139 1151 per-host basis.
1140 1152
1141 1153 The following per-host settings can be defined.
1142 1154
1143 1155 ``ciphers``
1144 1156 This behaves like ``ciphers`` as described above except it only applies
1145 1157 to the host on which it is defined.
1146 1158
1147 1159 ``fingerprints``
1148 1160 A list of hashes of the DER encoded peer/remote certificate. Values have
1149 1161 the form ``algorithm``:``fingerprint``. e.g.
1150 1162 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1151 1163 In addition, colons (``:``) can appear in the fingerprint part.
1152 1164
1153 1165 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1154 1166 ``sha512``.
1155 1167
1156 1168 Use of ``sha256`` or ``sha512`` is preferred.
1157 1169
1158 1170 If a fingerprint is specified, the CA chain is not validated for this
1159 1171 host and Mercurial will require the remote certificate to match one
1160 1172 of the fingerprints specified. This means if the server updates its
1161 1173 certificate, Mercurial will abort until a new fingerprint is defined.
1162 1174 This can provide stronger security than traditional CA-based validation
1163 1175 at the expense of convenience.
1164 1176
1165 1177 This option takes precedence over ``verifycertsfile``.
1166 1178
1167 1179 ``minimumprotocol``
1168 1180 This behaves like ``minimumprotocol`` as described above except it
1169 1181 only applies to the host on which it is defined.
1170 1182
1171 1183 ``verifycertsfile``
1172 1184 Path to file a containing a list of PEM encoded certificates used to
1173 1185 verify the server certificate. Environment variables and ``~user``
1174 1186 constructs are expanded in the filename.
1175 1187
1176 1188 The server certificate or the certificate's certificate authority (CA)
1177 1189 must match a certificate from this file or certificate verification
1178 1190 will fail and connections to the server will be refused.
1179 1191
1180 1192 If defined, only certificates provided by this file will be used:
1181 1193 ``web.cacerts`` and any system/default certificates will not be
1182 1194 used.
1183 1195
1184 1196 This option has no effect if the per-host ``fingerprints`` option
1185 1197 is set.
1186 1198
1187 1199 The format of the file is as follows::
1188 1200
1189 1201 -----BEGIN CERTIFICATE-----
1190 1202 ... (certificate in base64 PEM encoding) ...
1191 1203 -----END CERTIFICATE-----
1192 1204 -----BEGIN CERTIFICATE-----
1193 1205 ... (certificate in base64 PEM encoding) ...
1194 1206 -----END CERTIFICATE-----
1195 1207
1196 1208 For example::
1197 1209
1198 1210 [hostsecurity]
1199 1211 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1200 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 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 1214 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1203 1215
1204 1216 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1205 1217 when connecting to ``hg.example.com``::
1206 1218
1207 1219 [hostsecurity]
1208 1220 minimumprotocol = tls1.2
1209 1221 hg.example.com:minimumprotocol = tls1.1
1210 1222
1211 1223 ``http_proxy``
1212 1224 --------------
1213 1225
1214 1226 Used to access web-based Mercurial repositories through a HTTP
1215 1227 proxy.
1216 1228
1217 1229 ``host``
1218 1230 Host name and (optional) port of the proxy server, for example
1219 1231 "myproxy:8000".
1220 1232
1221 1233 ``no``
1222 1234 Optional. Comma-separated list of host names that should bypass
1223 1235 the proxy.
1224 1236
1225 1237 ``passwd``
1226 1238 Optional. Password to authenticate with at the proxy server.
1227 1239
1228 1240 ``user``
1229 1241 Optional. User name to authenticate with at the proxy server.
1230 1242
1231 1243 ``always``
1232 1244 Optional. Always use the proxy, even for localhost and any entries
1233 1245 in ``http_proxy.no``. (default: False)
1234 1246
1235 1247 ``merge``
1236 1248 ---------
1237 1249
1238 1250 This section specifies behavior during merges and updates.
1239 1251
1240 1252 ``checkignored``
1241 1253 Controls behavior when an ignored file on disk has the same name as a tracked
1242 1254 file in the changeset being merged or updated to, and has different
1243 1255 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1244 1256 abort on such files. With ``warn``, warn on such files and back them up as
1245 1257 ``.orig``. With ``ignore``, don't print a warning and back them up as
1246 1258 ``.orig``. (default: ``abort``)
1247 1259
1248 1260 ``checkunknown``
1249 1261 Controls behavior when an unknown file that isn't ignored has the same name
1250 1262 as a tracked file in the changeset being merged or updated to, and has
1251 1263 different contents. Similar to ``merge.checkignored``, except for files that
1252 1264 are not ignored. (default: ``abort``)
1253 1265
1254 1266 ``merge-patterns``
1255 1267 ------------------
1256 1268
1257 1269 This section specifies merge tools to associate with particular file
1258 1270 patterns. Tools matched here will take precedence over the default
1259 1271 merge tool. Patterns are globs by default, rooted at the repository
1260 1272 root.
1261 1273
1262 1274 Example::
1263 1275
1264 1276 [merge-patterns]
1265 1277 **.c = kdiff3
1266 1278 **.jpg = myimgmerge
1267 1279
1268 1280 ``merge-tools``
1269 1281 ---------------
1270 1282
1271 1283 This section configures external merge tools to use for file-level
1272 1284 merges. This section has likely been preconfigured at install time.
1273 1285 Use :hg:`config merge-tools` to check the existing configuration.
1274 1286 Also see :hg:`help merge-tools` for more details.
1275 1287
1276 1288 Example ``~/.hgrc``::
1277 1289
1278 1290 [merge-tools]
1279 1291 # Override stock tool location
1280 1292 kdiff3.executable = ~/bin/kdiff3
1281 1293 # Specify command line
1282 1294 kdiff3.args = $base $local $other -o $output
1283 1295 # Give higher priority
1284 1296 kdiff3.priority = 1
1285 1297
1286 1298 # Changing the priority of preconfigured tool
1287 1299 meld.priority = 0
1288 1300
1289 1301 # Disable a preconfigured tool
1290 1302 vimdiff.disabled = yes
1291 1303
1292 1304 # Define new tool
1293 1305 myHtmlTool.args = -m $local $other $base $output
1294 1306 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1295 1307 myHtmlTool.priority = 1
1296 1308
1297 1309 Supported arguments:
1298 1310
1299 1311 ``priority``
1300 1312 The priority in which to evaluate this tool.
1301 1313 (default: 0)
1302 1314
1303 1315 ``executable``
1304 1316 Either just the name of the executable or its pathname.
1305 1317
1306 1318 .. container:: windows
1307 1319
1308 1320 On Windows, the path can use environment variables with ${ProgramFiles}
1309 1321 syntax.
1310 1322
1311 1323 (default: the tool name)
1312 1324
1313 1325 ``args``
1314 1326 The arguments to pass to the tool executable. You can refer to the
1315 1327 files being merged as well as the output file through these
1316 1328 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1317 1329 of ``$local`` and ``$other`` can vary depending on which action is being
1318 1330 performed. During and update or merge, ``$local`` represents the original
1319 1331 state of the file, while ``$other`` represents the commit you are updating
1320 1332 to or the commit you are merging with. During a rebase ``$local``
1321 1333 represents the destination of the rebase, and ``$other`` represents the
1322 1334 commit being rebased.
1323 1335 (default: ``$local $base $other``)
1324 1336
1325 1337 ``premerge``
1326 1338 Attempt to run internal non-interactive 3-way merge tool before
1327 1339 launching external tool. Options are ``true``, ``false``, ``keep`` or
1328 1340 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1329 1341 premerge fails. The ``keep-merge3`` will do the same but include information
1330 1342 about the base of the merge in the marker (see internal :merge3 in
1331 1343 :hg:`help merge-tools`).
1332 1344 (default: True)
1333 1345
1334 1346 ``binary``
1335 1347 This tool can merge binary files. (default: False, unless tool
1336 1348 was selected by file pattern match)
1337 1349
1338 1350 ``symlink``
1339 1351 This tool can merge symlinks. (default: False)
1340 1352
1341 1353 ``check``
1342 1354 A list of merge success-checking options:
1343 1355
1344 1356 ``changed``
1345 1357 Ask whether merge was successful when the merged file shows no changes.
1346 1358 ``conflicts``
1347 1359 Check whether there are conflicts even though the tool reported success.
1348 1360 ``prompt``
1349 1361 Always prompt for merge success, regardless of success reported by tool.
1350 1362
1351 1363 ``fixeol``
1352 1364 Attempt to fix up EOL changes caused by the merge tool.
1353 1365 (default: False)
1354 1366
1355 1367 ``gui``
1356 1368 This tool requires a graphical interface to run. (default: False)
1357 1369
1358 1370 .. container:: windows
1359 1371
1360 1372 ``regkey``
1361 1373 Windows registry key which describes install location of this
1362 1374 tool. Mercurial will search for this key first under
1363 1375 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1364 1376 (default: None)
1365 1377
1366 1378 ``regkeyalt``
1367 1379 An alternate Windows registry key to try if the first key is not
1368 1380 found. The alternate key uses the same ``regname`` and ``regappend``
1369 1381 semantics of the primary key. The most common use for this key
1370 1382 is to search for 32bit applications on 64bit operating systems.
1371 1383 (default: None)
1372 1384
1373 1385 ``regname``
1374 1386 Name of value to read from specified registry key.
1375 1387 (default: the unnamed (default) value)
1376 1388
1377 1389 ``regappend``
1378 1390 String to append to the value read from the registry, typically
1379 1391 the executable name of the tool.
1380 1392 (default: None)
1381 1393
1382 1394 ``pager``
1383 1395 ---------
1384 1396
1385 1397 Setting used to control when to paginate and with what external tool. See
1386 1398 :hg:`help pager` for details.
1387 1399
1388 1400 ``pager``
1389 1401 Define the external tool used as pager.
1390 1402
1391 1403 If no pager is set, Mercurial uses the environment variable $PAGER.
1392 1404 If neither pager.pager, nor $PAGER is set, a default pager will be
1393 1405 used, typically `less` on Unix and `more` on Windows. Example::
1394 1406
1395 1407 [pager]
1396 1408 pager = less -FRX
1397 1409
1398 1410 ``ignore``
1399 1411 List of commands to disable the pager for. Example::
1400 1412
1401 1413 [pager]
1402 1414 ignore = version, help, update
1403 1415
1404 1416 ``patch``
1405 1417 ---------
1406 1418
1407 1419 Settings used when applying patches, for instance through the 'import'
1408 1420 command or with Mercurial Queues extension.
1409 1421
1410 1422 ``eol``
1411 1423 When set to 'strict' patch content and patched files end of lines
1412 1424 are preserved. When set to ``lf`` or ``crlf``, both files end of
1413 1425 lines are ignored when patching and the result line endings are
1414 1426 normalized to either LF (Unix) or CRLF (Windows). When set to
1415 1427 ``auto``, end of lines are again ignored while patching but line
1416 1428 endings in patched files are normalized to their original setting
1417 1429 on a per-file basis. If target file does not exist or has no end
1418 1430 of line, patch line endings are preserved.
1419 1431 (default: strict)
1420 1432
1421 1433 ``fuzz``
1422 1434 The number of lines of 'fuzz' to allow when applying patches. This
1423 1435 controls how much context the patcher is allowed to ignore when
1424 1436 trying to apply a patch.
1425 1437 (default: 2)
1426 1438
1427 1439 ``paths``
1428 1440 ---------
1429 1441
1430 1442 Assigns symbolic names and behavior to repositories.
1431 1443
1432 1444 Options are symbolic names defining the URL or directory that is the
1433 1445 location of the repository. Example::
1434 1446
1435 1447 [paths]
1436 1448 my_server = https://example.com/my_repo
1437 1449 local_path = /home/me/repo
1438 1450
1439 1451 These symbolic names can be used from the command line. To pull
1440 1452 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1441 1453 :hg:`push local_path`.
1442 1454
1443 1455 Options containing colons (``:``) denote sub-options that can influence
1444 1456 behavior for that specific path. Example::
1445 1457
1446 1458 [paths]
1447 1459 my_server = https://example.com/my_path
1448 1460 my_server:pushurl = ssh://example.com/my_path
1449 1461
1450 1462 The following sub-options can be defined:
1451 1463
1452 1464 ``pushurl``
1453 1465 The URL to use for push operations. If not defined, the location
1454 1466 defined by the path's main entry is used.
1455 1467
1456 1468 ``pushrev``
1457 1469 A revset defining which revisions to push by default.
1458 1470
1459 1471 When :hg:`push` is executed without a ``-r`` argument, the revset
1460 1472 defined by this sub-option is evaluated to determine what to push.
1461 1473
1462 1474 For example, a value of ``.`` will push the working directory's
1463 1475 revision by default.
1464 1476
1465 1477 Revsets specifying bookmarks will not result in the bookmark being
1466 1478 pushed.
1467 1479
1468 1480 The following special named paths exist:
1469 1481
1470 1482 ``default``
1471 1483 The URL or directory to use when no source or remote is specified.
1472 1484
1473 1485 :hg:`clone` will automatically define this path to the location the
1474 1486 repository was cloned from.
1475 1487
1476 1488 ``default-push``
1477 1489 (deprecated) The URL or directory for the default :hg:`push` location.
1478 1490 ``default:pushurl`` should be used instead.
1479 1491
1480 1492 ``phases``
1481 1493 ----------
1482 1494
1483 1495 Specifies default handling of phases. See :hg:`help phases` for more
1484 1496 information about working with phases.
1485 1497
1486 1498 ``publish``
1487 1499 Controls draft phase behavior when working as a server. When true,
1488 1500 pushed changesets are set to public in both client and server and
1489 1501 pulled or cloned changesets are set to public in the client.
1490 1502 (default: True)
1491 1503
1492 1504 ``new-commit``
1493 1505 Phase of newly-created commits.
1494 1506 (default: draft)
1495 1507
1496 1508 ``checksubrepos``
1497 1509 Check the phase of the current revision of each subrepository. Allowed
1498 1510 values are "ignore", "follow" and "abort". For settings other than
1499 1511 "ignore", the phase of the current revision of each subrepository is
1500 1512 checked before committing the parent repository. If any of those phases is
1501 1513 greater than the phase of the parent repository (e.g. if a subrepo is in a
1502 1514 "secret" phase while the parent repo is in "draft" phase), the commit is
1503 1515 either aborted (if checksubrepos is set to "abort") or the higher phase is
1504 1516 used for the parent repository commit (if set to "follow").
1505 1517 (default: follow)
1506 1518
1507 1519
1508 1520 ``profiling``
1509 1521 -------------
1510 1522
1511 1523 Specifies profiling type, format, and file output. Two profilers are
1512 1524 supported: an instrumenting profiler (named ``ls``), and a sampling
1513 1525 profiler (named ``stat``).
1514 1526
1515 1527 In this section description, 'profiling data' stands for the raw data
1516 1528 collected during profiling, while 'profiling report' stands for a
1517 1529 statistical text report generated from the profiling data. The
1518 1530 profiling is done using lsprof.
1519 1531
1520 1532 ``enabled``
1521 1533 Enable the profiler.
1522 1534 (default: false)
1523 1535
1524 1536 This is equivalent to passing ``--profile`` on the command line.
1525 1537
1526 1538 ``type``
1527 1539 The type of profiler to use.
1528 1540 (default: stat)
1529 1541
1530 1542 ``ls``
1531 1543 Use Python's built-in instrumenting profiler. This profiler
1532 1544 works on all platforms, but each line number it reports is the
1533 1545 first line of a function. This restriction makes it difficult to
1534 1546 identify the expensive parts of a non-trivial function.
1535 1547 ``stat``
1536 1548 Use a statistical profiler, statprof. This profiler is most
1537 1549 useful for profiling commands that run for longer than about 0.1
1538 1550 seconds.
1539 1551
1540 1552 ``format``
1541 1553 Profiling format. Specific to the ``ls`` instrumenting profiler.
1542 1554 (default: text)
1543 1555
1544 1556 ``text``
1545 1557 Generate a profiling report. When saving to a file, it should be
1546 1558 noted that only the report is saved, and the profiling data is
1547 1559 not kept.
1548 1560 ``kcachegrind``
1549 1561 Format profiling data for kcachegrind use: when saving to a
1550 1562 file, the generated file can directly be loaded into
1551 1563 kcachegrind.
1552 1564
1553 1565 ``statformat``
1554 1566 Profiling format for the ``stat`` profiler.
1555 1567 (default: hotpath)
1556 1568
1557 1569 ``hotpath``
1558 1570 Show a tree-based display containing the hot path of execution (where
1559 1571 most time was spent).
1560 1572 ``bymethod``
1561 1573 Show a table of methods ordered by how frequently they are active.
1562 1574 ``byline``
1563 1575 Show a table of lines in files ordered by how frequently they are active.
1564 1576 ``json``
1565 1577 Render profiling data as JSON.
1566 1578
1567 1579 ``frequency``
1568 1580 Sampling frequency. Specific to the ``stat`` sampling profiler.
1569 1581 (default: 1000)
1570 1582
1571 1583 ``output``
1572 1584 File path where profiling data or report should be saved. If the
1573 1585 file exists, it is replaced. (default: None, data is printed on
1574 1586 stderr)
1575 1587
1576 1588 ``sort``
1577 1589 Sort field. Specific to the ``ls`` instrumenting profiler.
1578 1590 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1579 1591 ``inlinetime``.
1580 1592 (default: inlinetime)
1581 1593
1582 1594 ``limit``
1583 1595 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1584 1596 (default: 30)
1585 1597
1586 1598 ``nested``
1587 1599 Show at most this number of lines of drill-down info after each main entry.
1588 1600 This can help explain the difference between Total and Inline.
1589 1601 Specific to the ``ls`` instrumenting profiler.
1590 1602 (default: 5)
1591 1603
1592 1604 ``showmin``
1593 1605 Minimum fraction of samples an entry must have for it to be displayed.
1594 1606 Can be specified as a float between ``0.0`` and ``1.0`` or can have a
1595 1607 ``%`` afterwards to allow values up to ``100``. e.g. ``5%``.
1596 1608
1597 1609 Only used by the ``stat`` profiler.
1598 1610
1599 1611 For the ``hotpath`` format, default is ``0.05``.
1600 1612 For the ``chrome`` format, default is ``0.005``.
1601 1613
1602 1614 The option is unused on other formats.
1603 1615
1604 1616 ``showmax``
1605 1617 Maximum fraction of samples an entry can have before it is ignored in
1606 1618 display. Values format is the same as ``showmin``.
1607 1619
1608 1620 Only used by the ``stat`` profiler.
1609 1621
1610 1622 For the ``chrome`` format, default is ``0.999``.
1611 1623
1612 1624 The option is unused on other formats.
1613 1625
1614 1626 ``progress``
1615 1627 ------------
1616 1628
1617 1629 Mercurial commands can draw progress bars that are as informative as
1618 1630 possible. Some progress bars only offer indeterminate information, while others
1619 1631 have a definite end point.
1620 1632
1621 1633 ``delay``
1622 1634 Number of seconds (float) before showing the progress bar. (default: 3)
1623 1635
1624 1636 ``changedelay``
1625 1637 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1626 1638 that value will be used instead. (default: 1)
1627 1639
1628 1640 ``estimateinterval``
1629 1641 Maximum sampling interval in seconds for speed and estimated time
1630 1642 calculation. (default: 60)
1631 1643
1632 1644 ``refresh``
1633 1645 Time in seconds between refreshes of the progress bar. (default: 0.1)
1634 1646
1635 1647 ``format``
1636 1648 Format of the progress bar.
1637 1649
1638 1650 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1639 1651 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1640 1652 last 20 characters of the item, but this can be changed by adding either
1641 1653 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1642 1654 first num characters.
1643 1655
1644 1656 (default: topic bar number estimate)
1645 1657
1646 1658 ``width``
1647 1659 If set, the maximum width of the progress information (that is, min(width,
1648 1660 term width) will be used).
1649 1661
1650 1662 ``clear-complete``
1651 1663 Clear the progress bar after it's done. (default: True)
1652 1664
1653 1665 ``disable``
1654 1666 If true, don't show a progress bar.
1655 1667
1656 1668 ``assume-tty``
1657 1669 If true, ALWAYS show a progress bar, unless disable is given.
1658 1670
1659 1671 ``rebase``
1660 1672 ----------
1661 1673
1662 1674 ``allowdivergence``
1663 1675 Default to False, when True allow creating divergence when performing
1664 1676 rebase of obsolete changesets.
1665 1677
1666 1678 ``revsetalias``
1667 1679 ---------------
1668 1680
1669 1681 Alias definitions for revsets. See :hg:`help revsets` for details.
1670 1682
1671 1683 ``server``
1672 1684 ----------
1673 1685
1674 1686 Controls generic server settings.
1675 1687
1676 1688 ``compressionengines``
1677 1689 List of compression engines and their relative priority to advertise
1678 1690 to clients.
1679 1691
1680 1692 The order of compression engines determines their priority, the first
1681 1693 having the highest priority. If a compression engine is not listed
1682 1694 here, it won't be advertised to clients.
1683 1695
1684 1696 If not set (the default), built-in defaults are used. Run
1685 1697 :hg:`debuginstall` to list available compression engines and their
1686 1698 default wire protocol priority.
1687 1699
1688 1700 Older Mercurial clients only support zlib compression and this setting
1689 1701 has no effect for legacy clients.
1690 1702
1691 1703 ``uncompressed``
1692 1704 Whether to allow clients to clone a repository using the
1693 1705 uncompressed streaming protocol. This transfers about 40% more
1694 1706 data than a regular clone, but uses less memory and CPU on both
1695 1707 server and client. Over a LAN (100 Mbps or better) or a very fast
1696 1708 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1697 1709 regular clone. Over most WAN connections (anything slower than
1698 1710 about 6 Mbps), uncompressed streaming is slower, because of the
1699 1711 extra data transfer overhead. This mode will also temporarily hold
1700 1712 the write lock while determining what data to transfer.
1701 1713 (default: True)
1702 1714
1703 1715 ``uncompressedallowsecret``
1704 1716 Whether to allow stream clones when the repository contains secret
1705 1717 changesets. (default: False)
1706 1718
1707 1719 ``preferuncompressed``
1708 1720 When set, clients will try to use the uncompressed streaming
1709 1721 protocol. (default: False)
1710 1722
1711 1723 ``disablefullbundle``
1712 1724 When set, servers will refuse attempts to do pull-based clones.
1713 1725 If this option is set, ``preferuncompressed`` and/or clone bundles
1714 1726 are highly recommended. Partial clones will still be allowed.
1715 1727 (default: False)
1716 1728
1717 1729 ``concurrent-push-mode``
1718 1730 Level of allowed race condition between two pushing clients.
1719 1731
1720 1732 - 'strict': push is abort if another client touched the repository
1721 1733 while the push was preparing. (default)
1722 1734 - 'check-related': push is only aborted if it affects head that got also
1723 1735 affected while the push was preparing.
1724 1736
1725 1737 This requires compatible client (version 4.3 and later). Old client will
1726 1738 use 'strict'.
1727 1739
1728 1740 ``validate``
1729 1741 Whether to validate the completeness of pushed changesets by
1730 1742 checking that all new file revisions specified in manifests are
1731 1743 present. (default: False)
1732 1744
1733 1745 ``maxhttpheaderlen``
1734 1746 Instruct HTTP clients not to send request headers longer than this
1735 1747 many bytes. (default: 1024)
1736 1748
1737 1749 ``bundle1``
1738 1750 Whether to allow clients to push and pull using the legacy bundle1
1739 1751 exchange format. (default: True)
1740 1752
1741 1753 ``bundle1gd``
1742 1754 Like ``bundle1`` but only used if the repository is using the
1743 1755 *generaldelta* storage format. (default: True)
1744 1756
1745 1757 ``bundle1.push``
1746 1758 Whether to allow clients to push using the legacy bundle1 exchange
1747 1759 format. (default: True)
1748 1760
1749 1761 ``bundle1gd.push``
1750 1762 Like ``bundle1.push`` but only used if the repository is using the
1751 1763 *generaldelta* storage format. (default: True)
1752 1764
1753 1765 ``bundle1.pull``
1754 1766 Whether to allow clients to pull using the legacy bundle1 exchange
1755 1767 format. (default: True)
1756 1768
1757 1769 ``bundle1gd.pull``
1758 1770 Like ``bundle1.pull`` but only used if the repository is using the
1759 1771 *generaldelta* storage format. (default: True)
1760 1772
1761 1773 Large repositories using the *generaldelta* storage format should
1762 1774 consider setting this option because converting *generaldelta*
1763 1775 repositories to the exchange format required by the bundle1 data
1764 1776 format can consume a lot of CPU.
1765 1777
1766 1778 ``zliblevel``
1767 1779 Integer between ``-1`` and ``9`` that controls the zlib compression level
1768 1780 for wire protocol commands that send zlib compressed output (notably the
1769 1781 commands that send repository history data).
1770 1782
1771 1783 The default (``-1``) uses the default zlib compression level, which is
1772 1784 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1773 1785 maximum compression.
1774 1786
1775 1787 Setting this option allows server operators to make trade-offs between
1776 1788 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1777 1789 but sends more bytes to clients.
1778 1790
1779 1791 This option only impacts the HTTP server.
1780 1792
1781 1793 ``zstdlevel``
1782 1794 Integer between ``1`` and ``22`` that controls the zstd compression level
1783 1795 for wire protocol commands. ``1`` is the minimal amount of compression and
1784 1796 ``22`` is the highest amount of compression.
1785 1797
1786 1798 The default (``3``) should be significantly faster than zlib while likely
1787 1799 delivering better compression ratios.
1788 1800
1789 1801 This option only impacts the HTTP server.
1790 1802
1791 1803 See also ``server.zliblevel``.
1792 1804
1793 1805 ``smtp``
1794 1806 --------
1795 1807
1796 1808 Configuration for extensions that need to send email messages.
1797 1809
1798 1810 ``host``
1799 1811 Host name of mail server, e.g. "mail.example.com".
1800 1812
1801 1813 ``port``
1802 1814 Optional. Port to connect to on mail server. (default: 465 if
1803 1815 ``tls`` is smtps; 25 otherwise)
1804 1816
1805 1817 ``tls``
1806 1818 Optional. Method to enable TLS when connecting to mail server: starttls,
1807 1819 smtps or none. (default: none)
1808 1820
1809 1821 ``username``
1810 1822 Optional. User name for authenticating with the SMTP server.
1811 1823 (default: None)
1812 1824
1813 1825 ``password``
1814 1826 Optional. Password for authenticating with the SMTP server. If not
1815 1827 specified, interactive sessions will prompt the user for a
1816 1828 password; non-interactive sessions will fail. (default: None)
1817 1829
1818 1830 ``local_hostname``
1819 1831 Optional. The hostname that the sender can use to identify
1820 1832 itself to the MTA.
1821 1833
1822 1834
1823 1835 ``subpaths``
1824 1836 ------------
1825 1837
1826 1838 Subrepository source URLs can go stale if a remote server changes name
1827 1839 or becomes temporarily unavailable. This section lets you define
1828 1840 rewrite rules of the form::
1829 1841
1830 1842 <pattern> = <replacement>
1831 1843
1832 1844 where ``pattern`` is a regular expression matching a subrepository
1833 1845 source URL and ``replacement`` is the replacement string used to
1834 1846 rewrite it. Groups can be matched in ``pattern`` and referenced in
1835 1847 ``replacements``. For instance::
1836 1848
1837 1849 http://server/(.*)-hg/ = http://hg.server/\1/
1838 1850
1839 1851 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1840 1852
1841 1853 Relative subrepository paths are first made absolute, and the
1842 1854 rewrite rules are then applied on the full (absolute) path. If ``pattern``
1843 1855 doesn't match the full path, an attempt is made to apply it on the
1844 1856 relative path alone. The rules are applied in definition order.
1845 1857
1846 1858 ``templatealias``
1847 1859 -----------------
1848 1860
1849 1861 Alias definitions for templates. See :hg:`help templates` for details.
1850 1862
1851 1863 ``templates``
1852 1864 -------------
1853 1865
1854 1866 Use the ``[templates]`` section to define template strings.
1855 1867 See :hg:`help templates` for details.
1856 1868
1857 1869 ``trusted``
1858 1870 -----------
1859 1871
1860 1872 Mercurial will not use the settings in the
1861 1873 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1862 1874 user or to a trusted group, as various hgrc features allow arbitrary
1863 1875 commands to be run. This issue is often encountered when configuring
1864 1876 hooks or extensions for shared repositories or servers. However,
1865 1877 the web interface will use some safe settings from the ``[web]``
1866 1878 section.
1867 1879
1868 1880 This section specifies what users and groups are trusted. The
1869 1881 current user is always trusted. To trust everybody, list a user or a
1870 1882 group with name ``*``. These settings must be placed in an
1871 1883 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1872 1884 user or service running Mercurial.
1873 1885
1874 1886 ``users``
1875 1887 Comma-separated list of trusted users.
1876 1888
1877 1889 ``groups``
1878 1890 Comma-separated list of trusted groups.
1879 1891
1880 1892
1881 1893 ``ui``
1882 1894 ------
1883 1895
1884 1896 User interface controls.
1885 1897
1886 1898 ``archivemeta``
1887 1899 Whether to include the .hg_archival.txt file containing meta data
1888 1900 (hashes for the repository base and for tip) in archives created
1889 1901 by the :hg:`archive` command or downloaded via hgweb.
1890 1902 (default: True)
1891 1903
1892 1904 ``askusername``
1893 1905 Whether to prompt for a username when committing. If True, and
1894 1906 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1895 1907 be prompted to enter a username. If no username is entered, the
1896 1908 default ``USER@HOST`` is used instead.
1897 1909 (default: False)
1898 1910
1899 1911 ``clonebundles``
1900 1912 Whether the "clone bundles" feature is enabled.
1901 1913
1902 1914 When enabled, :hg:`clone` may download and apply a server-advertised
1903 1915 bundle file from a URL instead of using the normal exchange mechanism.
1904 1916
1905 1917 This can likely result in faster and more reliable clones.
1906 1918
1907 1919 (default: True)
1908 1920
1909 1921 ``clonebundlefallback``
1910 1922 Whether failure to apply an advertised "clone bundle" from a server
1911 1923 should result in fallback to a regular clone.
1912 1924
1913 1925 This is disabled by default because servers advertising "clone
1914 1926 bundles" often do so to reduce server load. If advertised bundles
1915 1927 start mass failing and clients automatically fall back to a regular
1916 1928 clone, this would add significant and unexpected load to the server
1917 1929 since the server is expecting clone operations to be offloaded to
1918 1930 pre-generated bundles. Failing fast (the default behavior) ensures
1919 1931 clients don't overwhelm the server when "clone bundle" application
1920 1932 fails.
1921 1933
1922 1934 (default: False)
1923 1935
1924 1936 ``clonebundleprefers``
1925 1937 Defines preferences for which "clone bundles" to use.
1926 1938
1927 1939 Servers advertising "clone bundles" may advertise multiple available
1928 1940 bundles. Each bundle may have different attributes, such as the bundle
1929 1941 type and compression format. This option is used to prefer a particular
1930 1942 bundle over another.
1931 1943
1932 1944 The following keys are defined by Mercurial:
1933 1945
1934 1946 BUNDLESPEC
1935 1947 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
1936 1948 e.g. ``gzip-v2`` or ``bzip2-v1``.
1937 1949
1938 1950 COMPRESSION
1939 1951 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
1940 1952
1941 1953 Server operators may define custom keys.
1942 1954
1943 1955 Example values: ``COMPRESSION=bzip2``,
1944 1956 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
1945 1957
1946 1958 By default, the first bundle advertised by the server is used.
1947 1959
1948 1960 ``color``
1949 1961 When to colorize output. Possible value are Boolean ("yes" or "no"), or
1950 1962 "debug", or "always". (default: "yes"). "yes" will use color whenever it
1951 1963 seems possible. See :hg:`help color` for details.
1952 1964
1953 1965 ``commitsubrepos``
1954 1966 Whether to commit modified subrepositories when committing the
1955 1967 parent repository. If False and one subrepository has uncommitted
1956 1968 changes, abort the commit.
1957 1969 (default: False)
1958 1970
1959 1971 ``debug``
1960 1972 Print debugging information. (default: False)
1961 1973
1962 1974 ``editor``
1963 1975 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
1964 1976
1965 1977 ``fallbackencoding``
1966 1978 Encoding to try if it's not possible to decode the changelog using
1967 1979 UTF-8. (default: ISO-8859-1)
1968 1980
1969 1981 ``graphnodetemplate``
1970 1982 The template used to print changeset nodes in an ASCII revision graph.
1971 1983 (default: ``{graphnode}``)
1972 1984
1973 1985 ``ignore``
1974 1986 A file to read per-user ignore patterns from. This file should be
1975 1987 in the same format as a repository-wide .hgignore file. Filenames
1976 1988 are relative to the repository root. This option supports hook syntax,
1977 1989 so if you want to specify multiple ignore files, you can do so by
1978 1990 setting something like ``ignore.other = ~/.hgignore2``. For details
1979 1991 of the ignore file format, see the ``hgignore(5)`` man page.
1980 1992
1981 1993 ``interactive``
1982 1994 Allow to prompt the user. (default: True)
1983 1995
1984 1996 ``interface``
1985 1997 Select the default interface for interactive features (default: text).
1986 1998 Possible values are 'text' and 'curses'.
1987 1999
1988 2000 ``interface.chunkselector``
1989 2001 Select the interface for change recording (e.g. :hg:`commit -i`).
1990 2002 Possible values are 'text' and 'curses'.
1991 2003 This config overrides the interface specified by ui.interface.
1992 2004
1993 2005 ``logtemplate``
1994 2006 Template string for commands that print changesets.
1995 2007
1996 2008 ``merge``
1997 2009 The conflict resolution program to use during a manual merge.
1998 2010 For more information on merge tools see :hg:`help merge-tools`.
1999 2011 For configuring merge tools see the ``[merge-tools]`` section.
2000 2012
2001 2013 ``mergemarkers``
2002 2014 Sets the merge conflict marker label styling. The ``detailed``
2003 2015 style uses the ``mergemarkertemplate`` setting to style the labels.
2004 2016 The ``basic`` style just uses 'local' and 'other' as the marker label.
2005 2017 One of ``basic`` or ``detailed``.
2006 2018 (default: ``basic``)
2007 2019
2008 2020 ``mergemarkertemplate``
2009 2021 The template used to print the commit description next to each conflict
2010 2022 marker during merge conflicts. See :hg:`help templates` for the template
2011 2023 format.
2012 2024
2013 2025 Defaults to showing the hash, tags, branches, bookmarks, author, and
2014 2026 the first line of the commit description.
2015 2027
2016 2028 If you use non-ASCII characters in names for tags, branches, bookmarks,
2017 2029 authors, and/or commit descriptions, you must pay attention to encodings of
2018 2030 managed files. At template expansion, non-ASCII characters use the encoding
2019 2031 specified by the ``--encoding`` global option, ``HGENCODING`` or other
2020 2032 environment variables that govern your locale. If the encoding of the merge
2021 2033 markers is different from the encoding of the merged files,
2022 2034 serious problems may occur.
2023 2035
2024 2036 ``origbackuppath``
2025 2037 The path to a directory used to store generated .orig files. If the path is
2026 2038 not a directory, one will be created. If set, files stored in this
2027 2039 directory have the same name as the original file and do not have a .orig
2028 2040 suffix.
2029 2041
2030 2042 ``paginate``
2031 2043 Control the pagination of command output (default: True). See :hg:`help pager`
2032 2044 for details.
2033 2045
2034 2046 ``patch``
2035 2047 An optional external tool that ``hg import`` and some extensions
2036 2048 will use for applying patches. By default Mercurial uses an
2037 2049 internal patch utility. The external tool must work as the common
2038 2050 Unix ``patch`` program. In particular, it must accept a ``-p``
2039 2051 argument to strip patch headers, a ``-d`` argument to specify the
2040 2052 current directory, a file name to patch, and a patch file to take
2041 2053 from stdin.
2042 2054
2043 2055 It is possible to specify a patch tool together with extra
2044 2056 arguments. For example, setting this option to ``patch --merge``
2045 2057 will use the ``patch`` program with its 2-way merge option.
2046 2058
2047 2059 ``portablefilenames``
2048 2060 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
2049 2061 (default: ``warn``)
2050 2062
2051 2063 ``warn``
2052 2064 Print a warning message on POSIX platforms, if a file with a non-portable
2053 2065 filename is added (e.g. a file with a name that can't be created on
2054 2066 Windows because it contains reserved parts like ``AUX``, reserved
2055 2067 characters like ``:``, or would cause a case collision with an existing
2056 2068 file).
2057 2069
2058 2070 ``ignore``
2059 2071 Don't print a warning.
2060 2072
2061 2073 ``abort``
2062 2074 The command is aborted.
2063 2075
2064 2076 ``true``
2065 2077 Alias for ``warn``.
2066 2078
2067 2079 ``false``
2068 2080 Alias for ``ignore``.
2069 2081
2070 2082 .. container:: windows
2071 2083
2072 2084 On Windows, this configuration option is ignored and the command aborted.
2073 2085
2074 2086 ``quiet``
2075 2087 Reduce the amount of output printed.
2076 2088 (default: False)
2077 2089
2078 2090 ``remotecmd``
2079 2091 Remote command to use for clone/push/pull operations.
2080 2092 (default: ``hg``)
2081 2093
2082 2094 ``report_untrusted``
2083 2095 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
2084 2096 trusted user or group.
2085 2097 (default: True)
2086 2098
2087 2099 ``slash``
2088 2100 Display paths using a slash (``/``) as the path separator. This
2089 2101 only makes a difference on systems where the default path
2090 2102 separator is not the slash character (e.g. Windows uses the
2091 2103 backslash character (``\``)).
2092 2104 (default: False)
2093 2105
2094 2106 ``statuscopies``
2095 2107 Display copies in the status command.
2096 2108
2097 2109 ``ssh``
2098 2110 Command to use for SSH connections. (default: ``ssh``)
2099 2111
2100 2112 ``strict``
2101 2113 Require exact command names, instead of allowing unambiguous
2102 2114 abbreviations. (default: False)
2103 2115
2104 2116 ``style``
2105 2117 Name of style to use for command output.
2106 2118
2107 2119 ``supportcontact``
2108 2120 A URL where users should report a Mercurial traceback. Use this if you are a
2109 2121 large organisation with its own Mercurial deployment process and crash
2110 2122 reports should be addressed to your internal support.
2111 2123
2112 2124 ``textwidth``
2113 2125 Maximum width of help text. A longer line generated by ``hg help`` or
2114 2126 ``hg subcommand --help`` will be broken after white space to get this
2115 2127 width or the terminal width, whichever comes first.
2116 2128 A non-positive value will disable this and the terminal width will be
2117 2129 used. (default: 78)
2118 2130
2119 2131 ``timeout``
2120 2132 The timeout used when a lock is held (in seconds), a negative value
2121 2133 means no timeout. (default: 600)
2122 2134
2123 2135 ``traceback``
2124 2136 Mercurial always prints a traceback when an unknown exception
2125 2137 occurs. Setting this to True will make Mercurial print a traceback
2126 2138 on all exceptions, even those recognized by Mercurial (such as
2127 2139 IOError or MemoryError). (default: False)
2128 2140
2129 2141 ``tweakdefaults``
2130 2142
2131 2143 By default Mercurial's behavior changes very little from release
2132 2144 to release, but over time the recommended config settings
2133 2145 shift. Enable this config to opt in to get automatic tweaks to
2134 2146 Mercurial's behavior over time. This config setting will have no
2135 2147 effet if ``HGPLAIN` is set or ``HGPLAINEXCEPT`` is set and does
2136 2148 not include ``tweakdefaults``. (default: False)
2137 2149
2138 2150 ``username``
2139 2151 The committer of a changeset created when running "commit".
2140 2152 Typically a person's name and email address, e.g. ``Fred Widget
2141 2153 <fred@example.com>``. Environment variables in the
2142 2154 username are expanded.
2143 2155
2144 2156 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2145 2157 hgrc is empty, e.g. if the system admin set ``username =`` in the
2146 2158 system hgrc, it has to be specified manually or in a different
2147 2159 hgrc file)
2148 2160
2149 2161 ``verbose``
2150 2162 Increase the amount of output printed. (default: False)
2151 2163
2152 2164
2153 2165 ``web``
2154 2166 -------
2155 2167
2156 2168 Web interface configuration. The settings in this section apply to
2157 2169 both the builtin webserver (started by :hg:`serve`) and the script you
2158 2170 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2159 2171 and WSGI).
2160 2172
2161 2173 The Mercurial webserver does no authentication (it does not prompt for
2162 2174 usernames and passwords to validate *who* users are), but it does do
2163 2175 authorization (it grants or denies access for *authenticated users*
2164 2176 based on settings in this section). You must either configure your
2165 2177 webserver to do authentication for you, or disable the authorization
2166 2178 checks.
2167 2179
2168 2180 For a quick setup in a trusted environment, e.g., a private LAN, where
2169 2181 you want it to accept pushes from anybody, you can use the following
2170 2182 command line::
2171 2183
2172 2184 $ hg --config web.allow_push=* --config web.push_ssl=False serve
2173 2185
2174 2186 Note that this will allow anybody to push anything to the server and
2175 2187 that this should not be used for public servers.
2176 2188
2177 2189 The full set of options is:
2178 2190
2179 2191 ``accesslog``
2180 2192 Where to output the access log. (default: stdout)
2181 2193
2182 2194 ``address``
2183 2195 Interface address to bind to. (default: all)
2184 2196
2185 2197 ``allow_archive``
2186 2198 List of archive format (bz2, gz, zip) allowed for downloading.
2187 2199 (default: empty)
2188 2200
2189 2201 ``allowbz2``
2190 2202 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2191 2203 revisions.
2192 2204 (default: False)
2193 2205
2194 2206 ``allowgz``
2195 2207 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2196 2208 revisions.
2197 2209 (default: False)
2198 2210
2199 2211 ``allowpull``
2200 2212 Whether to allow pulling from the repository. (default: True)
2201 2213
2202 2214 ``allow_push``
2203 2215 Whether to allow pushing to the repository. If empty or not set,
2204 2216 pushing is not allowed. If the special value ``*``, any remote
2205 2217 user can push, including unauthenticated users. Otherwise, the
2206 2218 remote user must have been authenticated, and the authenticated
2207 2219 user name must be present in this list. The contents of the
2208 2220 allow_push list are examined after the deny_push list.
2209 2221
2210 2222 ``allow_read``
2211 2223 If the user has not already been denied repository access due to
2212 2224 the contents of deny_read, this list determines whether to grant
2213 2225 repository access to the user. If this list is not empty, and the
2214 2226 user is unauthenticated or not present in the list, then access is
2215 2227 denied for the user. If the list is empty or not set, then access
2216 2228 is permitted to all users by default. Setting allow_read to the
2217 2229 special value ``*`` is equivalent to it not being set (i.e. access
2218 2230 is permitted to all users). The contents of the allow_read list are
2219 2231 examined after the deny_read list.
2220 2232
2221 2233 ``allowzip``
2222 2234 (DEPRECATED) Whether to allow .zip downloading of repository
2223 2235 revisions. This feature creates temporary files.
2224 2236 (default: False)
2225 2237
2226 2238 ``archivesubrepos``
2227 2239 Whether to recurse into subrepositories when archiving.
2228 2240 (default: False)
2229 2241
2230 2242 ``baseurl``
2231 2243 Base URL to use when publishing URLs in other locations, so
2232 2244 third-party tools like email notification hooks can construct
2233 2245 URLs. Example: ``http://hgserver/repos/``.
2234 2246
2235 2247 ``cacerts``
2236 2248 Path to file containing a list of PEM encoded certificate
2237 2249 authority certificates. Environment variables and ``~user``
2238 2250 constructs are expanded in the filename. If specified on the
2239 2251 client, then it will verify the identity of remote HTTPS servers
2240 2252 with these certificates.
2241 2253
2242 2254 To disable SSL verification temporarily, specify ``--insecure`` from
2243 2255 command line.
2244 2256
2245 2257 You can use OpenSSL's CA certificate file if your platform has
2246 2258 one. On most Linux systems this will be
2247 2259 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2248 2260 generate this file manually. The form must be as follows::
2249 2261
2250 2262 -----BEGIN CERTIFICATE-----
2251 2263 ... (certificate in base64 PEM encoding) ...
2252 2264 -----END CERTIFICATE-----
2253 2265 -----BEGIN CERTIFICATE-----
2254 2266 ... (certificate in base64 PEM encoding) ...
2255 2267 -----END CERTIFICATE-----
2256 2268
2257 2269 ``cache``
2258 2270 Whether to support caching in hgweb. (default: True)
2259 2271
2260 2272 ``certificate``
2261 2273 Certificate to use when running :hg:`serve`.
2262 2274
2263 2275 ``collapse``
2264 2276 With ``descend`` enabled, repositories in subdirectories are shown at
2265 2277 a single level alongside repositories in the current path. With
2266 2278 ``collapse`` also enabled, repositories residing at a deeper level than
2267 2279 the current path are grouped behind navigable directory entries that
2268 2280 lead to the locations of these repositories. In effect, this setting
2269 2281 collapses each collection of repositories found within a subdirectory
2270 2282 into a single entry for that subdirectory. (default: False)
2271 2283
2272 2284 ``comparisoncontext``
2273 2285 Number of lines of context to show in side-by-side file comparison. If
2274 2286 negative or the value ``full``, whole files are shown. (default: 5)
2275 2287
2276 2288 This setting can be overridden by a ``context`` request parameter to the
2277 2289 ``comparison`` command, taking the same values.
2278 2290
2279 2291 ``contact``
2280 2292 Name or email address of the person in charge of the repository.
2281 2293 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2282 2294
2283 2295 ``csp``
2284 2296 Send a ``Content-Security-Policy`` HTTP header with this value.
2285 2297
2286 2298 The value may contain a special string ``%nonce%``, which will be replaced
2287 2299 by a randomly-generated one-time use value. If the value contains
2288 2300 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2289 2301 one-time property of the nonce. This nonce will also be inserted into
2290 2302 ``<script>`` elements containing inline JavaScript.
2291 2303
2292 2304 Note: lots of HTML content sent by the server is derived from repository
2293 2305 data. Please consider the potential for malicious repository data to
2294 2306 "inject" itself into generated HTML content as part of your security
2295 2307 threat model.
2296 2308
2297 2309 ``deny_push``
2298 2310 Whether to deny pushing to the repository. If empty or not set,
2299 2311 push is not denied. If the special value ``*``, all remote users are
2300 2312 denied push. Otherwise, unauthenticated users are all denied, and
2301 2313 any authenticated user name present in this list is also denied. The
2302 2314 contents of the deny_push list are examined before the allow_push list.
2303 2315
2304 2316 ``deny_read``
2305 2317 Whether to deny reading/viewing of the repository. If this list is
2306 2318 not empty, unauthenticated users are all denied, and any
2307 2319 authenticated user name present in this list is also denied access to
2308 2320 the repository. If set to the special value ``*``, all remote users
2309 2321 are denied access (rarely needed ;). If deny_read is empty or not set,
2310 2322 the determination of repository access depends on the presence and
2311 2323 content of the allow_read list (see description). If both
2312 2324 deny_read and allow_read are empty or not set, then access is
2313 2325 permitted to all users by default. If the repository is being
2314 2326 served via hgwebdir, denied users will not be able to see it in
2315 2327 the list of repositories. The contents of the deny_read list have
2316 2328 priority over (are examined before) the contents of the allow_read
2317 2329 list.
2318 2330
2319 2331 ``descend``
2320 2332 hgwebdir indexes will not descend into subdirectories. Only repositories
2321 2333 directly in the current path will be shown (other repositories are still
2322 2334 available from the index corresponding to their containing path).
2323 2335
2324 2336 ``description``
2325 2337 Textual description of the repository's purpose or contents.
2326 2338 (default: "unknown")
2327 2339
2328 2340 ``encoding``
2329 2341 Character encoding name. (default: the current locale charset)
2330 2342 Example: "UTF-8".
2331 2343
2332 2344 ``errorlog``
2333 2345 Where to output the error log. (default: stderr)
2334 2346
2335 2347 ``guessmime``
2336 2348 Control MIME types for raw download of file content.
2337 2349 Set to True to let hgweb guess the content type from the file
2338 2350 extension. This will serve HTML files as ``text/html`` and might
2339 2351 allow cross-site scripting attacks when serving untrusted
2340 2352 repositories. (default: False)
2341 2353
2342 2354 ``hidden``
2343 2355 Whether to hide the repository in the hgwebdir index.
2344 2356 (default: False)
2345 2357
2346 2358 ``ipv6``
2347 2359 Whether to use IPv6. (default: False)
2348 2360
2349 2361 ``labels``
2350 2362 List of string *labels* associated with the repository.
2351 2363
2352 2364 Labels are exposed as a template keyword and can be used to customize
2353 2365 output. e.g. the ``index`` template can group or filter repositories
2354 2366 by labels and the ``summary`` template can display additional content
2355 2367 if a specific label is present.
2356 2368
2357 2369 ``logoimg``
2358 2370 File name of the logo image that some templates display on each page.
2359 2371 The file name is relative to ``staticurl``. That is, the full path to
2360 2372 the logo image is "staticurl/logoimg".
2361 2373 If unset, ``hglogo.png`` will be used.
2362 2374
2363 2375 ``logourl``
2364 2376 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2365 2377 will be used.
2366 2378
2367 2379 ``maxchanges``
2368 2380 Maximum number of changes to list on the changelog. (default: 10)
2369 2381
2370 2382 ``maxfiles``
2371 2383 Maximum number of files to list per changeset. (default: 10)
2372 2384
2373 2385 ``maxshortchanges``
2374 2386 Maximum number of changes to list on the shortlog, graph or filelog
2375 2387 pages. (default: 60)
2376 2388
2377 2389 ``name``
2378 2390 Repository name to use in the web interface.
2379 2391 (default: current working directory)
2380 2392
2381 2393 ``port``
2382 2394 Port to listen on. (default: 8000)
2383 2395
2384 2396 ``prefix``
2385 2397 Prefix path to serve from. (default: '' (server root))
2386 2398
2387 2399 ``push_ssl``
2388 2400 Whether to require that inbound pushes be transported over SSL to
2389 2401 prevent password sniffing. (default: True)
2390 2402
2391 2403 ``refreshinterval``
2392 2404 How frequently directory listings re-scan the filesystem for new
2393 2405 repositories, in seconds. This is relevant when wildcards are used
2394 2406 to define paths. Depending on how much filesystem traversal is
2395 2407 required, refreshing may negatively impact performance.
2396 2408
2397 2409 Values less than or equal to 0 always refresh.
2398 2410 (default: 20)
2399 2411
2400 2412 ``staticurl``
2401 2413 Base URL to use for static files. If unset, static files (e.g. the
2402 2414 hgicon.png favicon) will be served by the CGI script itself. Use
2403 2415 this setting to serve them directly with the HTTP server.
2404 2416 Example: ``http://hgserver/static/``.
2405 2417
2406 2418 ``stripes``
2407 2419 How many lines a "zebra stripe" should span in multi-line output.
2408 2420 Set to 0 to disable. (default: 1)
2409 2421
2410 2422 ``style``
2411 2423 Which template map style to use. The available options are the names of
2412 2424 subdirectories in the HTML templates path. (default: ``paper``)
2413 2425 Example: ``monoblue``.
2414 2426
2415 2427 ``templates``
2416 2428 Where to find the HTML templates. The default path to the HTML templates
2417 2429 can be obtained from ``hg debuginstall``.
2418 2430
2419 2431 ``websub``
2420 2432 ----------
2421 2433
2422 2434 Web substitution filter definition. You can use this section to
2423 2435 define a set of regular expression substitution patterns which
2424 2436 let you automatically modify the hgweb server output.
2425 2437
2426 2438 The default hgweb templates only apply these substitution patterns
2427 2439 on the revision description fields. You can apply them anywhere
2428 2440 you want when you create your own templates by adding calls to the
2429 2441 "websub" filter (usually after calling the "escape" filter).
2430 2442
2431 2443 This can be used, for example, to convert issue references to links
2432 2444 to your issue tracker, or to convert "markdown-like" syntax into
2433 2445 HTML (see the examples below).
2434 2446
2435 2447 Each entry in this section names a substitution filter.
2436 2448 The value of each entry defines the substitution expression itself.
2437 2449 The websub expressions follow the old interhg extension syntax,
2438 2450 which in turn imitates the Unix sed replacement syntax::
2439 2451
2440 2452 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2441 2453
2442 2454 You can use any separator other than "/". The final "i" is optional
2443 2455 and indicates that the search must be case insensitive.
2444 2456
2445 2457 Examples::
2446 2458
2447 2459 [websub]
2448 2460 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2449 2461 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2450 2462 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2451 2463
2452 2464 ``worker``
2453 2465 ----------
2454 2466
2455 2467 Parallel master/worker configuration. We currently perform working
2456 2468 directory updates in parallel on Unix-like systems, which greatly
2457 2469 helps performance.
2458 2470
2459 2471 ``numcpus``
2460 2472 Number of CPUs to use for parallel operations. A zero or
2461 2473 negative value is treated as ``use the default``.
2462 2474 (default: 4 or the number of CPUs on the system, whichever is larger)
2463 2475
2464 2476 ``backgroundclose``
2465 2477 Whether to enable closing file handles on background threads during certain
2466 2478 operations. Some platforms aren't very efficient at closing file
2467 2479 handles that have been written or appended to. By performing file closing
2468 2480 on background threads, file write rate can increase substantially.
2469 2481 (default: true on Windows, false elsewhere)
2470 2482
2471 2483 ``backgroundcloseminfilecount``
2472 2484 Minimum number of files required to trigger background file closing.
2473 2485 Operations not writing this many files won't start background close
2474 2486 threads.
2475 2487 (default: 2048)
2476 2488
2477 2489 ``backgroundclosemaxqueue``
2478 2490 The maximum number of opened file handles waiting to be closed in the
2479 2491 background. This option only has an effect if ``backgroundclose`` is
2480 2492 enabled.
2481 2493 (default: 384)
2482 2494
2483 2495 ``backgroundclosethreadcount``
2484 2496 Number of threads to process background file closes. Only relevant if
2485 2497 ``backgroundclose`` is enabled.
2486 2498 (default: 4)
@@ -1,2302 +1,2311 b''
1 1 # localrepo.py - read/write repository class for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import errno
11 11 import hashlib
12 12 import inspect
13 13 import os
14 14 import random
15 15 import time
16 16 import weakref
17 17
18 18 from .i18n import _
19 19 from .node import (
20 20 hex,
21 21 nullid,
22 22 short,
23 23 )
24 24 from . import (
25 25 bookmarks,
26 26 branchmap,
27 27 bundle2,
28 28 changegroup,
29 29 changelog,
30 30 color,
31 31 context,
32 32 dirstate,
33 33 dirstateguard,
34 34 discovery,
35 35 encoding,
36 36 error,
37 37 exchange,
38 38 extensions,
39 39 filelog,
40 40 hook,
41 41 lock as lockmod,
42 42 manifest,
43 43 match as matchmod,
44 44 merge as mergemod,
45 45 mergeutil,
46 46 namespaces,
47 47 obsolete,
48 48 pathutil,
49 49 peer,
50 50 phases,
51 51 pushkey,
52 52 pycompat,
53 53 repository,
54 54 repoview,
55 55 revset,
56 56 revsetlang,
57 57 scmutil,
58 58 sparse,
59 59 store,
60 60 subrepo,
61 61 tags as tagsmod,
62 62 transaction,
63 63 txnutil,
64 64 util,
65 65 vfs as vfsmod,
66 66 )
67 67
68 68 release = lockmod.release
69 69 urlerr = util.urlerr
70 70 urlreq = util.urlreq
71 71
72 72 # set of (path, vfs-location) tuples. vfs-location is:
73 73 # - 'plain for vfs relative paths
74 74 # - '' for svfs relative paths
75 75 _cachedfiles = set()
76 76
77 77 class _basefilecache(scmutil.filecache):
78 78 """All filecache usage on repo are done for logic that should be unfiltered
79 79 """
80 80 def __get__(self, repo, type=None):
81 81 if repo is None:
82 82 return self
83 83 return super(_basefilecache, self).__get__(repo.unfiltered(), type)
84 84 def __set__(self, repo, value):
85 85 return super(_basefilecache, self).__set__(repo.unfiltered(), value)
86 86 def __delete__(self, repo):
87 87 return super(_basefilecache, self).__delete__(repo.unfiltered())
88 88
89 89 class repofilecache(_basefilecache):
90 90 """filecache for files in .hg but outside of .hg/store"""
91 91 def __init__(self, *paths):
92 92 super(repofilecache, self).__init__(*paths)
93 93 for path in paths:
94 94 _cachedfiles.add((path, 'plain'))
95 95
96 96 def join(self, obj, fname):
97 97 return obj.vfs.join(fname)
98 98
99 99 class storecache(_basefilecache):
100 100 """filecache for files in the store"""
101 101 def __init__(self, *paths):
102 102 super(storecache, self).__init__(*paths)
103 103 for path in paths:
104 104 _cachedfiles.add((path, ''))
105 105
106 106 def join(self, obj, fname):
107 107 return obj.sjoin(fname)
108 108
109 109 def isfilecached(repo, name):
110 110 """check if a repo has already cached "name" filecache-ed property
111 111
112 112 This returns (cachedobj-or-None, iscached) tuple.
113 113 """
114 114 cacheentry = repo.unfiltered()._filecache.get(name, None)
115 115 if not cacheentry:
116 116 return None, False
117 117 return cacheentry.obj, True
118 118
119 119 class unfilteredpropertycache(util.propertycache):
120 120 """propertycache that apply to unfiltered repo only"""
121 121
122 122 def __get__(self, repo, type=None):
123 123 unfi = repo.unfiltered()
124 124 if unfi is repo:
125 125 return super(unfilteredpropertycache, self).__get__(unfi)
126 126 return getattr(unfi, self.name)
127 127
128 128 class filteredpropertycache(util.propertycache):
129 129 """propertycache that must take filtering in account"""
130 130
131 131 def cachevalue(self, obj, value):
132 132 object.__setattr__(obj, self.name, value)
133 133
134 134
135 135 def hasunfilteredcache(repo, name):
136 136 """check if a repo has an unfilteredpropertycache value for <name>"""
137 137 return name in vars(repo.unfiltered())
138 138
139 139 def unfilteredmethod(orig):
140 140 """decorate method that always need to be run on unfiltered version"""
141 141 def wrapper(repo, *args, **kwargs):
142 142 return orig(repo.unfiltered(), *args, **kwargs)
143 143 return wrapper
144 144
145 145 moderncaps = {'lookup', 'branchmap', 'pushkey', 'known', 'getbundle',
146 146 'unbundle'}
147 147 legacycaps = moderncaps.union({'changegroupsubset'})
148 148
149 149 class localpeer(repository.peer):
150 150 '''peer for a local repo; reflects only the most recent API'''
151 151
152 152 def __init__(self, repo, caps=None):
153 153 super(localpeer, self).__init__()
154 154
155 155 if caps is None:
156 156 caps = moderncaps.copy()
157 157 self._repo = repo.filtered('served')
158 158 self._ui = repo.ui
159 159 self._caps = repo._restrictcapabilities(caps)
160 160
161 161 # Begin of _basepeer interface.
162 162
163 163 @util.propertycache
164 164 def ui(self):
165 165 return self._ui
166 166
167 167 def url(self):
168 168 return self._repo.url()
169 169
170 170 def local(self):
171 171 return self._repo
172 172
173 173 def peer(self):
174 174 return self
175 175
176 176 def canpush(self):
177 177 return True
178 178
179 179 def close(self):
180 180 self._repo.close()
181 181
182 182 # End of _basepeer interface.
183 183
184 184 # Begin of _basewirecommands interface.
185 185
186 186 def branchmap(self):
187 187 return self._repo.branchmap()
188 188
189 189 def capabilities(self):
190 190 return self._caps
191 191
192 192 def debugwireargs(self, one, two, three=None, four=None, five=None):
193 193 """Used to test argument passing over the wire"""
194 194 return "%s %s %s %s %s" % (one, two, three, four, five)
195 195
196 196 def getbundle(self, source, heads=None, common=None, bundlecaps=None,
197 197 **kwargs):
198 198 chunks = exchange.getbundlechunks(self._repo, source, heads=heads,
199 199 common=common, bundlecaps=bundlecaps,
200 200 **kwargs)
201 201 cb = util.chunkbuffer(chunks)
202 202
203 203 if exchange.bundle2requested(bundlecaps):
204 204 # When requesting a bundle2, getbundle returns a stream to make the
205 205 # wire level function happier. We need to build a proper object
206 206 # from it in local peer.
207 207 return bundle2.getunbundler(self.ui, cb)
208 208 else:
209 209 return changegroup.getunbundler('01', cb, None)
210 210
211 211 def heads(self):
212 212 return self._repo.heads()
213 213
214 214 def known(self, nodes):
215 215 return self._repo.known(nodes)
216 216
217 217 def listkeys(self, namespace):
218 218 return self._repo.listkeys(namespace)
219 219
220 220 def lookup(self, key):
221 221 return self._repo.lookup(key)
222 222
223 223 def pushkey(self, namespace, key, old, new):
224 224 return self._repo.pushkey(namespace, key, old, new)
225 225
226 226 def stream_out(self):
227 227 raise error.Abort(_('cannot perform stream clone against local '
228 228 'peer'))
229 229
230 230 def unbundle(self, cg, heads, url):
231 231 """apply a bundle on a repo
232 232
233 233 This function handles the repo locking itself."""
234 234 try:
235 235 try:
236 236 cg = exchange.readbundle(self.ui, cg, None)
237 237 ret = exchange.unbundle(self._repo, cg, heads, 'push', url)
238 238 if util.safehasattr(ret, 'getchunks'):
239 239 # This is a bundle20 object, turn it into an unbundler.
240 240 # This little dance should be dropped eventually when the
241 241 # API is finally improved.
242 242 stream = util.chunkbuffer(ret.getchunks())
243 243 ret = bundle2.getunbundler(self.ui, stream)
244 244 return ret
245 245 except Exception as exc:
246 246 # If the exception contains output salvaged from a bundle2
247 247 # reply, we need to make sure it is printed before continuing
248 248 # to fail. So we build a bundle2 with such output and consume
249 249 # it directly.
250 250 #
251 251 # This is not very elegant but allows a "simple" solution for
252 252 # issue4594
253 253 output = getattr(exc, '_bundle2salvagedoutput', ())
254 254 if output:
255 255 bundler = bundle2.bundle20(self._repo.ui)
256 256 for out in output:
257 257 bundler.addpart(out)
258 258 stream = util.chunkbuffer(bundler.getchunks())
259 259 b = bundle2.getunbundler(self.ui, stream)
260 260 bundle2.processbundle(self._repo, b)
261 261 raise
262 262 except error.PushRaced as exc:
263 263 raise error.ResponseError(_('push failed:'), str(exc))
264 264
265 265 # End of _basewirecommands interface.
266 266
267 267 # Begin of peer interface.
268 268
269 269 def iterbatch(self):
270 270 return peer.localiterbatcher(self)
271 271
272 272 # End of peer interface.
273 273
274 274 class locallegacypeer(repository.legacypeer, localpeer):
275 275 '''peer extension which implements legacy methods too; used for tests with
276 276 restricted capabilities'''
277 277
278 278 def __init__(self, repo):
279 279 super(locallegacypeer, self).__init__(repo, caps=legacycaps)
280 280
281 281 # Begin of baselegacywirecommands interface.
282 282
283 283 def between(self, pairs):
284 284 return self._repo.between(pairs)
285 285
286 286 def branches(self, nodes):
287 287 return self._repo.branches(nodes)
288 288
289 289 def changegroup(self, basenodes, source):
290 290 outgoing = discovery.outgoing(self._repo, missingroots=basenodes,
291 291 missingheads=self._repo.heads())
292 292 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
293 293
294 294 def changegroupsubset(self, bases, heads, source):
295 295 outgoing = discovery.outgoing(self._repo, missingroots=bases,
296 296 missingheads=heads)
297 297 return changegroup.makechangegroup(self._repo, outgoing, '01', source)
298 298
299 299 # End of baselegacywirecommands interface.
300 300
301 301 # Increment the sub-version when the revlog v2 format changes to lock out old
302 302 # clients.
303 303 REVLOGV2_REQUIREMENT = 'exp-revlogv2.0'
304 304
305 305 class localrepository(object):
306 306
307 307 supportedformats = {
308 308 'revlogv1',
309 309 'generaldelta',
310 310 'treemanifest',
311 311 'manifestv2',
312 312 REVLOGV2_REQUIREMENT,
313 313 }
314 314 _basesupported = supportedformats | {
315 315 'store',
316 316 'fncache',
317 317 'shared',
318 318 'relshared',
319 319 'dotencode',
320 320 'exp-sparse',
321 321 }
322 322 openerreqs = {
323 323 'revlogv1',
324 324 'generaldelta',
325 325 'treemanifest',
326 326 'manifestv2',
327 327 }
328 328
329 329 # a list of (ui, featureset) functions.
330 330 # only functions defined in module of enabled extensions are invoked
331 331 featuresetupfuncs = set()
332 332
333 333 # list of prefix for file which can be written without 'wlock'
334 334 # Extensions should extend this list when needed
335 335 _wlockfreeprefix = {
336 336 # We migh consider requiring 'wlock' for the next
337 337 # two, but pretty much all the existing code assume
338 338 # wlock is not needed so we keep them excluded for
339 339 # now.
340 340 'hgrc',
341 341 'requires',
342 342 # XXX cache is a complicatged business someone
343 343 # should investigate this in depth at some point
344 344 'cache/',
345 345 # XXX shouldn't be dirstate covered by the wlock?
346 346 'dirstate',
347 347 # XXX bisect was still a bit too messy at the time
348 348 # this changeset was introduced. Someone should fix
349 349 # the remainig bit and drop this line
350 350 'bisect.state',
351 351 }
352 352
353 353 def __init__(self, baseui, path, create=False):
354 354 self.requirements = set()
355 355 self.filtername = None
356 356 # wvfs: rooted at the repository root, used to access the working copy
357 357 self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True)
358 358 # vfs: rooted at .hg, used to access repo files outside of .hg/store
359 359 self.vfs = None
360 360 # svfs: usually rooted at .hg/store, used to access repository history
361 361 # If this is a shared repository, this vfs may point to another
362 362 # repository's .hg/store directory.
363 363 self.svfs = None
364 364 self.root = self.wvfs.base
365 365 self.path = self.wvfs.join(".hg")
366 366 self.origroot = path
367 367 # These auditor are not used by the vfs,
368 368 # only used when writing this comment: basectx.match
369 369 self.auditor = pathutil.pathauditor(self.root, self._checknested)
370 370 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
371 371 realfs=False, cached=True)
372 372 self.baseui = baseui
373 373 self.ui = baseui.copy()
374 374 self.ui.copy = baseui.copy # prevent copying repo configuration
375 375 self.vfs = vfsmod.vfs(self.path, cacheaudited=True)
376 376 if (self.ui.configbool('devel', 'all-warnings') or
377 377 self.ui.configbool('devel', 'check-locks')):
378 378 self.vfs.audit = self._getvfsward(self.vfs.audit)
379 379 # A list of callback to shape the phase if no data were found.
380 380 # Callback are in the form: func(repo, roots) --> processed root.
381 381 # This list it to be filled by extension during repo setup
382 382 self._phasedefaults = []
383 383 try:
384 384 self.ui.readconfig(self.vfs.join("hgrc"), self.root)
385 385 self._loadextensions()
386 386 except IOError:
387 387 pass
388 388
389 389 if self.featuresetupfuncs:
390 390 self.supported = set(self._basesupported) # use private copy
391 391 extmods = set(m.__name__ for n, m
392 392 in extensions.extensions(self.ui))
393 393 for setupfunc in self.featuresetupfuncs:
394 394 if setupfunc.__module__ in extmods:
395 395 setupfunc(self.ui, self.supported)
396 396 else:
397 397 self.supported = self._basesupported
398 398 color.setup(self.ui)
399 399
400 400 # Add compression engines.
401 401 for name in util.compengines:
402 402 engine = util.compengines[name]
403 403 if engine.revlogheader():
404 404 self.supported.add('exp-compression-%s' % name)
405 405
406 406 if not self.vfs.isdir():
407 407 if create:
408 408 self.requirements = newreporequirements(self)
409 409
410 410 if not self.wvfs.exists():
411 411 self.wvfs.makedirs()
412 412 self.vfs.makedir(notindexed=True)
413 413
414 414 if 'store' in self.requirements:
415 415 self.vfs.mkdir("store")
416 416
417 417 # create an invalid changelog
418 418 self.vfs.append(
419 419 "00changelog.i",
420 420 '\0\0\0\2' # represents revlogv2
421 421 ' dummy changelog to prevent using the old repo layout'
422 422 )
423 423 else:
424 424 raise error.RepoError(_("repository %s not found") % path)
425 425 elif create:
426 426 raise error.RepoError(_("repository %s already exists") % path)
427 427 else:
428 428 try:
429 429 self.requirements = scmutil.readrequires(
430 430 self.vfs, self.supported)
431 431 except IOError as inst:
432 432 if inst.errno != errno.ENOENT:
433 433 raise
434 434
435 435 cachepath = self.vfs.join('cache')
436 436 self.sharedpath = self.path
437 437 try:
438 438 sharedpath = self.vfs.read("sharedpath").rstrip('\n')
439 439 if 'relshared' in self.requirements:
440 440 sharedpath = self.vfs.join(sharedpath)
441 441 vfs = vfsmod.vfs(sharedpath, realpath=True)
442 442 cachepath = vfs.join('cache')
443 443 s = vfs.base
444 444 if not vfs.exists():
445 445 raise error.RepoError(
446 446 _('.hg/sharedpath points to nonexistent directory %s') % s)
447 447 self.sharedpath = s
448 448 except IOError as inst:
449 449 if inst.errno != errno.ENOENT:
450 450 raise
451 451
452 452 if 'exp-sparse' in self.requirements and not sparse.enabled:
453 453 raise error.RepoError(_('repository is using sparse feature but '
454 454 'sparse is not enabled; enable the '
455 455 '"sparse" extensions to access'))
456 456
457 457 self.store = store.store(
458 458 self.requirements, self.sharedpath,
459 459 lambda base: vfsmod.vfs(base, cacheaudited=True))
460 460 self.spath = self.store.path
461 461 self.svfs = self.store.vfs
462 462 self.sjoin = self.store.join
463 463 self.vfs.createmode = self.store.createmode
464 464 self.cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
465 465 self.cachevfs.createmode = self.store.createmode
466 466 if (self.ui.configbool('devel', 'all-warnings') or
467 467 self.ui.configbool('devel', 'check-locks')):
468 468 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs
469 469 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit)
470 470 else: # standard vfs
471 471 self.svfs.audit = self._getsvfsward(self.svfs.audit)
472 472 self._applyopenerreqs()
473 473 if create:
474 474 self._writerequirements()
475 475
476 476 self._dirstatevalidatewarned = False
477 477
478 478 self._branchcaches = {}
479 479 self._revbranchcache = None
480 480 self.filterpats = {}
481 481 self._datafilters = {}
482 482 self._transref = self._lockref = self._wlockref = None
483 483
484 484 # A cache for various files under .hg/ that tracks file changes,
485 485 # (used by the filecache decorator)
486 486 #
487 487 # Maps a property name to its util.filecacheentry
488 488 self._filecache = {}
489 489
490 490 # hold sets of revision to be filtered
491 491 # should be cleared when something might have changed the filter value:
492 492 # - new changesets,
493 493 # - phase change,
494 494 # - new obsolescence marker,
495 495 # - working directory parent change,
496 496 # - bookmark changes
497 497 self.filteredrevcache = {}
498 498
499 499 # post-dirstate-status hooks
500 500 self._postdsstatus = []
501 501
502 502 # Cache of types representing filtered repos.
503 503 self._filteredrepotypes = weakref.WeakKeyDictionary()
504 504
505 505 # generic mapping between names and nodes
506 506 self.names = namespaces.namespaces()
507 507
508 508 # Key to signature value.
509 509 self._sparsesignaturecache = {}
510 510 # Signature to cached matcher instance.
511 511 self._sparsematchercache = {}
512 512
513 513 def _getvfsward(self, origfunc):
514 514 """build a ward for self.vfs"""
515 515 rref = weakref.ref(self)
516 516 def checkvfs(path, mode=None):
517 517 ret = origfunc(path, mode=mode)
518 518 repo = rref()
519 519 if (repo is None
520 520 or not util.safehasattr(repo, '_wlockref')
521 521 or not util.safehasattr(repo, '_lockref')):
522 522 return
523 523 if mode in (None, 'r', 'rb'):
524 524 return
525 525 if path.startswith(repo.path):
526 526 # truncate name relative to the repository (.hg)
527 527 path = path[len(repo.path) + 1:]
528 528 if path.startswith('cache/'):
529 529 msg = 'accessing cache with vfs instead of cachevfs: "%s"'
530 530 repo.ui.develwarn(msg % path, stacklevel=2, config="cache-vfs")
531 531 if path.startswith('journal.'):
532 532 # journal is covered by 'lock'
533 533 if repo._currentlock(repo._lockref) is None:
534 534 repo.ui.develwarn('write with no lock: "%s"' % path,
535 535 stacklevel=2, config='check-locks')
536 536 elif repo._currentlock(repo._wlockref) is None:
537 537 # rest of vfs files are covered by 'wlock'
538 538 #
539 539 # exclude special files
540 540 for prefix in self._wlockfreeprefix:
541 541 if path.startswith(prefix):
542 542 return
543 543 repo.ui.develwarn('write with no wlock: "%s"' % path,
544 544 stacklevel=2, config='check-locks')
545 545 return ret
546 546 return checkvfs
547 547
548 548 def _getsvfsward(self, origfunc):
549 549 """build a ward for self.svfs"""
550 550 rref = weakref.ref(self)
551 551 def checksvfs(path, mode=None):
552 552 ret = origfunc(path, mode=mode)
553 553 repo = rref()
554 554 if repo is None or not util.safehasattr(repo, '_lockref'):
555 555 return
556 556 if mode in (None, 'r', 'rb'):
557 557 return
558 558 if path.startswith(repo.sharedpath):
559 559 # truncate name relative to the repository (.hg)
560 560 path = path[len(repo.sharedpath) + 1:]
561 561 if repo._currentlock(repo._lockref) is None:
562 562 repo.ui.develwarn('write with no lock: "%s"' % path,
563 563 stacklevel=3)
564 564 return ret
565 565 return checksvfs
566 566
567 567 def close(self):
568 568 self._writecaches()
569 569
570 570 def _loadextensions(self):
571 571 extensions.loadall(self.ui)
572 572
573 573 def _writecaches(self):
574 574 if self._revbranchcache:
575 575 self._revbranchcache.write()
576 576
577 577 def _restrictcapabilities(self, caps):
578 578 if self.ui.configbool('experimental', 'bundle2-advertise'):
579 579 caps = set(caps)
580 580 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self))
581 581 caps.add('bundle2=' + urlreq.quote(capsblob))
582 582 return caps
583 583
584 584 def _applyopenerreqs(self):
585 585 self.svfs.options = dict((r, 1) for r in self.requirements
586 586 if r in self.openerreqs)
587 587 # experimental config: format.chunkcachesize
588 588 chunkcachesize = self.ui.configint('format', 'chunkcachesize')
589 589 if chunkcachesize is not None:
590 590 self.svfs.options['chunkcachesize'] = chunkcachesize
591 591 # experimental config: format.maxchainlen
592 592 maxchainlen = self.ui.configint('format', 'maxchainlen')
593 593 if maxchainlen is not None:
594 594 self.svfs.options['maxchainlen'] = maxchainlen
595 595 # experimental config: format.manifestcachesize
596 596 manifestcachesize = self.ui.configint('format', 'manifestcachesize')
597 597 if manifestcachesize is not None:
598 598 self.svfs.options['manifestcachesize'] = manifestcachesize
599 599 # experimental config: format.aggressivemergedeltas
600 600 aggressivemergedeltas = self.ui.configbool('format',
601 601 'aggressivemergedeltas')
602 602 self.svfs.options['aggressivemergedeltas'] = aggressivemergedeltas
603 603 self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui)
604 604 chainspan = self.ui.configbytes('experimental', 'maxdeltachainspan')
605 605 if 0 <= chainspan:
606 606 self.svfs.options['maxdeltachainspan'] = chainspan
607 607 mmapindexthreshold = self.ui.configbytes('experimental',
608 608 'mmapindexthreshold')
609 609 if mmapindexthreshold is not None:
610 610 self.svfs.options['mmapindexthreshold'] = mmapindexthreshold
611 611
612 612 for r in self.requirements:
613 613 if r.startswith('exp-compression-'):
614 614 self.svfs.options['compengine'] = r[len('exp-compression-'):]
615 615
616 616 # TODO move "revlogv2" to openerreqs once finalized.
617 617 if REVLOGV2_REQUIREMENT in self.requirements:
618 618 self.svfs.options['revlogv2'] = True
619 619
620 620 def _writerequirements(self):
621 621 scmutil.writerequires(self.vfs, self.requirements)
622 622
623 623 def _checknested(self, path):
624 624 """Determine if path is a legal nested repository."""
625 625 if not path.startswith(self.root):
626 626 return False
627 627 subpath = path[len(self.root) + 1:]
628 628 normsubpath = util.pconvert(subpath)
629 629
630 630 # XXX: Checking against the current working copy is wrong in
631 631 # the sense that it can reject things like
632 632 #
633 633 # $ hg cat -r 10 sub/x.txt
634 634 #
635 635 # if sub/ is no longer a subrepository in the working copy
636 636 # parent revision.
637 637 #
638 638 # However, it can of course also allow things that would have
639 639 # been rejected before, such as the above cat command if sub/
640 640 # is a subrepository now, but was a normal directory before.
641 641 # The old path auditor would have rejected by mistake since it
642 642 # panics when it sees sub/.hg/.
643 643 #
644 644 # All in all, checking against the working copy seems sensible
645 645 # since we want to prevent access to nested repositories on
646 646 # the filesystem *now*.
647 647 ctx = self[None]
648 648 parts = util.splitpath(subpath)
649 649 while parts:
650 650 prefix = '/'.join(parts)
651 651 if prefix in ctx.substate:
652 652 if prefix == normsubpath:
653 653 return True
654 654 else:
655 655 sub = ctx.sub(prefix)
656 656 return sub.checknested(subpath[len(prefix) + 1:])
657 657 else:
658 658 parts.pop()
659 659 return False
660 660
661 661 def peer(self):
662 662 return localpeer(self) # not cached to avoid reference cycle
663 663
664 664 def unfiltered(self):
665 665 """Return unfiltered version of the repository
666 666
667 667 Intended to be overwritten by filtered repo."""
668 668 return self
669 669
670 670 def filtered(self, name):
671 671 """Return a filtered version of a repository"""
672 672 # Python <3.4 easily leaks types via __mro__. See
673 673 # https://bugs.python.org/issue17950. We cache dynamically
674 674 # created types so this method doesn't leak on every
675 675 # invocation.
676 676
677 677 key = self.unfiltered().__class__
678 678 if key not in self._filteredrepotypes:
679 679 # Build a new type with the repoview mixin and the base
680 680 # class of this repo. Give it a name containing the
681 681 # filter name to aid debugging.
682 682 bases = (repoview.repoview, key)
683 683 cls = type(r'%sfilteredrepo' % name, bases, {})
684 684 self._filteredrepotypes[key] = cls
685 685
686 686 return self._filteredrepotypes[key](self, name)
687 687
688 688 @repofilecache('bookmarks', 'bookmarks.current')
689 689 def _bookmarks(self):
690 690 return bookmarks.bmstore(self)
691 691
692 692 @property
693 693 def _activebookmark(self):
694 694 return self._bookmarks.active
695 695
696 696 # _phaserevs and _phasesets depend on changelog. what we need is to
697 697 # call _phasecache.invalidate() if '00changelog.i' was changed, but it
698 698 # can't be easily expressed in filecache mechanism.
699 699 @storecache('phaseroots', '00changelog.i')
700 700 def _phasecache(self):
701 701 return phases.phasecache(self, self._phasedefaults)
702 702
703 703 @storecache('obsstore')
704 704 def obsstore(self):
705 705 return obsolete.makestore(self.ui, self)
706 706
707 707 @storecache('00changelog.i')
708 708 def changelog(self):
709 709 return changelog.changelog(self.svfs,
710 710 trypending=txnutil.mayhavepending(self.root))
711 711
712 712 def _constructmanifest(self):
713 713 # This is a temporary function while we migrate from manifest to
714 714 # manifestlog. It allows bundlerepo and unionrepo to intercept the
715 715 # manifest creation.
716 716 return manifest.manifestrevlog(self.svfs)
717 717
718 718 @storecache('00manifest.i')
719 719 def manifestlog(self):
720 720 return manifest.manifestlog(self.svfs, self)
721 721
722 722 @repofilecache('dirstate')
723 723 def dirstate(self):
724 724 sparsematchfn = lambda: sparse.matcher(self)
725 725
726 726 return dirstate.dirstate(self.vfs, self.ui, self.root,
727 727 self._dirstatevalidate, sparsematchfn)
728 728
729 729 def _dirstatevalidate(self, node):
730 730 try:
731 731 self.changelog.rev(node)
732 732 return node
733 733 except error.LookupError:
734 734 if not self._dirstatevalidatewarned:
735 735 self._dirstatevalidatewarned = True
736 736 self.ui.warn(_("warning: ignoring unknown"
737 737 " working parent %s!\n") % short(node))
738 738 return nullid
739 739
740 740 def __getitem__(self, changeid):
741 741 if changeid is None:
742 742 return context.workingctx(self)
743 743 if isinstance(changeid, slice):
744 744 # wdirrev isn't contiguous so the slice shouldn't include it
745 745 return [context.changectx(self, i)
746 746 for i in xrange(*changeid.indices(len(self)))
747 747 if i not in self.changelog.filteredrevs]
748 748 try:
749 749 return context.changectx(self, changeid)
750 750 except error.WdirUnsupported:
751 751 return context.workingctx(self)
752 752
753 753 def __contains__(self, changeid):
754 754 """True if the given changeid exists
755 755
756 756 error.LookupError is raised if an ambiguous node specified.
757 757 """
758 758 try:
759 759 self[changeid]
760 760 return True
761 761 except error.RepoLookupError:
762 762 return False
763 763
764 764 def __nonzero__(self):
765 765 return True
766 766
767 767 __bool__ = __nonzero__
768 768
769 769 def __len__(self):
770 770 return len(self.changelog)
771 771
772 772 def __iter__(self):
773 773 return iter(self.changelog)
774 774
775 775 def revs(self, expr, *args):
776 776 '''Find revisions matching a revset.
777 777
778 778 The revset is specified as a string ``expr`` that may contain
779 779 %-formatting to escape certain types. See ``revsetlang.formatspec``.
780 780
781 781 Revset aliases from the configuration are not expanded. To expand
782 782 user aliases, consider calling ``scmutil.revrange()`` or
783 783 ``repo.anyrevs([expr], user=True)``.
784 784
785 785 Returns a revset.abstractsmartset, which is a list-like interface
786 786 that contains integer revisions.
787 787 '''
788 788 expr = revsetlang.formatspec(expr, *args)
789 789 m = revset.match(None, expr)
790 790 return m(self)
791 791
792 792 def set(self, expr, *args):
793 793 '''Find revisions matching a revset and emit changectx instances.
794 794
795 795 This is a convenience wrapper around ``revs()`` that iterates the
796 796 result and is a generator of changectx instances.
797 797
798 798 Revset aliases from the configuration are not expanded. To expand
799 799 user aliases, consider calling ``scmutil.revrange()``.
800 800 '''
801 801 for r in self.revs(expr, *args):
802 802 yield self[r]
803 803
804 804 def anyrevs(self, specs, user=False, localalias=None):
805 805 '''Find revisions matching one of the given revsets.
806 806
807 807 Revset aliases from the configuration are not expanded by default. To
808 808 expand user aliases, specify ``user=True``. To provide some local
809 809 definitions overriding user aliases, set ``localalias`` to
810 810 ``{name: definitionstring}``.
811 811 '''
812 812 if user:
813 813 m = revset.matchany(self.ui, specs, repo=self,
814 814 localalias=localalias)
815 815 else:
816 816 m = revset.matchany(None, specs, localalias=localalias)
817 817 return m(self)
818 818
819 819 def url(self):
820 820 return 'file:' + self.root
821 821
822 822 def hook(self, name, throw=False, **args):
823 823 """Call a hook, passing this repo instance.
824 824
825 825 This a convenience method to aid invoking hooks. Extensions likely
826 826 won't call this unless they have registered a custom hook or are
827 827 replacing code that is expected to call a hook.
828 828 """
829 829 return hook.hook(self.ui, self, name, throw, **args)
830 830
831 831 @filteredpropertycache
832 832 def _tagscache(self):
833 833 '''Returns a tagscache object that contains various tags related
834 834 caches.'''
835 835
836 836 # This simplifies its cache management by having one decorated
837 837 # function (this one) and the rest simply fetch things from it.
838 838 class tagscache(object):
839 839 def __init__(self):
840 840 # These two define the set of tags for this repository. tags
841 841 # maps tag name to node; tagtypes maps tag name to 'global' or
842 842 # 'local'. (Global tags are defined by .hgtags across all
843 843 # heads, and local tags are defined in .hg/localtags.)
844 844 # They constitute the in-memory cache of tags.
845 845 self.tags = self.tagtypes = None
846 846
847 847 self.nodetagscache = self.tagslist = None
848 848
849 849 cache = tagscache()
850 850 cache.tags, cache.tagtypes = self._findtags()
851 851
852 852 return cache
853 853
854 854 def tags(self):
855 855 '''return a mapping of tag to node'''
856 856 t = {}
857 857 if self.changelog.filteredrevs:
858 858 tags, tt = self._findtags()
859 859 else:
860 860 tags = self._tagscache.tags
861 861 for k, v in tags.iteritems():
862 862 try:
863 863 # ignore tags to unknown nodes
864 864 self.changelog.rev(v)
865 865 t[k] = v
866 866 except (error.LookupError, ValueError):
867 867 pass
868 868 return t
869 869
870 870 def _findtags(self):
871 871 '''Do the hard work of finding tags. Return a pair of dicts
872 872 (tags, tagtypes) where tags maps tag name to node, and tagtypes
873 873 maps tag name to a string like \'global\' or \'local\'.
874 874 Subclasses or extensions are free to add their own tags, but
875 875 should be aware that the returned dicts will be retained for the
876 876 duration of the localrepo object.'''
877 877
878 878 # XXX what tagtype should subclasses/extensions use? Currently
879 879 # mq and bookmarks add tags, but do not set the tagtype at all.
880 880 # Should each extension invent its own tag type? Should there
881 881 # be one tagtype for all such "virtual" tags? Or is the status
882 882 # quo fine?
883 883
884 884
885 885 # map tag name to (node, hist)
886 886 alltags = tagsmod.findglobaltags(self.ui, self)
887 887 # map tag name to tag type
888 888 tagtypes = dict((tag, 'global') for tag in alltags)
889 889
890 890 tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
891 891
892 892 # Build the return dicts. Have to re-encode tag names because
893 893 # the tags module always uses UTF-8 (in order not to lose info
894 894 # writing to the cache), but the rest of Mercurial wants them in
895 895 # local encoding.
896 896 tags = {}
897 897 for (name, (node, hist)) in alltags.iteritems():
898 898 if node != nullid:
899 899 tags[encoding.tolocal(name)] = node
900 900 tags['tip'] = self.changelog.tip()
901 901 tagtypes = dict([(encoding.tolocal(name), value)
902 902 for (name, value) in tagtypes.iteritems()])
903 903 return (tags, tagtypes)
904 904
905 905 def tagtype(self, tagname):
906 906 '''
907 907 return the type of the given tag. result can be:
908 908
909 909 'local' : a local tag
910 910 'global' : a global tag
911 911 None : tag does not exist
912 912 '''
913 913
914 914 return self._tagscache.tagtypes.get(tagname)
915 915
916 916 def tagslist(self):
917 917 '''return a list of tags ordered by revision'''
918 918 if not self._tagscache.tagslist:
919 919 l = []
920 920 for t, n in self.tags().iteritems():
921 921 l.append((self.changelog.rev(n), t, n))
922 922 self._tagscache.tagslist = [(t, n) for r, t, n in sorted(l)]
923 923
924 924 return self._tagscache.tagslist
925 925
926 926 def nodetags(self, node):
927 927 '''return the tags associated with a node'''
928 928 if not self._tagscache.nodetagscache:
929 929 nodetagscache = {}
930 930 for t, n in self._tagscache.tags.iteritems():
931 931 nodetagscache.setdefault(n, []).append(t)
932 932 for tags in nodetagscache.itervalues():
933 933 tags.sort()
934 934 self._tagscache.nodetagscache = nodetagscache
935 935 return self._tagscache.nodetagscache.get(node, [])
936 936
937 937 def nodebookmarks(self, node):
938 938 """return the list of bookmarks pointing to the specified node"""
939 939 marks = []
940 940 for bookmark, n in self._bookmarks.iteritems():
941 941 if n == node:
942 942 marks.append(bookmark)
943 943 return sorted(marks)
944 944
945 945 def branchmap(self):
946 946 '''returns a dictionary {branch: [branchheads]} with branchheads
947 947 ordered by increasing revision number'''
948 948 branchmap.updatecache(self)
949 949 return self._branchcaches[self.filtername]
950 950
951 951 @unfilteredmethod
952 952 def revbranchcache(self):
953 953 if not self._revbranchcache:
954 954 self._revbranchcache = branchmap.revbranchcache(self.unfiltered())
955 955 return self._revbranchcache
956 956
957 957 def branchtip(self, branch, ignoremissing=False):
958 958 '''return the tip node for a given branch
959 959
960 960 If ignoremissing is True, then this method will not raise an error.
961 961 This is helpful for callers that only expect None for a missing branch
962 962 (e.g. namespace).
963 963
964 964 '''
965 965 try:
966 966 return self.branchmap().branchtip(branch)
967 967 except KeyError:
968 968 if not ignoremissing:
969 969 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
970 970 else:
971 971 pass
972 972
973 973 def lookup(self, key):
974 974 return self[key].node()
975 975
976 976 def lookupbranch(self, key, remote=None):
977 977 repo = remote or self
978 978 if key in repo.branchmap():
979 979 return key
980 980
981 981 repo = (remote and remote.local()) and remote or self
982 982 return repo[key].branch()
983 983
984 984 def known(self, nodes):
985 985 cl = self.changelog
986 986 nm = cl.nodemap
987 987 filtered = cl.filteredrevs
988 988 result = []
989 989 for n in nodes:
990 990 r = nm.get(n)
991 991 resp = not (r is None or r in filtered)
992 992 result.append(resp)
993 993 return result
994 994
995 995 def local(self):
996 996 return self
997 997
998 998 def publishing(self):
999 999 # it's safe (and desirable) to trust the publish flag unconditionally
1000 1000 # so that we don't finalize changes shared between users via ssh or nfs
1001 1001 return self.ui.configbool('phases', 'publish', untrusted=True)
1002 1002
1003 1003 def cancopy(self):
1004 1004 # so statichttprepo's override of local() works
1005 1005 if not self.local():
1006 1006 return False
1007 1007 if not self.publishing():
1008 1008 return True
1009 1009 # if publishing we can't copy if there is filtered content
1010 1010 return not self.filtered('visible').changelog.filteredrevs
1011 1011
1012 1012 def shared(self):
1013 1013 '''the type of shared repository (None if not shared)'''
1014 1014 if self.sharedpath != self.path:
1015 1015 return 'store'
1016 1016 return None
1017 1017
1018 1018 def wjoin(self, f, *insidef):
1019 1019 return self.vfs.reljoin(self.root, f, *insidef)
1020 1020
1021 1021 def file(self, f):
1022 1022 if f[0] == '/':
1023 1023 f = f[1:]
1024 1024 return filelog.filelog(self.svfs, f)
1025 1025
1026 1026 def changectx(self, changeid):
1027 1027 return self[changeid]
1028 1028
1029 1029 def setparents(self, p1, p2=nullid):
1030 1030 with self.dirstate.parentchange():
1031 1031 copies = self.dirstate.setparents(p1, p2)
1032 1032 pctx = self[p1]
1033 1033 if copies:
1034 1034 # Adjust copy records, the dirstate cannot do it, it
1035 1035 # requires access to parents manifests. Preserve them
1036 1036 # only for entries added to first parent.
1037 1037 for f in copies:
1038 1038 if f not in pctx and copies[f] in pctx:
1039 1039 self.dirstate.copy(copies[f], f)
1040 1040 if p2 == nullid:
1041 1041 for f, s in sorted(self.dirstate.copies().items()):
1042 1042 if f not in pctx and s not in pctx:
1043 1043 self.dirstate.copy(None, f)
1044 1044
1045 1045 def filectx(self, path, changeid=None, fileid=None):
1046 1046 """changeid can be a changeset revision, node, or tag.
1047 1047 fileid can be a file revision or node."""
1048 1048 return context.filectx(self, path, changeid, fileid)
1049 1049
1050 1050 def getcwd(self):
1051 1051 return self.dirstate.getcwd()
1052 1052
1053 1053 def pathto(self, f, cwd=None):
1054 1054 return self.dirstate.pathto(f, cwd)
1055 1055
1056 1056 def _loadfilter(self, filter):
1057 1057 if filter not in self.filterpats:
1058 1058 l = []
1059 1059 for pat, cmd in self.ui.configitems(filter):
1060 1060 if cmd == '!':
1061 1061 continue
1062 1062 mf = matchmod.match(self.root, '', [pat])
1063 1063 fn = None
1064 1064 params = cmd
1065 1065 for name, filterfn in self._datafilters.iteritems():
1066 1066 if cmd.startswith(name):
1067 1067 fn = filterfn
1068 1068 params = cmd[len(name):].lstrip()
1069 1069 break
1070 1070 if not fn:
1071 1071 fn = lambda s, c, **kwargs: util.filter(s, c)
1072 1072 # Wrap old filters not supporting keyword arguments
1073 1073 if not inspect.getargspec(fn)[2]:
1074 1074 oldfn = fn
1075 1075 fn = lambda s, c, **kwargs: oldfn(s, c)
1076 1076 l.append((mf, fn, params))
1077 1077 self.filterpats[filter] = l
1078 1078 return self.filterpats[filter]
1079 1079
1080 1080 def _filter(self, filterpats, filename, data):
1081 1081 for mf, fn, cmd in filterpats:
1082 1082 if mf(filename):
1083 1083 self.ui.debug("filtering %s through %s\n" % (filename, cmd))
1084 1084 data = fn(data, cmd, ui=self.ui, repo=self, filename=filename)
1085 1085 break
1086 1086
1087 1087 return data
1088 1088
1089 1089 @unfilteredpropertycache
1090 1090 def _encodefilterpats(self):
1091 1091 return self._loadfilter('encode')
1092 1092
1093 1093 @unfilteredpropertycache
1094 1094 def _decodefilterpats(self):
1095 1095 return self._loadfilter('decode')
1096 1096
1097 1097 def adddatafilter(self, name, filter):
1098 1098 self._datafilters[name] = filter
1099 1099
1100 1100 def wread(self, filename):
1101 1101 if self.wvfs.islink(filename):
1102 1102 data = self.wvfs.readlink(filename)
1103 1103 else:
1104 1104 data = self.wvfs.read(filename)
1105 1105 return self._filter(self._encodefilterpats, filename, data)
1106 1106
1107 1107 def wwrite(self, filename, data, flags, backgroundclose=False):
1108 1108 """write ``data`` into ``filename`` in the working directory
1109 1109
1110 1110 This returns length of written (maybe decoded) data.
1111 1111 """
1112 1112 data = self._filter(self._decodefilterpats, filename, data)
1113 1113 if 'l' in flags:
1114 1114 self.wvfs.symlink(data, filename)
1115 1115 else:
1116 1116 self.wvfs.write(filename, data, backgroundclose=backgroundclose)
1117 1117 if 'x' in flags:
1118 1118 self.wvfs.setflags(filename, False, True)
1119 1119 return len(data)
1120 1120
1121 1121 def wwritedata(self, filename, data):
1122 1122 return self._filter(self._decodefilterpats, filename, data)
1123 1123
1124 1124 def currenttransaction(self):
1125 1125 """return the current transaction or None if non exists"""
1126 1126 if self._transref:
1127 1127 tr = self._transref()
1128 1128 else:
1129 1129 tr = None
1130 1130
1131 1131 if tr and tr.running():
1132 1132 return tr
1133 1133 return None
1134 1134
1135 1135 def transaction(self, desc, report=None):
1136 1136 if (self.ui.configbool('devel', 'all-warnings')
1137 1137 or self.ui.configbool('devel', 'check-locks')):
1138 1138 if self._currentlock(self._lockref) is None:
1139 1139 raise error.ProgrammingError('transaction requires locking')
1140 1140 tr = self.currenttransaction()
1141 1141 if tr is not None:
1142 1142 scmutil.registersummarycallback(self, tr, desc)
1143 1143 return tr.nest()
1144 1144
1145 1145 # abort here if the journal already exists
1146 1146 if self.svfs.exists("journal"):
1147 1147 raise error.RepoError(
1148 1148 _("abandoned transaction found"),
1149 1149 hint=_("run 'hg recover' to clean up transaction"))
1150 1150
1151 1151 idbase = "%.40f#%f" % (random.random(), time.time())
1152 1152 ha = hex(hashlib.sha1(idbase).digest())
1153 1153 txnid = 'TXN:' + ha
1154 1154 self.hook('pretxnopen', throw=True, txnname=desc, txnid=txnid)
1155 1155
1156 1156 self._writejournal(desc)
1157 1157 renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
1158 1158 if report:
1159 1159 rp = report
1160 1160 else:
1161 1161 rp = self.ui.warn
1162 1162 vfsmap = {'plain': self.vfs} # root of .hg/
1163 1163 # we must avoid cyclic reference between repo and transaction.
1164 1164 reporef = weakref.ref(self)
1165 1165 # Code to track tag movement
1166 1166 #
1167 1167 # Since tags are all handled as file content, it is actually quite hard
1168 1168 # to track these movement from a code perspective. So we fallback to a
1169 1169 # tracking at the repository level. One could envision to track changes
1170 1170 # to the '.hgtags' file through changegroup apply but that fails to
1171 1171 # cope with case where transaction expose new heads without changegroup
1172 1172 # being involved (eg: phase movement).
1173 1173 #
1174 1174 # For now, We gate the feature behind a flag since this likely comes
1175 1175 # with performance impacts. The current code run more often than needed
1176 1176 # and do not use caches as much as it could. The current focus is on
1177 1177 # the behavior of the feature so we disable it by default. The flag
1178 1178 # will be removed when we are happy with the performance impact.
1179 1179 #
1180 1180 # Once this feature is no longer experimental move the following
1181 1181 # documentation to the appropriate help section:
1182 1182 #
1183 1183 # The ``HG_TAG_MOVED`` variable will be set if the transaction touched
1184 1184 # tags (new or changed or deleted tags). In addition the details of
1185 1185 # these changes are made available in a file at:
1186 1186 # ``REPOROOT/.hg/changes/tags.changes``.
1187 1187 # Make sure you check for HG_TAG_MOVED before reading that file as it
1188 1188 # might exist from a previous transaction even if no tag were touched
1189 1189 # in this one. Changes are recorded in a line base format::
1190 1190 #
1191 1191 # <action> <hex-node> <tag-name>\n
1192 1192 #
1193 1193 # Actions are defined as follow:
1194 1194 # "-R": tag is removed,
1195 1195 # "+A": tag is added,
1196 1196 # "-M": tag is moved (old value),
1197 1197 # "+M": tag is moved (new value),
1198 1198 tracktags = lambda x: None
1199 1199 # experimental config: experimental.hook-track-tags
1200 1200 shouldtracktags = self.ui.configbool('experimental', 'hook-track-tags')
1201 1201 if desc != 'strip' and shouldtracktags:
1202 1202 oldheads = self.changelog.headrevs()
1203 1203 def tracktags(tr2):
1204 1204 repo = reporef()
1205 1205 oldfnodes = tagsmod.fnoderevs(repo.ui, repo, oldheads)
1206 1206 newheads = repo.changelog.headrevs()
1207 1207 newfnodes = tagsmod.fnoderevs(repo.ui, repo, newheads)
1208 1208 # notes: we compare lists here.
1209 1209 # As we do it only once buiding set would not be cheaper
1210 1210 changes = tagsmod.difftags(repo.ui, repo, oldfnodes, newfnodes)
1211 1211 if changes:
1212 1212 tr2.hookargs['tag_moved'] = '1'
1213 1213 with repo.vfs('changes/tags.changes', 'w',
1214 1214 atomictemp=True) as changesfile:
1215 1215 # note: we do not register the file to the transaction
1216 1216 # because we needs it to still exist on the transaction
1217 1217 # is close (for txnclose hooks)
1218 1218 tagsmod.writediff(changesfile, changes)
1219 1219 def validate(tr2):
1220 1220 """will run pre-closing hooks"""
1221 1221 # XXX the transaction API is a bit lacking here so we take a hacky
1222 1222 # path for now
1223 1223 #
1224 1224 # We cannot add this as a "pending" hooks since the 'tr.hookargs'
1225 1225 # dict is copied before these run. In addition we needs the data
1226 1226 # available to in memory hooks too.
1227 1227 #
1228 1228 # Moreover, we also need to make sure this runs before txnclose
1229 1229 # hooks and there is no "pending" mechanism that would execute
1230 1230 # logic only if hooks are about to run.
1231 1231 #
1232 1232 # Fixing this limitation of the transaction is also needed to track
1233 1233 # other families of changes (bookmarks, phases, obsolescence).
1234 1234 #
1235 1235 # This will have to be fixed before we remove the experimental
1236 1236 # gating.
1237 1237 tracktags(tr2)
1238 1238 reporef().hook('pretxnclose', throw=True,
1239 1239 txnname=desc, **pycompat.strkwargs(tr.hookargs))
1240 1240 def releasefn(tr, success):
1241 1241 repo = reporef()
1242 1242 if success:
1243 1243 # this should be explicitly invoked here, because
1244 1244 # in-memory changes aren't written out at closing
1245 1245 # transaction, if tr.addfilegenerator (via
1246 1246 # dirstate.write or so) isn't invoked while
1247 1247 # transaction running
1248 1248 repo.dirstate.write(None)
1249 1249 else:
1250 1250 # discard all changes (including ones already written
1251 1251 # out) in this transaction
1252 1252 repo.dirstate.restorebackup(None, 'journal.dirstate')
1253 1253
1254 1254 repo.invalidate(clearfilecache=True)
1255 1255
1256 1256 tr = transaction.transaction(rp, self.svfs, vfsmap,
1257 1257 "journal",
1258 1258 "undo",
1259 1259 aftertrans(renames),
1260 1260 self.store.createmode,
1261 1261 validator=validate,
1262 1262 releasefn=releasefn,
1263 1263 checkambigfiles=_cachedfiles)
1264 1264 tr.changes['revs'] = set()
1265 1265 tr.changes['obsmarkers'] = set()
1266 1266 tr.changes['phases'] = {}
1267 1267 tr.changes['bookmarks'] = {}
1268 1268
1269 1269 tr.hookargs['txnid'] = txnid
1270 1270 # note: writing the fncache only during finalize mean that the file is
1271 1271 # outdated when running hooks. As fncache is used for streaming clone,
1272 1272 # this is not expected to break anything that happen during the hooks.
1273 1273 tr.addfinalize('flush-fncache', self.store.write)
1274 1274 def txnclosehook(tr2):
1275 1275 """To be run if transaction is successful, will schedule a hook run
1276 1276 """
1277 1277 # Don't reference tr2 in hook() so we don't hold a reference.
1278 1278 # This reduces memory consumption when there are multiple
1279 1279 # transactions per lock. This can likely go away if issue5045
1280 1280 # fixes the function accumulation.
1281 1281 hookargs = tr2.hookargs
1282 1282
1283 def hook():
1284 reporef().hook('txnclose', throw=False, txnname=desc,
1285 **pycompat.strkwargs(hookargs))
1286 reporef()._afterlock(hook)
1283 def hookfunc():
1284 repo = reporef()
1285 if hook.hashook(repo.ui, 'txnclose-bookmark'):
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 1296 tr.addfinalize('txnclose-hook', txnclosehook)
1288 1297 tr.addpostclose('warms-cache', self._buildcacheupdater(tr))
1289 1298 def txnaborthook(tr2):
1290 1299 """To be run if transaction is aborted
1291 1300 """
1292 1301 reporef().hook('txnabort', throw=False, txnname=desc,
1293 1302 **tr2.hookargs)
1294 1303 tr.addabort('txnabort-hook', txnaborthook)
1295 1304 # avoid eager cache invalidation. in-memory data should be identical
1296 1305 # to stored data if transaction has no error.
1297 1306 tr.addpostclose('refresh-filecachestats', self._refreshfilecachestats)
1298 1307 self._transref = weakref.ref(tr)
1299 1308 scmutil.registersummarycallback(self, tr, desc)
1300 1309 return tr
1301 1310
1302 1311 def _journalfiles(self):
1303 1312 return ((self.svfs, 'journal'),
1304 1313 (self.vfs, 'journal.dirstate'),
1305 1314 (self.vfs, 'journal.branch'),
1306 1315 (self.vfs, 'journal.desc'),
1307 1316 (self.vfs, 'journal.bookmarks'),
1308 1317 (self.svfs, 'journal.phaseroots'))
1309 1318
1310 1319 def undofiles(self):
1311 1320 return [(vfs, undoname(x)) for vfs, x in self._journalfiles()]
1312 1321
1313 1322 @unfilteredmethod
1314 1323 def _writejournal(self, desc):
1315 1324 self.dirstate.savebackup(None, 'journal.dirstate')
1316 1325 self.vfs.write("journal.branch",
1317 1326 encoding.fromlocal(self.dirstate.branch()))
1318 1327 self.vfs.write("journal.desc",
1319 1328 "%d\n%s\n" % (len(self), desc))
1320 1329 self.vfs.write("journal.bookmarks",
1321 1330 self.vfs.tryread("bookmarks"))
1322 1331 self.svfs.write("journal.phaseroots",
1323 1332 self.svfs.tryread("phaseroots"))
1324 1333
1325 1334 def recover(self):
1326 1335 with self.lock():
1327 1336 if self.svfs.exists("journal"):
1328 1337 self.ui.status(_("rolling back interrupted transaction\n"))
1329 1338 vfsmap = {'': self.svfs,
1330 1339 'plain': self.vfs,}
1331 1340 transaction.rollback(self.svfs, vfsmap, "journal",
1332 1341 self.ui.warn,
1333 1342 checkambigfiles=_cachedfiles)
1334 1343 self.invalidate()
1335 1344 return True
1336 1345 else:
1337 1346 self.ui.warn(_("no interrupted transaction available\n"))
1338 1347 return False
1339 1348
1340 1349 def rollback(self, dryrun=False, force=False):
1341 1350 wlock = lock = dsguard = None
1342 1351 try:
1343 1352 wlock = self.wlock()
1344 1353 lock = self.lock()
1345 1354 if self.svfs.exists("undo"):
1346 1355 dsguard = dirstateguard.dirstateguard(self, 'rollback')
1347 1356
1348 1357 return self._rollback(dryrun, force, dsguard)
1349 1358 else:
1350 1359 self.ui.warn(_("no rollback information available\n"))
1351 1360 return 1
1352 1361 finally:
1353 1362 release(dsguard, lock, wlock)
1354 1363
1355 1364 @unfilteredmethod # Until we get smarter cache management
1356 1365 def _rollback(self, dryrun, force, dsguard):
1357 1366 ui = self.ui
1358 1367 try:
1359 1368 args = self.vfs.read('undo.desc').splitlines()
1360 1369 (oldlen, desc, detail) = (int(args[0]), args[1], None)
1361 1370 if len(args) >= 3:
1362 1371 detail = args[2]
1363 1372 oldtip = oldlen - 1
1364 1373
1365 1374 if detail and ui.verbose:
1366 1375 msg = (_('repository tip rolled back to revision %d'
1367 1376 ' (undo %s: %s)\n')
1368 1377 % (oldtip, desc, detail))
1369 1378 else:
1370 1379 msg = (_('repository tip rolled back to revision %d'
1371 1380 ' (undo %s)\n')
1372 1381 % (oldtip, desc))
1373 1382 except IOError:
1374 1383 msg = _('rolling back unknown transaction\n')
1375 1384 desc = None
1376 1385
1377 1386 if not force and self['.'] != self['tip'] and desc == 'commit':
1378 1387 raise error.Abort(
1379 1388 _('rollback of last commit while not checked out '
1380 1389 'may lose data'), hint=_('use -f to force'))
1381 1390
1382 1391 ui.status(msg)
1383 1392 if dryrun:
1384 1393 return 0
1385 1394
1386 1395 parents = self.dirstate.parents()
1387 1396 self.destroying()
1388 1397 vfsmap = {'plain': self.vfs, '': self.svfs}
1389 1398 transaction.rollback(self.svfs, vfsmap, 'undo', ui.warn,
1390 1399 checkambigfiles=_cachedfiles)
1391 1400 if self.vfs.exists('undo.bookmarks'):
1392 1401 self.vfs.rename('undo.bookmarks', 'bookmarks', checkambig=True)
1393 1402 if self.svfs.exists('undo.phaseroots'):
1394 1403 self.svfs.rename('undo.phaseroots', 'phaseroots', checkambig=True)
1395 1404 self.invalidate()
1396 1405
1397 1406 parentgone = (parents[0] not in self.changelog.nodemap or
1398 1407 parents[1] not in self.changelog.nodemap)
1399 1408 if parentgone:
1400 1409 # prevent dirstateguard from overwriting already restored one
1401 1410 dsguard.close()
1402 1411
1403 1412 self.dirstate.restorebackup(None, 'undo.dirstate')
1404 1413 try:
1405 1414 branch = self.vfs.read('undo.branch')
1406 1415 self.dirstate.setbranch(encoding.tolocal(branch))
1407 1416 except IOError:
1408 1417 ui.warn(_('named branch could not be reset: '
1409 1418 'current branch is still \'%s\'\n')
1410 1419 % self.dirstate.branch())
1411 1420
1412 1421 parents = tuple([p.rev() for p in self[None].parents()])
1413 1422 if len(parents) > 1:
1414 1423 ui.status(_('working directory now based on '
1415 1424 'revisions %d and %d\n') % parents)
1416 1425 else:
1417 1426 ui.status(_('working directory now based on '
1418 1427 'revision %d\n') % parents)
1419 1428 mergemod.mergestate.clean(self, self['.'].node())
1420 1429
1421 1430 # TODO: if we know which new heads may result from this rollback, pass
1422 1431 # them to destroy(), which will prevent the branchhead cache from being
1423 1432 # invalidated.
1424 1433 self.destroyed()
1425 1434 return 0
1426 1435
1427 1436 def _buildcacheupdater(self, newtransaction):
1428 1437 """called during transaction to build the callback updating cache
1429 1438
1430 1439 Lives on the repository to help extension who might want to augment
1431 1440 this logic. For this purpose, the created transaction is passed to the
1432 1441 method.
1433 1442 """
1434 1443 # we must avoid cyclic reference between repo and transaction.
1435 1444 reporef = weakref.ref(self)
1436 1445 def updater(tr):
1437 1446 repo = reporef()
1438 1447 repo.updatecaches(tr)
1439 1448 return updater
1440 1449
1441 1450 @unfilteredmethod
1442 1451 def updatecaches(self, tr=None):
1443 1452 """warm appropriate caches
1444 1453
1445 1454 If this function is called after a transaction closed. The transaction
1446 1455 will be available in the 'tr' argument. This can be used to selectively
1447 1456 update caches relevant to the changes in that transaction.
1448 1457 """
1449 1458 if tr is not None and tr.hookargs.get('source') == 'strip':
1450 1459 # During strip, many caches are invalid but
1451 1460 # later call to `destroyed` will refresh them.
1452 1461 return
1453 1462
1454 1463 if tr is None or tr.changes['revs']:
1455 1464 # updating the unfiltered branchmap should refresh all the others,
1456 1465 self.ui.debug('updating the branch cache\n')
1457 1466 branchmap.updatecache(self.filtered('served'))
1458 1467
1459 1468 def invalidatecaches(self):
1460 1469
1461 1470 if '_tagscache' in vars(self):
1462 1471 # can't use delattr on proxy
1463 1472 del self.__dict__['_tagscache']
1464 1473
1465 1474 self.unfiltered()._branchcaches.clear()
1466 1475 self.invalidatevolatilesets()
1467 1476 self._sparsesignaturecache.clear()
1468 1477
1469 1478 def invalidatevolatilesets(self):
1470 1479 self.filteredrevcache.clear()
1471 1480 obsolete.clearobscaches(self)
1472 1481
1473 1482 def invalidatedirstate(self):
1474 1483 '''Invalidates the dirstate, causing the next call to dirstate
1475 1484 to check if it was modified since the last time it was read,
1476 1485 rereading it if it has.
1477 1486
1478 1487 This is different to dirstate.invalidate() that it doesn't always
1479 1488 rereads the dirstate. Use dirstate.invalidate() if you want to
1480 1489 explicitly read the dirstate again (i.e. restoring it to a previous
1481 1490 known good state).'''
1482 1491 if hasunfilteredcache(self, 'dirstate'):
1483 1492 for k in self.dirstate._filecache:
1484 1493 try:
1485 1494 delattr(self.dirstate, k)
1486 1495 except AttributeError:
1487 1496 pass
1488 1497 delattr(self.unfiltered(), 'dirstate')
1489 1498
1490 1499 def invalidate(self, clearfilecache=False):
1491 1500 '''Invalidates both store and non-store parts other than dirstate
1492 1501
1493 1502 If a transaction is running, invalidation of store is omitted,
1494 1503 because discarding in-memory changes might cause inconsistency
1495 1504 (e.g. incomplete fncache causes unintentional failure, but
1496 1505 redundant one doesn't).
1497 1506 '''
1498 1507 unfiltered = self.unfiltered() # all file caches are stored unfiltered
1499 1508 for k in list(self._filecache.keys()):
1500 1509 # dirstate is invalidated separately in invalidatedirstate()
1501 1510 if k == 'dirstate':
1502 1511 continue
1503 1512 if (k == 'changelog' and
1504 1513 self.currenttransaction() and
1505 1514 self.changelog._delayed):
1506 1515 # The changelog object may store unwritten revisions. We don't
1507 1516 # want to lose them.
1508 1517 # TODO: Solve the problem instead of working around it.
1509 1518 continue
1510 1519
1511 1520 if clearfilecache:
1512 1521 del self._filecache[k]
1513 1522 try:
1514 1523 delattr(unfiltered, k)
1515 1524 except AttributeError:
1516 1525 pass
1517 1526 self.invalidatecaches()
1518 1527 if not self.currenttransaction():
1519 1528 # TODO: Changing contents of store outside transaction
1520 1529 # causes inconsistency. We should make in-memory store
1521 1530 # changes detectable, and abort if changed.
1522 1531 self.store.invalidatecaches()
1523 1532
1524 1533 def invalidateall(self):
1525 1534 '''Fully invalidates both store and non-store parts, causing the
1526 1535 subsequent operation to reread any outside changes.'''
1527 1536 # extension should hook this to invalidate its caches
1528 1537 self.invalidate()
1529 1538 self.invalidatedirstate()
1530 1539
1531 1540 @unfilteredmethod
1532 1541 def _refreshfilecachestats(self, tr):
1533 1542 """Reload stats of cached files so that they are flagged as valid"""
1534 1543 for k, ce in self._filecache.items():
1535 1544 if k == 'dirstate' or k not in self.__dict__:
1536 1545 continue
1537 1546 ce.refresh()
1538 1547
1539 1548 def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc,
1540 1549 inheritchecker=None, parentenvvar=None):
1541 1550 parentlock = None
1542 1551 # the contents of parentenvvar are used by the underlying lock to
1543 1552 # determine whether it can be inherited
1544 1553 if parentenvvar is not None:
1545 1554 parentlock = encoding.environ.get(parentenvvar)
1546 1555 try:
1547 1556 l = lockmod.lock(vfs, lockname, 0, releasefn=releasefn,
1548 1557 acquirefn=acquirefn, desc=desc,
1549 1558 inheritchecker=inheritchecker,
1550 1559 parentlock=parentlock)
1551 1560 except error.LockHeld as inst:
1552 1561 if not wait:
1553 1562 raise
1554 1563 # show more details for new-style locks
1555 1564 if ':' in inst.locker:
1556 1565 host, pid = inst.locker.split(":", 1)
1557 1566 self.ui.warn(
1558 1567 _("waiting for lock on %s held by process %r "
1559 1568 "on host %r\n") % (desc, pid, host))
1560 1569 else:
1561 1570 self.ui.warn(_("waiting for lock on %s held by %r\n") %
1562 1571 (desc, inst.locker))
1563 1572 # default to 600 seconds timeout
1564 1573 l = lockmod.lock(vfs, lockname,
1565 1574 int(self.ui.config("ui", "timeout")),
1566 1575 releasefn=releasefn, acquirefn=acquirefn,
1567 1576 desc=desc)
1568 1577 self.ui.warn(_("got lock after %s seconds\n") % l.delay)
1569 1578 return l
1570 1579
1571 1580 def _afterlock(self, callback):
1572 1581 """add a callback to be run when the repository is fully unlocked
1573 1582
1574 1583 The callback will be executed when the outermost lock is released
1575 1584 (with wlock being higher level than 'lock')."""
1576 1585 for ref in (self._wlockref, self._lockref):
1577 1586 l = ref and ref()
1578 1587 if l and l.held:
1579 1588 l.postrelease.append(callback)
1580 1589 break
1581 1590 else: # no lock have been found.
1582 1591 callback()
1583 1592
1584 1593 def lock(self, wait=True):
1585 1594 '''Lock the repository store (.hg/store) and return a weak reference
1586 1595 to the lock. Use this before modifying the store (e.g. committing or
1587 1596 stripping). If you are opening a transaction, get a lock as well.)
1588 1597
1589 1598 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
1590 1599 'wlock' first to avoid a dead-lock hazard.'''
1591 1600 l = self._currentlock(self._lockref)
1592 1601 if l is not None:
1593 1602 l.lock()
1594 1603 return l
1595 1604
1596 1605 l = self._lock(self.svfs, "lock", wait, None,
1597 1606 self.invalidate, _('repository %s') % self.origroot)
1598 1607 self._lockref = weakref.ref(l)
1599 1608 return l
1600 1609
1601 1610 def _wlockchecktransaction(self):
1602 1611 if self.currenttransaction() is not None:
1603 1612 raise error.LockInheritanceContractViolation(
1604 1613 'wlock cannot be inherited in the middle of a transaction')
1605 1614
1606 1615 def wlock(self, wait=True):
1607 1616 '''Lock the non-store parts of the repository (everything under
1608 1617 .hg except .hg/store) and return a weak reference to the lock.
1609 1618
1610 1619 Use this before modifying files in .hg.
1611 1620
1612 1621 If both 'lock' and 'wlock' must be acquired, ensure you always acquires
1613 1622 'wlock' first to avoid a dead-lock hazard.'''
1614 1623 l = self._wlockref and self._wlockref()
1615 1624 if l is not None and l.held:
1616 1625 l.lock()
1617 1626 return l
1618 1627
1619 1628 # We do not need to check for non-waiting lock acquisition. Such
1620 1629 # acquisition would not cause dead-lock as they would just fail.
1621 1630 if wait and (self.ui.configbool('devel', 'all-warnings')
1622 1631 or self.ui.configbool('devel', 'check-locks')):
1623 1632 if self._currentlock(self._lockref) is not None:
1624 1633 self.ui.develwarn('"wlock" acquired after "lock"')
1625 1634
1626 1635 def unlock():
1627 1636 if self.dirstate.pendingparentchange():
1628 1637 self.dirstate.invalidate()
1629 1638 else:
1630 1639 self.dirstate.write(None)
1631 1640
1632 1641 self._filecache['dirstate'].refresh()
1633 1642
1634 1643 l = self._lock(self.vfs, "wlock", wait, unlock,
1635 1644 self.invalidatedirstate, _('working directory of %s') %
1636 1645 self.origroot,
1637 1646 inheritchecker=self._wlockchecktransaction,
1638 1647 parentenvvar='HG_WLOCK_LOCKER')
1639 1648 self._wlockref = weakref.ref(l)
1640 1649 return l
1641 1650
1642 1651 def _currentlock(self, lockref):
1643 1652 """Returns the lock if it's held, or None if it's not."""
1644 1653 if lockref is None:
1645 1654 return None
1646 1655 l = lockref()
1647 1656 if l is None or not l.held:
1648 1657 return None
1649 1658 return l
1650 1659
1651 1660 def currentwlock(self):
1652 1661 """Returns the wlock if it's held, or None if it's not."""
1653 1662 return self._currentlock(self._wlockref)
1654 1663
1655 1664 def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
1656 1665 """
1657 1666 commit an individual file as part of a larger transaction
1658 1667 """
1659 1668
1660 1669 fname = fctx.path()
1661 1670 fparent1 = manifest1.get(fname, nullid)
1662 1671 fparent2 = manifest2.get(fname, nullid)
1663 1672 if isinstance(fctx, context.filectx):
1664 1673 node = fctx.filenode()
1665 1674 if node in [fparent1, fparent2]:
1666 1675 self.ui.debug('reusing %s filelog entry\n' % fname)
1667 1676 if manifest1.flags(fname) != fctx.flags():
1668 1677 changelist.append(fname)
1669 1678 return node
1670 1679
1671 1680 flog = self.file(fname)
1672 1681 meta = {}
1673 1682 copy = fctx.renamed()
1674 1683 if copy and copy[0] != fname:
1675 1684 # Mark the new revision of this file as a copy of another
1676 1685 # file. This copy data will effectively act as a parent
1677 1686 # of this new revision. If this is a merge, the first
1678 1687 # parent will be the nullid (meaning "look up the copy data")
1679 1688 # and the second one will be the other parent. For example:
1680 1689 #
1681 1690 # 0 --- 1 --- 3 rev1 changes file foo
1682 1691 # \ / rev2 renames foo to bar and changes it
1683 1692 # \- 2 -/ rev3 should have bar with all changes and
1684 1693 # should record that bar descends from
1685 1694 # bar in rev2 and foo in rev1
1686 1695 #
1687 1696 # this allows this merge to succeed:
1688 1697 #
1689 1698 # 0 --- 1 --- 3 rev4 reverts the content change from rev2
1690 1699 # \ / merging rev3 and rev4 should use bar@rev2
1691 1700 # \- 2 --- 4 as the merge base
1692 1701 #
1693 1702
1694 1703 cfname = copy[0]
1695 1704 crev = manifest1.get(cfname)
1696 1705 newfparent = fparent2
1697 1706
1698 1707 if manifest2: # branch merge
1699 1708 if fparent2 == nullid or crev is None: # copied on remote side
1700 1709 if cfname in manifest2:
1701 1710 crev = manifest2[cfname]
1702 1711 newfparent = fparent1
1703 1712
1704 1713 # Here, we used to search backwards through history to try to find
1705 1714 # where the file copy came from if the source of a copy was not in
1706 1715 # the parent directory. However, this doesn't actually make sense to
1707 1716 # do (what does a copy from something not in your working copy even
1708 1717 # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
1709 1718 # the user that copy information was dropped, so if they didn't
1710 1719 # expect this outcome it can be fixed, but this is the correct
1711 1720 # behavior in this circumstance.
1712 1721
1713 1722 if crev:
1714 1723 self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
1715 1724 meta["copy"] = cfname
1716 1725 meta["copyrev"] = hex(crev)
1717 1726 fparent1, fparent2 = nullid, newfparent
1718 1727 else:
1719 1728 self.ui.warn(_("warning: can't find ancestor for '%s' "
1720 1729 "copied from '%s'!\n") % (fname, cfname))
1721 1730
1722 1731 elif fparent1 == nullid:
1723 1732 fparent1, fparent2 = fparent2, nullid
1724 1733 elif fparent2 != nullid:
1725 1734 # is one parent an ancestor of the other?
1726 1735 fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
1727 1736 if fparent1 in fparentancestors:
1728 1737 fparent1, fparent2 = fparent2, nullid
1729 1738 elif fparent2 in fparentancestors:
1730 1739 fparent2 = nullid
1731 1740
1732 1741 # is the file changed?
1733 1742 text = fctx.data()
1734 1743 if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
1735 1744 changelist.append(fname)
1736 1745 return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
1737 1746 # are just the flags changed during merge?
1738 1747 elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
1739 1748 changelist.append(fname)
1740 1749
1741 1750 return fparent1
1742 1751
1743 1752 def checkcommitpatterns(self, wctx, vdirs, match, status, fail):
1744 1753 """check for commit arguments that aren't committable"""
1745 1754 if match.isexact() or match.prefix():
1746 1755 matched = set(status.modified + status.added + status.removed)
1747 1756
1748 1757 for f in match.files():
1749 1758 f = self.dirstate.normalize(f)
1750 1759 if f == '.' or f in matched or f in wctx.substate:
1751 1760 continue
1752 1761 if f in status.deleted:
1753 1762 fail(f, _('file not found!'))
1754 1763 if f in vdirs: # visited directory
1755 1764 d = f + '/'
1756 1765 for mf in matched:
1757 1766 if mf.startswith(d):
1758 1767 break
1759 1768 else:
1760 1769 fail(f, _("no match under directory!"))
1761 1770 elif f not in self.dirstate:
1762 1771 fail(f, _("file not tracked!"))
1763 1772
1764 1773 @unfilteredmethod
1765 1774 def commit(self, text="", user=None, date=None, match=None, force=False,
1766 1775 editor=False, extra=None):
1767 1776 """Add a new revision to current repository.
1768 1777
1769 1778 Revision information is gathered from the working directory,
1770 1779 match can be used to filter the committed files. If editor is
1771 1780 supplied, it is called to get a commit message.
1772 1781 """
1773 1782 if extra is None:
1774 1783 extra = {}
1775 1784
1776 1785 def fail(f, msg):
1777 1786 raise error.Abort('%s: %s' % (f, msg))
1778 1787
1779 1788 if not match:
1780 1789 match = matchmod.always(self.root, '')
1781 1790
1782 1791 if not force:
1783 1792 vdirs = []
1784 1793 match.explicitdir = vdirs.append
1785 1794 match.bad = fail
1786 1795
1787 1796 wlock = lock = tr = None
1788 1797 try:
1789 1798 wlock = self.wlock()
1790 1799 lock = self.lock() # for recent changelog (see issue4368)
1791 1800
1792 1801 wctx = self[None]
1793 1802 merge = len(wctx.parents()) > 1
1794 1803
1795 1804 if not force and merge and not match.always():
1796 1805 raise error.Abort(_('cannot partially commit a merge '
1797 1806 '(do not specify files or patterns)'))
1798 1807
1799 1808 status = self.status(match=match, clean=force)
1800 1809 if force:
1801 1810 status.modified.extend(status.clean) # mq may commit clean files
1802 1811
1803 1812 # check subrepos
1804 1813 subs = []
1805 1814 commitsubs = set()
1806 1815 newstate = wctx.substate.copy()
1807 1816 # only manage subrepos and .hgsubstate if .hgsub is present
1808 1817 if '.hgsub' in wctx:
1809 1818 # we'll decide whether to track this ourselves, thanks
1810 1819 for c in status.modified, status.added, status.removed:
1811 1820 if '.hgsubstate' in c:
1812 1821 c.remove('.hgsubstate')
1813 1822
1814 1823 # compare current state to last committed state
1815 1824 # build new substate based on last committed state
1816 1825 oldstate = wctx.p1().substate
1817 1826 for s in sorted(newstate.keys()):
1818 1827 if not match(s):
1819 1828 # ignore working copy, use old state if present
1820 1829 if s in oldstate:
1821 1830 newstate[s] = oldstate[s]
1822 1831 continue
1823 1832 if not force:
1824 1833 raise error.Abort(
1825 1834 _("commit with new subrepo %s excluded") % s)
1826 1835 dirtyreason = wctx.sub(s).dirtyreason(True)
1827 1836 if dirtyreason:
1828 1837 if not self.ui.configbool('ui', 'commitsubrepos'):
1829 1838 raise error.Abort(dirtyreason,
1830 1839 hint=_("use --subrepos for recursive commit"))
1831 1840 subs.append(s)
1832 1841 commitsubs.add(s)
1833 1842 else:
1834 1843 bs = wctx.sub(s).basestate()
1835 1844 newstate[s] = (newstate[s][0], bs, newstate[s][2])
1836 1845 if oldstate.get(s, (None, None, None))[1] != bs:
1837 1846 subs.append(s)
1838 1847
1839 1848 # check for removed subrepos
1840 1849 for p in wctx.parents():
1841 1850 r = [s for s in p.substate if s not in newstate]
1842 1851 subs += [s for s in r if match(s)]
1843 1852 if subs:
1844 1853 if (not match('.hgsub') and
1845 1854 '.hgsub' in (wctx.modified() + wctx.added())):
1846 1855 raise error.Abort(
1847 1856 _("can't commit subrepos without .hgsub"))
1848 1857 status.modified.insert(0, '.hgsubstate')
1849 1858
1850 1859 elif '.hgsub' in status.removed:
1851 1860 # clean up .hgsubstate when .hgsub is removed
1852 1861 if ('.hgsubstate' in wctx and
1853 1862 '.hgsubstate' not in (status.modified + status.added +
1854 1863 status.removed)):
1855 1864 status.removed.insert(0, '.hgsubstate')
1856 1865
1857 1866 # make sure all explicit patterns are matched
1858 1867 if not force:
1859 1868 self.checkcommitpatterns(wctx, vdirs, match, status, fail)
1860 1869
1861 1870 cctx = context.workingcommitctx(self, status,
1862 1871 text, user, date, extra)
1863 1872
1864 1873 # internal config: ui.allowemptycommit
1865 1874 allowemptycommit = (wctx.branch() != wctx.p1().branch()
1866 1875 or extra.get('close') or merge or cctx.files()
1867 1876 or self.ui.configbool('ui', 'allowemptycommit'))
1868 1877 if not allowemptycommit:
1869 1878 return None
1870 1879
1871 1880 if merge and cctx.deleted():
1872 1881 raise error.Abort(_("cannot commit merge with missing files"))
1873 1882
1874 1883 ms = mergemod.mergestate.read(self)
1875 1884 mergeutil.checkunresolved(ms)
1876 1885
1877 1886 if editor:
1878 1887 cctx._text = editor(self, cctx, subs)
1879 1888 edited = (text != cctx._text)
1880 1889
1881 1890 # Save commit message in case this transaction gets rolled back
1882 1891 # (e.g. by a pretxncommit hook). Leave the content alone on
1883 1892 # the assumption that the user will use the same editor again.
1884 1893 msgfn = self.savecommitmessage(cctx._text)
1885 1894
1886 1895 # commit subs and write new state
1887 1896 if subs:
1888 1897 for s in sorted(commitsubs):
1889 1898 sub = wctx.sub(s)
1890 1899 self.ui.status(_('committing subrepository %s\n') %
1891 1900 subrepo.subrelpath(sub))
1892 1901 sr = sub.commit(cctx._text, user, date)
1893 1902 newstate[s] = (newstate[s][0], sr)
1894 1903 subrepo.writestate(self, newstate)
1895 1904
1896 1905 p1, p2 = self.dirstate.parents()
1897 1906 hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
1898 1907 try:
1899 1908 self.hook("precommit", throw=True, parent1=hookp1,
1900 1909 parent2=hookp2)
1901 1910 tr = self.transaction('commit')
1902 1911 ret = self.commitctx(cctx, True)
1903 1912 except: # re-raises
1904 1913 if edited:
1905 1914 self.ui.write(
1906 1915 _('note: commit message saved in %s\n') % msgfn)
1907 1916 raise
1908 1917 # update bookmarks, dirstate and mergestate
1909 1918 bookmarks.update(self, [p1, p2], ret)
1910 1919 cctx.markcommitted(ret)
1911 1920 ms.reset()
1912 1921 tr.close()
1913 1922
1914 1923 finally:
1915 1924 lockmod.release(tr, lock, wlock)
1916 1925
1917 1926 def commithook(node=hex(ret), parent1=hookp1, parent2=hookp2):
1918 1927 # hack for command that use a temporary commit (eg: histedit)
1919 1928 # temporary commit got stripped before hook release
1920 1929 if self.changelog.hasnode(ret):
1921 1930 self.hook("commit", node=node, parent1=parent1,
1922 1931 parent2=parent2)
1923 1932 self._afterlock(commithook)
1924 1933 return ret
1925 1934
1926 1935 @unfilteredmethod
1927 1936 def commitctx(self, ctx, error=False):
1928 1937 """Add a new revision to current repository.
1929 1938 Revision information is passed via the context argument.
1930 1939 """
1931 1940
1932 1941 tr = None
1933 1942 p1, p2 = ctx.p1(), ctx.p2()
1934 1943 user = ctx.user()
1935 1944
1936 1945 lock = self.lock()
1937 1946 try:
1938 1947 tr = self.transaction("commit")
1939 1948 trp = weakref.proxy(tr)
1940 1949
1941 1950 if ctx.manifestnode():
1942 1951 # reuse an existing manifest revision
1943 1952 mn = ctx.manifestnode()
1944 1953 files = ctx.files()
1945 1954 elif ctx.files():
1946 1955 m1ctx = p1.manifestctx()
1947 1956 m2ctx = p2.manifestctx()
1948 1957 mctx = m1ctx.copy()
1949 1958
1950 1959 m = mctx.read()
1951 1960 m1 = m1ctx.read()
1952 1961 m2 = m2ctx.read()
1953 1962
1954 1963 # check in files
1955 1964 added = []
1956 1965 changed = []
1957 1966 removed = list(ctx.removed())
1958 1967 linkrev = len(self)
1959 1968 self.ui.note(_("committing files:\n"))
1960 1969 for f in sorted(ctx.modified() + ctx.added()):
1961 1970 self.ui.note(f + "\n")
1962 1971 try:
1963 1972 fctx = ctx[f]
1964 1973 if fctx is None:
1965 1974 removed.append(f)
1966 1975 else:
1967 1976 added.append(f)
1968 1977 m[f] = self._filecommit(fctx, m1, m2, linkrev,
1969 1978 trp, changed)
1970 1979 m.setflag(f, fctx.flags())
1971 1980 except OSError as inst:
1972 1981 self.ui.warn(_("trouble committing %s!\n") % f)
1973 1982 raise
1974 1983 except IOError as inst:
1975 1984 errcode = getattr(inst, 'errno', errno.ENOENT)
1976 1985 if error or errcode and errcode != errno.ENOENT:
1977 1986 self.ui.warn(_("trouble committing %s!\n") % f)
1978 1987 raise
1979 1988
1980 1989 # update manifest
1981 1990 self.ui.note(_("committing manifest\n"))
1982 1991 removed = [f for f in sorted(removed) if f in m1 or f in m2]
1983 1992 drop = [f for f in removed if f in m]
1984 1993 for f in drop:
1985 1994 del m[f]
1986 1995 mn = mctx.write(trp, linkrev,
1987 1996 p1.manifestnode(), p2.manifestnode(),
1988 1997 added, drop)
1989 1998 files = changed + removed
1990 1999 else:
1991 2000 mn = p1.manifestnode()
1992 2001 files = []
1993 2002
1994 2003 # update changelog
1995 2004 self.ui.note(_("committing changelog\n"))
1996 2005 self.changelog.delayupdate(tr)
1997 2006 n = self.changelog.add(mn, files, ctx.description(),
1998 2007 trp, p1.node(), p2.node(),
1999 2008 user, ctx.date(), ctx.extra().copy())
2000 2009 xp1, xp2 = p1.hex(), p2 and p2.hex() or ''
2001 2010 self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
2002 2011 parent2=xp2)
2003 2012 # set the new commit is proper phase
2004 2013 targetphase = subrepo.newcommitphase(self.ui, ctx)
2005 2014 if targetphase:
2006 2015 # retract boundary do not alter parent changeset.
2007 2016 # if a parent have higher the resulting phase will
2008 2017 # be compliant anyway
2009 2018 #
2010 2019 # if minimal phase was 0 we don't need to retract anything
2011 2020 phases.registernew(self, tr, targetphase, [n])
2012 2021 tr.close()
2013 2022 return n
2014 2023 finally:
2015 2024 if tr:
2016 2025 tr.release()
2017 2026 lock.release()
2018 2027
2019 2028 @unfilteredmethod
2020 2029 def destroying(self):
2021 2030 '''Inform the repository that nodes are about to be destroyed.
2022 2031 Intended for use by strip and rollback, so there's a common
2023 2032 place for anything that has to be done before destroying history.
2024 2033
2025 2034 This is mostly useful for saving state that is in memory and waiting
2026 2035 to be flushed when the current lock is released. Because a call to
2027 2036 destroyed is imminent, the repo will be invalidated causing those
2028 2037 changes to stay in memory (waiting for the next unlock), or vanish
2029 2038 completely.
2030 2039 '''
2031 2040 # When using the same lock to commit and strip, the phasecache is left
2032 2041 # dirty after committing. Then when we strip, the repo is invalidated,
2033 2042 # causing those changes to disappear.
2034 2043 if '_phasecache' in vars(self):
2035 2044 self._phasecache.write()
2036 2045
2037 2046 @unfilteredmethod
2038 2047 def destroyed(self):
2039 2048 '''Inform the repository that nodes have been destroyed.
2040 2049 Intended for use by strip and rollback, so there's a common
2041 2050 place for anything that has to be done after destroying history.
2042 2051 '''
2043 2052 # When one tries to:
2044 2053 # 1) destroy nodes thus calling this method (e.g. strip)
2045 2054 # 2) use phasecache somewhere (e.g. commit)
2046 2055 #
2047 2056 # then 2) will fail because the phasecache contains nodes that were
2048 2057 # removed. We can either remove phasecache from the filecache,
2049 2058 # causing it to reload next time it is accessed, or simply filter
2050 2059 # the removed nodes now and write the updated cache.
2051 2060 self._phasecache.filterunknown(self)
2052 2061 self._phasecache.write()
2053 2062
2054 2063 # refresh all repository caches
2055 2064 self.updatecaches()
2056 2065
2057 2066 # Ensure the persistent tag cache is updated. Doing it now
2058 2067 # means that the tag cache only has to worry about destroyed
2059 2068 # heads immediately after a strip/rollback. That in turn
2060 2069 # guarantees that "cachetip == currenttip" (comparing both rev
2061 2070 # and node) always means no nodes have been added or destroyed.
2062 2071
2063 2072 # XXX this is suboptimal when qrefresh'ing: we strip the current
2064 2073 # head, refresh the tag cache, then immediately add a new head.
2065 2074 # But I think doing it this way is necessary for the "instant
2066 2075 # tag cache retrieval" case to work.
2067 2076 self.invalidate()
2068 2077
2069 2078 def walk(self, match, node=None):
2070 2079 '''
2071 2080 walk recursively through the directory tree or a given
2072 2081 changeset, finding all files matched by the match
2073 2082 function
2074 2083 '''
2075 2084 self.ui.deprecwarn('use repo[node].walk instead of repo.walk', '4.3')
2076 2085 return self[node].walk(match)
2077 2086
2078 2087 def status(self, node1='.', node2=None, match=None,
2079 2088 ignored=False, clean=False, unknown=False,
2080 2089 listsubrepos=False):
2081 2090 '''a convenience method that calls node1.status(node2)'''
2082 2091 return self[node1].status(node2, match, ignored, clean, unknown,
2083 2092 listsubrepos)
2084 2093
2085 2094 def addpostdsstatus(self, ps):
2086 2095 """Add a callback to run within the wlock, at the point at which status
2087 2096 fixups happen.
2088 2097
2089 2098 On status completion, callback(wctx, status) will be called with the
2090 2099 wlock held, unless the dirstate has changed from underneath or the wlock
2091 2100 couldn't be grabbed.
2092 2101
2093 2102 Callbacks should not capture and use a cached copy of the dirstate --
2094 2103 it might change in the meanwhile. Instead, they should access the
2095 2104 dirstate via wctx.repo().dirstate.
2096 2105
2097 2106 This list is emptied out after each status run -- extensions should
2098 2107 make sure it adds to this list each time dirstate.status is called.
2099 2108 Extensions should also make sure they don't call this for statuses
2100 2109 that don't involve the dirstate.
2101 2110 """
2102 2111
2103 2112 # The list is located here for uniqueness reasons -- it is actually
2104 2113 # managed by the workingctx, but that isn't unique per-repo.
2105 2114 self._postdsstatus.append(ps)
2106 2115
2107 2116 def postdsstatus(self):
2108 2117 """Used by workingctx to get the list of post-dirstate-status hooks."""
2109 2118 return self._postdsstatus
2110 2119
2111 2120 def clearpostdsstatus(self):
2112 2121 """Used by workingctx to clear post-dirstate-status hooks."""
2113 2122 del self._postdsstatus[:]
2114 2123
2115 2124 def heads(self, start=None):
2116 2125 if start is None:
2117 2126 cl = self.changelog
2118 2127 headrevs = reversed(cl.headrevs())
2119 2128 return [cl.node(rev) for rev in headrevs]
2120 2129
2121 2130 heads = self.changelog.heads(start)
2122 2131 # sort the output in rev descending order
2123 2132 return sorted(heads, key=self.changelog.rev, reverse=True)
2124 2133
2125 2134 def branchheads(self, branch=None, start=None, closed=False):
2126 2135 '''return a (possibly filtered) list of heads for the given branch
2127 2136
2128 2137 Heads are returned in topological order, from newest to oldest.
2129 2138 If branch is None, use the dirstate branch.
2130 2139 If start is not None, return only heads reachable from start.
2131 2140 If closed is True, return heads that are marked as closed as well.
2132 2141 '''
2133 2142 if branch is None:
2134 2143 branch = self[None].branch()
2135 2144 branches = self.branchmap()
2136 2145 if branch not in branches:
2137 2146 return []
2138 2147 # the cache returns heads ordered lowest to highest
2139 2148 bheads = list(reversed(branches.branchheads(branch, closed=closed)))
2140 2149 if start is not None:
2141 2150 # filter out the heads that cannot be reached from startrev
2142 2151 fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
2143 2152 bheads = [h for h in bheads if h in fbheads]
2144 2153 return bheads
2145 2154
2146 2155 def branches(self, nodes):
2147 2156 if not nodes:
2148 2157 nodes = [self.changelog.tip()]
2149 2158 b = []
2150 2159 for n in nodes:
2151 2160 t = n
2152 2161 while True:
2153 2162 p = self.changelog.parents(n)
2154 2163 if p[1] != nullid or p[0] == nullid:
2155 2164 b.append((t, n, p[0], p[1]))
2156 2165 break
2157 2166 n = p[0]
2158 2167 return b
2159 2168
2160 2169 def between(self, pairs):
2161 2170 r = []
2162 2171
2163 2172 for top, bottom in pairs:
2164 2173 n, l, i = top, [], 0
2165 2174 f = 1
2166 2175
2167 2176 while n != bottom and n != nullid:
2168 2177 p = self.changelog.parents(n)[0]
2169 2178 if i == f:
2170 2179 l.append(n)
2171 2180 f = f * 2
2172 2181 n = p
2173 2182 i += 1
2174 2183
2175 2184 r.append(l)
2176 2185
2177 2186 return r
2178 2187
2179 2188 def checkpush(self, pushop):
2180 2189 """Extensions can override this function if additional checks have
2181 2190 to be performed before pushing, or call it if they override push
2182 2191 command.
2183 2192 """
2184 2193
2185 2194 @unfilteredpropertycache
2186 2195 def prepushoutgoinghooks(self):
2187 2196 """Return util.hooks consists of a pushop with repo, remote, outgoing
2188 2197 methods, which are called before pushing changesets.
2189 2198 """
2190 2199 return util.hooks()
2191 2200
2192 2201 def pushkey(self, namespace, key, old, new):
2193 2202 try:
2194 2203 tr = self.currenttransaction()
2195 2204 hookargs = {}
2196 2205 if tr is not None:
2197 2206 hookargs.update(tr.hookargs)
2198 2207 hookargs['namespace'] = namespace
2199 2208 hookargs['key'] = key
2200 2209 hookargs['old'] = old
2201 2210 hookargs['new'] = new
2202 2211 self.hook('prepushkey', throw=True, **hookargs)
2203 2212 except error.HookAbort as exc:
2204 2213 self.ui.write_err(_("pushkey-abort: %s\n") % exc)
2205 2214 if exc.hint:
2206 2215 self.ui.write_err(_("(%s)\n") % exc.hint)
2207 2216 return False
2208 2217 self.ui.debug('pushing key for "%s:%s"\n' % (namespace, key))
2209 2218 ret = pushkey.push(self, namespace, key, old, new)
2210 2219 def runhook():
2211 2220 self.hook('pushkey', namespace=namespace, key=key, old=old, new=new,
2212 2221 ret=ret)
2213 2222 self._afterlock(runhook)
2214 2223 return ret
2215 2224
2216 2225 def listkeys(self, namespace):
2217 2226 self.hook('prelistkeys', throw=True, namespace=namespace)
2218 2227 self.ui.debug('listing keys for "%s"\n' % namespace)
2219 2228 values = pushkey.list(self, namespace)
2220 2229 self.hook('listkeys', namespace=namespace, values=values)
2221 2230 return values
2222 2231
2223 2232 def debugwireargs(self, one, two, three=None, four=None, five=None):
2224 2233 '''used to test argument passing over the wire'''
2225 2234 return "%s %s %s %s %s" % (one, two, three, four, five)
2226 2235
2227 2236 def savecommitmessage(self, text):
2228 2237 fp = self.vfs('last-message.txt', 'wb')
2229 2238 try:
2230 2239 fp.write(text)
2231 2240 finally:
2232 2241 fp.close()
2233 2242 return self.pathto(fp.name[len(self.root) + 1:])
2234 2243
2235 2244 # used to avoid circular references so destructors work
2236 2245 def aftertrans(files):
2237 2246 renamefiles = [tuple(t) for t in files]
2238 2247 def a():
2239 2248 for vfs, src, dest in renamefiles:
2240 2249 # if src and dest refer to a same file, vfs.rename is a no-op,
2241 2250 # leaving both src and dest on disk. delete dest to make sure
2242 2251 # the rename couldn't be such a no-op.
2243 2252 vfs.tryunlink(dest)
2244 2253 try:
2245 2254 vfs.rename(src, dest)
2246 2255 except OSError: # journal file does not yet exist
2247 2256 pass
2248 2257 return a
2249 2258
2250 2259 def undoname(fn):
2251 2260 base, name = os.path.split(fn)
2252 2261 assert name.startswith('journal')
2253 2262 return os.path.join(base, name.replace('journal', 'undo', 1))
2254 2263
2255 2264 def instance(ui, path, create):
2256 2265 return localrepository(ui, util.urllocalpath(path), create)
2257 2266
2258 2267 def islocal(path):
2259 2268 return True
2260 2269
2261 2270 def newreporequirements(repo):
2262 2271 """Determine the set of requirements for a new local repository.
2263 2272
2264 2273 Extensions can wrap this function to specify custom requirements for
2265 2274 new repositories.
2266 2275 """
2267 2276 ui = repo.ui
2268 2277 requirements = {'revlogv1'}
2269 2278 if ui.configbool('format', 'usestore'):
2270 2279 requirements.add('store')
2271 2280 if ui.configbool('format', 'usefncache'):
2272 2281 requirements.add('fncache')
2273 2282 if ui.configbool('format', 'dotencode'):
2274 2283 requirements.add('dotencode')
2275 2284
2276 2285 compengine = ui.config('experimental', 'format.compression')
2277 2286 if compengine not in util.compengines:
2278 2287 raise error.Abort(_('compression engine %s defined by '
2279 2288 'experimental.format.compression not available') %
2280 2289 compengine,
2281 2290 hint=_('run "hg debuginstall" to list available '
2282 2291 'compression engines'))
2283 2292
2284 2293 # zlib is the historical default and doesn't need an explicit requirement.
2285 2294 if compengine != 'zlib':
2286 2295 requirements.add('exp-compression-%s' % compengine)
2287 2296
2288 2297 if scmutil.gdinitconfig(ui):
2289 2298 requirements.add('generaldelta')
2290 2299 if ui.configbool('experimental', 'treemanifest'):
2291 2300 requirements.add('treemanifest')
2292 2301 if ui.configbool('experimental', 'manifestv2'):
2293 2302 requirements.add('manifestv2')
2294 2303
2295 2304 revlogv2 = ui.config('experimental', 'revlogv2')
2296 2305 if revlogv2 == 'enable-unstable-format-and-corrupt-my-data':
2297 2306 requirements.remove('revlogv1')
2298 2307 # generaldelta is implied by revlogv2.
2299 2308 requirements.discard('generaldelta')
2300 2309 requirements.add(REVLOGV2_REQUIREMENT)
2301 2310
2302 2311 return requirements
@@ -1,889 +1,905 b''
1 1 #require serve
2 2
3 3 $ cat << EOF >> $HGRCPATH
4 4 > [ui]
5 5 > logtemplate={rev}:{node|short} {desc|firstline}
6 6 > [phases]
7 7 > publish=False
8 8 > [experimental]
9 9 > stabilization=createmarkers,exchange
10 10 > EOF
11 11
12 $ TESTHOOK='hooks.txnclose-bookmark.test=echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"'
13
12 14 initialize
13 15
14 16 $ hg init a
15 17 $ cd a
16 18 $ echo 'test' > test
17 19 $ hg commit -Am'test'
18 20 adding test
19 21
20 22 set bookmarks
21 23
22 24 $ hg bookmark X
23 25 $ hg bookmark Y
24 26 $ hg bookmark Z
25 27
26 28 import bookmark by name
27 29
28 30 $ hg init ../b
29 31 $ cd ../b
30 32 $ hg book Y
31 33 $ hg book
32 34 * Y -1:000000000000
33 $ hg pull ../a
35 $ hg pull ../a --config "$TESTHOOK"
34 36 pulling from ../a
35 37 requesting all changes
36 38 adding changesets
37 39 adding manifests
38 40 adding file changes
39 41 added 1 changesets with 1 changes to 1 files
40 42 adding remote bookmark X
41 43 updating bookmark Y
42 44 adding remote bookmark Z
43 45 new changesets 4e3505fd9583
46 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
47 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
48 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
44 49 (run 'hg update' to get a working copy)
45 50 $ hg bookmarks
46 51 X 0:4e3505fd9583
47 52 * Y 0:4e3505fd9583
48 53 Z 0:4e3505fd9583
49 54 $ hg debugpushkey ../a namespaces
50 55 bookmarks
51 56 namespaces
52 57 obsolete
53 58 phases
54 59 $ hg debugpushkey ../a bookmarks
55 60 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
56 61 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
57 62 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
58 63
59 64 delete the bookmark to re-pull it
60 65
61 66 $ hg book -d X
62 67 $ hg pull -B X ../a
63 68 pulling from ../a
64 69 no changes found
65 70 adding remote bookmark X
66 71
67 72 finally no-op pull
68 73
69 74 $ hg pull -B X ../a
70 75 pulling from ../a
71 76 no changes found
72 77 $ hg bookmark
73 78 X 0:4e3505fd9583
74 79 * Y 0:4e3505fd9583
75 80 Z 0:4e3505fd9583
76 81
77 82 export bookmark by name
78 83
79 84 $ hg bookmark W
80 85 $ hg bookmark foo
81 86 $ hg bookmark foobar
82 87 $ hg push -B W ../a
83 88 pushing to ../a
84 89 searching for changes
85 90 no changes found
86 91 exporting bookmark W
87 92 [1]
88 93 $ hg -R ../a bookmarks
89 94 W -1:000000000000
90 95 X 0:4e3505fd9583
91 96 Y 0:4e3505fd9583
92 97 * Z 0:4e3505fd9583
93 98
94 99 delete a remote bookmark
95 100
96 101 $ hg book -d W
97 $ hg push -B W ../a
102 $ hg push -B W ../a --config "$TESTHOOK"
98 103 pushing to ../a
99 104 searching for changes
100 105 no changes found
106 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
101 107 deleting remote bookmark W
102 108 [1]
103 109
104 110 export the active bookmark
105 111
106 112 $ hg bookmark V
107 113 $ hg push -B . ../a
108 114 pushing to ../a
109 115 searching for changes
110 116 no changes found
111 117 exporting bookmark V
112 118 [1]
113 119
114 120 exporting the active bookmark with 'push -B .'
115 121 demand that one of the bookmarks is activated
116 122
117 123 $ hg update -r default
118 124 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
119 125 (leaving bookmark V)
120 126 $ hg push -B . ../a
121 127 abort: no active bookmark
122 128 [255]
123 129 $ hg update -r V
124 130 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
125 131 (activating bookmark V)
126 132
127 133 delete the bookmark
128 134
129 135 $ hg book -d V
130 136 $ hg push -B V ../a
131 137 pushing to ../a
132 138 searching for changes
133 139 no changes found
134 140 deleting remote bookmark V
135 141 [1]
136 142 $ hg up foobar
137 143 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
138 144 (activating bookmark foobar)
139 145
140 146 push/pull name that doesn't exist
141 147
142 148 $ hg push -B badname ../a
143 149 pushing to ../a
144 150 searching for changes
145 151 bookmark badname does not exist on the local or remote repository!
146 152 no changes found
147 153 [2]
148 154 $ hg pull -B anotherbadname ../a
149 155 pulling from ../a
150 156 abort: remote bookmark anotherbadname not found!
151 157 [255]
152 158
153 159 divergent bookmarks
154 160
155 161 $ cd ../a
156 162 $ echo c1 > f1
157 163 $ hg ci -Am1
158 164 adding f1
159 165 $ hg book -f @
160 166 $ hg book -f X
161 167 $ hg book
162 168 @ 1:0d2164f0ce0d
163 169 * X 1:0d2164f0ce0d
164 170 Y 0:4e3505fd9583
165 171 Z 1:0d2164f0ce0d
166 172
167 173 $ cd ../b
168 $ hg up
174 $ hg up --config
169 175 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 176 updating bookmark foobar
171 177 $ echo c2 > f2
172 178 $ hg ci -Am2
173 179 adding f2
174 180 $ hg book -if @
175 181 $ hg book -if X
176 182 $ hg book
177 183 @ 1:9b140be10808
178 184 X 1:9b140be10808
179 185 Y 0:4e3505fd9583
180 186 Z 0:4e3505fd9583
181 187 foo -1:000000000000
182 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 191 pulling from $TESTTMP/a (glob)
186 192 searching for changes
187 193 adding changesets
188 194 adding manifests
189 195 adding file changes
190 196 added 1 changesets with 1 changes to 1 files (+1 heads)
191 197 divergent bookmark @ stored as @foo
192 198 divergent bookmark X stored as X@foo
193 199 updating bookmark Z
194 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 204 (run 'hg heads' to see heads, 'hg merge' to merge)
196 205 $ hg book
197 206 @ 1:9b140be10808
198 207 @foo 2:0d2164f0ce0d
199 208 X 1:9b140be10808
200 209 X@foo 2:0d2164f0ce0d
201 210 Y 0:4e3505fd9583
202 211 Z 2:0d2164f0ce0d
203 212 foo -1:000000000000
204 213 * foobar 1:9b140be10808
205 214
206 215 (test that too many divergence of bookmark)
207 216
208 217 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
209 218 $ hg pull ../a
210 219 pulling from ../a
211 220 searching for changes
212 221 no changes found
213 222 warning: failed to assign numbered name to divergent bookmark X
214 223 divergent bookmark @ stored as @1
215 224 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
216 225 X 1:9b140be10808
217 226 X@foo 2:0d2164f0ce0d
218 227
219 228 (test that remotely diverged bookmarks are reused if they aren't changed)
220 229
221 230 $ hg bookmarks | grep '^ @'
222 231 @ 1:9b140be10808
223 232 @1 2:0d2164f0ce0d
224 233 @foo 2:0d2164f0ce0d
225 234 $ hg pull ../a
226 235 pulling from ../a
227 236 searching for changes
228 237 no changes found
229 238 warning: failed to assign numbered name to divergent bookmark X
230 239 divergent bookmark @ stored as @1
231 240 $ hg bookmarks | grep '^ @'
232 241 @ 1:9b140be10808
233 242 @1 2:0d2164f0ce0d
234 243 @foo 2:0d2164f0ce0d
235 244
236 245 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
237 246 $ hg bookmarks -d "@1"
238 247
239 248 $ hg push -f ../a
240 249 pushing to ../a
241 250 searching for changes
242 251 adding changesets
243 252 adding manifests
244 253 adding file changes
245 254 added 1 changesets with 1 changes to 1 files (+1 heads)
246 255 $ hg -R ../a book
247 256 @ 1:0d2164f0ce0d
248 257 * X 1:0d2164f0ce0d
249 258 Y 0:4e3505fd9583
250 259 Z 1:0d2164f0ce0d
251 260
252 261 explicit pull should overwrite the local version (issue4439)
253 262
254 263 $ hg update -r X
255 264 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
256 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 267 pulling from $TESTTMP/a (glob)
259 268 no changes found
260 269 divergent bookmark @ stored as @foo
261 270 importing bookmark X
271 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
272 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
262 273
263 274 reinstall state for further testing:
264 275
265 276 $ hg book -fr 9b140be10808 X
266 277
267 278 revsets should not ignore divergent bookmarks
268 279
269 280 $ hg bookmark -fr 1 Z
270 281 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
271 282 0:4e3505fd9583 Y
272 283 1:9b140be10808 @ X Z foobar
273 284 2:0d2164f0ce0d @foo X@foo
274 285 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
275 286 2:0d2164f0ce0d @foo X@foo
276 287 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
277 288 2:0d2164f0ce0d @foo X@foo
278 289
279 290 update a remote bookmark from a non-head to a head
280 291
281 292 $ hg up -q Y
282 293 $ echo c3 > f2
283 294 $ hg ci -Am3
284 295 adding f2
285 296 created new head
286 $ hg push ../a
297 $ hg push ../a --config "$TESTHOOK"
287 298 pushing to ../a
288 299 searching for changes
289 300 adding changesets
290 301 adding manifests
291 302 adding file changes
292 303 added 1 changesets with 1 changes to 1 files (+1 heads)
304 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
293 305 updating bookmark Y
294 306 $ hg -R ../a book
295 307 @ 1:0d2164f0ce0d
296 308 * X 1:0d2164f0ce0d
297 309 Y 3:f6fc62dde3c0
298 310 Z 1:0d2164f0ce0d
299 311
300 312 update a bookmark in the middle of a client pulling changes
301 313
302 314 $ cd ..
303 315 $ hg clone -q a pull-race
304 316
305 317 We want to use http because it is stateless and therefore more susceptible to
306 318 race conditions
307 319
308 320 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
309 321 $ cat pull-race.pid >> $DAEMON_PIDS
310 322
311 323 $ cat <<EOF > $TESTTMP/out_makecommit.sh
312 324 > #!/bin/sh
313 325 > hg ci -Am5
314 326 > echo committed in pull-race
315 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 334 $ cd pull-race
319 335 $ hg up -q Y
320 336 $ echo c4 > f2
321 337 $ hg ci -Am4
322 338 $ echo c5 > f3
323 339 $ cat <<EOF > .hg/hgrc
324 340 > [hooks]
325 341 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
326 342 > EOF
327 343
328 344 (new config needs a server restart)
329 345
330 346 $ cd ..
331 347 $ killdaemons.py
332 348 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
333 349 $ cat pull-race.pid >> $DAEMON_PIDS
334 350 $ cd pull-race2
335 351 $ hg -R $TESTTMP/pull-race book
336 352 @ 1:0d2164f0ce0d
337 353 X 1:0d2164f0ce0d
338 354 * Y 4:b0a5eff05604
339 355 Z 1:0d2164f0ce0d
340 356 $ hg pull
341 357 pulling from http://localhost:$HGPORT/
342 358 searching for changes
343 359 adding changesets
344 360 adding manifests
345 361 adding file changes
346 362 added 1 changesets with 1 changes to 1 files
347 363 updating bookmark Y
348 364 new changesets b0a5eff05604
349 365 (run 'hg update' to get a working copy)
350 366 $ hg book
351 367 * @ 1:0d2164f0ce0d
352 368 X 1:0d2164f0ce0d
353 369 Y 4:b0a5eff05604
354 370 Z 1:0d2164f0ce0d
355 371
356 372 Update a bookmark right after the initial lookup -B (issue4689)
357 373
358 374 $ echo c6 > ../pull-race/f3 # to be committed during the race
359 375 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
360 376 > #!/bin/sh
361 377 > if hg st | grep -q M; then
362 378 > hg commit -m race
363 379 > echo committed in pull-race
364 380 > else
365 381 > exit 0
366 382 > fi
367 383 > EOF
368 384 $ cat <<EOF > ../pull-race/.hg/hgrc
369 385 > [hooks]
370 386 > # If anything to commit, commit it right after the first key listing used
371 387 > # during lookup. This makes the commit appear before the actual getbundle
372 388 > # call.
373 389 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
374 390 > EOF
375 391
376 392 (new config need server restart)
377 393
378 394 $ killdaemons.py
379 395 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
380 396 $ cat ../pull-race.pid >> $DAEMON_PIDS
381 397
382 398 $ hg -R $TESTTMP/pull-race book
383 399 @ 1:0d2164f0ce0d
384 400 X 1:0d2164f0ce0d
385 401 * Y 5:35d1ef0a8d1b
386 402 Z 1:0d2164f0ce0d
387 403 $ hg update -r Y
388 404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
389 405 (activating bookmark Y)
390 406 $ hg pull -B .
391 407 pulling from http://localhost:$HGPORT/
392 408 searching for changes
393 409 adding changesets
394 410 adding manifests
395 411 adding file changes
396 412 added 1 changesets with 1 changes to 1 files
397 413 updating bookmark Y
398 414 new changesets 35d1ef0a8d1b
399 415 (run 'hg update' to get a working copy)
400 416 $ hg book
401 417 @ 1:0d2164f0ce0d
402 418 X 1:0d2164f0ce0d
403 419 * Y 5:35d1ef0a8d1b
404 420 Z 1:0d2164f0ce0d
405 421
406 422 (done with this section of the test)
407 423
408 424 $ killdaemons.py
409 425 $ cd ../b
410 426
411 427 diverging a remote bookmark fails
412 428
413 429 $ hg up -q 4e3505fd9583
414 430 $ echo c4 > f2
415 431 $ hg ci -Am4
416 432 adding f2
417 433 created new head
418 434 $ echo c5 > f2
419 435 $ hg ci -Am5
420 436 $ hg log -G
421 437 @ 5:c922c0139ca0 5
422 438 |
423 439 o 4:4efff6d98829 4
424 440 |
425 441 | o 3:f6fc62dde3c0 3
426 442 |/
427 443 | o 2:0d2164f0ce0d 1
428 444 |/
429 445 | o 1:9b140be10808 2
430 446 |/
431 447 o 0:4e3505fd9583 test
432 448
433 449
434 450 $ hg book -f Y
435 451
436 452 $ cat <<EOF > ../a/.hg/hgrc
437 453 > [web]
438 454 > push_ssl = false
439 455 > allow_push = *
440 456 > EOF
441 457
442 458 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
443 459 $ cat ../hg2.pid >> $DAEMON_PIDS
444 460
445 461 $ hg push http://localhost:$HGPORT2/
446 462 pushing to http://localhost:$HGPORT2/
447 463 searching for changes
448 464 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
449 465 (merge or see 'hg help push' for details about pushing new heads)
450 466 [255]
451 467 $ hg -R ../a book
452 468 @ 1:0d2164f0ce0d
453 469 * X 1:0d2164f0ce0d
454 470 Y 3:f6fc62dde3c0
455 471 Z 1:0d2164f0ce0d
456 472
457 473
458 474 Unrelated marker does not alter the decision
459 475
460 476 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
461 477 $ hg push http://localhost:$HGPORT2/
462 478 pushing to http://localhost:$HGPORT2/
463 479 searching for changes
464 480 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
465 481 (merge or see 'hg help push' for details about pushing new heads)
466 482 [255]
467 483 $ hg -R ../a book
468 484 @ 1:0d2164f0ce0d
469 485 * X 1:0d2164f0ce0d
470 486 Y 3:f6fc62dde3c0
471 487 Z 1:0d2164f0ce0d
472 488
473 489 Update to a successor works
474 490
475 491 $ hg id --debug -r 3
476 492 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
477 493 $ hg id --debug -r 4
478 494 4efff6d98829d9c824c621afd6e3f01865f5439f
479 495 $ hg id --debug -r 5
480 496 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
481 497 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
482 498 obsoleted 1 changesets
483 499 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
484 500 $ hg push http://localhost:$HGPORT2/
485 501 pushing to http://localhost:$HGPORT2/
486 502 searching for changes
487 503 remote: adding changesets
488 504 remote: adding manifests
489 505 remote: adding file changes
490 506 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
491 507 remote: 2 new obsolescence markers
492 508 remote: obsoleted 1 changesets
493 509 updating bookmark Y
494 510 $ hg -R ../a book
495 511 @ 1:0d2164f0ce0d
496 512 * X 1:0d2164f0ce0d
497 513 Y 5:c922c0139ca0
498 514 Z 1:0d2164f0ce0d
499 515
500 516 hgweb
501 517
502 518 $ cat <<EOF > .hg/hgrc
503 519 > [web]
504 520 > push_ssl = false
505 521 > allow_push = *
506 522 > EOF
507 523
508 524 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
509 525 $ cat ../hg.pid >> $DAEMON_PIDS
510 526 $ cd ../a
511 527
512 528 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
513 529 bookmarks
514 530 namespaces
515 531 obsolete
516 532 phases
517 533 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
518 534 @ 9b140be1080824d768c5a4691a564088eede71f9
519 535 X 9b140be1080824d768c5a4691a564088eede71f9
520 536 Y c922c0139ca03858f655e4a2af4dd02796a63969
521 537 Z 9b140be1080824d768c5a4691a564088eede71f9
522 538 foo 0000000000000000000000000000000000000000
523 539 foobar 9b140be1080824d768c5a4691a564088eede71f9
524 540 $ hg out -B http://localhost:$HGPORT/
525 541 comparing with http://localhost:$HGPORT/
526 542 searching for changed bookmarks
527 543 @ 0d2164f0ce0d
528 544 X 0d2164f0ce0d
529 545 Z 0d2164f0ce0d
530 546 foo
531 547 foobar
532 548 $ hg push -B Z http://localhost:$HGPORT/
533 549 pushing to http://localhost:$HGPORT/
534 550 searching for changes
535 551 no changes found
536 552 updating bookmark Z
537 553 [1]
538 554 $ hg book -d Z
539 555 $ hg in -B http://localhost:$HGPORT/
540 556 comparing with http://localhost:$HGPORT/
541 557 searching for changed bookmarks
542 558 @ 9b140be10808
543 559 X 9b140be10808
544 560 Z 0d2164f0ce0d
545 561 foo 000000000000
546 562 foobar 9b140be10808
547 563 $ hg pull -B Z http://localhost:$HGPORT/
548 564 pulling from http://localhost:$HGPORT/
549 565 no changes found
550 566 divergent bookmark @ stored as @1
551 567 divergent bookmark X stored as X@1
552 568 adding remote bookmark Z
553 569 adding remote bookmark foo
554 570 adding remote bookmark foobar
555 571 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
556 572 requesting all changes
557 573 adding changesets
558 574 adding manifests
559 575 adding file changes
560 576 added 5 changesets with 5 changes to 3 files (+2 heads)
561 577 2 new obsolescence markers
562 578 new changesets 4e3505fd9583:c922c0139ca0
563 579 updating to bookmark @
564 580 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
565 581 $ hg -R cloned-bookmarks bookmarks
566 582 * @ 1:9b140be10808
567 583 X 1:9b140be10808
568 584 Y 4:c922c0139ca0
569 585 Z 2:0d2164f0ce0d
570 586 foo -1:000000000000
571 587 foobar 1:9b140be10808
572 588
573 589 $ cd ..
574 590
575 591 Test to show result of bookmarks comparison
576 592
577 593 $ mkdir bmcomparison
578 594 $ cd bmcomparison
579 595
580 596 $ hg init source
581 597 $ hg -R source debugbuilddag '+2*2*3*4'
582 598 $ hg -R source log -G --template '{rev}:{node|short}'
583 599 o 4:e7bd5218ca15
584 600 |
585 601 | o 3:6100d3090acf
586 602 |/
587 603 | o 2:fa942426a6fd
588 604 |/
589 605 | o 1:66f7d451a68b
590 606 |/
591 607 o 0:1ea73414a91b
592 608
593 609 $ hg -R source bookmarks -r 0 SAME
594 610 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
595 611 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
596 612 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
597 613 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
598 614 $ hg -R source bookmarks -r 1 DIVERGED
599 615
600 616 $ hg clone -U source repo1
601 617
602 618 (test that incoming/outgoing exit with 1, if there is no bookmark to
603 619 be exchanged)
604 620
605 621 $ hg -R repo1 incoming -B
606 622 comparing with $TESTTMP/bmcomparison/source (glob)
607 623 searching for changed bookmarks
608 624 no changed bookmarks found
609 625 [1]
610 626 $ hg -R repo1 outgoing -B
611 627 comparing with $TESTTMP/bmcomparison/source (glob)
612 628 searching for changed bookmarks
613 629 no changed bookmarks found
614 630 [1]
615 631
616 632 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
617 633 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
618 634 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
619 635 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
620 636 $ hg -R repo1 -q --config extensions.mq= strip 4
621 637 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
622 638 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
623 639 |
624 640 | o fa942426a6fd (ADV_ON_REPO1)
625 641 |/
626 642 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
627 643 |/
628 644 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
629 645
630 646
631 647 $ hg clone -U source repo2
632 648 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
633 649 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
634 650 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
635 651 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
636 652 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
637 653 $ hg -R repo2 -q --config extensions.mq= strip 3
638 654 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
639 655 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
640 656 |
641 657 | o fa942426a6fd (DIVERGED)
642 658 |/
643 659 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
644 660 |/
645 661 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
646 662
647 663
648 664 (test that difference of bookmarks between repositories are fully shown)
649 665
650 666 $ hg -R repo1 incoming -B repo2 -v
651 667 comparing with repo2
652 668 searching for changed bookmarks
653 669 ADD_ON_REPO2 66f7d451a68b added
654 670 ADV_ON_REPO2 66f7d451a68b advanced
655 671 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
656 672 DIFF_DIVERGED e7bd5218ca15 changed
657 673 DIVERGED fa942426a6fd diverged
658 674 $ hg -R repo1 outgoing -B repo2 -v
659 675 comparing with repo2
660 676 searching for changed bookmarks
661 677 ADD_ON_REPO1 66f7d451a68b added
662 678 ADD_ON_REPO2 deleted
663 679 ADV_ON_REPO1 fa942426a6fd advanced
664 680 DIFF_ADV_ON_REPO1 6100d3090acf advanced
665 681 DIFF_ADV_ON_REPO2 1ea73414a91b changed
666 682 DIFF_DIVERGED 6100d3090acf changed
667 683 DIVERGED 66f7d451a68b diverged
668 684
669 685 $ hg -R repo2 incoming -B repo1 -v
670 686 comparing with repo1
671 687 searching for changed bookmarks
672 688 ADD_ON_REPO1 66f7d451a68b added
673 689 ADV_ON_REPO1 fa942426a6fd advanced
674 690 DIFF_ADV_ON_REPO1 6100d3090acf changed
675 691 DIFF_DIVERGED 6100d3090acf changed
676 692 DIVERGED 66f7d451a68b diverged
677 693 $ hg -R repo2 outgoing -B repo1 -v
678 694 comparing with repo1
679 695 searching for changed bookmarks
680 696 ADD_ON_REPO1 deleted
681 697 ADD_ON_REPO2 66f7d451a68b added
682 698 ADV_ON_REPO2 66f7d451a68b advanced
683 699 DIFF_ADV_ON_REPO1 1ea73414a91b changed
684 700 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
685 701 DIFF_DIVERGED e7bd5218ca15 changed
686 702 DIVERGED fa942426a6fd diverged
687 703
688 704 $ cd ..
689 705
690 706 Pushing a bookmark should only push the changes required by that
691 707 bookmark, not all outgoing changes:
692 708 $ hg clone http://localhost:$HGPORT/ addmarks
693 709 requesting all changes
694 710 adding changesets
695 711 adding manifests
696 712 adding file changes
697 713 added 5 changesets with 5 changes to 3 files (+2 heads)
698 714 2 new obsolescence markers
699 715 new changesets 4e3505fd9583:c922c0139ca0
700 716 updating to bookmark @
701 717 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
702 718 $ cd addmarks
703 719 $ echo foo > foo
704 720 $ hg add foo
705 721 $ hg commit -m 'add foo'
706 722 $ echo bar > bar
707 723 $ hg add bar
708 724 $ hg commit -m 'add bar'
709 725 $ hg co "tip^"
710 726 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
711 727 (leaving bookmark @)
712 728 $ hg book add-foo
713 729 $ hg book -r tip add-bar
714 730 Note: this push *must* push only a single changeset, as that's the point
715 731 of this test.
716 732 $ hg push -B add-foo --traceback
717 733 pushing to http://localhost:$HGPORT/
718 734 searching for changes
719 735 remote: adding changesets
720 736 remote: adding manifests
721 737 remote: adding file changes
722 738 remote: added 1 changesets with 1 changes to 1 files
723 739 exporting bookmark add-foo
724 740
725 741 pushing a new bookmark on a new head does not require -f if -B is specified
726 742
727 743 $ hg up -q X
728 744 $ hg book W
729 745 $ echo c5 > f2
730 746 $ hg ci -Am5
731 747 created new head
732 748 $ hg push -B .
733 749 pushing to http://localhost:$HGPORT/
734 750 searching for changes
735 751 remote: adding changesets
736 752 remote: adding manifests
737 753 remote: adding file changes
738 754 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
739 755 exporting bookmark W
740 756 $ hg -R ../b id -r W
741 757 cc978a373a53 tip W
742 758
743 759 pushing an existing but divergent bookmark with -B still requires -f
744 760
745 761 $ hg clone -q . ../r
746 762 $ hg up -q X
747 763 $ echo 1 > f2
748 764 $ hg ci -qAml
749 765
750 766 $ cd ../r
751 767 $ hg up -q X
752 768 $ echo 2 > f2
753 769 $ hg ci -qAmr
754 770 $ hg push -B X
755 771 pushing to $TESTTMP/addmarks (glob)
756 772 searching for changes
757 773 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
758 774 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
759 775 (pull and merge or see 'hg help push' for details about pushing new heads)
760 776 [255]
761 777 $ cd ../addmarks
762 778
763 779 Check summary output for incoming/outgoing bookmarks
764 780
765 781 $ hg bookmarks -d X
766 782 $ hg bookmarks -d Y
767 783 $ hg summary --remote | grep '^remote:'
768 784 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
769 785
770 786 $ cd ..
771 787
772 788 pushing an unchanged bookmark should result in no changes
773 789
774 790 $ hg init unchanged-a
775 791 $ hg init unchanged-b
776 792 $ cd unchanged-a
777 793 $ echo initial > foo
778 794 $ hg commit -A -m initial
779 795 adding foo
780 796 $ hg bookmark @
781 797 $ hg push -B @ ../unchanged-b
782 798 pushing to ../unchanged-b
783 799 searching for changes
784 800 adding changesets
785 801 adding manifests
786 802 adding file changes
787 803 added 1 changesets with 1 changes to 1 files
788 804 exporting bookmark @
789 805
790 806 $ hg push -B @ ../unchanged-b
791 807 pushing to ../unchanged-b
792 808 searching for changes
793 809 no changes found
794 810 [1]
795 811
796 812
797 813 Check hook preventing push (issue4455)
798 814 ======================================
799 815
800 816 $ hg bookmarks
801 817 * @ 0:55482a6fb4b1
802 818 $ hg log -G
803 819 @ 0:55482a6fb4b1 initial
804 820
805 821 $ hg init ../issue4455-dest
806 822 $ hg push ../issue4455-dest # changesets only
807 823 pushing to ../issue4455-dest
808 824 searching for changes
809 825 adding changesets
810 826 adding manifests
811 827 adding file changes
812 828 added 1 changesets with 1 changes to 1 files
813 829 $ cat >> .hg/hgrc << EOF
814 830 > [paths]
815 831 > local=../issue4455-dest/
816 832 > ssh=ssh://user@dummy/issue4455-dest
817 833 > http=http://localhost:$HGPORT/
818 834 > [ui]
819 835 > ssh=$PYTHON "$TESTDIR/dummyssh"
820 836 > EOF
821 837 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
822 838 > [hooks]
823 839 > prepushkey=false
824 840 > [web]
825 841 > push_ssl = false
826 842 > allow_push = *
827 843 > EOF
828 844 $ killdaemons.py
829 845 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
830 846 $ cat ../issue4455.pid >> $DAEMON_PIDS
831 847
832 848 Local push
833 849 ----------
834 850
835 851 $ hg push -B @ local
836 852 pushing to $TESTTMP/issue4455-dest (glob)
837 853 searching for changes
838 854 no changes found
839 855 pushkey-abort: prepushkey hook exited with status 1
840 856 abort: exporting bookmark @ failed!
841 857 [255]
842 858 $ hg -R ../issue4455-dest/ bookmarks
843 859 no bookmarks set
844 860
845 861 Using ssh
846 862 ---------
847 863
848 864 $ hg push -B @ ssh # bundle2+
849 865 pushing to ssh://user@dummy/issue4455-dest
850 866 searching for changes
851 867 no changes found
852 868 remote: pushkey-abort: prepushkey hook exited with status 1
853 869 abort: exporting bookmark @ failed!
854 870 [255]
855 871 $ hg -R ../issue4455-dest/ bookmarks
856 872 no bookmarks set
857 873
858 874 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
859 875 pushing to ssh://user@dummy/issue4455-dest
860 876 searching for changes
861 877 no changes found
862 878 remote: pushkey-abort: prepushkey hook exited with status 1
863 879 exporting bookmark @ failed!
864 880 [1]
865 881 $ hg -R ../issue4455-dest/ bookmarks
866 882 no bookmarks set
867 883
868 884 Using http
869 885 ----------
870 886
871 887 $ hg push -B @ http # bundle2+
872 888 pushing to http://localhost:$HGPORT/
873 889 searching for changes
874 890 no changes found
875 891 remote: pushkey-abort: prepushkey hook exited with status 1
876 892 abort: exporting bookmark @ failed!
877 893 [255]
878 894 $ hg -R ../issue4455-dest/ bookmarks
879 895 no bookmarks set
880 896
881 897 $ hg push -B @ http --config devel.legacy.exchange=bundle1
882 898 pushing to http://localhost:$HGPORT/
883 899 searching for changes
884 900 no changes found
885 901 remote: pushkey-abort: prepushkey hook exited with status 1
886 902 exporting bookmark @ failed!
887 903 [1]
888 904 $ hg -R ../issue4455-dest/ bookmarks
889 905 no bookmarks set
@@ -1,1052 +1,1065 b''
1
1 2 $ hg init repo
2 3 $ cd repo
3 4
5 $ TESTHOOK='hooks.txnclose-bookmark.test=echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"'
6
4 7 no bookmarks
5 8
6 9 $ hg bookmarks
7 10 no bookmarks set
8 11
9 12 $ hg bookmarks -Tjson
10 13 [
11 14 ]
12 15
13 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 21 list bookmarks
18 22
19 23 $ hg bookmarks
20 24 * X -1:000000000000
21 25
22 26 list bookmarks with color
23 27
24 28 $ hg --config extensions.color= --config color.mode=ansi \
25 29 > bookmarks --color=always
26 30 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
27 31
28 32 $ echo a > a
29 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 37 bookmark X moved to rev 0
33 38
34 39 $ hg bookmarks
35 40 * X 0:f7b1eb17ad24
36 41
37 42 look up bookmark
38 43
39 44 $ hg log -r X
40 45 changeset: 0:f7b1eb17ad24
41 46 bookmark: X
42 47 tag: tip
43 48 user: test
44 49 date: Thu Jan 01 00:00:00 1970 +0000
45 50 summary: 0
46 51
47 52
48 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 58 bookmark rev -1 again
53 59
54 60 $ hg bookmark -r null Y
55 61
56 62 list bookmarks
57 63
58 64 $ hg bookmarks
59 65 X 0:f7b1eb17ad24
60 66 * X2 0:f7b1eb17ad24
61 67 Y -1:000000000000
62 68
63 69 $ echo b > b
64 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 74 $ hg bookmarks -Tjson
68 75 [
69 76 {
70 77 "active": false,
71 78 "bookmark": "X",
72 79 "node": "f7b1eb17ad24730a1651fccd46c43826d1bbc2ac",
73 80 "rev": 0
74 81 },
75 82 {
76 83 "active": true,
77 84 "bookmark": "X2",
78 85 "node": "925d80f479bb026b0fb3deb27503780b13f74123",
79 86 "rev": 1
80 87 },
81 88 {
82 89 "active": false,
83 90 "bookmark": "Y",
84 91 "node": "0000000000000000000000000000000000000000",
85 92 "rev": -1
86 93 }
87 94 ]
88 95
89 96 bookmarks revset
90 97
91 98 $ hg log -r 'bookmark()'
92 99 changeset: 0:f7b1eb17ad24
93 100 bookmark: X
94 101 user: test
95 102 date: Thu Jan 01 00:00:00 1970 +0000
96 103 summary: 0
97 104
98 105 changeset: 1:925d80f479bb
99 106 bookmark: X2
100 107 tag: tip
101 108 user: test
102 109 date: Thu Jan 01 00:00:00 1970 +0000
103 110 summary: 1
104 111
105 112 $ hg log -r 'bookmark(Y)'
106 113 $ hg log -r 'bookmark(X2)'
107 114 changeset: 1:925d80f479bb
108 115 bookmark: X2
109 116 tag: tip
110 117 user: test
111 118 date: Thu Jan 01 00:00:00 1970 +0000
112 119 summary: 1
113 120
114 121 $ hg log -r 'bookmark("re:X")'
115 122 changeset: 0:f7b1eb17ad24
116 123 bookmark: X
117 124 user: test
118 125 date: Thu Jan 01 00:00:00 1970 +0000
119 126 summary: 0
120 127
121 128 changeset: 1:925d80f479bb
122 129 bookmark: X2
123 130 tag: tip
124 131 user: test
125 132 date: Thu Jan 01 00:00:00 1970 +0000
126 133 summary: 1
127 134
128 135 $ hg log -r 'bookmark("literal:X")'
129 136 changeset: 0:f7b1eb17ad24
130 137 bookmark: X
131 138 user: test
132 139 date: Thu Jan 01 00:00:00 1970 +0000
133 140 summary: 0
134 141
135 142
136 143 $ hg log -r 'bookmark(unknown)'
137 144 abort: bookmark 'unknown' does not exist!
138 145 [255]
139 146 $ hg log -r 'bookmark("literal:unknown")'
140 147 abort: bookmark 'unknown' does not exist!
141 148 [255]
142 149 $ hg log -r 'bookmark("re:unknown")'
143 150 abort: no bookmarks exist that match 'unknown'!
144 151 [255]
145 152 $ hg log -r 'present(bookmark("literal:unknown"))'
146 153 $ hg log -r 'present(bookmark("re:unknown"))'
147 154
148 155 $ hg help revsets | grep 'bookmark('
149 156 "bookmark([name])"
150 157
151 158 bookmarks X and X2 moved to rev 1, Y at rev -1
152 159
153 160 $ hg bookmarks
154 161 X 0:f7b1eb17ad24
155 162 * X2 1:925d80f479bb
156 163 Y -1:000000000000
157 164
158 165 bookmark rev 0 again
159 166
160 167 $ hg bookmark -r 0 Z
161 168
162 169 $ hg update X
163 170 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
164 171 (activating bookmark X)
165 172 $ echo c > c
166 173 $ hg add c
167 174 $ hg commit -m 2
168 175 created new head
169 176
170 177 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
171 178
172 179 $ hg bookmarks
173 180 * X 2:db815d6d32e6
174 181 X2 1:925d80f479bb
175 182 Y -1:000000000000
176 183 Z 0:f7b1eb17ad24
177 184
178 185 rename nonexistent bookmark
179 186
180 187 $ hg bookmark -m A B
181 188 abort: bookmark 'A' does not exist
182 189 [255]
183 190
184 191 rename to existent bookmark
185 192
186 193 $ hg bookmark -m X Y
187 194 abort: bookmark 'Y' already exists (use -f to force)
188 195 [255]
189 196
190 197 force rename to existent bookmark
191 198
192 199 $ hg bookmark -f -m X Y
193 200
194 201 rename bookmark using .
195 202
196 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 207 $ hg bookmark
199 208 X2 1:925d80f479bb
200 209 Y 2:db815d6d32e6
201 210 Z 0:f7b1eb17ad24
202 211 * renamed 2:db815d6d32e6
203 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 216 rename bookmark using . with no active bookmark
207 217
208 218 $ hg book rename-me
209 219 $ hg book -i rename-me
210 220 $ hg book -m . renamed
211 221 abort: no active bookmark
212 222 [255]
213 223 $ hg up -q Y
214 224 $ hg book -d rename-me
215 225
216 226 delete bookmark using .
217 227
218 228 $ hg book delete-me
219 229 $ hg book -d .
220 230 $ hg bookmark
221 231 X2 1:925d80f479bb
222 232 Y 2:db815d6d32e6
223 233 Z 0:f7b1eb17ad24
224 234 $ hg up -q Y
225 235
226 236 delete bookmark using . with no active bookmark
227 237
228 238 $ hg book delete-me
229 239 $ hg book -i delete-me
230 240 $ hg book -d .
231 241 abort: no active bookmark
232 242 [255]
233 243 $ hg up -q Y
234 244 $ hg book -d delete-me
235 245
236 246 list bookmarks
237 247
238 248 $ hg bookmark
239 249 X2 1:925d80f479bb
240 250 * Y 2:db815d6d32e6
241 251 Z 0:f7b1eb17ad24
242 252
243 253 bookmarks from a revset
244 254 $ hg bookmark -r '.^1' REVSET
245 255 $ hg bookmark -r ':tip' TIP
246 256 $ hg up -q TIP
247 257 $ hg bookmarks
248 258 REVSET 0:f7b1eb17ad24
249 259 * TIP 2:db815d6d32e6
250 260 X2 1:925d80f479bb
251 261 Y 2:db815d6d32e6
252 262 Z 0:f7b1eb17ad24
253 263
254 264 $ hg bookmark -d REVSET
255 265 $ hg bookmark -d TIP
256 266
257 267 rename without new name or multiple names
258 268
259 269 $ hg bookmark -m Y
260 270 abort: new bookmark name required
261 271 [255]
262 272 $ hg bookmark -m Y Y2 Y3
263 273 abort: only one new bookmark name allowed
264 274 [255]
265 275
266 276 delete without name
267 277
268 278 $ hg bookmark -d
269 279 abort: bookmark name required
270 280 [255]
271 281
272 282 delete nonexistent bookmark
273 283
274 284 $ hg bookmark -d A
275 285 abort: bookmark 'A' does not exist
276 286 [255]
277 287
278 288 bookmark name with spaces should be stripped
279 289
280 290 $ hg bookmark ' x y '
281 291
282 292 list bookmarks
283 293
284 294 $ hg bookmarks
285 295 X2 1:925d80f479bb
286 296 Y 2:db815d6d32e6
287 297 Z 0:f7b1eb17ad24
288 298 * x y 2:db815d6d32e6
289 299
290 300 look up stripped bookmark name
291 301
292 302 $ hg log -r '"x y"'
293 303 changeset: 2:db815d6d32e6
294 304 bookmark: Y
295 305 bookmark: x y
296 306 tag: tip
297 307 parent: 0:f7b1eb17ad24
298 308 user: test
299 309 date: Thu Jan 01 00:00:00 1970 +0000
300 310 summary: 2
301 311
302 312
303 313 reject bookmark name with newline
304 314
305 315 $ hg bookmark '
306 316 > '
307 317 abort: bookmark names cannot consist entirely of whitespace
308 318 [255]
309 319
310 320 $ hg bookmark -m Z '
311 321 > '
312 322 abort: bookmark names cannot consist entirely of whitespace
313 323 [255]
314 324
315 325 bookmark with reserved name
316 326
317 327 $ hg bookmark tip
318 328 abort: the name 'tip' is reserved
319 329 [255]
320 330
321 331 $ hg bookmark .
322 332 abort: the name '.' is reserved
323 333 [255]
324 334
325 335 $ hg bookmark null
326 336 abort: the name 'null' is reserved
327 337 [255]
328 338
329 339
330 340 bookmark with existing name
331 341
332 342 $ hg bookmark X2
333 343 abort: bookmark 'X2' already exists (use -f to force)
334 344 [255]
335 345
336 346 $ hg bookmark -m Y Z
337 347 abort: bookmark 'Z' already exists (use -f to force)
338 348 [255]
339 349
340 350 bookmark with name of branch
341 351
342 352 $ hg bookmark default
343 353 abort: a bookmark cannot have the name of an existing branch
344 354 [255]
345 355
346 356 $ hg bookmark -m Y default
347 357 abort: a bookmark cannot have the name of an existing branch
348 358 [255]
349 359
350 360 bookmark with integer name
351 361
352 362 $ hg bookmark 10
353 363 abort: cannot use an integer as a name
354 364 [255]
355 365
356 366 bookmark with a name that matches a node id
357 $ hg bookmark 925d80f479bb db815d6d32e6
367 $ hg bookmark 925d80f479bb db815d6d32e6 --config "$TESTHOOK"
358 368 bookmark 925d80f479bb matches a changeset hash
359 369 (did you leave a -r out of an 'hg bookmark' command?)
360 370 bookmark db815d6d32e6 matches a changeset hash
361 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 374 $ hg bookmark -d 925d80f479bb
363 375 $ hg bookmark -d db815d6d32e6
364 376
365 377 $ cd ..
366 378
367 379 bookmark with a name that matches an ambiguous node id
368 380
369 381 $ hg init ambiguous
370 382 $ cd ambiguous
371 383 $ echo 0 > a
372 384 $ hg ci -qAm 0
373 385 $ for i in 1057 2857 4025; do
374 386 > hg up -q 0
375 387 > echo $i > a
376 388 > hg ci -qm $i
377 389 > done
378 390 $ hg up -q null
379 391 $ hg log -r0: -T '{rev}:{node}\n'
380 392 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
381 393 1:c56256a09cd28e5764f32e8e2810d0f01e2e357a
382 394 2:c5623987d205cd6d9d8389bfc40fff9dbb670b48
383 395 3:c562ddd9c94164376c20b86b0b4991636a3bf84f
384 396
385 397 $ hg bookmark -r0 c562
386 398 $ hg bookmarks
387 399 c562 0:b4e73ffab476
388 400
389 401 $ cd ..
390 402
391 403 incompatible options
392 404
393 405 $ cd repo
394 406
395 407 $ hg bookmark -m Y -d Z
396 408 abort: --delete and --rename are incompatible
397 409 [255]
398 410
399 411 $ hg bookmark -r 1 -d Z
400 412 abort: --rev is incompatible with --delete
401 413 [255]
402 414
403 415 $ hg bookmark -r 1 -m Z Y
404 416 abort: --rev is incompatible with --rename
405 417 [255]
406 418
407 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 424 force bookmark back to where it was, should deactivate it
412 425
413 426 $ hg bookmark -fr1 X2
414 427 $ hg bookmarks
415 428 X2 1:925d80f479bb
416 429 Y 2:db815d6d32e6
417 430 Z 0:f7b1eb17ad24
418 431 x y 2:db815d6d32e6
419 432
420 433 forward bookmark to descendant without --force
421 434
422 435 $ hg bookmark Z
423 436 moving bookmark 'Z' forward from f7b1eb17ad24
424 437
425 438 list bookmarks
426 439
427 440 $ hg bookmark
428 441 X2 1:925d80f479bb
429 442 Y 2:db815d6d32e6
430 443 * Z 2:db815d6d32e6
431 444 x y 2:db815d6d32e6
432 445
433 446 revision but no bookmark name
434 447
435 448 $ hg bookmark -r .
436 449 abort: bookmark name required
437 450 [255]
438 451
439 452 bookmark name with whitespace only
440 453
441 454 $ hg bookmark ' '
442 455 abort: bookmark names cannot consist entirely of whitespace
443 456 [255]
444 457
445 458 $ hg bookmark -m Y ' '
446 459 abort: bookmark names cannot consist entirely of whitespace
447 460 [255]
448 461
449 462 invalid bookmark
450 463
451 464 $ hg bookmark 'foo:bar'
452 465 abort: ':' cannot be used in a name
453 466 [255]
454 467
455 468 $ hg bookmark 'foo
456 469 > bar'
457 470 abort: '\n' cannot be used in a name
458 471 [255]
459 472
460 473 the bookmark extension should be ignored now that it is part of core
461 474
462 475 $ echo "[extensions]" >> $HGRCPATH
463 476 $ echo "bookmarks=" >> $HGRCPATH
464 477 $ hg bookmarks
465 478 X2 1:925d80f479bb
466 479 Y 2:db815d6d32e6
467 480 * Z 2:db815d6d32e6
468 481 x y 2:db815d6d32e6
469 482
470 483 test summary
471 484
472 485 $ hg summary
473 486 parent: 2:db815d6d32e6 tip
474 487 2
475 488 branch: default
476 489 bookmarks: *Z Y x y
477 490 commit: (clean)
478 491 update: 1 new changesets, 2 branch heads (merge)
479 492 phases: 3 draft
480 493
481 494 test id
482 495
483 496 $ hg id
484 497 db815d6d32e6 tip Y/Z/x y
485 498
486 499 test rollback
487 500
488 501 $ echo foo > f1
489 502 $ hg bookmark tmp-rollback
490 503 $ hg ci -Amr
491 504 adding f1
492 505 $ hg bookmarks
493 506 X2 1:925d80f479bb
494 507 Y 2:db815d6d32e6
495 508 Z 2:db815d6d32e6
496 509 * tmp-rollback 3:2bf5cfec5864
497 510 x y 2:db815d6d32e6
498 511 $ hg rollback
499 512 repository tip rolled back to revision 2 (undo commit)
500 513 working directory now based on revision 2
501 514 $ hg bookmarks
502 515 X2 1:925d80f479bb
503 516 Y 2:db815d6d32e6
504 517 Z 2:db815d6d32e6
505 518 * tmp-rollback 2:db815d6d32e6
506 519 x y 2:db815d6d32e6
507 520 $ hg bookmark -f Z -r 1
508 521 $ hg rollback
509 522 repository tip rolled back to revision 2 (undo bookmark)
510 523 $ hg bookmarks
511 524 X2 1:925d80f479bb
512 525 Y 2:db815d6d32e6
513 526 Z 2:db815d6d32e6
514 527 * tmp-rollback 2:db815d6d32e6
515 528 x y 2:db815d6d32e6
516 529 $ hg bookmark -d tmp-rollback
517 530
518 531 activate bookmark on working dir parent without --force
519 532
520 533 $ hg bookmark --inactive Z
521 534 $ hg bookmark Z
522 535
523 536 test clone
524 537
525 538 $ hg bookmark -r 2 -i @
526 539 $ hg bookmark -r 2 -i a@
527 540 $ hg bookmarks
528 541 @ 2:db815d6d32e6
529 542 X2 1:925d80f479bb
530 543 Y 2:db815d6d32e6
531 544 * Z 2:db815d6d32e6
532 545 a@ 2:db815d6d32e6
533 546 x y 2:db815d6d32e6
534 547 $ hg clone . cloned-bookmarks
535 548 updating to bookmark @
536 549 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
537 550 $ hg -R cloned-bookmarks bookmarks
538 551 * @ 2:db815d6d32e6
539 552 X2 1:925d80f479bb
540 553 Y 2:db815d6d32e6
541 554 Z 2:db815d6d32e6
542 555 a@ 2:db815d6d32e6
543 556 x y 2:db815d6d32e6
544 557
545 558 test clone with pull protocol
546 559
547 560 $ hg clone --pull . cloned-bookmarks-pull
548 561 requesting all changes
549 562 adding changesets
550 563 adding manifests
551 564 adding file changes
552 565 added 3 changesets with 3 changes to 3 files (+1 heads)
553 566 new changesets f7b1eb17ad24:db815d6d32e6
554 567 updating to bookmark @
555 568 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
556 569 $ hg -R cloned-bookmarks-pull bookmarks
557 570 * @ 2:db815d6d32e6
558 571 X2 1:925d80f479bb
559 572 Y 2:db815d6d32e6
560 573 Z 2:db815d6d32e6
561 574 a@ 2:db815d6d32e6
562 575 x y 2:db815d6d32e6
563 576
564 577 delete multiple bookmarks at once
565 578
566 579 $ hg bookmark -d @ a@
567 580
568 581 test clone with a bookmark named "default" (issue3677)
569 582
570 583 $ hg bookmark -r 1 -f -i default
571 584 $ hg clone . cloned-bookmark-default
572 585 updating to branch default
573 586 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
574 587 $ hg -R cloned-bookmark-default bookmarks
575 588 X2 1:925d80f479bb
576 589 Y 2:db815d6d32e6
577 590 Z 2:db815d6d32e6
578 591 default 1:925d80f479bb
579 592 x y 2:db815d6d32e6
580 593 $ hg -R cloned-bookmark-default parents -q
581 594 2:db815d6d32e6
582 595 $ hg bookmark -d default
583 596
584 597 test clone with a specific revision
585 598
586 599 $ hg clone -r 925d80 . cloned-bookmarks-rev
587 600 adding changesets
588 601 adding manifests
589 602 adding file changes
590 603 added 2 changesets with 2 changes to 2 files
591 604 new changesets f7b1eb17ad24:925d80f479bb
592 605 updating to branch default
593 606 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
594 607 $ hg -R cloned-bookmarks-rev bookmarks
595 608 X2 1:925d80f479bb
596 609
597 610 test clone with update to a bookmark
598 611
599 612 $ hg clone -u Z . ../cloned-bookmarks-update
600 613 updating to branch default
601 614 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
602 615 $ hg -R ../cloned-bookmarks-update bookmarks
603 616 X2 1:925d80f479bb
604 617 Y 2:db815d6d32e6
605 618 * Z 2:db815d6d32e6
606 619 x y 2:db815d6d32e6
607 620
608 621 create bundle with two heads
609 622
610 623 $ hg clone . tobundle
611 624 updating to branch default
612 625 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
613 626 $ echo x > tobundle/x
614 627 $ hg -R tobundle add tobundle/x
615 628 $ hg -R tobundle commit -m'x'
616 629 $ hg -R tobundle update -r -2
617 630 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
618 631 $ echo y > tobundle/y
619 632 $ hg -R tobundle branch test
620 633 marked working directory as branch test
621 634 (branches are permanent and global, did you want a bookmark?)
622 635 $ hg -R tobundle add tobundle/y
623 636 $ hg -R tobundle commit -m'y'
624 637 $ hg -R tobundle bundle tobundle.hg
625 638 searching for changes
626 639 2 changesets found
627 640 $ hg unbundle tobundle.hg
628 641 adding changesets
629 642 adding manifests
630 643 adding file changes
631 644 added 2 changesets with 2 changes to 2 files (+1 heads)
632 645 new changesets 125c9a1d6df6:9ba5f110a0b3
633 646 (run 'hg heads' to see heads, 'hg merge' to merge)
634 647
635 648 update to active bookmark if it's not the parent
636 649
637 650 (it is known issue that fsmonitor can't handle nested repositories. In
638 651 this test scenario, cloned-bookmark-default and tobundle exist in the
639 652 working directory of current repository)
640 653
641 654 $ hg summary
642 655 parent: 2:db815d6d32e6
643 656 2
644 657 branch: default
645 658 bookmarks: *Z Y x y
646 659 commit: 1 added, 1 unknown (new branch head) (no-fsmonitor !)
647 660 commit: 1 added, * unknown (new branch head) (glob) (fsmonitor !)
648 661 update: 2 new changesets (update)
649 662 phases: 5 draft
650 663 $ hg update
651 664 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
652 665 updating bookmark Z
653 666 $ hg bookmarks
654 667 X2 1:925d80f479bb
655 668 Y 2:db815d6d32e6
656 669 * Z 3:125c9a1d6df6
657 670 x y 2:db815d6d32e6
658 671
659 672 pull --update works the same as pull && update
660 673
661 674 $ hg bookmark -r3 Y
662 675 moving bookmark 'Y' forward from db815d6d32e6
663 676 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update
664 677 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update-with-divergence
665 678
666 679 (manual version)
667 680
668 681 $ hg -R ../cloned-bookmarks-manual-update update Y
669 682 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
670 683 (activating bookmark Y)
671 684 $ hg -R ../cloned-bookmarks-manual-update pull .
672 685 pulling from .
673 686 searching for changes
674 687 adding changesets
675 688 adding manifests
676 689 adding file changes
677 690 added 2 changesets with 2 changes to 2 files (+1 heads)
678 691 updating bookmark Y
679 692 updating bookmark Z
680 693 new changesets 125c9a1d6df6:9ba5f110a0b3
681 694 (run 'hg heads' to see heads, 'hg merge' to merge)
682 695
683 696 (# tests strange but with --date crashing when bookmark have to move)
684 697
685 698 $ hg -R ../cloned-bookmarks-manual-update update -d 1986
686 699 abort: revision matching date not found
687 700 [255]
688 701 $ hg -R ../cloned-bookmarks-manual-update update
689 702 updating to active bookmark Y
690 703 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
691 704
692 705 (all in one version)
693 706
694 707 $ hg -R ../cloned-bookmarks-update update Y
695 708 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
696 709 (activating bookmark Y)
697 710 $ hg -R ../cloned-bookmarks-update pull --update .
698 711 pulling from .
699 712 searching for changes
700 713 adding changesets
701 714 adding manifests
702 715 adding file changes
703 716 added 2 changesets with 2 changes to 2 files (+1 heads)
704 717 updating bookmark Y
705 718 updating bookmark Z
706 719 new changesets 125c9a1d6df6:9ba5f110a0b3
707 720 updating to active bookmark Y
708 721 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
709 722
710 723 We warn about divergent during bare update to the active bookmark
711 724
712 725 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update Y
713 726 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
714 727 (activating bookmark Y)
715 728 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks -r X2 Y@1
716 729 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks
717 730 X2 1:925d80f479bb
718 731 * Y 2:db815d6d32e6
719 732 Y@1 1:925d80f479bb
720 733 Z 2:db815d6d32e6
721 734 x y 2:db815d6d32e6
722 735 $ hg -R ../cloned-bookmarks-manual-update-with-divergence pull
723 736 pulling from $TESTTMP/repo (glob)
724 737 searching for changes
725 738 adding changesets
726 739 adding manifests
727 740 adding file changes
728 741 added 2 changesets with 2 changes to 2 files (+1 heads)
729 742 updating bookmark Y
730 743 updating bookmark Z
731 744 new changesets 125c9a1d6df6:9ba5f110a0b3
732 745 (run 'hg heads' to see heads, 'hg merge' to merge)
733 746 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update
734 747 updating to active bookmark Y
735 748 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
736 749 1 other divergent bookmarks for "Y"
737 750
738 751 test wrongly formated bookmark
739 752
740 753 $ echo '' >> .hg/bookmarks
741 754 $ hg bookmarks
742 755 X2 1:925d80f479bb
743 756 Y 3:125c9a1d6df6
744 757 * Z 3:125c9a1d6df6
745 758 x y 2:db815d6d32e6
746 759 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
747 760 $ hg bookmarks
748 761 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
749 762 X2 1:925d80f479bb
750 763 Y 3:125c9a1d6df6
751 764 * Z 3:125c9a1d6df6
752 765 x y 2:db815d6d32e6
753 766
754 767 test missing revisions
755 768
756 769 $ echo "925d80f479b925d80f479bc925d80f479bccabab z" > .hg/bookmarks
757 770 $ hg book
758 771 no bookmarks set
759 772
760 773 test stripping a non-checked-out but bookmarked revision
761 774
762 775 $ hg log --graph
763 776 o changeset: 4:9ba5f110a0b3
764 777 | branch: test
765 778 | tag: tip
766 779 | parent: 2:db815d6d32e6
767 780 | user: test
768 781 | date: Thu Jan 01 00:00:00 1970 +0000
769 782 | summary: y
770 783 |
771 784 | @ changeset: 3:125c9a1d6df6
772 785 |/ user: test
773 786 | date: Thu Jan 01 00:00:00 1970 +0000
774 787 | summary: x
775 788 |
776 789 o changeset: 2:db815d6d32e6
777 790 | parent: 0:f7b1eb17ad24
778 791 | user: test
779 792 | date: Thu Jan 01 00:00:00 1970 +0000
780 793 | summary: 2
781 794 |
782 795 | o changeset: 1:925d80f479bb
783 796 |/ user: test
784 797 | date: Thu Jan 01 00:00:00 1970 +0000
785 798 | summary: 1
786 799 |
787 800 o changeset: 0:f7b1eb17ad24
788 801 user: test
789 802 date: Thu Jan 01 00:00:00 1970 +0000
790 803 summary: 0
791 804
792 805 $ hg book should-end-on-two
793 806 $ hg co --clean 4
794 807 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
795 808 (leaving bookmark should-end-on-two)
796 809 $ hg book four
797 810 $ hg --config extensions.mq= strip 3
798 811 saved backup bundle to * (glob)
799 812 should-end-on-two should end up pointing to revision 2, as that's the
800 813 tipmost surviving ancestor of the stripped revision.
801 814 $ hg log --graph
802 815 @ changeset: 3:9ba5f110a0b3
803 816 | branch: test
804 817 | bookmark: four
805 818 | tag: tip
806 819 | user: test
807 820 | date: Thu Jan 01 00:00:00 1970 +0000
808 821 | summary: y
809 822 |
810 823 o changeset: 2:db815d6d32e6
811 824 | bookmark: should-end-on-two
812 825 | parent: 0:f7b1eb17ad24
813 826 | user: test
814 827 | date: Thu Jan 01 00:00:00 1970 +0000
815 828 | summary: 2
816 829 |
817 830 | o changeset: 1:925d80f479bb
818 831 |/ user: test
819 832 | date: Thu Jan 01 00:00:00 1970 +0000
820 833 | summary: 1
821 834 |
822 835 o changeset: 0:f7b1eb17ad24
823 836 user: test
824 837 date: Thu Jan 01 00:00:00 1970 +0000
825 838 summary: 0
826 839
827 840
828 841 no-op update doesn't deactivate bookmarks
829 842
830 843 (it is known issue that fsmonitor can't handle nested repositories. In
831 844 this test scenario, cloned-bookmark-default and tobundle exist in the
832 845 working directory of current repository)
833 846
834 847 $ hg bookmarks
835 848 * four 3:9ba5f110a0b3
836 849 should-end-on-two 2:db815d6d32e6
837 850 $ hg up four
838 851 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
839 852 $ hg up
840 853 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
841 854 $ hg sum
842 855 parent: 3:9ba5f110a0b3 tip
843 856 y
844 857 branch: test
845 858 bookmarks: *four
846 859 commit: 2 unknown (clean) (no-fsmonitor !)
847 860 commit: * unknown (clean) (glob) (fsmonitor !)
848 861 update: (current)
849 862 phases: 4 draft
850 863
851 864 test clearing divergent bookmarks of linear ancestors
852 865
853 866 $ hg bookmark Z -r 0
854 867 $ hg bookmark Z@1 -r 1
855 868 $ hg bookmark Z@2 -r 2
856 869 $ hg bookmark Z@3 -r 3
857 870 $ hg book
858 871 Z 0:f7b1eb17ad24
859 872 Z@1 1:925d80f479bb
860 873 Z@2 2:db815d6d32e6
861 874 Z@3 3:9ba5f110a0b3
862 875 * four 3:9ba5f110a0b3
863 876 should-end-on-two 2:db815d6d32e6
864 877 $ hg bookmark Z
865 878 moving bookmark 'Z' forward from f7b1eb17ad24
866 879 $ hg book
867 880 * Z 3:9ba5f110a0b3
868 881 Z@1 1:925d80f479bb
869 882 four 3:9ba5f110a0b3
870 883 should-end-on-two 2:db815d6d32e6
871 884
872 885 test clearing only a single divergent bookmark across branches
873 886
874 887 $ hg book foo -r 1
875 888 $ hg book foo@1 -r 0
876 889 $ hg book foo@2 -r 2
877 890 $ hg book foo@3 -r 3
878 891 $ hg book foo -r foo@3
879 892 $ hg book
880 893 * Z 3:9ba5f110a0b3
881 894 Z@1 1:925d80f479bb
882 895 foo 3:9ba5f110a0b3
883 896 foo@1 0:f7b1eb17ad24
884 897 foo@2 2:db815d6d32e6
885 898 four 3:9ba5f110a0b3
886 899 should-end-on-two 2:db815d6d32e6
887 900
888 901 pull --update works the same as pull && update (case #2)
889 902
890 903 It is assumed that "hg pull" itself doesn't update current active
891 904 bookmark ('Y' in tests below).
892 905
893 906 $ hg pull -q ../cloned-bookmarks-update
894 907 divergent bookmark Z stored as Z@2
895 908
896 909 (pulling revision on another named branch with --update updates
897 910 neither the working directory nor current active bookmark: "no-op"
898 911 case)
899 912
900 913 $ echo yy >> y
901 914 $ hg commit -m yy
902 915
903 916 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
904 917 * Y 3:125c9a1d6df6
905 918 $ hg -R ../cloned-bookmarks-update pull . --update
906 919 pulling from .
907 920 searching for changes
908 921 adding changesets
909 922 adding manifests
910 923 adding file changes
911 924 added 1 changesets with 1 changes to 1 files
912 925 divergent bookmark Z stored as Z@default
913 926 adding remote bookmark foo
914 927 adding remote bookmark four
915 928 adding remote bookmark should-end-on-two
916 929 new changesets 5fb12f0f2d51
917 930 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
918 931 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
919 932 3:125c9a1d6df6
920 933 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
921 934 * Y 3:125c9a1d6df6
922 935
923 936 (pulling revision on current named/topological branch with --update
924 937 updates the working directory and current active bookmark)
925 938
926 939 $ hg update -C -q 125c9a1d6df6
927 940 $ echo xx >> x
928 941 $ hg commit -m xx
929 942
930 943 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
931 944 * Y 3:125c9a1d6df6
932 945 $ hg -R ../cloned-bookmarks-update pull . --update
933 946 pulling from .
934 947 searching for changes
935 948 adding changesets
936 949 adding manifests
937 950 adding file changes
938 951 added 1 changesets with 1 changes to 1 files
939 952 divergent bookmark Z stored as Z@default
940 953 new changesets 81dcce76aa0b
941 954 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
942 955 updating bookmark Y
943 956 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
944 957 6:81dcce76aa0b
945 958 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
946 959 * Y 6:81dcce76aa0b
947 960
948 961 $ cd ..
949 962
950 963 ensure changelog is written before bookmarks
951 964 $ hg init orderrepo
952 965 $ cd orderrepo
953 966 $ touch a
954 967 $ hg commit -Aqm one
955 968 $ hg book mybook
956 969 $ echo a > a
957 970
958 971 $ cat > $TESTTMP/pausefinalize.py <<EOF
959 972 > from __future__ import absolute_import
960 973 > import os
961 974 > import time
962 975 > from mercurial import extensions, localrepo
963 976 > def transaction(orig, self, desc, report=None):
964 977 > tr = orig(self, desc, report)
965 978 > def sleep(*args, **kwargs):
966 979 > retry = 20
967 980 > while retry > 0 and not os.path.exists("$TESTTMP/unpause"):
968 981 > retry -= 1
969 982 > time.sleep(0.5)
970 983 > if os.path.exists("$TESTTMP/unpause"):
971 984 > os.remove("$TESTTMP/unpause")
972 985 > # It is important that this finalizer start with 'a', so it runs before
973 986 > # the changelog finalizer appends to the changelog.
974 987 > tr.addfinalize('a-sleep', sleep)
975 988 > return tr
976 989 >
977 990 > def extsetup(ui):
978 991 > # This extension inserts an artifical pause during the transaction
979 992 > # finalizer, so we can run commands mid-transaction-close.
980 993 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
981 994 > transaction)
982 995 > EOF
983 996 $ hg commit -qm two --config extensions.pausefinalize=$TESTTMP/pausefinalize.py &
984 997 $ sleep 2
985 998 $ hg log -r .
986 999 changeset: 0:867bc5792c8c
987 1000 bookmark: mybook
988 1001 tag: tip
989 1002 user: test
990 1003 date: Thu Jan 01 00:00:00 1970 +0000
991 1004 summary: one
992 1005
993 1006 $ hg bookmarks
994 1007 * mybook 0:867bc5792c8c
995 1008 $ touch $TESTTMP/unpause
996 1009
997 1010 $ cd ..
998 1011
999 1012 check whether HG_PENDING makes pending changes only in related
1000 1013 repositories visible to an external hook.
1001 1014
1002 1015 (emulate a transaction running concurrently by copied
1003 1016 .hg/bookmarks.pending in subsequent test)
1004 1017
1005 1018 $ cat > $TESTTMP/savepending.sh <<EOF
1006 1019 > cp .hg/bookmarks.pending .hg/bookmarks.pending.saved
1007 1020 > exit 1 # to avoid adding new bookmark for subsequent tests
1008 1021 > EOF
1009 1022
1010 1023 $ hg init unrelated
1011 1024 $ cd unrelated
1012 1025 $ echo a > a
1013 1026 $ hg add a
1014 1027 $ hg commit -m '#0'
1015 1028 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" bookmarks INVISIBLE
1016 1029 transaction abort!
1017 1030 rollback completed
1018 1031 abort: pretxnclose hook exited with status 1
1019 1032 [255]
1020 1033 $ cp .hg/bookmarks.pending.saved .hg/bookmarks.pending
1021 1034
1022 1035 (check visible bookmarks while transaction running in repo)
1023 1036
1024 1037 $ cat > $TESTTMP/checkpending.sh <<EOF
1025 1038 > echo "@repo"
1026 1039 > hg -R "$TESTTMP/repo" bookmarks
1027 1040 > echo "@unrelated"
1028 1041 > hg -R "$TESTTMP/unrelated" bookmarks
1029 1042 > exit 1 # to avoid adding new bookmark for subsequent tests
1030 1043 > EOF
1031 1044
1032 1045 $ cd ../repo
1033 1046 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" bookmarks NEW
1034 1047 @repo
1035 1048 * NEW 6:81dcce76aa0b
1036 1049 X2 1:925d80f479bb
1037 1050 Y 4:125c9a1d6df6
1038 1051 Z 5:5fb12f0f2d51
1039 1052 Z@1 1:925d80f479bb
1040 1053 Z@2 4:125c9a1d6df6
1041 1054 foo 3:9ba5f110a0b3
1042 1055 foo@1 0:f7b1eb17ad24
1043 1056 foo@2 2:db815d6d32e6
1044 1057 four 3:9ba5f110a0b3
1045 1058 should-end-on-two 2:db815d6d32e6
1046 1059 x y 2:db815d6d32e6
1047 1060 @unrelated
1048 1061 no bookmarks set
1049 1062 transaction abort!
1050 1063 rollback completed
1051 1064 abort: pretxnclose hook exited with status 1
1052 1065 [255]
General Comments 0
You need to be logged in to leave comments. Login now