comparison mercurial/context.py @ 23979:087603b50889 stable

filectx: move _adjustlinkrev to a method We are going to introduce some wider caching mechanisms during linkrev adjustment. As there is no specific reason to not be a method and some reasons to be a method, let's make it a method.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Fri, 30 Jan 2015 14:39:03 +0000
parents 81349f4b47f4
children c1ce5442453f
comparison
equal deleted inserted replaced
23978:eeb5d5ab14a6 23979:087603b50889
19 19
20 # Phony node value to stand-in for new files in some uses of 20 # Phony node value to stand-in for new files in some uses of
21 # manifests. Manifests support 21-byte hashes for nodes which are 21 # manifests. Manifests support 21-byte hashes for nodes which are
22 # dirty in the working copy. 22 # dirty in the working copy.
23 _newnode = '!' * 21 23 _newnode = '!' * 21
24
25 def _adjustlinkrev(repo, path, filelog, fnode, srcrev, inclusive=False):
26 """return the first ancestor of <srcrev> introducting <fnode>
27
28 If the linkrev of the file revision does not point to an ancestor of
29 srcrev, we'll walk down the ancestors until we find one introducing this
30 file revision.
31
32 :repo: a localrepository object (used to access changelog and manifest)
33 :path: the file path
34 :fnode: the nodeid of the file revision
35 :filelog: the filelog of this path
36 :srcrev: the changeset revision we search ancestors from
37 :inclusive: if true, the src revision will also be checked
38 """
39 cl = repo.unfiltered().changelog
40 ma = repo.manifest
41 # fetch the linkrev
42 fr = filelog.rev(fnode)
43 lkr = filelog.linkrev(fr)
44 # check if this linkrev is an ancestor of srcrev
45 anc = cl.ancestors([srcrev], lkr, inclusive=inclusive)
46 if lkr not in anc:
47 for a in anc:
48 ac = cl.read(a) # get changeset data (we avoid object creation).
49 if path in ac[3]: # checking the 'files' field.
50 # The file has been touched, check if the content is similar
51 # to the one we search for.
52 if fnode == ma.readfast(ac[0]).get(path):
53 return a
54 # In theory, we should never get out of that loop without a result. But
55 # if manifest uses a buggy file revision (not children of the one it
56 # replaces) we could. Such a buggy situation will likely result is crash
57 # somewhere else at to some point.
58 return lkr
59 24
60 class basectx(object): 25 class basectx(object):
61 """A basectx object represents the common logic for its children: 26 """A basectx object represents the common logic for its children:
62 changectx: read-only context that is already present in the repo, 27 changectx: read-only context that is already present in the repo,
63 workingctx: a context that represents the working directory and can 28 workingctx: a context that represents the working directory and can
779 or self.size() == fctx.size()): 744 or self.size() == fctx.size()):
780 return self._filelog.cmp(self._filenode, fctx.data()) 745 return self._filelog.cmp(self._filenode, fctx.data())
781 746
782 return True 747 return True
783 748
749 def _adjustlinkrev(self, path, filelog, fnode, srcrev, inclusive=False):
750 """return the first ancestor of <srcrev> introducting <fnode>
751
752 If the linkrev of the file revision does not point to an ancestor of
753 srcrev, we'll walk down the ancestors until we find one introducing
754 this file revision.
755
756 :repo: a localrepository object (used to access changelog and manifest)
757 :path: the file path
758 :fnode: the nodeid of the file revision
759 :filelog: the filelog of this path
760 :srcrev: the changeset revision we search ancestors from
761 :inclusive: if true, the src revision will also be checked
762 """
763 repo = self._repo
764 cl = repo.unfiltered().changelog
765 ma = repo.manifest
766 # fetch the linkrev
767 fr = filelog.rev(fnode)
768 lkr = filelog.linkrev(fr)
769 # check if this linkrev is an ancestor of srcrev
770 anc = cl.ancestors([srcrev], lkr, inclusive=inclusive)
771 if lkr not in anc:
772 for a in anc:
773 ac = cl.read(a) # get changeset data (we avoid object creation)
774 if path in ac[3]: # checking the 'files' field.
775 # The file has been touched, check if the content is
776 # similar to the one we search for.
777 if fnode == ma.readfast(ac[0]).get(path):
778 return a
779 # In theory, we should never get out of that loop without a result.
780 # But if manifest uses a buggy file revision (not children of the
781 # one it replaces) we could. Such a buggy situation will likely
782 # result is crash somewhere else at to some point.
783 return lkr
784
784 def introrev(self): 785 def introrev(self):
785 """return the rev of the changeset which introduced this file revision 786 """return the rev of the changeset which introduced this file revision
786 787
787 This method is different from linkrev because it take into account the 788 This method is different from linkrev because it take into account the
788 changeset the filectx was created from. It ensures the returned 789 changeset the filectx was created from. It ensures the returned
793 lkr = self.linkrev() 794 lkr = self.linkrev()
794 attrs = vars(self) 795 attrs = vars(self)
795 noctx = not ('_changeid' in attrs or '_changectx' in attrs) 796 noctx = not ('_changeid' in attrs or '_changectx' in attrs)
796 if noctx or self.rev() == lkr: 797 if noctx or self.rev() == lkr:
797 return self.linkrev() 798 return self.linkrev()
798 return _adjustlinkrev(self._repo, self._path, self._filelog, 799 return self._adjustlinkrev(self._path, self._filelog, self._filenode,
799 self._filenode, self.rev(), inclusive=True) 800 self.rev(), inclusive=True)
800 801
801 def parents(self): 802 def parents(self):
802 _path = self._path 803 _path = self._path
803 fl = self._filelog 804 fl = self._filelog
804 parents = self._filelog.parents(self._filenode) 805 parents = self._filelog.parents(self._filenode)
820 for path, fnode, l in pl: 821 for path, fnode, l in pl:
821 if '_changeid' in vars(self) or '_changectx' in vars(self): 822 if '_changeid' in vars(self) or '_changectx' in vars(self):
822 # If self is associated with a changeset (probably explicitly 823 # If self is associated with a changeset (probably explicitly
823 # fed), ensure the created filectx is associated with a 824 # fed), ensure the created filectx is associated with a
824 # changeset that is an ancestor of self.changectx. 825 # changeset that is an ancestor of self.changectx.
825 rev = _adjustlinkrev(self._repo, path, l, fnode, self.rev()) 826 rev = self._adjustlinkrev(path, l, fnode, self.rev())
826 fctx = filectx(self._repo, path, fileid=fnode, filelog=l, 827 fctx = filectx(self._repo, path, fileid=fnode, filelog=l,
827 changeid=rev) 828 changeid=rev)
828 else: 829 else:
829 fctx = filectx(self._repo, path, fileid=fnode, filelog=l) 830 fctx = filectx(self._repo, path, fileid=fnode, filelog=l)
830 ret.append(fctx) 831 ret.append(fctx)