mercurial/context.py
branchstable
changeset 23979 087603b50889
parent 23865 81349f4b47f4
child 23980 c1ce5442453f
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)