# HG changeset patch # User Gregory Szorc <gregory.sz...@gmail.com> # Date 1496980564 25200 # Thu Jun 08 20:56:04 2017 -0700 # Node ID 872abe4302f5fab719ac0774d5725aff9afa5c20 # Parent 1075b79fc1809c69e1819c654ea1f635c70f1d70 hg: hook immutable repos up to registrar and dispatch
An end goal of the mutable/immutable repo split is for commands to be passed immutable repos by default so all operations are fast and safe. Getting there will be a long endeavor and will be a significant BC breakage. In this commit, we introduce a new argument to @command that specifies an immutable repo is wanted. The value is plugged into the dispatch and repo instantiation mechanism so commands can opt into immutable repos. There are no backwards incompatibilities with the implementation. diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py --- a/mercurial/dispatch.py +++ b/mercurial/dispatch.py @@ -489,8 +489,12 @@ class cmdalias(object): return aliasargs(self.fn, args) def __getattr__(self, name): - adefaults = {r'norepo': True, - r'optionalrepo': False, r'inferrepo': False} + adefaults = { + r'norepo': True, + r'optionalrepo': False, + r'inferrepo': False, + r'immutablerepo': False, + } if name not in adefaults: raise AttributeError(name) if self.badalias or util.safehasattr(self, 'shell'): @@ -883,7 +887,8 @@ def _dispatch(req): else: try: repo = hg.repository(ui, path=path, - presetupfuncs=req.prereposetups) + presetupfuncs=req.prereposetups, + immutable=func.immutablerepo) if not repo.local(): raise error.Abort(_("repository '%s' is not local") % path) diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -10,6 +10,7 @@ from __future__ import absolute_import import errno import hashlib +import inspect import os import shutil @@ -148,9 +149,18 @@ def openpath(ui, path): # a list of (ui, repo) functions called for wire peer initialization wirepeersetupfuncs = [] -def _peerorrepo(ui, path, create=False, presetupfuncs=None): +def _peerorrepo(ui, path, create=False, presetupfuncs=None, immutable=False): """return a repository object for the specified path""" - obj = _peerlookup(path).instance(ui, path, create) + factory = _peerlookup(path) + try: + obj = factory.instance(ui, path, create, immutable=immutable) + except TypeError: + # Not all types support immutable argument. + keywords = inspect.getargspec(factory.instance).keywords or {} + if 'immutable' in keywords: + raise + obj = factory.instance(ui, path, create) + ui = getattr(obj, "ui", ui) for f in presetupfuncs or []: f(ui, obj) @@ -163,9 +173,10 @@ def _peerorrepo(ui, path, create=False, f(ui, obj) return obj -def repository(ui, path='', create=False, presetupfuncs=None): +def repository(ui, path='', create=False, presetupfuncs=None, immutable=False): """return a repository object for the specified path""" - peer = _peerorrepo(ui, path, create, presetupfuncs=presetupfuncs) + peer = _peerorrepo(ui, path, create, presetupfuncs=presetupfuncs, + immutable=immutable) repo = peer.local() if not repo: raise error.Abort(_("repository '%s' is not local") % diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -2060,8 +2060,9 @@ def undoname(fn): assert name.startswith('journal') return os.path.join(base, name.replace('journal', 'undo', 1)) -def instance(ui, path, create): - return localrepository(ui, util.urllocalpath(path), create) +def instance(ui, path, create, immutable=False): + cls = immutablelocalrepository if immutable else localrepository + return cls(ui, util.urllocalpath(path), create) def islocal(path): return True diff --git a/mercurial/registrar.py b/mercurial/registrar.py --- a/mercurial/registrar.py +++ b/mercurial/registrar.py @@ -124,13 +124,21 @@ class command(_funcregistrarbase): command line arguments. If True, arguments will be examined for potential repository locations. See ``findrepo()``. If a repository is found, it will be used. + + The _immutablerepo argument defines whether the command is read-only. If + set, an immutable repository instance will be passed to the command instead + of a mutable one. Once the mutable/immutable split is complete, this API + will be refactored. So it should be considered temporary and not used by + extensions. """ def _doregister(self, func, name, options=(), synopsis=None, - norepo=False, optionalrepo=False, inferrepo=False): + norepo=False, optionalrepo=False, inferrepo=False, + _immutablerepo=False): func.norepo = norepo func.optionalrepo = optionalrepo func.inferrepo = inferrepo + func.immutablerepo = _immutablerepo if synopsis: self._table[name] = func, list(options), synopsis else: _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel