Skip to content

Instantly share code, notes, and snippets.

@dmpayton
Last active January 28, 2016 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmpayton/2fc0c5353c5a54c7c624 to your computer and use it in GitHub Desktop.
Save dmpayton/2fc0c5353c5a54c7c624 to your computer and use it in GitHub Desktop.
Django+Git server proof of concept
import itertools
from django.conf import settings
from django.conf.urls import url
from django.http import HttpResponse
from django.utils.decorators import classonlymethod
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View
from dulwich.repo import Repo
from dulwich.server import DictBackend
from dulwich.web import HTTPGitApplication
class GitWeb(View):
prefix = None
@classonlymethod
def mount(cls, prefix, name=None):
regex = r'^{0}'.format(prefix.lstrip('/'))
return url(regex, csrf_exempt(cls.as_view(prefix=prefix)), name=name)
def dispatch(self, request, *args, **kwargs):
self.patch_request(request)
self.app = self.make_wsgi_app()
return self.generate_response()
def make_wsgi_app(self):
gitdir = settings.BASE_DIR
backend = DictBackend({'/': Repo(gitdir)})
app = HTTPGitApplication(backend)
return app
def generate_response(self):
response_data = {}
buffer = []
def start_response(status, headers, exc_info=None):
if exc_info is not None:
raise exc_info[0], exc_info[1], exc_info[2]
response_data['status'] = int(status.split()[0])
response_data['headers'] = headers
return buffer.append
response = self.app(self.request.environ, start_response)
response = HttpResponse(itertools.chain(buffer, list(response)),
status=response_data['status'])
for key, value in response_data['headers']:
response[key] = value
return response
def patch_request(self, request):
patched = request.environ['PATH_INFO'][len(self.prefix):]
original_script_name = request.environ.get('SCRIPT_NAME', '')
request.environ['PATH_INFO'] = patched
request.environ['SCRIPT_NAME'] = original_script_name + self.prefix
request.environ['wsgi.input'] = request._stream
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment