comparison mercurial/branchmap.py @ 34091:abf91c4f9608

branches: correctly show inactive multiheaded branches Issue being fixed here: `hg branches` incorrectly renders inactive multiheaded branches as active if they have closed heads. Example: ``` $ hg log --template '{rev}:{node|short} "{desc}" ({branch}) [parents: {parents}]\n' 4:2e2fa7af8357 "merge" (default) [parents: 0:c94e548c8c7d 3:7be622ae5832 ] 3:7be622ae5832 "2" (somebranch) [parents: 1:81c1d9458987 ] 2:be82cf30409c "close" (somebranch) [parents: ] 1:81c1d9458987 "1" (somebranch) [parents: ] 0:c94e548c8c7d "initial" (default) [parents: ] $ hg branches default 4:2e2fa7af8357 somebranch 3:7be622ae5832 ``` Branch `somebranch` have two heads, the 1st one being closed (rev 2) and the other one being merged into default (rev 3). This branch should be shown as inactive one. This happens because we intersect branch heads with repo heads to check branch activity. In this case intersection in a set with one node (rev 2). This head is closed but the branch is marked as active nevertheless. Fix is to check branch activity by intersecting only open heads set. Fixed output: ``` $ hg branches default 4:2e2fa7af8357 somebranch 3:7be622ae5832 (inactive) ``` Relevant tests for multihead branches added to test-branches suite. Implentation note about adding `iteropen` method: At first I have tried to modify `iterbranches` is such a way that it would filter out closed heads itself. For example it could have `closed=False` parameter. But in this case we would have to filter closed tips as well. Reasoning in terms of `hg branches` we actually are not allowed to do this. Also, we need to do heads filtering only if tip is not closed itself. But if it is - we are ok to skip filtering, because branch is already known to be inactive. So we can't implement heads filtering in `iterbranches` in elegant way, because we will end up with something like `closed_heads=False` or even `closed_heads_is_tip_is_open`. Finally I decided to move this logic to the `branches` function, adding `iteropen` helper method. Differential Revision: https://phab.mercurial-scm.org/D583
author the31k <the31k@thethirty.one>
date Thu, 31 Aug 2017 18:24:08 +0300
parents 1814ca418b30
children d0db41af73c0
comparison
equal deleted inserted replaced
34090:7bbc4e113e5f 34091:abf91c4f9608
209 '''Return the tipmost open head on branch head, otherwise return the 209 '''Return the tipmost open head on branch head, otherwise return the
210 tipmost closed head on branch. 210 tipmost closed head on branch.
211 Raise KeyError for unknown branch.''' 211 Raise KeyError for unknown branch.'''
212 return self._branchtip(self[branch])[0] 212 return self._branchtip(self[branch])[0]
213 213
214 def iteropen(self, nodes):
215 return (n for n in nodes if n not in self._closednodes)
216
214 def branchheads(self, branch, closed=False): 217 def branchheads(self, branch, closed=False):
215 heads = self[branch] 218 heads = self[branch]
216 if not closed: 219 if not closed:
217 heads = [h for h in heads if h not in self._closednodes] 220 heads = list(self.iteropen(heads))
218 return heads 221 return heads
219 222
220 def iterbranches(self): 223 def iterbranches(self):
221 for bn, heads in self.iteritems(): 224 for bn, heads in self.iteritems():
222 yield (bn, heads) + self._branchtip(heads) 225 yield (bn, heads) + self._branchtip(heads)