D4535: hg: allow extra arguments to be passed to repo creation

indygreg (Gregory Szorc) phabricator at mercurial-scm.org
Wed Sep 12 09:02:38 EDT 2018


This revision was automatically updated to reflect the committed changes.
Closed by commit rHG089fc0db0954: hg: allow extra arguments to be passed to repo creation (API) (authored by indygreg, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D4535?vs=10912&id=10925#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4535?vs=10912&id=10925

REVISION DETAIL
  https://phab.mercurial-scm.org/D4535

AFFECTED FILES
  hgext/schemes.py
  mercurial/bundlerepo.py
  mercurial/hg.py
  mercurial/httppeer.py
  mercurial/localrepo.py
  mercurial/sshpeer.py
  mercurial/statichttprepo.py
  mercurial/unionrepo.py

CHANGE DETAILS

diff --git a/mercurial/unionrepo.py b/mercurial/unionrepo.py
--- a/mercurial/unionrepo.py
+++ b/mercurial/unionrepo.py
@@ -233,7 +233,7 @@
     def getcwd(self):
         return pycompat.getcwd() # always outside the repo
 
-def instance(ui, path, create, intents=None):
+def instance(ui, path, create, intents=None, createopts=None):
     if create:
         raise error.Abort(_('cannot create new union repository'))
     parentpath = ui.config("bundle", "mainreporoot")
diff --git a/mercurial/statichttprepo.py b/mercurial/statichttprepo.py
--- a/mercurial/statichttprepo.py
+++ b/mercurial/statichttprepo.py
@@ -215,7 +215,7 @@
     def _writecaches(self):
         pass # statichttprepository are read only
 
-def instance(ui, path, create, intents=None):
+def instance(ui, path, create, intents=None, createopts=None):
     if create:
         raise error.Abort(_('cannot create new static-http repository'))
     return statichttprepository(ui, path[7:])
diff --git a/mercurial/sshpeer.py b/mercurial/sshpeer.py
--- a/mercurial/sshpeer.py
+++ b/mercurial/sshpeer.py
@@ -597,7 +597,7 @@
         raise error.RepoError(_('unknown version of SSH protocol: %s') %
                               protoname)
 
-def instance(ui, path, create, intents=None):
+def instance(ui, path, create, intents=None, createopts=None):
     """Create an SSH peer.
 
     The returned object conforms to the ``wireprotov1peer.wirepeer`` interface.
@@ -620,6 +620,14 @@
     args = procutil.sshargs(sshcmd, u.host, u.user, u.port)
 
     if create:
+        # We /could/ do this, but only if the remote init command knows how to
+        # handle them. We don't yet make any assumptions about that. And without
+        # querying the remote, there's no way of knowing if the remote even
+        # supports said requested feature.
+        if createopts:
+            raise error.RepoError(_('cannot create remote SSH repositories '
+                                    'with extra options'))
+
         cmd = '%s %s %s' % (sshcmd, args,
             procutil.shellquote('%s init %s' %
                 (_serverquote(remotecmd), _serverquote(remotepath))))
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -2380,26 +2380,28 @@
     assert name.startswith('journal')
     return os.path.join(base, name.replace('journal', 'undo', 1))
 
-def instance(ui, path, create, intents=None):
+def instance(ui, path, create, intents=None, createopts=None):
     if create:
         vfs = vfsmod.vfs(path, expandpath=True, realpath=True)
 
         if vfs.exists('.hg'):
             raise error.RepoError(_('repository %s already exists') % path)
 
-        createrepository(ui, vfs)
+        createrepository(ui, vfs, createopts=createopts)
 
     return localrepository(ui, util.urllocalpath(path), intents=intents)
 
 def islocal(path):
     return True
 
-def newreporequirements(ui):
+def newreporequirements(ui, createopts=None):
     """Determine the set of requirements for a new local repository.
 
     Extensions can wrap this function to specify custom requirements for
     new repositories.
     """
+    createopts = createopts or {}
+
     requirements = {'revlogv1'}
     if ui.configbool('format', 'usestore'):
         requirements.add('store')
@@ -2440,13 +2442,43 @@
 
     return requirements
 
-def createrepository(ui, wdirvfs):
+def filterknowncreateopts(ui, createopts):
+    """Filters a dict of repo creation options against options that are known.
+
+    Receives a dict of repo creation options and returns a dict of those
+    options that we don't know how to handle.
+
+    This function is called as part of repository creation. If the
+    returned dict contains any items, repository creation will not
+    be allowed, as it means there was a request to create a repository
+    with options not recognized by loaded code.
+
+    Extensions can wrap this function to filter out creation options
+    they know how to handle.
+    """
+    return dict(createopts)
+
+def createrepository(ui, wdirvfs, createopts=None):
     """Create a new repository in a vfs.
 
     ``wdirvfs`` is a vfs instance pointing at the working directory.
     ``requirements`` is a set of requirements for the new repository.
     """
-    requirements = newreporequirements(ui)
+    createopts = createopts or {}
+
+    unknownopts = filterknowncreateopts(ui, createopts)
+
+    if not isinstance(unknownopts, dict):
+        raise error.ProgrammingError('filterknowncreateopts() did not return '
+                                     'a dict')
+
+    if unknownopts:
+        raise error.Abort(_('unable to create repository because of unknown '
+                            'creation option: %s') %
+                          ', '.sorted(unknownopts),
+                          hint=_('is a required extension not loaded?'))
+
+    requirements = newreporequirements(ui, createopts=createopts)
 
     if not wdirvfs.exists():
         wdirvfs.makedirs()
diff --git a/mercurial/httppeer.py b/mercurial/httppeer.py
--- a/mercurial/httppeer.py
+++ b/mercurial/httppeer.py
@@ -982,7 +982,7 @@
     return httppeer(ui, path, respurl, opener, requestbuilder,
                     info['v1capabilities'])
 
-def instance(ui, path, create, intents=None):
+def instance(ui, path, create, intents=None, createopts=None):
     if create:
         raise error.Abort(_('cannot create new http repository'))
     try:
diff --git a/mercurial/hg.py b/mercurial/hg.py
--- a/mercurial/hg.py
+++ b/mercurial/hg.py
@@ -158,9 +158,10 @@
 wirepeersetupfuncs = []
 
 def _peerorrepo(ui, path, create=False, presetupfuncs=None,
-                intents=None):
+                intents=None, createopts=None):
     """return a repository object for the specified path"""
-    obj = _peerlookup(path).instance(ui, path, create, intents=intents)
+    obj = _peerlookup(path).instance(ui, path, create, intents=intents,
+                                     createopts=createopts)
     ui = getattr(obj, "ui", ui)
     if ui.configbool('devel', 'debug.extensions'):
         log = lambda msg, *values: ui.debug('debug.extensions: ',
@@ -184,20 +185,22 @@
             f(ui, obj)
     return obj
 
-def repository(ui, path='', create=False, presetupfuncs=None, intents=None):
+def repository(ui, path='', create=False, presetupfuncs=None, intents=None,
+               createopts=None):
     """return a repository object for the specified path"""
     peer = _peerorrepo(ui, path, create, presetupfuncs=presetupfuncs,
-                       intents=intents)
+                       intents=intents, createopts=createopts)
     repo = peer.local()
     if not repo:
         raise error.Abort(_("repository '%s' is not local") %
                          (path or peer.url()))
     return repo.filtered('visible')
 
-def peer(uiorrepo, opts, path, create=False, intents=None):
+def peer(uiorrepo, opts, path, create=False, intents=None, createopts=None):
     '''return a repository peer for the specified path'''
     rui = remoteui(uiorrepo, opts)
-    return _peerorrepo(rui, path, create, intents=intents).peer()
+    return _peerorrepo(rui, path, create, intents=intents,
+                       createopts=createopts).peer()
 
 def defaultdest(source):
     '''return default destination of clone if none is given
diff --git a/mercurial/bundlerepo.py b/mercurial/bundlerepo.py
--- a/mercurial/bundlerepo.py
+++ b/mercurial/bundlerepo.py
@@ -449,7 +449,7 @@
             self.ui.warn(msg % nodemod.hex(p2))
         return super(bundlerepository, self).setparents(p1, p2)
 
-def instance(ui, path, create, intents=None):
+def instance(ui, path, create, intents=None, createopts=None):
     if create:
         raise error.Abort(_('cannot create new bundle repository'))
     # internal config: bundle.mainreporoot
diff --git a/hgext/schemes.py b/hgext/schemes.py
--- a/hgext/schemes.py
+++ b/hgext/schemes.py
@@ -78,9 +78,10 @@
     def __repr__(self):
         return '<ShortRepository: %s>' % self.scheme
 
-    def instance(self, ui, url, create, intents=None):
+    def instance(self, ui, url, create, intents=None, createopts=None):
         url = self.resolve(url)
-        return hg._peerlookup(url).instance(ui, url, create, intents=intents)
+        return hg._peerlookup(url).instance(ui, url, create, intents=intents,
+                                            createopts=createopts)
 
     def resolve(self, url):
         # Should this use the util.url class, or is manual parsing better?



To: indygreg, #hg-reviewers
Cc: yuja, mercurial-devel


More information about the Mercurial-devel mailing list