Mercurial > public > mercurial-scm > hg
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) |