mercurial/hg.py
changeset 898 3616c0d7ab88
parent 896 01215ad04283
child 900 ba8cf1f2210c
equal deleted inserted replaced
897:fe30f5434b51 898:3616c0d7ab88
  1070             self.dirstate.copy(source, dest)
  1070             self.dirstate.copy(source, dest)
  1071 
  1071 
  1072     def heads(self):
  1072     def heads(self):
  1073         return self.changelog.heads()
  1073         return self.changelog.heads()
  1074 
  1074 
       
  1075     # branchlookup returns a dict giving a list of branches for
       
  1076     # each head.  A branch is defined as the tag of a node or
       
  1077     # the branch of the node's parents.  If a node has multiple
       
  1078     # branch tags, tags are eliminated if they are visible from other
       
  1079     # branch tags.
       
  1080     #
       
  1081     # So, for this graph:  a->b->c->d->e
       
  1082     #                       \         /
       
  1083     #                        aa -----/
       
  1084     # a has tag 2.6.12                     
       
  1085     # d has tag 2.6.13
       
  1086     # e would have branch tags for 2.6.12 and 2.6.13.  Because the node
       
  1087     # for 2.6.12 can be reached from the node 2.6.13, that is eliminated
       
  1088     # from the list.
       
  1089     #
       
  1090     # It is possible that more than one head will have the same branch tag.
       
  1091     # callers need to check the result for multiple heads under the same
       
  1092     # branch tag if that is a problem for them (ie checkout of a specific
       
  1093     # branch).
       
  1094     #
       
  1095     # passing in a specific branch will limit the depth of the search
       
  1096     # through the parents.  It won't limit the branches returned in the
       
  1097     # result though.
       
  1098     def branchlookup(self, heads=None, branch=None):
       
  1099         if not heads:
       
  1100             heads = self.heads()
       
  1101         headt = [ h for h in heads ]
       
  1102         chlog = self.changelog
       
  1103         branches = {}
       
  1104         merges = []
       
  1105         seenmerge = {}
       
  1106 
       
  1107         # traverse the tree once for each head, recording in the branches
       
  1108         # dict which tags are visible from this head.  The branches
       
  1109         # dict also records which tags are visible from each tag
       
  1110         # while we traverse.
       
  1111         while headt or merges:
       
  1112             if merges:
       
  1113                 n, found = merges.pop()
       
  1114                 visit = [n]
       
  1115             else:
       
  1116                 h = headt.pop()
       
  1117                 visit = [h]
       
  1118                 found = [h]
       
  1119                 seen = {}
       
  1120             while visit:
       
  1121                 n = visit.pop()
       
  1122                 if n in seen:
       
  1123                     continue
       
  1124                 pp = chlog.parents(n)
       
  1125                 tags = self.nodetags(n)
       
  1126                 if tags:
       
  1127                     for x in tags:
       
  1128                         if x == 'tip':
       
  1129                             continue
       
  1130                         for f in found:
       
  1131                             branches.setdefault(f, {})[n] = 1
       
  1132                         branches.setdefault(n, {})[n] = 1
       
  1133                         break
       
  1134                     if n not in found:
       
  1135                         found.append(n)
       
  1136                     if branch in tags:
       
  1137                         continue
       
  1138                 seen[n] = 1
       
  1139                 if pp[1] != nullid and n not in seenmerge:
       
  1140                     merges.append((pp[1], [x for x in found]))
       
  1141                     seenmerge[n] = 1
       
  1142                 if pp[0] != nullid:
       
  1143                     visit.append(pp[0])
       
  1144         # traverse the branches dict, eliminating branch tags from each
       
  1145         # head that are visible from another branch tag for that head.
       
  1146         out = {}
       
  1147         viscache = {}
       
  1148         for h in heads:
       
  1149             def visible(node):
       
  1150                 if node in viscache:
       
  1151                     return viscache[node]
       
  1152                 ret = {}
       
  1153                 visit = [node]
       
  1154                 while visit:
       
  1155                     x = visit.pop()
       
  1156                     if x in viscache:
       
  1157                         ret.update(viscache[x])
       
  1158                     elif x not in ret:
       
  1159                         ret[x] = 1
       
  1160                         if x in branches:
       
  1161                             visit[len(visit):] = branches[x].keys()
       
  1162                 viscache[node] = ret
       
  1163                 return ret
       
  1164             if h not in branches:
       
  1165                 continue
       
  1166             # O(n^2), but somewhat limited.  This only searches the
       
  1167             # tags visible from a specific head, not all the tags in the
       
  1168             # whole repo.
       
  1169             for b in branches[h]:
       
  1170                 vis = False
       
  1171                 for bb in branches[h].keys():
       
  1172                     if b != bb:
       
  1173                         if b in visible(bb):
       
  1174                             vis = True
       
  1175                             break
       
  1176                 if not vis:
       
  1177                     l = out.setdefault(h, [])
       
  1178                     l[len(l):] = self.nodetags(b)
       
  1179         return out
       
  1180 
  1075     def branches(self, nodes):
  1181     def branches(self, nodes):
  1076         if not nodes: nodes = [self.changelog.tip()]
  1182         if not nodes: nodes = [self.changelog.tip()]
  1077         b = []
  1183         b = []
  1078         for n in nodes:
  1184         for n in nodes:
  1079             t = n
  1185             t = n