comparison mercurial/destutil.py @ 28385:3f9e25a42e69

destutil: choose non-closed branch head at first (BC) Before this patch, destupdate() returns the tipmost (descendant) branch head regardless of closed or not. But updating to closed branch head isn't reasonable for ordinary workflow, because: - "hg heads" doesn't show closed heads (= updated parent itself) by default - subsequent committing on it re-opens closed branch even if inactivation of closed head is needed, update destination isn't it, because it should be merged into to another branch in such case. This patch chooses non-closed descendant branch head as default update destination at first. If all descendant branch heads are closed, destupdate() returns the tipmost closed branch head. For simplicity, this patch chooses adding _destupdatebranchfallback() instead largely changing _destupdatebranch(). This patch changes not only normal lookup code path, but also the "no default branch" code path, for consistency.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Mon, 07 Mar 2016 03:14:19 +0900
parents de8b09482fb7
children d0210a35c81a
comparison
equal deleted inserted replaced
28384:3356bf61fa25 28385:3f9e25a42e69
86 if node is not None: 86 if node is not None:
87 activemark = node 87 activemark = node
88 return node, movemark, activemark 88 return node, movemark, activemark
89 89
90 def _destupdatebranch(repo, clean, check): 90 def _destupdatebranch(repo, clean, check):
91 """decide on an update destination from current branch""" 91 """decide on an update destination from current branch
92
93 This ignores closed branch heads.
94 """
92 wc = repo[None] 95 wc = repo[None]
93 movemark = node = None 96 movemark = node = None
94 currentbranch = wc.branch() 97 currentbranch = wc.branch()
95 if currentbranch in repo.branchmap(): 98 if currentbranch in repo.branchmap():
96 heads = repo.branchheads(currentbranch, closed=True) 99 heads = repo.branchheads(currentbranch)
97 if heads: 100 if heads:
98 node = repo.revs('max(.::(%ln))', heads).first() 101 node = repo.revs('max(.::(%ln))', heads).first()
99 if bookmarks.isactivewdirparent(repo): 102 if bookmarks.isactivewdirparent(repo):
100 movemark = repo['.'].node() 103 movemark = repo['.'].node()
101 else: 104 else:
102 if currentbranch == 'default': # no default branch! 105 if currentbranch == 'default': # no default branch!
103 node = repo.lookup('tip') # update to tip 106 # update to the tipmost non-closed branch head
107 node = repo.revs('max(head() and not closed())').first()
104 else: 108 else:
105 raise error.Abort(_("branch %s not found") % currentbranch) 109 raise error.Abort(_("branch %s not found") % currentbranch)
106 return node, movemark, None 110 return node, movemark, None
107 111
112 def _destupdatebranchfallback(repo, clean, check):
113 """decide on an update destination from closed heads in current branch"""
114 wc = repo[None]
115 currentbranch = wc.branch()
116 movemark = None
117 if currentbranch in repo.branchmap():
118 # here, all descendant branch heads are closed
119 heads = repo.branchheads(currentbranch, closed=True)
120 assert heads, "any branch has at least one head"
121 node = repo.revs('max(.::(%ln))', heads).first()
122 assert node is not None, ("any revision has at least "
123 "one descendant branch head")
124 if bookmarks.isactivewdirparent(repo):
125 movemark = repo['.'].node()
126 else:
127 # here, no "default" branch, and all branches are closed
128 node = repo.lookup('tip')
129 assert node is not None, "'tip' exists even in empty repository"
130 return node, movemark, None
131
108 # order in which each step should be evalutated 132 # order in which each step should be evalutated
109 # steps are run until one finds a destination 133 # steps are run until one finds a destination
110 destupdatesteps = ['evolution', 'bookmark', 'branch'] 134 destupdatesteps = ['evolution', 'bookmark', 'branch', 'branchfallback']
111 # mapping to ease extension overriding steps. 135 # mapping to ease extension overriding steps.
112 destupdatestepmap = {'evolution': _destupdateobs, 136 destupdatestepmap = {'evolution': _destupdateobs,
113 'bookmark': _destupdatebook, 137 'bookmark': _destupdatebook,
114 'branch': _destupdatebranch, 138 'branch': _destupdatebranch,
139 'branchfallback': _destupdatebranchfallback,
115 } 140 }
116 141
117 def destupdate(repo, clean=False, check=False): 142 def destupdate(repo, clean=False, check=False):
118 """destination for bare update operation 143 """destination for bare update operation
119 144
360 currentbranch = repo.dirstate.branch() 385 currentbranch = repo.dirstate.branch()
361 allheads = repo.branchheads(currentbranch, closed=True) 386 allheads = repo.branchheads(currentbranch, closed=True)
362 heads = repo.branchheads(currentbranch) 387 heads = repo.branchheads(currentbranch)
363 if repo.revs('%ln and parents()', allheads): 388 if repo.revs('%ln and parents()', allheads):
364 # we are on a head, even though it might be closed 389 # we are on a head, even though it might be closed
390 #
391 # on closed otherheads
392 # ========= ==========
393 # o 0 all heads for current branch are closed
394 # N only descendant branch heads are closed
395 # x 0 there is only one non-closed branch head
396 # N there are some non-closed branch heads
397 # ========= ==========
365 otherheads = repo.revs('%ln - parents()', heads) 398 otherheads = repo.revs('%ln - parents()', heads)
366 if otherheads: 399 if repo['.'].closesbranch():
400 ui.status(_('updated to a closed branch head, '
401 'because all descendant heads are closed.\n'
402 'beware of re-opening closed head '
403 'by subsequent commit here.\n'))
404 if otherheads:
405 ui.status(_('%i other heads for branch "%s"\n') %
406 (len(otherheads), currentbranch))
407 else:
408 ui.status(_('all heads for branch "%s" are closed.\n') %
409 currentbranch)
410 elif otherheads:
367 ui.status(_('%i other heads for branch "%s"\n') % 411 ui.status(_('%i other heads for branch "%s"\n') %
368 (len(otherheads), currentbranch)) 412 (len(otherheads), currentbranch))
369 413
370 def statusotherdests(ui, repo): 414 def statusotherdests(ui, repo):
371 """Print message about other head""" 415 """Print message about other head"""