[PATCH 3 of 3 V3] memctx: allow the memlightctx thats reusing the manifest node
Augie Fackler
raf at durin42.com
Mon Nov 21 18:26:16 EST 2016
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?
> + """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, [], [], [], [])
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list