aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgy Redkozubov <georgy.redkozubov@linaro.org>2013-03-19 23:36:26 +0400
committerGeorgy Redkozubov <georgy.redkozubov@linaro.org>2013-03-19 23:36:26 +0400
commitd8e9daf300e4508e4cfb852bbbc14a63b1caceb3 (patch)
treea7e42be9462c43f5fcf3eea2ab880aaabdaa0d0c
parent637fcc9fc3f7f177097ed2c590d98a077cbeee26 (diff)
Added support for clone/pull operations using dumb http protocol.
-rw-r--r--rhodecode/__init__.py2
-rw-r--r--rhodecode/controllers/admin/settings.py10
-rw-r--r--rhodecode/lib/db_manage.py18
-rw-r--r--rhodecode/lib/middleware/pygrack.py158
-rw-r--r--rhodecode/lib/middleware/simplegit.py2
-rw-r--r--rhodecode/model/forms.py2
-rw-r--r--rhodecode/templates/admin/settings/settings.html32
7 files changed, 157 insertions, 67 deletions
diff --git a/rhodecode/__init__.py b/rhodecode/__init__.py
index a34a1390..03d8d5df 100644
--- a/rhodecode/__init__.py
+++ b/rhodecode/__init__.py
@@ -53,7 +53,7 @@ is_unix = not is_windows
BACKENDS = {
- 'hg': 'Mercurial repository',
+ # 'hg': 'Mercurial repository',
'git': 'Git repository',
}
diff --git a/rhodecode/controllers/admin/settings.py b/rhodecode/controllers/admin/settings.py
index 30181d62..712d6534 100644
--- a/rhodecode/controllers/admin/settings.py
+++ b/rhodecode/controllers/admin/settings.py
@@ -292,6 +292,16 @@ class SettingsController(BaseController):
# sett.ui_active = form_result[_f('extensions_hggit')]
# Session().add(sett)
+ sett = RhodeCodeUi.get_by_key('dumbgit')
+ if not sett:
+ #make one if it's not there !
+ sett = RhodeCodeUi()
+ sett.ui_key = 'dumbgit'
+ sett.ui_section = 'extensions'
+
+ sett.ui_active = form_result[_f('extensions_dumbgit')]
+ Session().add(sett)
+
Session().commit()
h.flash(_('Updated VCS settings'), category='success')
diff --git a/rhodecode/lib/db_manage.py b/rhodecode/lib/db_manage.py
index 2a0df345..7b7c0224 100644
--- a/rhodecode/lib/db_manage.py
+++ b/rhodecode/lib/db_manage.py
@@ -253,6 +253,16 @@ class DbManage(object):
hggit.ui_active = False
Session().add(hggit)
+ notify('installing dumbgit option')
+ # enable a dumb git protocol behavior for clone/pull operations
+ dumbgit = RhodeCodeUi()
+ dumbgit.ui_section = 'extensions'
+ dumbgit.ui_key = 'dumbgit'
+ dumbgit.ui_value = ''
+ dumbgit.ui_active = False
+ Session().ad(dumbgit)
+ RhodeCodeSetting('dumbgit', False)
+
notify('re-check default permissions')
default_user = User.get_by_username(User.DEFAULT_USER)
perm = Permission.get_by_key('hg.fork.repository')
@@ -479,6 +489,14 @@ class DbManage(object):
hggit.ui_active = False
self.sa.add(hggit)
+ # enable a dumb git protocol behavior for clone/pull operations
+ dumbgit = RhodeCodeUi()
+ dumbgit.ui_section = 'extensions'
+ dumbgit.ui_key = 'dumbgit'
+ dumbgit.ui_value = ''
+ dumbgit.ui_active = False
+ self.sa.add(dumbgit)
+
def create_ldap_options(self, skip_existing=False):
"""Creates ldap settings"""
diff --git a/rhodecode/lib/middleware/pygrack.py b/rhodecode/lib/middleware/pygrack.py
index 22384eed..af0fa247 100644
--- a/rhodecode/lib/middleware/pygrack.py
+++ b/rhodecode/lib/middleware/pygrack.py
@@ -7,6 +7,8 @@ import traceback
from webob import Request, Response, exc
from rhodecode.lib import subprocessio
+from rhodecode.model.db import RhodeCodeSetting
+from rhodecode.lib.utils2 import str2bool
log = logging.getLogger(__name__)
@@ -48,10 +50,12 @@ class GitRepository(object):
== self.git_folder_signature):
raise OSError('%s missing git signature' % content_path)
self.content_path = content_path
- self.valid_accepts = ['application/x-%s-result' %
+ self.accepts = ['text/plain']
+ self.valid_accepts = self.accepts + ['application/x-%s-result' %
c for c in self.commands]
self.repo_name = repo_name
self.extras = extras
+ self.dumb = str2bool(RhodeCodeSetting.get_by_name(key='extensions_dumbgit'))
def _get_fixedpath(self, path):
"""
@@ -68,33 +72,54 @@ class GitRepository(object):
HTTP /info/refs request.
"""
- git_command = request.GET.get('service')
- if git_command not in self.commands:
- log.debug('command %s not allowed' % git_command)
- return exc.HTTPMethodNotAllowed()
-
- # note to self:
- # please, resist the urge to add '\n' to git capture and increment
- # line count by 1.
- # The code in Git client not only does NOT need '\n', but actually
- # blows up if you sprinkle "flush" (0000) as "0001\n".
- # It reads binary, per number of bytes specified.
- # if you do add '\n' as part of data, count it.
- server_advert = '# service=%s' % git_command
- packet_len = str(hex(len(server_advert) + 4)[2:].rjust(4, '0')).lower()
- try:
- out = subprocessio.SubprocessIOChunker(
- r'git %s --stateless-rpc --advertise-refs "%s"' % (
- git_command[4:], self.content_path),
- starting_values=[
- packet_len + server_advert + '0000'
- ]
- )
- except EnvironmentError, e:
- log.error(traceback.format_exc())
- raise exc.HTTPExpectationFailed()
+ if self.dumb:
+ git_path = self._get_fixedpath(request.path_info)
+ filename = os.path.join(self.content_path, git_path)
+ if os.path.isfile(filename):
+ out = open(filename)
+ content_type = 'text/plain'
+ content_length = os.path.getsize(filename)
+ status = 200
+ else:
+ log.info("File not found: %s" % git_path)
+ content_type = 'text/html'
+ status = 404
+ out = ['', ]
+ else:
+ git_command = request.GET.get('service')
+ if git_command not in self.commands:
+ log.debug('command %s not allowed' % git_command)
+ return exc.HTTPMethodNotAllowed()
+ # note to self:
+ # please, resist the urge to add '\n' to git capture and increment
+ # line count by 1.
+ # The code in Git client not only does NOT need '\n', but actually
+ # blows up if you sprinkle "flush" (0000) as "0001\n".
+ # It reads binary, per number of bytes specified.
+ # if you do add '\n' as part of data, count it.
+ server_advert = '# service=%s' % git_command
+ packet_len = str(hex(len(server_advert) + 4)[2:].rjust(4, '0')).lower()
+ try:
+ out = subprocessio.SubprocessIOChunker(
+ r'git %s --stateless-rpc --advertise-refs "%s"' % (
+ git_command[4:], self.content_path),
+ starting_values=[
+ packet_len + server_advert + '0000'
+ ]
+ )
+ except EnvironmentError, e:
+ log.error(traceback.format_exc())
+ raise exc.HTTPExpectationFailed()
+
+ content_type = 'application/x-%s-advertisement' % str(git_command)
+ content_length = 0
+ status = 200
+
resp = Response()
- resp.content_type = 'application/x-%s-advertisement' % str(git_command)
+ resp.content_type = content_type
+ if content_length > 0:
+ resp.content_length = content_length
+ resp.status = status
resp.charset = None
resp.app_iter = out
return resp
@@ -107,37 +132,57 @@ class GitRepository(object):
response to stdout
"""
git_command = self._get_fixedpath(request.path_info)
- if git_command not in self.commands:
- log.debug('command %s not allowed' % git_command)
- return exc.HTTPMethodNotAllowed()
+ if self.dumb:
+ filename = os.path.join(self.content_path, git_command)
+
+ if os.path.isfile(filename):
+ out = open(filename)
+ content_type = 'text/plain'
+ content_length = os.path.getsize(filename)
+ status = 200
+ else:
+ log.info("File not found: %s" % git_command)
+ content_type = 'text/html'
+ content_length = 0
+ status = 404
+ out = ['', ]
+ #raise exc.HTTPExpectationFailed()
+ else:
+ if git_command not in self.commands:
+ log.debug('command %s not allowed' % git_command)
+ return exc.HTTPMethodNotAllowed()
- if 'CONTENT_LENGTH' in environ:
- inputstream = FileWrapper(environ['wsgi.input'],
+ if 'CONTENT_LENGTH' in environ:
+ inputstream = FileWrapper(environ['wsgi.input'],
request.content_length)
- else:
- inputstream = environ['wsgi.input']
+ else:
+ inputstream = environ['wsgi.input']
- try:
- gitenv = os.environ
- from rhodecode.lib.compat import json
- gitenv['RHODECODE_EXTRAS'] = json.dumps(self.extras)
- # forget all configs
- gitenv['GIT_CONFIG_NOGLOBAL'] = '1'
- opts = dict(
- env=gitenv,
- cwd=os.getcwd()
- )
- cmd = r'git %s --stateless-rpc "%s"' % (git_command[4:],
+ try:
+ gitenv = os.environ
+ from rhodecode.lib.compat import json
+ gitenv['RHODECODE_EXTRAS'] = json.dumps(self.extras)
+ # forget all configs
+ gitenv['GIT_CONFIG_NOGLOBAL'] = '1'
+ opts = dict(
+ env=gitenv,
+ cwd=os.getcwd()
+ )
+ cmd = r'git %s --stateless-rpc "%s"' % (git_command[4:],
self.content_path),
- log.debug('handling cmd %s' % cmd)
- out = subprocessio.SubprocessIOChunker(
- cmd,
- inputstream=inputstream,
- **opts
- )
- except EnvironmentError, e:
- log.error(traceback.format_exc())
- raise exc.HTTPExpectationFailed()
+ log.debug('handling cmd %s' % cmd)
+ out = subprocessio.SubprocessIOChunker(
+ cmd,
+ inputstream=inputstream,
+ **opts
+ )
+ except EnvironmentError, e:
+ log.error(traceback.format_exc())
+ raise exc.HTTPExpectationFailed()
+
+ content_type = 'application/x-%s-result' % git_command.encode('utf8')
+ content_length = 0
+ status = 200
if git_command in [u'git-receive-pack']:
# updating refs manually after each push.
@@ -148,7 +193,10 @@ class GitRepository(object):
subprocess.call(cmd, shell=True)
resp = Response()
- resp.content_type = 'application/x-%s-result' % git_command.encode('utf8')
+ resp.content_type = content_type
+ if content_length > 0:
+ resp.content_length = content_length
+ resp.status = status
resp.charset = None
resp.app_iter = out
return resp
diff --git a/rhodecode/lib/middleware/simplegit.py b/rhodecode/lib/middleware/simplegit.py
index e35f95ae..0e801c59 100644
--- a/rhodecode/lib/middleware/simplegit.py
+++ b/rhodecode/lib/middleware/simplegit.py
@@ -89,7 +89,7 @@ from rhodecode.model.db import User, RhodeCodeUi
log = logging.getLogger(__name__)
-GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack)')
+GIT_PROTO_PAT = re.compile(r'^/(.+)/(info/refs|git-upload-pack|git-receive-pack|HEAD|objects)')
def is_git(environ):
diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py
index d7c9d38f..407a0577 100644
--- a/rhodecode/model/forms.py
+++ b/rhodecode/model/forms.py
@@ -283,6 +283,8 @@ def ApplicationUiSettingsForm():
extensions_hgsubversion = v.StringBoolean(if_missing=False)
extensions_hggit = v.StringBoolean(if_missing=False)
+ extensions_dumbgit = v.StringBoolean(if_missing=False)
+
return _ApplicationUiSettingsForm
diff --git a/rhodecode/templates/admin/settings/settings.html b/rhodecode/templates/admin/settings/settings.html
index 9b98894b..30d3b497 100644
--- a/rhodecode/templates/admin/settings/settings.html
+++ b/rhodecode/templates/admin/settings/settings.html
@@ -209,14 +209,14 @@
<label>${_('Hooks')}:</label>
</div>
<div class="checkboxes">
- <div class="checkbox">
- ${h.checkbox('hooks_changegroup_update','True')}
- <label for="hooks_changegroup_update">${_('Update repository after push (hg update)')}</label>
- </div>
- <div class="checkbox">
- ${h.checkbox('hooks_changegroup_repo_size','True')}
- <label for="hooks_changegroup_repo_size">${_('Show repository size after push')}</label>
- </div>
+ <div class="checkbox">
+ ${h.checkbox('hooks_changegroup_update','True')}
+ <label for="hooks_changegroup_update">${_('Update repository after push (hg update)')}</label>
+ </div>
+ <div class="checkbox">
+ ${h.checkbox('hooks_changegroup_repo_size','True')}
+ <label for="hooks_changegroup_repo_size">${_('Show repository size after push')}</label>
+ </div>
<div class="checkbox">
${h.checkbox('hooks_changegroup_push_logger','True')}
<label for="hooks_changegroup_push_logger">${_('Log user push commands')}</label>
@@ -225,7 +225,7 @@
${h.checkbox('hooks_outgoing_pull_logger','True')}
<label for="hooks_outgoing_pull_logger">${_('Log user pull commands')}</label>
</div>
- </div>
+ </div>
<div class="input" style="margin-top:10px">
${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'),class_="ui-btn")}
</div>
@@ -237,7 +237,7 @@
<div class="checkboxes">
<div class="checkbox">
${h.checkbox('extensions_largefiles','True')}
- <label for="extensions_hgsubversion">${_('largefiles extensions')}</label>
+ <label for="extensions_largfiles">${_('largefiles extensions')}</label>
</div>
<div class="checkbox">
${h.checkbox('extensions_hgsubversion','True')}
@@ -251,6 +251,18 @@
##<span class="help-block">${_('Requires hg-git library installed. Allows clonning from git remote locations')}</span>
</div>
</div>
+ <div class="field">
+ <div class="label label-checkbox">
+ <label>${_('Git Extensions')}:</label>
+ </div>
+ <div class="checkboxes">
+ <div class="checkbox">
+ ${h.checkbox('extensions_dumbgit', 'False')}
+ <label for="extensions_dumbgit">${_('dumb protocol')}</label>
+ </div>
+ <span class="help-block">${_('Serves files through a normal HTTP connection')}</span>
+ </div>
+ </div>
<div class="field">
<div class="label">
<label for="paths_root_path">${_('Repositories location')}:</label>