comparison mercurial/context.py @ 13552:7ab85fec60c3 stable

ancestor: rewrite to deal with crossed linkrevs (issue2682) This version is about 10% slower, possibly because it visits some revisions in a different topological order than what's in the revlog.
author Matt Mackall <mpm@selenic.com>
date Mon, 07 Mar 2011 15:44:43 -0600
parents 4eb1e9d6a7c9
children 653121e6941f
comparison
equal deleted inserted replaced
13551:bbfae32f178e 13552:7ab85fec60c3
464 if self.rev() != self.linkrev(): 464 if self.rev() != self.linkrev():
465 base = self.filectx(self.filerev()) 465 base = self.filectx(self.filerev())
466 else: 466 else:
467 base = self 467 base = self
468 468
469 # find all ancestors 469 # This algorithm would prefer to be recursive, but Python is a
470 # bit recursion-hostile. Instead we do an iterative
471 # depth-first search.
472
473 visit = [base]
474 hist = {}
475 pcache = {}
470 needed = {base: 1} 476 needed = {base: 1}
471 visit = [base]
472 files = [base._path]
473 while visit: 477 while visit:
474 f = visit.pop(0) 478 f = visit[-1]
475 for p in parents(f): 479 if f not in pcache:
476 if p not in needed: 480 pcache[f] = parents(f)
477 needed[p] = 1 481
482 ready = True
483 pl = pcache[f]
484 for p in pl:
485 if p not in hist:
486 ready = False
478 visit.append(p) 487 visit.append(p)
479 if p._path not in files: 488 needed[p] = needed.get(p, 0) + 1
480 files.append(p._path) 489 if ready:
481 else: 490 visit.pop()
482 # count how many times we'll use this 491 curr = decorate(f.data(), f)
483 needed[p] += 1 492 for p in pl:
484 493 curr = pair(hist[p], curr)
485 # sort by revision (per file) which is a topological order 494 if needed[p] == 1:
486 visit = [] 495 del hist[p]
487 for f in files: 496 else:
488 visit.extend(n for n in needed if n._path == f) 497 needed[p] -= 1
489 498
490 hist = {} 499 hist[f] = curr
491 for f in sorted(visit, key=lambda x: x.rev()): 500 pcache[f] = []
492 curr = decorate(f.data(), f) 501
493 for p in parents(f): 502 return zip(hist[base][0], hist[base][1].splitlines(True))
494 curr = pair(hist[p], curr)
495 # trim the history of unneeded revs
496 needed[p] -= 1
497 if not needed[p]:
498 del hist[p]
499 hist[f] = curr
500
501 return zip(hist[f][0], hist[f][1].splitlines(True))
502 503
503 def ancestor(self, fc2, actx=None): 504 def ancestor(self, fc2, actx=None):
504 """ 505 """
505 find the common ancestor file context, if any, of self, and fc2 506 find the common ancestor file context, if any, of self, and fc2
506 507