[PATCH 3 of 3 V3] memctx: allow the memlightctx thats reusing the manifest node

Mateusz Kwapich mitrandir at fb.com
Tue Nov 22 16:31:51 EST 2016


Excerpts from Augie Fackler's message of 2016-11-21 18:26:16 -0500:
> On Mon, Nov 21, 2016 at 08:13:32AM -0800, Mateusz Kwapich wrote:
> > # HG changeset patch
> > # User Mateusz Kwapich <mitrandir at fb.com>
> > # Date 1479744581 28800
> > #      Mon Nov 21 08:09:41 2016 -0800
> > # Node ID 4af70f21264ac8e52d9b218080bbc96ee5505606
> > # Parent  4a0824bead3ba5980bd8528937fba5f7bb31ba9f
> > memctx: allow the memlightctx thats reusing the manifest node
> >
> > When we have a lot of files writing a new manifest revision can be expensive.
> > This commit adds a possibility for memctx to reuse a manifest from a different
> > commit. This can be beneficial for commands that are creating metadata changes
> > without any actual files changed like "hg metaedit" in evolve extension.
> >
> > I will send the change for evolve that leverages this once this is accepted.
> >
> > diff --git a/mercurial/context.py b/mercurial/context.py
> > --- a/mercurial/context.py
> > +++ b/mercurial/context.py
> > @@ -1975,3 +1975,101 @@ class memfilectx(committablefilectx):
> >      def write(self, data, flags):
> >          """wraps repo.wwrite"""
> >          self._data = data
> > +
> > +class memlightctx(committablectx):
> 
> Could this instead be called "metadataonlyctx"? No need to do a
> resend, if you're happy with my bikeshed color I can fix it in flight.
> 
> Also, could histedit be updated to use this for 'mess' actions
> perhaps? Probably not easy, but if it is I'd love to see an in-tree
> client of this class. Can you take a look?

sure, feel free to rename it.

I can look into hooking this up into the histedit.  It won't be helpful
in general case of message editing but it can be used when the previous
actions were all "pick" or "mess" and it will be much faster in that
case.

> 
> > +    """Like memctx but it's reusing the manifest of different commit.
> > +    Intended to be used by lightweight operations that are creating
> > +    metadata-only changes.
> > +
> > +    Revision information is supplied at initialization time.  'repo' is the
> > +    current localrepo, 'ctx' is original revision which manifest we're reuisng
> > +    'parents' is a sequence of two parent revisions identifiers (pass None for
> > +    every missing parent), 'text' is the commit.
> > +
> > +    user receives the committer name and defaults to current repository
> > +    username, date is the commit date in any format supported by
> > +    util.parsedate() and defaults to current date, extra is a dictionary of
> > +    metadata or is left empty.
> > +    """
> > +    def __new__(cls, repo, path, *args, **kwargs):
> > +        return super(memlightctx, cls).__new__(cls, repo)
> > +
> > +    def __init__(self, repo, originalctx, parents, text, user=None, date=None,
> > +                 extra=None, editor=False):
> > +        super(memlightctx, self).__init__(repo, text, user, date, extra)
> > +        self._rev = None
> > +        self._node = None
> > +        self._originalctx = originalctx
> > +        self._manifestnode = originalctx.manifestnode()
> > +        parents = [(p or nullid) for p in parents]
> > +        p1, p2 = self._parents = [changectx(self._repo, p) for p in parents]
> > +
> > +        # sanity check to ensure that the reused manifest parents are
> > +        # manifests of our commit parents
> > +        mp1, mp2 = self.manifestctx().parents
> > +        if p1 != nullid and p1.manifestctx().node() != mp1:
> > +            raise RuntimeError('can\'t reuse the manifest: '
> > +                               'its p1 doesn\'t match the new ctx p1')
> > +        if p2 != nullid and p2.manifestctx().node() != mp2:
> > +            raise RuntimeError('can\'t reuse the manifest: '
> > +                               'its p2 doesn\'t match the new ctx p2')
> > +
> > +        self._files = originalctx.files()
> > +        self.substate = {}
> > +
> > +        if extra:
> > +            self._extra = extra.copy()
> > +        else:
> > +            self._extra = {}
> > +
> > +        if self._extra.get('branch', '') == '':
> > +            self._extra['branch'] = 'default'
> > +
> > +        if editor:
> > +            self._text = editor(self._repo, self, [])
> > +            self._repo.savecommitmessage(self._text)
> > +
> > +    def manifestnode(self):
> > +        return self._manifestnode
> > +
> > +    @propertycache
> > +    def _manifestctx(self):
> > +        return self._repo.manifestlog[self._manifestnode]
> > +
> > +    def filectx(self, path, filelog=None):
> > +        return self._originalctx.filectx(path, filelog=filelog)
> > +
> > +    def commit(self):
> > +        """commit context to the repo"""
> > +        return self._repo.commitctx(self)
> > +
> > +    @property
> > +    def _manifest(self):
> > +        return self._originalctx.manifest()
> > +
> > +    @propertycache
> > +    def _status(self):
> > +        """Calculate exact status from ``files`` specified in the ``origctx``
> > +        and parents manifests.
> > +        """
> > +        man1 = self.p1().manifest()
> > +        p2 = self._parents[1]
> > +        # "1 < len(self._parents)" can't be used for checking
> > +        # existence of the 2nd parent, because "memlightctx._parents" is
> > +        # explicitly initialized by the list, of which length is 2.
> > +        if p2.node() != nullid:
> > +            man2 = p2.manifest()
> > +            managing = lambda f: f in man1 or f in man2
> > +        else:
> > +            managing = lambda f: f in man1
> > +
> > +        modified, added, removed = [], [], []
> > +        for f in self._files:
> > +            if not managing(f):
> > +                added.append(f)
> > +            elif self[f]:
> > +                modified.append(f)
> > +            else:
> > +                removed.append(f)
> > +
> > +        return scmutil.status(modified, added, removed, [], [], [], [])
> > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel 

Best,
Mateusz

-- 


More information about the Mercurial-devel mailing list