##// END OF EJS Templates
Add searching for named branches...
mason@suse.com -
r898:3616c0d7 default
parent child Browse files
Show More
@@ -194,7 +194,7 b' def dodiff(fp, ui, repo, files=None, nod'
194 tn = None
194 tn = None
195 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
195 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r))
196
196
197 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
197 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None, brinfo=None):
198 """show a single changeset or file revision"""
198 """show a single changeset or file revision"""
199 changelog = repo.changelog
199 changelog = repo.changelog
200 if filelog:
200 if filelog:
@@ -236,6 +236,10 b' def show_changeset(ui, repo, rev=0, chan'
236 if filelog:
236 if filelog:
237 ui.debug("file rev: %d:%s\n" % (filerev, hg.hex(filenode)))
237 ui.debug("file rev: %d:%s\n" % (filerev, hg.hex(filenode)))
238
238
239 if brinfo and changenode in brinfo:
240 br = brinfo[changenode]
241 ui.write("branch: %s\n" % " ".join(br))
242
239 ui.debug("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
243 ui.debug("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
240 hg.hex(changes[0])))
244 hg.hex(changes[0])))
241 ui.status("user: %s\n" % changes[1])
245 ui.status("user: %s\n" % changes[1])
@@ -675,10 +679,14 b' def forget(ui, repo, *pats, **opts):'
675 if rel not in q: ui.status('forgetting ', rel, '\n')
679 if rel not in q: ui.status('forgetting ', rel, '\n')
676 repo.forget(forget)
680 repo.forget(forget)
677
681
678 def heads(ui, repo):
682 def heads(ui, repo, **opts):
679 """show current repository heads"""
683 """show current repository heads"""
684 heads = repo.changelog.heads()
685 br = None
686 if opts['branches']:
687 br = repo.branchlookup(heads)
680 for n in repo.changelog.heads():
688 for n in repo.changelog.heads():
681 show_changeset(ui, repo, changenode=n)
689 show_changeset(ui, repo, changenode=n, brinfo=br)
682
690
683 def identify(ui, repo):
691 def identify(ui, repo):
684 """print information about the working copy"""
692 """print information about the working copy"""
@@ -1150,7 +1158,7 b' def undo(ui, repo):'
1150 """
1158 """
1151 repo.undo()
1159 repo.undo()
1152
1160
1153 def update(ui, repo, node=None, merge=False, clean=False):
1161 def update(ui, repo, node=None, merge=False, clean=False, branch=None):
1154 '''update or merge working directory
1162 '''update or merge working directory
1155
1163
1156 If there are no outstanding changes in the working directory and
1164 If there are no outstanding changes in the working directory and
@@ -1163,7 +1171,25 b' def update(ui, repo, node=None, merge=Fa'
1163 commit and a commit must be performed before any further updates
1171 commit and a commit must be performed before any further updates
1164 are allowed.
1172 are allowed.
1165 '''
1173 '''
1166 node = node and repo.lookup(node) or repo.changelog.tip()
1174 if branch:
1175 br = repo.branchlookup(branch=branch)
1176 found = []
1177 for x in br:
1178 if branch in br[x]:
1179 found.append(x)
1180 if len(found) > 1:
1181 ui.warn("Found multiple heads for %s\n" % branch)
1182 for x in found:
1183 show_changeset(ui, repo, changenode=x, brinfo=br)
1184 return 1
1185 if len(found) == 1:
1186 node = found[0]
1187 ui.warn("Using head %s for branch %s\n" % (hg.short(node), branch))
1188 else:
1189 ui.warn("branch %s not found\n" % (branch))
1190 return 1
1191 else:
1192 node = node and repo.lookup(node) or repo.changelog.tip()
1167 return repo.update(node, allow=merge, force=clean)
1193 return repo.update(node, allow=merge, force=clean)
1168
1194
1169 def verify(ui, repo):
1195 def verify(ui, repo):
@@ -1236,7 +1262,7 b' table = {'
1236 [('I', 'include', [], 'include path in search'),
1262 [('I', 'include', [], 'include path in search'),
1237 ('X', 'exclude', [], 'exclude path from search')],
1263 ('X', 'exclude', [], 'exclude path from search')],
1238 "hg forget FILE..."),
1264 "hg forget FILE..."),
1239 "heads": (heads, [], 'hg heads'),
1265 "heads": (heads, [('b', 'branches', None, 'find branch info')], 'hg heads'),
1240 "help": (help_, [], 'hg help [COMMAND]'),
1266 "help": (help_, [], 'hg help [COMMAND]'),
1241 "identify|id": (identify, [], 'hg identify'),
1267 "identify|id": (identify, [], 'hg identify'),
1242 "import|patch":
1268 "import|patch":
@@ -1320,7 +1346,8 b' table = {'
1320 "undo": (undo, [], 'hg undo'),
1346 "undo": (undo, [], 'hg undo'),
1321 "^update|up|checkout|co":
1347 "^update|up|checkout|co":
1322 (update,
1348 (update,
1323 [('m', 'merge', None, 'allow merging of conflicts'),
1349 [('b', 'branch', "", 'checkout the head of a specific branch'),
1350 ('m', 'merge', None, 'allow merging of conflicts'),
1324 ('C', 'clean', None, 'overwrite locally modified files')],
1351 ('C', 'clean', None, 'overwrite locally modified files')],
1325 'hg update [-m] [-C] [REV]'),
1352 'hg update [-m] [-C] [REV]'),
1326 "verify": (verify, [], 'hg verify'),
1353 "verify": (verify, [], 'hg verify'),
@@ -1072,6 +1072,112 b' class localrepository:'
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 = []
General Comments 0
You need to be logged in to leave comments. Login now