1016 heads = self.changelog.heads(start) |
1016 heads = self.changelog.heads(start) |
1017 # sort the output in rev descending order |
1017 # sort the output in rev descending order |
1018 heads = [(-self.changelog.rev(h), h) for h in heads] |
1018 heads = [(-self.changelog.rev(h), h) for h in heads] |
1019 heads.sort() |
1019 heads.sort() |
1020 return [n for (r, n) in heads] |
1020 return [n for (r, n) in heads] |
|
1021 |
|
1022 def branchheads(self, branch, start=None): |
|
1023 branches = self.branchtags() |
|
1024 if branch not in branches: |
|
1025 return [] |
|
1026 # The basic algorithm is this: |
|
1027 # |
|
1028 # Start from the branch tip since there are no later revisions that can |
|
1029 # possibly be in this branch, and the tip is a guaranteed head. |
|
1030 # |
|
1031 # Remember the tip's parents as the first ancestors, since these by |
|
1032 # definition are not heads. |
|
1033 # |
|
1034 # Step backwards from the brach tip through all the revisions. We are |
|
1035 # guaranteed by the rules of Mercurial that we will now be visiting the |
|
1036 # nodes in reverse topological order (children before parents). |
|
1037 # |
|
1038 # If a revision is one of the ancestors of a head then we can toss it |
|
1039 # out of the ancestors set (we've already found it and won't be |
|
1040 # visiting it again) and put its parents in the ancestors set. |
|
1041 # |
|
1042 # Otherwise, if a revision is in the branch it's another head, since it |
|
1043 # wasn't in the ancestor list of an existing head. So add it to the |
|
1044 # head list, and add its parents to the ancestor list. |
|
1045 # |
|
1046 # If it is not in the branch ignore it. |
|
1047 # |
|
1048 # Once we have a list of heads, use nodesbetween to filter out all the |
|
1049 # heads that cannot be reached from startrev. There may be a more |
|
1050 # efficient way to do this as part of the previous algorithm. |
|
1051 |
|
1052 set = util.set |
|
1053 heads = [self.changelog.rev(branches[branch])] |
|
1054 # Don't care if ancestors contains nullrev or not. |
|
1055 ancestors = set(self.changelog.parentrevs(heads[0])) |
|
1056 for rev in xrange(heads[0] - 1, nullrev, -1): |
|
1057 if rev in ancestors: |
|
1058 ancestors.update(self.changelog.parentrevs(rev)) |
|
1059 ancestors.remove(rev) |
|
1060 elif self.changectx(rev).branch() == branch: |
|
1061 heads.append(rev) |
|
1062 ancestors.update(self.changelog.parentrevs(rev)) |
|
1063 heads = [self.changelog.node(rev) for rev in heads] |
|
1064 if start is not None: |
|
1065 heads = self.changelog.nodesbetween([start], heads)[2] |
|
1066 return heads |
1021 |
1067 |
1022 def branches(self, nodes): |
1068 def branches(self, nodes): |
1023 if not nodes: |
1069 if not nodes: |
1024 nodes = [self.changelog.tip()] |
1070 nodes = [self.changelog.tip()] |
1025 b = [] |
1071 b = [] |