##// END OF EJS Templates
sslutil: support defining cipher list...
sslutil: support defining cipher list Python 2.7 supports specifying a custom cipher list to TLS sockets. Advanced users may wish to specify a custom cipher list to increase security. Or in some cases they may wish to prefer weaker ciphers in order to increase performance (e.g. when doing stream clones of very large repositories). This patch introduces a [hostsecurity] config option for defining the cipher list. The help documentation states that it is for advanced users only. Honestly, I'm a bit on the fence about providing this because it is a footgun and can be used to decrease security. However, there are legitimate use cases for it, so I think support should be provided.

File last commit:

r29284:1c716700 default
r29577:9654ef41 default
Show More
destutil.py
437 lines | 16.4 KiB | text/x-python | PythonLexer
Pierre-Yves David
update: move default destination computation to a function...
r26569 # destutil.py - Mercurial utility function for command destination
#
# Copyright Matt Mackall <mpm@selenic.com> and other
#
# 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
destutil: use absolute_import
r27333 from __future__ import absolute_import
Pierre-Yves David
update: move default destination computation to a function...
r26569 from .i18n import _
from . import (
Pierre-Yves David
destupdate: also include bookmark related logic...
r26641 bookmarks,
Pierre-Yves David
update: move default destination computation to a function...
r26569 error,
obsolete,
)
Pierre-Yves David
destupdate: extract validation logic...
r26720 def _destupdatevalidate(repo, rev, clean, check):
"""validate that the destination comply to various rules
This exists as its own function to help wrapping from extensions."""
wc = repo[None]
p1 = wc.p1()
if not clean:
# Check that the update is linear.
#
# Mercurial do not allow update-merge for non linear pattern
# (that would be technically possible but was considered too confusing
# for user a long time ago)
#
# See mercurial.merge.update for details
if p1.rev() not in repo.changelog.ancestors([rev], inclusive=True):
dirty = wc.dirty(missing=True)
foreground = obsolete.foreground(repo, [p1.node()])
if not repo[rev].node() in foreground:
if dirty:
msg = _("uncommitted changes")
hint = _("commit and merge, or update --clean to"
" discard changes")
raise error.UpdateAbort(msg, hint=hint)
elif not check: # destination is not a descendant.
msg = _("not a linear update")
hint = _("merge or update --check to force update")
raise error.UpdateAbort(msg, hint=hint)
Pierre-Yves David
destupdate: extract logic based on obsolescence marker in its own function...
r26723 def _destupdateobs(repo, clean, check):
"""decide of an update destination from obsolescence markers"""
Pierre-Yves David
update: move default destination computation to a function...
r26569 node = None
wc = repo[None]
p1 = wc.p1()
Pierre-Yves David
destupdate: extract logic based on obsolescence marker in its own function...
r26723 movemark = None
Pierre-Yves David
update: move default destination computation to a function...
r26569
if p1.obsolete() and not p1.children():
# allow updating to successors
successors = obsolete.successorssets(repo, p1.node())
# behavior of certain cases is as follows,
#
# divergent changesets: update to highest rev, similar to what
# is currently done when there are more than one head
# (i.e. 'tip')
#
# replaced changesets: same as divergent except we know there
# is no conflict
#
# pruned changeset: no update is done; though, we could
# consider updating to the first non-obsolete parent,
# similar to what is current done for 'hg prune'
if successors:
# flatten the list here handles both divergent (len > 1)
# and the usual case (len = 1)
successors = [n for sub in successors for n in sub]
# get the max revision for the given successors set,
# i.e. the 'tip' of a set
node = repo.revs('max(%ln)', successors).first()
Pierre-Yves David
destupdate: move obsolete handling first...
r26722 if bookmarks.isactivewdirparent(repo):
movemark = repo['.'].node()
Pierre-Yves David
destupdate: extract logic based on obsolescence marker in its own function...
r26723 return node, movemark, None
Pierre-Yves David
destupdate: extract logic based on bookmarks in its own function...
r26724 def _destupdatebook(repo, clean, check):
"""decide on an update destination from active bookmark"""
# we also move the active bookmark, if any
activemark = None
node, movemark = bookmarks.calculateupdate(repo.ui, repo, None)
if node is not None:
activemark = node
return node, movemark, activemark
Pierre-Yves David
destupdate: extract logic based on branch in its own function...
r26725 def _destupdatebranch(repo, clean, check):
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 """decide on an update destination from current branch
This ignores closed branch heads.
"""
Pierre-Yves David
destupdate: extract logic based on branch in its own function...
r26725 wc = repo[None]
movemark = node = None
FUJIWARA Katsunori
destutil: replace wc.branch() invocations by cached value for efficiency
r28235 currentbranch = wc.branch()
liscju
update: fix bare --clean to work on new branch (issue5003) (BC)...
r29284
if clean:
currentbranch = repo['.'].branch()
FUJIWARA Katsunori
destutil: use cached branch information instead of query for efficiency...
r28236 if currentbranch in repo.branchmap():
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 heads = repo.branchheads(currentbranch)
FUJIWARA Katsunori
destutil: use cached branch information instead of query for efficiency...
r28236 if heads:
node = repo.revs('max(.::(%ln))', heads).first()
Pierre-Yves David
destupdate: extract logic based on branch in its own function...
r26725 if bookmarks.isactivewdirparent(repo):
movemark = repo['.'].node()
Yuya Nishihara
update: resurrect bare update from null parent to tip-most branch head...
r28924 elif currentbranch == 'default' and not wc.p1():
# "null" parent belongs to "default" branch, but it doesn't exist, so
# update to the tipmost non-closed branch head
node = repo.revs('max(head() and not closed())').first()
FUJIWARA Katsunori
destutil: use cached branch information instead of query for efficiency...
r28236 else:
liscju
update: fix bare update to work on new branch...
r28903 node = repo['.'].node()
Pierre-Yves David
destupdate: extract logic based on branch in its own function...
r26725 return node, movemark, None
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 def _destupdatebranchfallback(repo, clean, check):
"""decide on an update destination from closed heads in current branch"""
wc = repo[None]
currentbranch = wc.branch()
movemark = None
if currentbranch in repo.branchmap():
# here, all descendant branch heads are closed
heads = repo.branchheads(currentbranch, closed=True)
assert heads, "any branch has at least one head"
node = repo.revs('max(.::(%ln))', heads).first()
assert node is not None, ("any revision has at least "
"one descendant branch head")
if bookmarks.isactivewdirparent(repo):
movemark = repo['.'].node()
else:
# here, no "default" branch, and all branches are closed
node = repo.lookup('tip')
assert node is not None, "'tip' exists even in empty repository"
return node, movemark, None
Pierre-Yves David
destupdate: have a generic and extensible way to run each step...
r26726 # order in which each step should be evalutated
# steps are run until one finds a destination
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
Pierre-Yves David
destupdate: have a generic and extensible way to run each step...
r26726 # mapping to ease extension overriding steps.
destupdatestepmap = {'evolution': _destupdateobs,
'bookmark': _destupdatebook,
'branch': _destupdatebranch,
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 'branchfallback': _destupdatebranchfallback,
Pierre-Yves David
destupdate: have a generic and extensible way to run each step...
r26726 }
Pierre-Yves David
destupdate: extract logic based on obsolescence marker in its own function...
r26723 def destupdate(repo, clean=False, check=False):
"""destination for bare update operation
return (rev, movemark, activemark)
- rev: the revision to update to,
- movemark: node to move the active bookmark from
(cf bookmark.calculate update),
- activemark: a bookmark to activate at the end of the update.
"""
Pierre-Yves David
destupdate: have a generic and extensible way to run each step...
r26726 node = movemark = activemark = None
Pierre-Yves David
destupdate: extract logic based on obsolescence marker in its own function...
r26723
Pierre-Yves David
destupdate: have a generic and extensible way to run each step...
r26726 for step in destupdatesteps:
node, movemark, activemark = destupdatestepmap[step](repo, clean, check)
if node is not None:
break
Pierre-Yves David
destupdate: move the check related to the "clean" logic in the function...
r26628 rev = repo[node].rev()
Pierre-Yves David
destupdate: extract validation logic...
r26720 _destupdatevalidate(repo, rev, clean, check)
Pierre-Yves David
destupdate: move the check related to the "clean" logic in the function...
r26628
Pierre-Yves David
destupdate: also include bookmark related logic...
r26641 return rev, movemark, activemark
Pierre-Yves David
destutil: move default merge destination into a function...
r26714
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 msgdestmerge = {
# too many matching divergent bookmark
'toomanybookmarks':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_("multiple matching bookmarks to merge -"
" please merge with an explicit rev or bookmark"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 'rebase':
(_("multiple matching bookmarks to rebase -"
" please rebase to an explicit rev or bookmark"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # no other matching divergent bookmark
'nootherbookmarks':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_("no matching bookmark to merge - "
"please merge with an explicit rev or bookmark"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 'rebase':
(_("no matching bookmark to rebase - "
"please rebase to an explicit rev or bookmark"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # branch have too many unbookmarked heads, no obvious destination
'toomanyheads':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_("branch '%s' has %d heads - please merge with an explicit rev"),
_("run 'hg heads .' to see heads")),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 'rebase':
(_("branch '%s' has %d heads - please rebase to an explicit rev"),
_("run 'hg heads .' to see heads")),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # branch have no other unbookmarked heads
'bookmarkedheads':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_("heads are bookmarked - please merge with an explicit rev"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 'rebase':
(_("heads are bookmarked - please rebase to an explicit rev"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # branch have just a single heads, but there is other branches
'nootherbranchheads':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_("branch '%s' has one head - please merge with an explicit rev"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 'rebase':
(_("branch '%s' has one head - please rebase to an explicit rev"),
_("run 'hg heads' to see all heads")),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # repository have a single head
'nootherheads':
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 {'merge':
(_('nothing to merge'),
None),
'rebase':
(_('nothing to rebase'),
None),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # repository have a single head and we are not on it
'nootherheadsbehind':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_('nothing to merge'),
_("use 'hg update' instead")),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 'rebase':
(_('nothing to rebase'),
_("use 'hg update' instead")),
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 # We are not on a head
'notatheads':
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 {'merge':
(_('working directory not at a head revision'),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 _("use 'hg update' or merge with an explicit revision")),
'rebase':
(_('working directory not at a head revision'),
_("use 'hg update' or rebase to an explicit revision"))
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 },
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 'emptysourceset':
{'merge':
(_('source set is empty'),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 None),
'rebase':
(_('source set is empty'),
None),
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 },
'multiplebranchessourceset':
{'merge':
(_('source set is rooted in multiple branches'),
Pierre-Yves David
rebase: choose default destination the same way as 'hg merge' (BC)...
r28189 None),
'rebase':
(_('rebaseset is rooted in multiple named branches'),
_('specify an explicit destination with --dest')),
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 },
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 }
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 def _destmergebook(repo, action='merge', sourceset=None, destspace=None):
Pierre-Yves David
destmerge: extract logic based on bookmark into its own function...
r26727 """find merge destination in the active bookmark case"""
node = None
bmheads = repo.bookmarkheads(repo._activebookmark)
curhead = repo[repo._activebookmark].node()
if len(bmheads) == 2:
if curhead == bmheads[0]:
node = bmheads[1]
else:
node = bmheads[0]
elif len(bmheads) > 2:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['toomanybookmarks'][action]
Pierre-Yves David
destutil: add more precise error classes for destmerge...
r28141 raise error.ManyMergeDestAbort(msg, hint=hint)
Pierre-Yves David
destmerge: extract logic based on bookmark into its own function...
r26727 elif len(bmheads) <= 1:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['nootherbookmarks'][action]
Pierre-Yves David
destutil: add more precise error classes for destmerge...
r28141 raise error.NoMergeDestAbort(msg, hint=hint)
Pierre-Yves David
destmerge: extract logic based on bookmark into its own function...
r26727 assert node is not None
return node
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 def _destmergebranch(repo, action='merge', sourceset=None, onheadcheck=True,
destspace=None):
Pierre-Yves David
destmerge: extract logic based on branch heads in its own function...
r26728 """find merge destination based on branch heads"""
node = None
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139
if sourceset is None:
sourceset = [repo[repo.dirstate.p1()].rev()]
branch = repo.dirstate.branch()
elif not sourceset:
msg, hint = msgdestmerge['emptysourceset'][action]
Pierre-Yves David
destutil: add more precise error classes for destmerge...
r28141 raise error.NoMergeDestAbort(msg, hint=hint)
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 else:
branch = None
for ctx in repo.set('roots(%ld::%ld)', sourceset, sourceset):
if branch is not None and ctx.branch() != branch:
msg, hint = msgdestmerge['multiplebranchessourceset'][action]
Pierre-Yves David
destutil: add more precise error classes for destmerge...
r28141 raise error.ManyMergeDestAbort(msg, hint=hint)
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 branch = ctx.branch()
Pierre-Yves David
destmerge: extract logic based on branch heads in its own function...
r26728 bheads = repo.branchheads(branch)
Pierre-Yves David
destutil: ensure we offer 'hg update' hint when not at head in all cases...
r28161 onhead = repo.revs('%ld and %ln', sourceset, bheads)
if onheadcheck and not onhead:
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 # Case A: working copy if not on a head. (merge only)
Pierre-Yves David
destutil: document various failure cases...
r28105 #
# This is probably a user mistake We bailout pointing at 'hg update'
Pierre-Yves David
merge: give priority to "not at head" failures for bare 'hg merge'...
r28103 if len(repo.heads()) <= 1:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['nootherheadsbehind'][action]
Pierre-Yves David
merge: give priority to "not at head" failures for bare 'hg merge'...
r28103 else:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['notatheads'][action]
Pierre-Yves David
merge: give priority to "not at head" failures for bare 'hg merge'...
r28103 raise error.Abort(msg, hint=hint)
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 # remove heads descendants of source from the set
bheads = list(repo.revs('%ln - (%ld::)', bheads, sourceset))
Pierre-Yves David
destutil: remove current head from list of candidates early...
r28138 # filters out bookmarked heads
Pierre-Yves David
destutil: allow to specify an explicit source for the merge...
r28139 nbhs = list(repo.revs('%ld - bookmark()', bheads))
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043
if destspace is not None:
# restrict search space
# used in the 'hg pull --rebase' case, see issue 5214.
nbhs = list(repo.revs('%ld and %ld', destspace, nbhs))
Pierre-Yves David
destutil: remove current head from list of candidates early...
r28138 if len(nbhs) > 1:
# Case B: There is more than 1 other anonymous heads
Pierre-Yves David
destutil: document various failure cases...
r28105 #
# This means that there will be more than 1 candidate. This is
# ambiguous. We abort asking the user to pick as explicit destination
# instead.
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['toomanyheads'][action]
Pierre-Yves David
destutil: remove current head from list of candidates early...
r28138 msg %= (branch, len(bheads) + 1)
Pierre-Yves David
destutil: add more precise error classes for destmerge...
r28141 raise error.ManyMergeDestAbort(msg, hint=hint)
Pierre-Yves David
destutil: remove current head from list of candidates early...
r28138 elif not nbhs:
# Case B: There is no other anonymous heads
Pierre-Yves David
destutil: document various failure cases...
r28105 #
# This means that there is no natural candidate to merge with.
# We abort, with various messages for various cases.
Pierre-Yves David
destutil: remove current head from list of candidates early...
r28138 if bheads:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['bookmarkedheads'][action]
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 elif len(repo.heads()) > 1:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['nootherbranchheads'][action]
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 msg %= branch
Pierre-Yves David
destutil: ensure we offer 'hg update' hint when not at head in all cases...
r28161 elif not onhead:
# if 'onheadcheck == False' (rebase case),
# this was not caught in Case A.
msg, hint = msgdestmerge['nootherheadsbehind'][action]
Pierre-Yves David
destutil: extract all 'mergedest' abort messages into a dictionary...
r28102 else:
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 msg, hint = msgdestmerge['nootherheads'][action]
Pierre-Yves David
destutil: add more precise error classes for destmerge...
r28141 raise error.NoMergeDestAbort(msg, hint=hint)
Pierre-Yves David
destmerge: extract logic based on branch heads in its own function...
r26728 else:
node = nbhs[0]
assert node is not None
return node
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 def destmerge(repo, action='merge', sourceset=None, onheadcheck=True,
destspace=None):
Pierre-Yves David
destutil: add an 'action' layer to the destmerge message dictionary...
r28137 """return the default destination for a merge
(or raise exception about why it can't pick one)
:action: the action being performed, controls emitted error message
"""
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 # destspace is here to work around issues with `hg pull --rebase` see
# issue5214 for details
Pierre-Yves David
destutil: move default merge destination into a function...
r26714 if repo._activebookmark:
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 node = _destmergebook(repo, action=action, sourceset=sourceset,
destspace=destspace)
Pierre-Yves David
destutil: move default merge destination into a function...
r26714 else:
Pierre-Yves David
destutil: allow to disable the "on head check" in destmerge...
r28140 node = _destmergebranch(repo, action=action, sourceset=sourceset,
Pierre-Yves David
destutil: add the ability to specify a search space for rebase destination...
r29043 onheadcheck=onheadcheck, destspace=destspace)
Pierre-Yves David
destutil: move default merge destination into a function...
r26714 return repo[node].rev()
Gregory Szorc
histedit: pick an appropriate base changeset by default (BC)...
r27262
histeditdefaultrevset = 'reverse(only(.) and not public() and not ::merge())'
def desthistedit(ui, repo):
"""Default base revision to edit for `hg histedit`."""
Gregory Szorc
destutil: use scmutil.revrange for desthistedit (issue5001)...
r27559 # Avoid cycle: scmutil -> revset -> destutil
from . import scmutil
Gregory Szorc
histedit: pick an appropriate base changeset by default (BC)...
r27262 default = ui.config('histedit', 'defaultrev', histeditdefaultrevset)
if default:
Gregory Szorc
destutil: use scmutil.revrange for desthistedit (issue5001)...
r27559 revs = scmutil.revrange(repo, [default])
Gregory Szorc
histedit: pick an appropriate base changeset by default (BC)...
r27262 if revs:
# The revset supplied by the user may not be in ascending order nor
# take the first revision. So do this manually.
revs.sort()
return revs.first()
return None
Pierre-Yves David
update: warn about other topological heads on bare update...
r28029
def _statusotherbook(ui, repo):
bmheads = repo.bookmarkheads(repo._activebookmark)
curhead = repo[repo._activebookmark].node()
if repo.revs('%n and parents()', curhead):
# we are on the active bookmark
bmheads = [b for b in bmheads if curhead != b]
if bmheads:
msg = _('%i other divergent bookmarks for "%s"\n')
ui.status(msg % (len(bmheads), repo._activebookmark))
def _statusotherbranchheads(ui, repo):
currentbranch = repo.dirstate.branch()
FUJIWARA Katsunori
destutil: show message about other branch heads, even if on a closed head...
r28266 allheads = repo.branchheads(currentbranch, closed=True)
Pierre-Yves David
update: warn about other topological heads on bare update...
r28029 heads = repo.branchheads(currentbranch)
FUJIWARA Katsunori
destutil: show message about other branch heads, even if on a closed head...
r28266 if repo.revs('%ln and parents()', allheads):
# we are on a head, even though it might be closed
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 #
# on closed otherheads
# ========= ==========
# o 0 all heads for current branch are closed
# N only descendant branch heads are closed
# x 0 there is only one non-closed branch head
# N there are some non-closed branch heads
# ========= ==========
FUJIWARA Katsunori
destutil: add new local variable to increase readability...
r28233 otherheads = repo.revs('%ln - parents()', heads)
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 if repo['.'].closesbranch():
FUJIWARA Katsunori
destutil: show message and hint at updating to the closed head as warning
r28684 ui.warn(_('no open descendant heads on branch "%s", '
FUJIWARA Katsunori
destutil: make messages at updating to the closed head usual form...
r28683 'updating to a closed head\n') %
(currentbranch))
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 if otherheads:
FUJIWARA Katsunori
destutil: show message and hint at updating to the closed head as warning
r28684 ui.warn(_('(committing will reopen the head, '
FUJIWARA Katsunori
destutil: make messages at updating to the closed head usual form...
r28683 'use `hg heads .` to see %i other heads)\n') %
(len(otherheads)))
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 else:
FUJIWARA Katsunori
destutil: show message and hint at updating to the closed head as warning
r28684 ui.warn(_('(committing will reopen branch "%s")\n') %
FUJIWARA Katsunori
destutil: make messages at updating to the closed head usual form...
r28683 (currentbranch))
FUJIWARA Katsunori
destutil: choose non-closed branch head at first (BC)...
r28385 elif otherheads:
Pierre-Yves David
update: warn about other topological heads on bare update...
r28029 ui.status(_('%i other heads for branch "%s"\n') %
FUJIWARA Katsunori
destutil: add new local variable to increase readability...
r28233 (len(otherheads), currentbranch))
Pierre-Yves David
update: warn about other topological heads on bare update...
r28029
def statusotherdests(ui, repo):
"""Print message about other head"""
# XXX we should probably include a hint:
# - about what to do
# - how to see such heads
if repo._activebookmark:
_statusotherbook(ui, repo)
else:
_statusotherbranchheads(ui, repo)