diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -334,7 +334,8 @@ class localrepository: self.manifest = manifest(self.opener) self.changelog = changelog(self.opener) self.ignorelist = None - self.tags = None + self.tagscache = None + self.nodetagscache = None if not self.remote: self.dirstate = dirstate(self.opener, ui, self.root) @@ -355,9 +356,10 @@ class localrepository: if pat.search(f): return True return False - def lookup(self, key): - if self.tags is None: - self.tags = {} + def tags(self): + '''return a mapping of tag to node''' + if not self.tagscache: + self.tagscache = {} try: # read each head of the tags file, ending with the tip # and add each tag found to the map, with "newer" ones @@ -369,11 +371,35 @@ class localrepository: for l in fl.revision(r).splitlines(): if l: n, k = l.split(" ") - self.tags[k] = bin(n) + self.tagscache[k] = bin(n) except KeyError: pass - self.tags['tip'] = self.changelog.tip() + self.tagscache['tip'] = self.changelog.tip() + + return self.tagscache + + def tagslist(self): + '''return a list of tags ordered by revision''' + l = [] + for t,n in self.tags().items(): + try: + r = self.changelog.rev(n) + except: + r = -2 # sort to the beginning of the list if unknown + l.append((r,t,n)) + l.sort() + return [(t,n) for r,t,n in l] + + def nodetags(self, node): + '''return the tags associated with a node''' + if not self.nodetagscache: + self.nodetagscache = {} + for t,n in self.tags().items(): + self.nodetagscache.setdefault(n,[]).append(t) + return self.nodetagscache.get(node, []) + + def lookup(self, key): try: - return self.tags[key] + return self.tags()[key] except KeyError: return self.changelog.lookup(key)