comparison mercurial/context.py @ 3165:5c93dd0ae413

Refactor annotate copy support.
author Brendan Cully <brendan@kublai.com>
date Wed, 27 Sep 2006 09:10:21 -0700
parents 15d585dcdd1c
children 14792adabf80 0790dce2f3a8
comparison
equal deleted inserted replaced
3164:706277866251 3165:5c93dd0ae413
2 # 2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com> 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 # 4 #
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
8 from demandload import *
9 from node import *
10 demandload(globals(), 'bdiff')
7 11
8 from node import * 12 from node import *
9 from demandload import demandload 13 from demandload import demandload
10 demandload(globals(), "ancestor util") 14 demandload(globals(), "ancestor util")
11 15
163 # hard for renames 167 # hard for renames
164 c = self._filelog.children(self._filenode) 168 c = self._filelog.children(self._filenode)
165 return [ filectx(self._repo, self._path, fileid=x, 169 return [ filectx(self._repo, self._path, fileid=x,
166 filelog=self._filelog) for x in c ] 170 filelog=self._filelog) for x in c ]
167 171
168 def annotate(self): 172 def annotate(self, follow=False):
169 getctx = util.cachefunc(lambda x: filectx(self._repo, self._path, 173 '''returns a list of tuples of (ctx, line) for each line
170 changeid=x, 174 in the file, where ctx is the filectx of the node where
171 filelog=self._filelog)) 175 that line was last changed'''
172 hist = self._filelog.annotate(self._filenode) 176
173 177 def decorate(text, rev):
174 return [(getctx(rev), line) for rev, line in hist] 178 return ([rev] * len(text.splitlines()), text)
179
180 def pair(parent, child):
181 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
182 child[0][b1:b2] = parent[0][a1:a2]
183 return child
184
185 getlog = util.cachefunc(lambda x: self._repo.file(x))
186 def getctx(path, fileid):
187 log = path == self._path and self._filelog or getlog(path)
188 return filectx(self._repo, path, fileid=fileid, filelog=log)
189 getctx = util.cachefunc(getctx)
190
191 def parents(f):
192 # we want to reuse filectx objects as much as possible
193 p = f._path
194 pl = [ (p, f._filelog.rev(n)) for n in f._filelog.parents(f._filenode) ]
195
196 if follow:
197 r = f.renamed()
198 if r:
199 pl[0] = (r[0], getlog(r[0]).rev(r[1]))
200
201 return [ getctx(p, n) for p, n in pl if n != -1 ]
202
203 # find all ancestors
204 needed = {self: 1}
205 visit = [self]
206 files = [self._path]
207 while visit:
208 f = visit.pop(0)
209 for p in parents(f):
210 if p not in needed:
211 needed[p] = 1
212 visit.append(p)
213 if p._path not in files:
214 files.append(p._path)
215 else:
216 # count how many times we'll use this
217 needed[p] += 1
218
219 # sort by revision (per file) which is a topological order
220 visit = []
221 files.reverse()
222 for f in files:
223 fn = [(n._filerev, n) for n in needed.keys() if n._path == f]
224 fn.sort()
225 visit.extend(fn)
226 hist = {}
227
228 for r, f in visit:
229 curr = decorate(f.data(), f)
230 for p in parents(f):
231 if p != nullid:
232 curr = pair(hist[p], curr)
233 # trim the history of unneeded revs
234 needed[p] -= 1
235 if not needed[p]:
236 del hist[p]
237 hist[f] = curr
238
239 return zip(hist[f][0], hist[f][1].splitlines(1))
175 240
176 def ancestor(self, fc2): 241 def ancestor(self, fc2):
177 """ 242 """
178 find the common ancestor file context, if any, of self, and fc2 243 find the common ancestor file context, if any, of self, and fc2
179 """ 244 """