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