def _filecommit()

in eden/scm/edenscm/mercurial/localrepo.py [0:0]


    def _filecommit(self, fctx, manifest1, manifest2, linkrev, tr, changelist):
        """
        commit an individual file as part of a larger transaction
        """

        fname = fctx.path()
        fparent1 = manifest1.get(fname, nullid)
        fparent2 = manifest2.get(fname, nullid)
        node = fctx.filenode()
        if node in [fparent1, fparent2]:
            self.ui.debug("reusing %s filelog entry (parent match)\n" % fname)
            if node == fparent1:
                if manifest1.flags(fname) != fctx.flags():
                    changelist.append(fname)
            else:
                if manifest2.flags(fname) != fctx.flags():
                    changelist.append(fname)
            return node

        flog = self.file(fname)
        meta = {}
        copy = fctx.renamed()

        # Is filelog metadata (currently only the copy information) unchanged?
        # If it is, then filenode hash could be unchanged if data is also known
        # unchanged. This allows fast path of adding new file nodes without
        # calculating .data() or new hash.
        #
        # Metadata is unchanged if there is no copy information.
        # Otherwise, the "copy from" revision needs to be checked.
        metamatched = not bool(copy)

        if copy and copy[0] != fname:
            # Mark the new revision of this file as a copy of another
            # file.  This copy data will effectively act as a parent
            # of this new revision.  If this is a merge, the first
            # parent will be the nullid (meaning "look up the copy data")
            # and the second one will be the other parent.  For example:
            #
            # 0 --- 1 --- 3   rev1 changes file foo
            #   \       /     rev2 renames foo to bar and changes it
            #    \- 2 -/      rev3 should have bar with all changes and
            #                      should record that bar descends from
            #                      bar in rev2 and foo in rev1
            #
            # this allows this merge to succeed:
            #
            # 0 --- 1 --- 3   rev4 reverts the content change from rev2
            #   \       /     merging rev3 and rev4 should use bar@rev2
            #    \- 2 --- 4        as the merge base
            #

            cfname, oldcrev = copy
            crev = manifest1.get(cfname)
            newfparent = fparent2

            if manifest2:  # branch merge
                if fparent2 == nullid or crev is None:  # copied on remote side
                    if cfname in manifest2:
                        crev = manifest2[cfname]
                        newfparent = fparent1

            # Here, we used to search backwards through history to try to find
            # where the file copy came from if the source of a copy was not in
            # the parent directory. However, this doesn't actually make sense to
            # do (what does a copy from something not in your working copy even
            # mean?) and it causes bugs (eg, issue4476). Instead, we will warn
            # the user that copy information was dropped, so if they didn't
            # expect this outcome it can be fixed, but this is the correct
            # behavior in this circumstance.

            if crev:
                self.ui.debug(" %s: copy %s:%s\n" % (fname, cfname, hex(crev)))
                meta["copy"] = cfname
                meta["copyrev"] = hex(crev)
                metamatched = crev == oldcrev
                fparent1, fparent2 = nullid, newfparent
            else:
                self.ui.warn(
                    _("warning: can't find ancestor for '%s' " "copied from '%s'!\n")
                    % (fname, cfname)
                )

        elif fparent1 == nullid:
            fparent1, fparent2 = fparent2, nullid
        elif fparent2 != nullid:
            # is one parent an ancestor of the other?
            fparentancestors = flog.commonancestorsheads(fparent1, fparent2)
            if fparent1 in fparentancestors:
                fparent1, fparent2 = fparent2, nullid
            elif fparent2 in fparentancestors:
                fparent2 = nullid

        # Fast path: reuse rawdata? (skip .data() (ex. flagprocessors) and hash
        # calculation)
        if (
            metamatched
            and node is not None
            # some filectxs do not support rawdata or flags
            and util.safehasattr(fctx, "rawdata")
            and util.safehasattr(fctx, "rawflags")
            # some (external) filelogs do not have addrawrevision
            and util.safehasattr(flog, "addrawrevision")
            # parents must match to be able to reuse rawdata
            and fctx.filelog().parents(node) == (fparent1, fparent2)
        ):
            # node is different from fparents, no need to check manifest flag
            changelist.append(fname)
            if node in flog.nodemap:
                self.ui.debug("reusing %s filelog node (exact match)\n" % fname)
                return node
            self.ui.debug("reusing %s filelog rawdata\n" % fname)
            return flog.addrawrevision(
                fctx.rawdata(), tr, linkrev, fparent1, fparent2, node, fctx.rawflags()
            )

        # is the file changed?
        text = fctx.data()
        if fparent2 != nullid or flog.cmp(fparent1, text) or meta:
            changelist.append(fname)
            return flog.add(text, meta, tr, linkrev, fparent1, fparent2)
        # are just the flags changed during merge?
        elif fname in manifest1 and manifest1.flags(fname) != fctx.flags():
            changelist.append(fname)

        return fparent1