[PATCH 2 of 3] Implemented create for httprepo
Martin Vejnar
avakar at ratatanek.cz
Fri Sep 25 09:01:18 CDT 2009
# HG changeset patch
# User Martin Vejnar <avakar at ratatanek.cz>
# Date 1253887056 -7200
# Node ID 58ac824d65d43e7fd060425d4a86b7cd67c02277
# Parent ee8b03eebdf594b33bf0aa106da922d661b976af
Implemented create for httprepo
hgwebdir intercepts 'init' commands and creates an empty repository.
The user must have both allow_push and allow_init permissions
(the former is to ensure that a clone doesn't fail with an empty repo).
hgwebdir config must not specify any repos using [paths] section
(it might make the determination of the path of the new repository
ambiguous due to ** path wildcards). The entries in [collection]
are used the find a suitable path.
The 'init' web command fails if the repository already exists.
diff -r ee8b03eebdf5 -r 58ac824d65d4 doc/hgrc.5.txt
--- a/doc/hgrc.5.txt Fri Sep 25 15:54:56 2009 +0200
+++ b/doc/hgrc.5.txt Fri Sep 25 15:57:36 2009 +0200
@@ -835,6 +835,9 @@
Default is false.
``allowpull``
Whether to allow pulling from the repository. Default is true.
+``allow_init``
+ Whether to allow the creation of new repositories. The syntax
+ is the same as for allow_push below.
``allow_push``
Whether to allow pushing to the repository. If empty or not set,
push is not allowed. If the special value "``*``", any remote user can
@@ -864,6 +867,9 @@
``contact``
Name or email address of the person in charge of the repository.
Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
+``deny_init``
+ Whether to deny the creation of new repositories. The syntax is
+ the same as for deny_push below.
``deny_push``
Whether to deny pushing to the repository. If empty or not set,
push is not denied. If the special value "``*``", all remote users are
diff -r ee8b03eebdf5 -r 58ac824d65d4 mercurial/hgweb/hgwebdir_mod.py
--- a/mercurial/hgweb/hgwebdir_mod.py Fri Sep 25 15:54:56 2009 +0200
+++ b/mercurial/hgweb/hgwebdir_mod.py Fri Sep 25 15:57:36 2009 +0200
@@ -12,8 +12,9 @@
from mercurial import error, encoding
from common import ErrorResponse, get_mtime, staticfile, paritygen,\
get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
-from hgweb_mod import hgweb
+from hgweb_mod import hgweb, check_perms
from request import wsgirequest
+import protocol
import webutil
def cleannames(items):
@@ -48,10 +49,10 @@
self.conf = conf
self.baseui = baseui
self.lastrefresh = 0
- self.refresh()
+ self.refresh(force=True)
- def refresh(self):
- if self.lastrefresh + self.refreshinterval > time.time():
+ def refresh(self, force=False):
+ if not force and self.lastrefresh + self.refreshinterval > time.time():
return
if self.baseui:
@@ -70,6 +71,8 @@
elif isinstance(self.conf, dict):
paths = self.conf.items()
+ self._have_paths = bool(paths)
+
encoding.encoding = self.ui.config('web', 'encoding',
encoding.encoding)
self.motd = self.ui.config('web', 'motd')
@@ -92,6 +95,21 @@
self.repos.sort()
self.lastrefresh = time.time()
+ def guess_repo_path(self, name):
+ if self._have_paths:
+ return
+
+ for prefix, root in self.ui.configitems('collections'):
+ prefix = util.pconvert(prefix).rstrip('/')
+ root = util.pconvert(os.path.abspath(root)).rstrip('/')
+
+ path = prefix + '/' + name
+ if path.startswith(root):
+ return os.path.normpath(path)
+
+ if name.startswith(root) and not name.startswith(prefix):
+ return os.path.normpath(name)
+
def run(self):
if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
raise RuntimeError("This function is only intended to be "
@@ -149,6 +167,30 @@
req.respond(HTTP_OK, ctype)
return self.makeindex(req, tmpl)
+ elif 'cmd' in req.form and req.form['cmd'][0] == 'init':
+ try:
+ check_perms(self.ui, req, ['init', 'push'])
+ except ErrorResponse, inst:
+ req.respond(inst, protocol.HGTYPE)
+ if not inst.message:
+ return ['3\n']
+ return '3\n%s\n' % inst.message,
+
+ real = self.guess_repo_path(virtual)
+ self.ui.debug('new repository path: %s\n' % real)
+
+ req.respond(HTTP_OK, protocol.HGTYPE)
+ if not real:
+ return [_('2\ncannot create a repository with this name\n')]
+
+ try:
+ hg.repository(self.ui, real, create=True)
+ except error.RepoError, e:
+ return ['1\n']
+
+ self.refresh(force=True)
+ return ['0\n']
+
# nested indexes and hgwebs
repos = dict(self.repos)
diff -r ee8b03eebdf5 -r 58ac824d65d4 mercurial/httprepo.py
--- a/mercurial/httprepo.py Fri Sep 25 15:54:56 2009 +0200
+++ b/mercurial/httprepo.py Fri Sep 25 15:57:36 2009 +0200
@@ -22,7 +22,7 @@
yield zd.flush()
class httprepository(repo.repository):
- def __init__(self, ui, path):
+ def __init__(self, ui, path, create):
self.path = path
self.caps = None
self.handler = None
@@ -39,6 +39,22 @@
self.urlopener = url.opener(ui, authinfo)
+ if create:
+ resp = self.do_read('init', data='')
+ resp_code, output = resp.split('\n', 1)
+ try:
+ ret = int(resp_code)
+ except ValueError, err:
+ raise error.ResponseError(
+ _('http repository creation failed (unexpected response):'), resp)
+ self.ui.write(output)
+
+ if ret == 1:
+ raise util.Abort(_('remote repository already exists'))
+
+ if ret != 0:
+ raise util.Abort(_('http repository creation failed'))
+
def __del__(self):
for h in self.urlopener.handlers:
h.close()
@@ -237,20 +253,18 @@
return self.do_cmd('stream_out')
class httpsrepository(httprepository):
- def __init__(self, ui, path):
+ def __init__(self, ui, path, create):
if not url.has_https:
raise util.Abort(_('Python support for SSL and HTTPS '
'is not installed'))
- httprepository.__init__(self, ui, path)
+ httprepository.__init__(self, ui, path, create)
def instance(ui, path, create):
- if create:
- raise util.Abort(_('cannot create new http repository'))
try:
if path.startswith('https:'):
- inst = httpsrepository(ui, path)
+ inst = httpsrepository(ui, path, create)
else:
- inst = httprepository(ui, path)
+ inst = httprepository(ui, path, create)
inst.between([(nullid, nullid)])
return inst
except error.RepoError:
More information about the Mercurial-devel
mailing list