mercurial/filelog.py
changeset 3211 9a478efc16cc
parent 3131 4ea58eb3f0c9
child 3586 66a17364c30e
child 3794 630caaf29815
equal deleted inserted replaced
3210:7240f9e47144 3211:9a478efc16cc
     5 # This software may be used and distributed according to the terms
     5 # This software may be used and distributed according to the terms
     6 # of the GNU General Public License, incorporated herein by reference.
     6 # of the GNU General Public License, incorporated herein by reference.
     7 
     7 
     8 from revlog import *
     8 from revlog import *
     9 from demandload import *
     9 from demandload import *
    10 demandload(globals(), "bdiff os")
    10 demandload(globals(), "os")
    11 
    11 
    12 class filelog(revlog):
    12 class filelog(revlog):
    13     def __init__(self, opener, path, defversion=REVLOG_DEFAULT_VERSION):
    13     def __init__(self, opener, path, defversion=REVLOG_DEFAULT_VERSION):
    14         revlog.__init__(self, opener,
    14         revlog.__init__(self, opener,
    15                         os.path.join("data", self.encodedir(path + ".i")),
    15                         os.path.join("data", self.encodedir(path + ".i")),
    82         if self.renamed(node):
    82         if self.renamed(node):
    83             t2 = self.read(node)
    83             t2 = self.read(node)
    84             return t2 != text
    84             return t2 != text
    85 
    85 
    86         return revlog.cmp(self, node, text)
    86         return revlog.cmp(self, node, text)
    87 
       
    88     def annotate(self, node):
       
    89 
       
    90         def decorate(text, rev):
       
    91             return ([rev] * len(text.splitlines()), text)
       
    92 
       
    93         def pair(parent, child):
       
    94             for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
       
    95                 child[0][b1:b2] = parent[0][a1:a2]
       
    96             return child
       
    97 
       
    98         # find all ancestors
       
    99         needed = {(self, node):1}
       
   100         files = [self]
       
   101         visit = [(self, node)]
       
   102         while visit:
       
   103             f, n = visit.pop(0)
       
   104             rn = f.renamed(n)
       
   105             if rn:
       
   106                 f, n = rn
       
   107                 f = filelog(self.opener, f, self.defversion)
       
   108                 files.insert(0, f)
       
   109                 if (f, n) not in needed:
       
   110                     needed[(f, n)] = 1
       
   111                 else:
       
   112                     needed[(f, n)] += 1
       
   113             for p in f.parents(n):
       
   114                 if p == nullid:
       
   115                     continue
       
   116                 if (f, p) not in needed:
       
   117                     needed[(f, p)] = 1
       
   118                     visit.append((f, p))
       
   119                 else:
       
   120                     # count how many times we'll use this
       
   121                     needed[(f, p)] += 1
       
   122 
       
   123         # sort by revision (per file) which is a topological order
       
   124         visit = []
       
   125         for f in files:
       
   126             fn = [(f.rev(n[1]), f, n[1]) for n in needed.keys() if n[0] == f]
       
   127             fn.sort()
       
   128             visit.extend(fn)
       
   129         hist = {}
       
   130 
       
   131         for i in range(len(visit)):
       
   132             r, f, n = visit[i]
       
   133             curr = decorate(f.read(n), f.linkrev(n))
       
   134             if r == -1:
       
   135                 continue
       
   136             parents = f.parents(n)
       
   137             # follow parents across renames
       
   138             if r < 1 and i > 0:
       
   139                 j = i
       
   140                 while j > 0 and visit[j][1] == f:
       
   141                     j -= 1
       
   142                 parents = (visit[j][2],)
       
   143                 f = visit[j][1]
       
   144             else:
       
   145                 parents = f.parents(n)
       
   146             for p in parents:
       
   147                 if p != nullid:
       
   148                     curr = pair(hist[p], curr)
       
   149                     # trim the history of unneeded revs
       
   150                     needed[(f, p)] -= 1
       
   151                     if not needed[(f, p)]:
       
   152                         del hist[p]
       
   153             hist[n] = curr
       
   154 
       
   155         return zip(hist[n][0], hist[n][1].splitlines(1))