659 hist[f] = curr |
659 hist[f] = curr |
660 pcache[f] = [] |
660 pcache[f] = [] |
661 |
661 |
662 return zip(hist[base][0], hist[base][1].splitlines(True)) |
662 return zip(hist[base][0], hist[base][1].splitlines(True)) |
663 |
663 |
|
664 def ancestor(self, fc2, actx): |
|
665 """ |
|
666 find the common ancestor file context, if any, of self, and fc2 |
|
667 |
|
668 actx must be the changectx of the common ancestor |
|
669 of self's and fc2's respective changesets. |
|
670 """ |
|
671 |
|
672 # the easy case: no (relevant) renames |
|
673 if fc2.path() == self.path() and self.path() in actx: |
|
674 return actx[self.path()] |
|
675 |
|
676 # the next easiest cases: unambiguous predecessor (name trumps |
|
677 # history) |
|
678 if self.path() in actx and fc2.path() not in actx: |
|
679 return actx[self.path()] |
|
680 if fc2.path() in actx and self.path() not in actx: |
|
681 return actx[fc2.path()] |
|
682 |
|
683 # prime the ancestor cache for the working directory |
|
684 acache = {} |
|
685 for c in (self, fc2): |
|
686 if c.filenode() is None: |
|
687 pl = [(n.path(), n.filenode()) for n in c.parents()] |
|
688 acache[(c._path, None)] = pl |
|
689 |
|
690 flcache = {self._repopath:self._filelog, fc2._repopath:fc2._filelog} |
|
691 def parents(vertex): |
|
692 if vertex in acache: |
|
693 return acache[vertex] |
|
694 f, n = vertex |
|
695 if f not in flcache: |
|
696 flcache[f] = self._repo.file(f) |
|
697 fl = flcache[f] |
|
698 pl = [(f, p) for p in fl.parents(n) if p != nullid] |
|
699 re = fl.renamed(n) |
|
700 if re: |
|
701 pl.append(re) |
|
702 acache[vertex] = pl |
|
703 return pl |
|
704 |
|
705 a, b = (self._path, self._filenode), (fc2._path, fc2._filenode) |
|
706 v = ancestor.genericancestor(a, b, parents) |
|
707 if v: |
|
708 f, n = v |
|
709 return filectx(self._repo, f, fileid=n, filelog=flcache[f]) |
|
710 |
|
711 return None |
|
712 |
664 class filectx(basefilectx): |
713 class filectx(basefilectx): |
665 """A filecontext object makes access to data related to a particular |
714 """A filecontext object makes access to data related to a particular |
666 filerevision convenient.""" |
715 filerevision convenient.""" |
667 def __init__(self, repo, path, changeid=None, fileid=None, |
716 def __init__(self, repo, path, changeid=None, fileid=None, |
668 filelog=None, changectx=None): |
717 filelog=None, changectx=None): |
749 def children(self): |
798 def children(self): |
750 # hard for renames |
799 # hard for renames |
751 c = self._filelog.children(self._filenode) |
800 c = self._filelog.children(self._filenode) |
752 return [filectx(self._repo, self._path, fileid=x, |
801 return [filectx(self._repo, self._path, fileid=x, |
753 filelog=self._filelog) for x in c] |
802 filelog=self._filelog) for x in c] |
754 |
|
755 def ancestor(self, fc2, actx): |
|
756 """ |
|
757 find the common ancestor file context, if any, of self, and fc2 |
|
758 |
|
759 actx must be the changectx of the common ancestor |
|
760 of self's and fc2's respective changesets. |
|
761 """ |
|
762 |
|
763 # the easy case: no (relevant) renames |
|
764 if fc2.path() == self.path() and self.path() in actx: |
|
765 return actx[self.path()] |
|
766 |
|
767 # the next easiest cases: unambiguous predecessor (name trumps |
|
768 # history) |
|
769 if self.path() in actx and fc2.path() not in actx: |
|
770 return actx[self.path()] |
|
771 if fc2.path() in actx and self.path() not in actx: |
|
772 return actx[fc2.path()] |
|
773 |
|
774 # prime the ancestor cache for the working directory |
|
775 acache = {} |
|
776 for c in (self, fc2): |
|
777 if c.filenode() is None: |
|
778 pl = [(n.path(), n.filenode()) for n in c.parents()] |
|
779 acache[(c._path, None)] = pl |
|
780 |
|
781 flcache = {self._repopath:self._filelog, fc2._repopath:fc2._filelog} |
|
782 def parents(vertex): |
|
783 if vertex in acache: |
|
784 return acache[vertex] |
|
785 f, n = vertex |
|
786 if f not in flcache: |
|
787 flcache[f] = self._repo.file(f) |
|
788 fl = flcache[f] |
|
789 pl = [(f, p) for p in fl.parents(n) if p != nullid] |
|
790 re = fl.renamed(n) |
|
791 if re: |
|
792 pl.append(re) |
|
793 acache[vertex] = pl |
|
794 return pl |
|
795 |
|
796 a, b = (self._path, self._filenode), (fc2._path, fc2._filenode) |
|
797 v = ancestor.genericancestor(a, b, parents) |
|
798 if v: |
|
799 f, n = v |
|
800 return filectx(self._repo, f, fileid=n, filelog=flcache[f]) |
|
801 |
|
802 return None |
|
803 |
803 |
804 def ancestors(self, followfirst=False): |
804 def ancestors(self, followfirst=False): |
805 visit = {} |
805 visit = {} |
806 c = self |
806 c = self |
807 cut = followfirst and 1 or None |
807 cut = followfirst and 1 or None |