##// END OF EJS Templates
extensions: copy attributes to wrapper by wrapfunction()...
extensions: copy attributes to wrapper by wrapfunction() Before this patch, new partial function "wrap" had no useful docstring. It makes sense to copy __doc__ and __module__ as we do for wrapcommand().

File last commit:

r28182:e4fe4e90 default
r28311:1b0ef07b default
Show More
bookmarks.py
636 lines | 20.3 KiB | text/x-python | PythonLexer
Matt Mackall
bookmarks: move basic io to core
r13350 # Mercurial bookmark support code
#
# Copyright 2008 David Soria Parra <dsp@php.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Gregory Szorc
bookmarks: use absolute_import
r25917 from __future__ import absolute_import
import errno
Pierre-Yves David
bookmark: read pending data when appropriate...
r23360 import os
Gregory Szorc
bookmarks: use absolute_import
r25917
from .i18n import _
from .node import (
bin,
hex,
)
from . import (
encoding,
lock as lockmod,
obsolete,
util,
)
Matt Mackall
bookmarks: move basic io to core
r13350
Augie Fackler
bookmarks: hoist getbkfile out of bmstore class...
r27186 def _getbkfile(repo):
"""Hook so that extensions that mess with the store can hook bm storage.
For core, this just handles wether we should see pending
bookmarks or the committed ones. Other extensions (like share)
may need to tweak this behavior further.
"""
bkfile = None
if 'HG_PENDING' in os.environ:
try:
bkfile = repo.vfs('bookmarks.pending')
except IOError as inst:
if inst.errno != errno.ENOENT:
raise
if bkfile is None:
bkfile = repo.vfs('bookmarks')
return bkfile
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 class bmstore(dict):
"""Storage for bookmarks.
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 This object should do all bookmark-related reads and writes, so
that it's fairly simple to replace the storage underlying
bookmarks without having to clone the logic surrounding
bookmarks. This type also should manage the active bookmark, if
any.
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922
This particular bmstore implementation stores bookmarks as
{hash}\s{name}\n (the same format as localtags) in
.hg/bookmarks. The mapping is stored as {name: nodeid}.
"""
Matt Mackall
bookmarks: move read methods to core
r13351
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 def __init__(self, repo):
dict.__init__(self)
self._repo = repo
try:
Augie Fackler
bookmarks: hoist getbkfile out of bmstore class...
r27186 bkfile = _getbkfile(repo)
Pierre-Yves David
bookmark: read pending data when appropriate...
r23360 for line in bkfile:
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 line = line.strip()
if not line:
continue
if ' ' not in line:
repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n')
% line)
continue
sha, refspec = line.split(' ', 1)
refspec = encoding.tolocal(refspec)
try:
self[refspec] = repo.changelog.lookup(sha)
except LookupError:
pass
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 if inst.errno != errno.ENOENT:
raise
Augie Fackler
bmstore: add basic clean-state tracking...
r27187 self._clean = True
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 self._active = _readactive(repo, self)
self._aclean = True
@property
def active(self):
return self._active
@active.setter
def active(self, mark):
if mark is not None and mark not in self:
raise AssertionError('bookmark %s does not exist!' % mark)
self._active = mark
self._aclean = False
Augie Fackler
bmstore: add basic clean-state tracking...
r27187
def __setitem__(self, *args, **kwargs):
self._clean = False
return dict.__setitem__(self, *args, **kwargs)
def __delitem__(self, key):
self._clean = False
return dict.__delitem__(self, key)
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922
Pierre-Yves David
bookmark: add a `bmstore.recordupdate` to plug bookmarks into the transaction...
r22665 def recordchange(self, tr):
"""record that bookmarks have been changed in a transaction
The transaction is then responsible for updating the file content."""
tr.addfilegenerator('bookmarks', ('bookmarks',), self._write,
Pierre-Yves David
transaction: use 'location' instead of 'vfs' objects for file generation...
r23317 location='plain')
Pierre-Yves David
bookmarks: inform transaction-related hooks that some bookmarks were moved...
r22941 tr.hookargs['bookmark_moved'] = '1'
Pierre-Yves David
bookmark: add a `bmstore.recordupdate` to plug bookmarks into the transaction...
r22665
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 def write(self):
'''Write bookmarks
Write the given bookmark => hash dictionary to the .hg/bookmarks file
in a format equal to those of localtags.
We also store a backup of the previous state in undo.bookmarks that
can be copied back on rollback.
'''
Pierre-Yves David
bookmark: deprecate 'bmstore.write' method...
r27276 msg = 'bm.write() is deprecated, use bm.recordchange(transaction)'
self._repo.ui.deprecwarn(msg, '3.7')
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 # TODO: writing the active bookmark should probably also use a
# transaction.
self._writeactive()
Augie Fackler
bmstore: add basic clean-state tracking...
r27187 if self._clean:
return
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 repo = self._repo
Laurent Charignon
devel-warn: issue a warning when writing bookmarks without holding the wlock...
r26031 if (repo.ui.configbool('devel', 'all-warnings')
or repo.ui.configbool('devel', 'check-locks')):
l = repo._wlockref and repo._wlockref()
if l is None or not l.held:
repo.ui.develwarn('bookmarks write with no wlock')
FUJIWARA Katsunori
bookmarks: use recordchange instead of writing if transaction is active...
r26520
tr = repo.currenttransaction()
if tr:
self.recordchange(tr)
# invalidatevolatilesets() is omitted because this doesn't
# write changes out actually
return
Ryan McElroy
bookmarks: factor out repository lookup from writing bookmarks file...
r23469 self._writerepo(repo)
Laurent Charignon
repoview: invalidate 'visible' filtered revisions when bookmarks change...
r25569 repo.invalidatevolatilesets()
Ryan McElroy
bookmarks: factor out repository lookup from writing bookmarks file...
r23469
def _writerepo(self, repo):
"""Factored out for extensibility"""
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 rbm = repo._bookmarks
if rbm.active not in self:
rbm.active = None
rbm._writeactive()
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922
Bryan O'Sullivan
with: use context manager for wlock in _writerepo
r27799 with repo.wlock():
Augie Fackler
bmstore: close file in a finally block in _writerepo...
r27188 file_ = repo.vfs('bookmarks', 'w', atomictemp=True)
try:
self._write(file_)
except: # re-raises
file_.discard()
raise
finally:
file_.close()
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 def _writeactive(self):
if self._aclean:
return
Bryan O'Sullivan
with: use context manager for wlock in _writeactive
r27800 with self._repo.wlock():
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 if self._active is not None:
f = self._repo.vfs('bookmarks.current', 'w', atomictemp=True)
try:
f.write(encoding.fromlocal(self._active))
finally:
f.close()
else:
try:
self._repo.vfs.unlink('bookmarks.current')
except OSError as inst:
if inst.errno != errno.ENOENT:
raise
self._aclean = True
Pierre-Yves David
bookmarks: split bookmark serialization and file handling...
r22664 def _write(self, fp):
for name, node in self.iteritems():
fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
Augie Fackler
bmstore: add basic clean-state tracking...
r27187 self._clean = True
Pierre-Yves David
bookmarks: split bookmark serialization and file handling...
r22664
liscju
bookmarks: add 'hg push -B .' for pushing the active bookmark (issue4917)
r28182 def expandname(self, bname):
if bname == '.':
return self.active
return bname
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 def _readactive(repo, marks):
Ryan McElroy
bookmarks: rename readcurrent to readactive (API)...
r24946 """
Get the active bookmark. We can have an active bookmark that updates
itself as we commit. This function returns the name of that bookmark.
It is stored in .hg/bookmarks.current
"""
Matt Mackall
bookmarks: move read methods to core
r13351 mark = None
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 try:
Angel Ezquerra
localrepo: remove all external users of localrepo.opener...
r23877 file = repo.vfs('bookmarks.current')
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 if inst.errno != errno.ENOENT:
raise
return None
try:
Augie Fackler
bookmarks: make _readactive safe when readlines raises ENOENT...
r27685 # No readline() in osutil.posixfile, reading everything is
# cheap.
# Note that it's possible for readlines() here to raise
# IOError, since we might be reading the active mark over
# static-http which only tries to load the file when we try
# to read from it.
David Soria Parra
bookmarks: read current bookmark as utf-8 and convert it to local
r13381 mark = encoding.tolocal((file.readlines() or [''])[0])
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 if mark == '' or mark not in marks:
Matt Mackall
bookmarks: move read methods to core
r13351 mark = None
Augie Fackler
bookmarks: make _readactive safe when readlines raises ENOENT...
r27685 except IOError as inst:
if inst.errno != errno.ENOENT:
raise
return None
Benoit Boissinot
bookmarks: be more restrictive in our Exception catching
r14027 finally:
Matt Mackall
bookmarks: move read methods to core
r13351 file.close()
return mark
Ryan McElroy
bookmarks: rename setcurrent to activate (API)...
r24945 def activate(repo, mark):
"""
Set the given bookmark to be 'active', meaning that this bookmark will
follow new commits that are made.
Matt Mackall
bookmarks: move basic io to core
r13350 The name is recorded in .hg/bookmarks.current
Ryan McElroy
bookmarks: rename setcurrent to activate (API)...
r24945 """
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 repo._bookmarks.active = mark
repo._bookmarks._writeactive()
Matt Mackall
bookmarks: move update into core
r13352
Ryan McElroy
bookmarks: rename unsetcurrent to deactivate (API)...
r24944 def deactivate(repo):
"""
Mads Kiilerich
spelling: trivial spell checking
r26781 Unset the active bookmark in this repository.
Ryan McElroy
bookmarks: rename unsetcurrent to deactivate (API)...
r24944 """
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 repo._bookmarks.active = None
repo._bookmarks._writeactive()
Idan Kamara
update: delete bookmarks.current when explicitly updating to a rev (issue3276)
r16191
Ryan McElroy
bookmarks: simplify iscurrent to isactivewdirparent (API)...
r24986 def isactivewdirparent(repo):
"""
Tell whether the 'active' bookmark (the one that follows new commits)
points to one of the parents of the current working directory (wdir).
Kevin Bullock
update: update to current bookmark if it moved out from under us (issue3682)...
r18471
Ryan McElroy
bookmarks: simplify iscurrent to isactivewdirparent (API)...
r24986 While this is normally the case, it can on occasion be false; for example,
immediately after a pull, the active bookmark can be moved to point
to a place different than the wdir. This is solved by running `hg update`.
"""
mark = repo._activebookmark
Kevin Bullock
update: update to current bookmark if it moved out from under us (issue3682)...
r18471 marks = repo._bookmarks
Ryan McElroy
bookmarks: simplify iscurrent to isactivewdirparent (API)...
r24986 parents = [p.node() for p in repo[None].parents()]
Kevin Bullock
update: update to current bookmark if it moved out from under us (issue3682)...
r18471 return (mark in marks and marks[mark] in parents)
Siddharth Agarwal
bookmarks: factor out delete divergent code...
r18513 def deletedivergent(repo, deletefrom, bm):
'''Delete divergent versions of bm on nodes in deletefrom.
Return True if at least one bookmark was deleted, False otherwise.'''
deleted = False
marks = repo._bookmarks
divergent = [b for b in marks if b.split('@', 1)[0] == bm.split('@', 1)[0]]
for mark in divergent:
Matt Mackall
bookmarks: avoid deleting primary bookmarks on rebase...
r21843 if mark == '@' or '@' not in mark:
# can't be divergent by definition
continue
Siddharth Agarwal
bookmarks: factor out delete divergent code...
r18513 if mark and marks[mark] in deletefrom:
if mark != bm:
del marks[mark]
deleted = True
return deleted
Kevin Bullock
bookmarks: pull --update updates to active bookmark if it moved (issue4007)...
r19523 def calculateupdate(ui, repo, checkout):
'''Return a tuple (targetrev, movemarkfrom) indicating the rev to
check out and where to move the active bookmark from, if needed.'''
movemarkfrom = None
if checkout is None:
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 activemark = repo._activebookmark
Ryan McElroy
bookmarks: simplify iscurrent to isactivewdirparent (API)...
r24986 if isactivewdirparent(repo):
Kevin Bullock
bookmarks: pull --update updates to active bookmark if it moved (issue4007)...
r19523 movemarkfrom = repo['.'].node()
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 elif activemark:
ui.status(_("updating to active bookmark %s\n") % activemark)
checkout = activemark
Kevin Bullock
bookmarks: pull --update updates to active bookmark if it moved (issue4007)...
r19523 return (checkout, movemarkfrom)
Matt Mackall
bookmarks: move update into core
r13352 def update(repo, parents, node):
Sean Farley
bookmarks: resolve divergent bookmarks when moving active bookmark forward...
r19110 deletefrom = parents
Matt Mackall
bookmarks: move update into core
r13352 marks = repo._bookmarks
update = False
Augie Fackler
bmstore: add handling of the active bookmark...
r27698 active = marks.active
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 if not active:
David Soria Parra
bookmarks: delete divergent bookmarks on merge
r16706 return False
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 if marks[active] in parents:
Siddharth Agarwal
bookmarks: factor out delete divergent code...
r18513 new = repo[node]
Sean Farley
bookmarks: resolve divergent bookmarks when moving active bookmark forward...
r19110 divs = [repo[b] for b in marks
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 if b.split('@', 1)[0] == active.split('@', 1)[0]]
Sean Farley
bookmarks: resolve divergent bookmarks when moving active bookmark forward...
r19110 anc = repo.changelog.ancestors([new.rev()])
deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 if validdest(repo, repo[marks[active]], new):
marks[active] = new.node()
Siddharth Agarwal
bookmarks: factor out delete divergent code...
r18513 update = True
Ryan McElroy
bookmarks: rename current to active in variables and comments...
r25100 if deletedivergent(repo, deletefrom, active):
Siddharth Agarwal
bookmarks: factor out delete divergent code...
r18513 update = True
Matt Mackall
bookmarks: move update into core
r13352 if update:
Laurent Charignon
bookmarks: use repo._bookmarks.recordchange instead of repo._bookmarks.write...
r26999 lock = tr = None
try:
lock = repo.lock()
tr = repo.transaction('bookmark')
marks.recordchange(tr)
tr.close()
finally:
lockmod.release(tr, lock)
Kevin Bullock
bookmarks: update and updatecurrentbookmark return status...
r15621 return update
Matt Mackall
bookmarks: move pushkey functions into core
r13353
def listbookmarks(repo):
# We may try to list bookmarks on a repo type that does not
# support it (e.g., statichttprepository).
Augie Fackler
bookmarks: use getattr instead of hasattr
r14946 marks = getattr(repo, '_bookmarks', {})
Matt Mackall
bookmarks: move pushkey functions into core
r13353
d = {}
Kevin Bullock
bookmarks: hide bookmarks on filtered revs from listkeys...
r18496 hasnode = repo.changelog.hasnode
Augie Fackler
bookmarks: use getattr instead of hasattr
r14946 for k, v in marks.iteritems():
Matt Mackall
bookmarks: shadow divergent bookmarks of foo with foo@n
r15613 # don't expose local divergent bookmarks
Kevin Bullock
bookmarks: hide bookmarks on filtered revs from listkeys...
r18496 if hasnode(v) and ('@' not in k or k.endswith('@')):
Matt Mackall
bookmarks: shadow divergent bookmarks of foo with foo@n
r15613 d[k] = hex(v)
Matt Mackall
bookmarks: move pushkey functions into core
r13353 return d
def pushbookmark(repo, key, old, new):
Pierre-Yves David
push: update bookmarks (on server) within a transaction...
r22667 w = l = tr = None
Matt Mackall
bookmarks: move pushkey functions into core
r13353 try:
Pierre-Yves David
push: update bookmarks (on server) within a transaction...
r22667 w = repo.wlock()
l = repo.lock()
tr = repo.transaction('bookmarks')
Matt Mackall
bookmarks: move pushkey functions into core
r13353 marks = repo._bookmarks
Durham Goode
bookmarks: allow pushkey if new equals current...
r22364 existing = hex(marks.get(key, ''))
if existing != old and existing != new:
Matt Mackall
bookmarks: move pushkey functions into core
r13353 return False
if new == '':
del marks[key]
else:
if new not in repo:
return False
marks[key] = repo[new].node()
Pierre-Yves David
push: update bookmarks (on server) within a transaction...
r22667 marks.recordchange(tr)
tr.close()
Matt Mackall
bookmarks: move pushkey functions into core
r13353 return True
finally:
Pierre-Yves David
push: update bookmarks (on server) within a transaction...
r22667 lockmod.release(tr, l, w)
Matt Mackall
bookmarks: move diff to core
r13354
FUJIWARA Katsunori
bookmarks: add function to centralize the logic to compare bookmarks...
r20024 def compare(repo, srcmarks, dstmarks,
srchex=None, dsthex=None, targets=None):
'''Compare bookmarks between srcmarks and dstmarks
This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
differ, invalid)", each are list of bookmarks below:
:addsrc: added on src side (removed on dst side, perhaps)
:adddst: added on dst side (removed on src side, perhaps)
:advsrc: advanced on src side
:advdst: advanced on dst side
:diverge: diverge
:differ: changed, but changeset referred on src is unknown on dst
:invalid: unknown on both side
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 :same: same on both side
FUJIWARA Katsunori
bookmarks: add function to centralize the logic to compare bookmarks...
r20024
Each elements of lists in result tuple is tuple "(bookmark name,
changeset ID on source side, changeset ID on destination
side)". Each changeset IDs are 40 hexadecimal digit string or
None.
Changeset IDs of tuples in "addsrc", "adddst", "differ" or
"invalid" list may be unknown for repo.
This function expects that "srcmarks" and "dstmarks" return
changeset ID in 40 hexadecimal digit string for specified
bookmark. If not so (e.g. bmstore "repo._bookmarks" returning
binary value), "srchex" or "dsthex" should be specified to convert
into such form.
If "targets" is specified, only bookmarks listed in it are
examined.
'''
if not srchex:
srchex = lambda x: x
if not dsthex:
dsthex = lambda x: x
if targets:
bset = set(targets)
else:
srcmarkset = set(srcmarks)
dstmarkset = set(dstmarks)
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 bset = srcmarkset | dstmarkset
FUJIWARA Katsunori
bookmarks: add function to centralize the logic to compare bookmarks...
r20024
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 results = ([], [], [], [], [], [], [], [])
FUJIWARA Katsunori
bookmarks: add function to centralize the logic to compare bookmarks...
r20024 addsrc = results[0].append
adddst = results[1].append
advsrc = results[2].append
advdst = results[3].append
diverge = results[4].append
differ = results[5].append
invalid = results[6].append
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 same = results[7].append
FUJIWARA Katsunori
bookmarks: add function to centralize the logic to compare bookmarks...
r20024
for b in sorted(bset):
if b not in srcmarks:
if b in dstmarks:
adddst((b, None, dsthex(dstmarks[b])))
else:
invalid((b, None, None))
elif b not in dstmarks:
addsrc((b, srchex(srcmarks[b]), None))
else:
scid = srchex(srcmarks[b])
dcid = dsthex(dstmarks[b])
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 if scid == dcid:
same((b, scid, dcid))
elif scid in repo and dcid in repo:
FUJIWARA Katsunori
bookmarks: add function to centralize the logic to compare bookmarks...
r20024 sctx = repo[scid]
dctx = repo[dcid]
if sctx.rev() < dctx.rev():
if validdest(repo, sctx, dctx):
advdst((b, scid, dcid))
else:
diverge((b, scid, dcid))
else:
if validdest(repo, dctx, sctx):
advsrc((b, scid, dcid))
else:
diverge((b, scid, dcid))
else:
# it is too expensive to examine in detail, in this case
differ((b, scid, dcid))
return results
FUJIWARA Katsunori
bookmarks: reuse @number bookmark, if it refers changeset referred remotely...
r24355 def _diverge(ui, b, path, localmarks, remotenode):
FUJIWARA Katsunori
bookmarks: prevent divergent bookmark from being updated unexpectedly...
r24353 '''Return appropriate diverged bookmark for specified ``path``
This returns None, if it is failed to assign any divergent
bookmark name.
FUJIWARA Katsunori
bookmarks: reuse @number bookmark, if it refers changeset referred remotely...
r24355
This reuses already existing one with "@number" suffix, if it
refers ``remotenode``.
FUJIWARA Katsunori
bookmarks: prevent divergent bookmark from being updated unexpectedly...
r24353 '''
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 if b == '@':
b = ''
# try to use an @pathalias suffix
# if an @pathalias already exists, we overwrite (update) it
Matt Mackall
bookmarks: fix divergent bookmark path normalization
r22629 if path.startswith("file:"):
path = util.url(path).path
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 for p, u in ui.configitems("paths"):
Matt Mackall
bookmarks: fix divergent bookmark path normalization
r22629 if u.startswith("file:"):
u = util.url(u).path
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 if path == u:
FUJIWARA Katsunori
bookmarks: check @pathalias suffix before available @number for efficiency...
r24354 return '%s@%s' % (b, p)
# assign a unique "@number" suffix newly
for x in range(1, 100):
n = '%s@%d' % (b, x)
FUJIWARA Katsunori
bookmarks: reuse @number bookmark, if it refers changeset referred remotely...
r24355 if n not in localmarks or localmarks[n] == remotenode:
FUJIWARA Katsunori
bookmarks: check @pathalias suffix before available @number for efficiency...
r24354 return n
return None
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025
Pierre-Yves David
pull: perform bookmark updates in the transaction
r22666 def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()):
David Soria Parra
bookmarks: separate bookmarks update code from localrepo's pull....
r13646 ui.debug("checking for updated bookmarks\n")
Augie Fackler
bookmarks: introduce a bmstore to manage bookmark persistence...
r17922 localmarks = repo._bookmarks
Gregory Szorc
bookmarks: explicitly track identical bookmarks...
r23081 (addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 ) = compare(repo, remotemarks, localmarks, dsthex=hex)
Matt Mackall
bookmarks: mark divergent bookmarks with book@pathalias when source in [paths]
r15614
Pierre-Yves David
bookmarks: allow `updatefromremote` to be quiet...
r22644 status = ui.status
warn = ui.warn
if ui.configbool('ui', 'quietbookmarkmove', False):
status = warn = ui.debug
Pierre-Yves David
pull: merge bookmark updates and imports...
r22659 explicit = set(explicit)
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 changed = []
for b, scid, dcid in addsrc:
if scid in repo: # add remote bookmarks for changes we already have
Pierre-Yves David
bookmarks: allow `updatefromremote` to be quiet...
r22644 changed.append((b, bin(scid), status,
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 _("adding remote bookmark %s\n") % (b)))
Pierre-Yves David
bookmark: informs of failure to upgrade a bookmark...
r25564 elif b in explicit:
explicit.remove(b)
ui.warn(_("remote bookmark %s points to locally missing %s\n")
% (b, scid[:12]))
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 for b, scid, dcid in advsrc:
Pierre-Yves David
bookmarks: allow `updatefromremote` to be quiet...
r22644 changed.append((b, bin(scid), status,
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 _("updating bookmark %s\n") % (b)))
Pierre-Yves David
pull: merge bookmark updates and imports...
r22659 # remove normal movement from explicit set
explicit.difference_update(d[0] for d in changed)
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 for b, scid, dcid in diverge:
Pierre-Yves David
pull: merge bookmark updates and imports...
r22659 if b in explicit:
explicit.discard(b)
changed.append((b, bin(scid), status,
Pierre-Yves David
bookmarks: fix formatting of exchange message (issue4439)...
r23199 _("importing bookmark %s\n") % (b)))
Pierre-Yves David
pull: merge bookmark updates and imports...
r22659 else:
FUJIWARA Katsunori
bookmarks: reuse @number bookmark, if it refers changeset referred remotely...
r24355 snode = bin(scid)
db = _diverge(ui, b, path, localmarks, snode)
FUJIWARA Katsunori
bookmarks: prevent divergent bookmark from being updated unexpectedly...
r24353 if db:
FUJIWARA Katsunori
bookmarks: reuse @number bookmark, if it refers changeset referred remotely...
r24355 changed.append((db, snode, warn,
FUJIWARA Katsunori
bookmarks: prevent divergent bookmark from being updated unexpectedly...
r24353 _("divergent bookmark %s stored as %s\n") %
(b, db)))
else:
warn(_("warning: failed to assign numbered name "
"to divergent bookmark %s\n") % (b))
Pierre-Yves David
pull: merge bookmark updates and imports...
r22659 for b, scid, dcid in adddst + advdst:
if b in explicit:
explicit.discard(b)
changed.append((b, bin(scid), status,
Pierre-Yves David
bookmarks: fix formatting of exchange message (issue4439)...
r23199 _("importing bookmark %s\n") % (b)))
Pierre-Yves David
bookmark: informs of failure to upgrade a bookmark...
r25564 for b, scid, dcid in differ:
if b in explicit:
explicit.remove(b)
ui.warn(_("remote bookmark %s points to locally missing %s\n")
% (b, scid[:12]))
Pierre-Yves David
pull: merge bookmark updates and imports...
r22659
David Soria Parra
bookmarks: separate bookmarks update code from localrepo's pull....
r13646 if changed:
Pierre-Yves David
pull: perform bookmark updates in the transaction
r22666 tr = trfunc()
FUJIWARA Katsunori
bookmarks: rewrite "updatefromremote()" by "compare()"...
r20025 for b, node, writer, msg in sorted(changed):
localmarks[b] = node
writer(msg)
Pierre-Yves David
pull: perform bookmark updates in the transaction
r22666 localmarks.recordchange(tr)
David Soria Parra
bookmarks: separate bookmarks update code from localrepo's pull....
r13646
FUJIWARA Katsunori
bookmarks: add incoming() to replace diff() for incoming bookmarks...
r24397 def incoming(ui, repo, other):
'''Show bookmarks incoming from other to repo
'''
ui.status(_("searching for changed bookmarks\n"))
r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
dsthex=hex)
addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
incomings = []
if ui.debugflag:
getid = lambda id: id
else:
getid = lambda id: id[:12]
FUJIWARA Katsunori
bookmarks: show detailed status about incoming bookmarks...
r24660 if ui.verbose:
def add(b, id, st):
incomings.append(" %-25s %s %s\n" % (b, getid(id), st))
else:
def add(b, id, st):
incomings.append(" %-25s %s\n" % (b, getid(id)))
FUJIWARA Katsunori
bookmarks: add incoming() to replace diff() for incoming bookmarks...
r24397 for b, scid, dcid in addsrc:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "added" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about incoming bookmarks...
r24660 add(b, scid, _('added'))
FUJIWARA Katsunori
bookmarks: show incoming bookmarks more exactly...
r24657 for b, scid, dcid in advsrc:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "advanced" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about incoming bookmarks...
r24660 add(b, scid, _('advanced'))
FUJIWARA Katsunori
bookmarks: show incoming bookmarks more exactly...
r24657 for b, scid, dcid in diverge:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "diverged" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about incoming bookmarks...
r24660 add(b, scid, _('diverged'))
FUJIWARA Katsunori
bookmarks: show incoming bookmarks more exactly...
r24657 for b, scid, dcid in differ:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "changed" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about incoming bookmarks...
r24660 add(b, scid, _('changed'))
FUJIWARA Katsunori
bookmarks: add incoming() to replace diff() for incoming bookmarks...
r24397
if not incomings:
ui.status(_("no changed bookmarks found\n"))
return 1
for s in sorted(incomings):
ui.write(s)
return 0
FUJIWARA Katsunori
bookmarks: add outgoing() to replace diff() for outgoing bookmarks...
r24398 def outgoing(ui, repo, other):
'''Show bookmarks outgoing from repo to other
'''
ui.status(_("searching for changed bookmarks\n"))
r = compare(repo, repo._bookmarks, other.listkeys('bookmarks'),
srchex=hex)
addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
outgoings = []
if ui.debugflag:
getid = lambda id: id
else:
getid = lambda id: id[:12]
FUJIWARA Katsunori
bookmarks: show detailed status about outgoing bookmarks...
r24661 if ui.verbose:
def add(b, id, st):
outgoings.append(" %-25s %s %s\n" % (b, getid(id), st))
else:
def add(b, id, st):
outgoings.append(" %-25s %s\n" % (b, getid(id)))
FUJIWARA Katsunori
bookmarks: add outgoing() to replace diff() for outgoing bookmarks...
r24398 for b, scid, dcid in addsrc:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "added refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about outgoing bookmarks...
r24661 add(b, scid, _('added'))
FUJIWARA Katsunori
bookmarks: show outgoing bookmarks more exactly...
r24658 for b, scid, dcid in adddst:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "deleted" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about outgoing bookmarks...
r24661 add(b, ' ' * 40, _('deleted'))
FUJIWARA Katsunori
bookmarks: show outgoing bookmarks more exactly...
r24658 for b, scid, dcid in advsrc:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "advanced" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about outgoing bookmarks...
r24661 add(b, scid, _('advanced'))
FUJIWARA Katsunori
bookmarks: show outgoing bookmarks more exactly...
r24658 for b, scid, dcid in diverge:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "diverged" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about outgoing bookmarks...
r24661 add(b, scid, _('diverged'))
FUJIWARA Katsunori
bookmarks: show outgoing bookmarks more exactly...
r24658 for b, scid, dcid in differ:
Wagner Bruna
bookmarks: add i18n hints to bookmark sync states
r24832 # i18n: "changed" refers to a bookmark
FUJIWARA Katsunori
bookmarks: show detailed status about outgoing bookmarks...
r24661 add(b, scid, _('changed'))
FUJIWARA Katsunori
bookmarks: add outgoing() to replace diff() for outgoing bookmarks...
r24398
if not outgoings:
ui.status(_("no changed bookmarks found\n"))
return 1
for s in sorted(outgoings):
ui.write(s)
return 0
FUJIWARA Katsunori
bookmarks: rewrite comparing bookmarks in commands.summary() by compare()...
r24400 def summary(repo, other):
'''Compare bookmarks between repo and other for "hg summary" output
This returns "(# of incoming, # of outgoing)" tuple.
'''
r = compare(repo, other.listkeys('bookmarks'), repo._bookmarks,
dsthex=hex)
addsrc, adddst, advsrc, advdst, diverge, differ, invalid, same = r
return (len(addsrc), len(adddst))
Pierre-Yves David
bookmarks: extract valid destination logic in a dedicated function...
r17550 def validdest(repo, old, new):
"""Is the new bookmark destination a valid update from the old one"""
Pierre-Yves David
clfilter: `bookmark.validdest` should run on unfiltered repo...
r18008 repo = repo.unfiltered()
Pierre-Yves David
bookmark: take successors into account when updating (issue3561)...
r17551 if old == new:
# Old == new -> nothing to update.
FUJIWARA Katsunori
bookmarks: avoid redundant creation/assignment of "validdests" in "validdest()"
r17625 return False
Pierre-Yves David
bookmark: take successors into account when updating (issue3561)...
r17551 elif not old:
# old is nullrev, anything is valid.
# (new != nullrev has been excluded by the previous check)
FUJIWARA Katsunori
bookmarks: avoid redundant creation/assignment of "validdests" in "validdest()"
r17625 return True
Pierre-Yves David
bookmark: take successors into account when updating (issue3561)...
r17551 elif repo.obsstore:
Pierre-Yves David
obsolete: extract foreground computation from bookmark.validdest...
r18984 return new.node() in obsolete.foreground(repo, [old.node()])
Pierre-Yves David
bookmark: take successors into account when updating (issue3561)...
r17551 else:
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r24180 # still an independent clause as it is lazier (and therefore faster)
FUJIWARA Katsunori
bookmarks: use "changectx.descendant()" for efficient descendant examination...
r17627 return old.descendant(new)