def repo_detail(request, pattern): slug = pattern.split('/')[0] repo = get_object_or_404(Repository, slug=slug) response = HttpResponse() hgr = HgRequestWrapper( request, response, script_name=repo.get_absolute_url(), ) """ Authenticate on all requests. To authenticate only against 'POST' requests, uncomment the line below the comment. Currently, repositories are only viewable by authenticated users. If authentication is only done on 'POST' request, then repositories are readable by anyone. but only authenticated users can push. """ realm = hgwebproxy_settings.AUTH_REALM # Change if you want. if is_mercurial(request): # This is a request by a mercurial client # If slash not present then add slash regardless of APPEND_SLASH setting # since hgweb returns 404 if it isn't present. if not request.path.endswith('/'): new_url = [request.get_host(), request.path+'/'] if new_url[0]: newurl = "%s://%s%s" % ( request.is_secure() and 'https' or 'http', new_url[0], urlquote(new_url[1])) else: newurl = urlquote(new_url[1]) if request.GET: newurl += '?' + request.META['QUERY_STRING'] return HttpResponsePermanentRedirect(newurl) authed = basic_auth(request, realm, repo) else: # This is a standard web request if not repo.has_view_permission(request.user): raise PermissionDenied(_("You do not have access to this repository")) authed = request.user.username #if not request.user.is_authenticated(): # return HttpResponseRedirect('%s?next=%s' % # (settings.LOGIN_URL,request.path)) #else: # authed = request.user.username if not authed: response.status_code = 401 response['WWW-Authenticate'] = '''Basic realm="%s"''' % realm return response else: hgr.set_user(authed) """ Run the `hgwebdir` method from Mercurial directly, with our incognito request wrapper, output will be buffered. Wrapped in a try:except: since `hgweb` *can* crash. Mercurial now sends the content through as a generator. We need to iterate over the output in order to get all of the content """ template_dir = os.path.join(os.path.dirname(__file__), 'templates') hgserve = hgweb(str(repo.location)) hgserve.reponame = repo.slug if hgwebproxy_settings.TEMPLATE_PATHS is not None: hgserve.templatepath = hgwebproxy_settings.TEMPLATE_PATHS hgserve.repo.ui.setconfig('web', 'description', smart_str(repo.description)) hgserve.repo.ui.setconfig('web', 'name', smart_str(hgserve.reponame)) # encode('utf-8') FIX "decoding Unicode is not supported" exception on mercurial hgserve.repo.ui.setconfig('web', 'contact', smart_str(repo.owner.get_full_name())) hgserve.repo.ui.setconfig('web', 'allow_archive', repo.allow_archive) # Set the style style = repo.style or hgwebproxy_settings.STYLE if not templater.templatepath(style): raise ImproperlyConfigured(_("'%s' is not an available style. Please check the HGPROXY_STYLE property in your settings.py" % style)) hgserve.repo.ui.setconfig('web', 'style', style) hgserve.repo.ui.setconfig('web', 'baseurl', repo.get_absolute_url() ) # Allow push to the current user hgserve.repo.ui.setconfig('web', 'allow_push', authed) #Allow serving static content from a seperate URL if not settings.DEBUG: hgserve.repo.ui.setconfig('web', 'staticurl', hgwebproxy_settings.STATIC_URL) if settings.DEBUG or hgwebproxy_settings.ALLOW_HTTP_PUSH: # Allow pushing in using http when debugging hgserve.repo.ui.setconfig('web', 'push_ssl', 'false') # Allow hgweb errors to propagate response.write(''.join([each for each in hgserve.run_wsgi(hgr)])) return response
def repo_detail(request, username, pattern): """ Repository detail view. """ repo_name = pattern.split('/')[0] repo = get_object_or_404(Repository, slug=repo_name, owner__username=username) """ Instance the hgweb wrapper """ response = HttpResponse() hgr = HgRequestWrapper(request, response, script_name=repo.get_absolute_url()) """ Authenticate on all requests. To authenticate only against 'POST' requests """ realm = hgwebproxy_settings.AUTH_REALM mercurial_request = is_mercurial(request) if mercurial_request: """ If a slash is not present, would be added a slash regardless of APPEND_SLASH django setting since hgweb returns 404 if it isn't present. """ if not request.path.endswith('/'): new_url = [request.get_host(), request.path + '/'] if new_url[0]: newurl = "%s://%s%s" % (request.is_secure() and 'https' or 'http', new_url[0], urlquote(new_url[1])) else: newurl = urlquote(new_url[1]) if request.GET: newurl += '?' + request.META['QUERY_STRING'] return HttpResponseRedirect(newurl) authed = basic_auth(request, realm, repo) else: if not repo.can_browse(request.user): raise PermissionDenied( _("You do not have access to this repository")) authed = request.user.username if not authed: response.status_code = 401 response['WWW-Authenticate'] = '''Basic realm="%s"''' % realm if request.META['REQUEST_METHOD'] == 'POST' and request.META[ 'QUERY_STRING'].startswith("cmd=unbundle"): # drain request, this is a fix/workaround for http://mercurial.selenic.com/btw/issue1876 hgr.drain() return response else: hgr.set_user(authed) hgserve = hgweb(str(repo.location)) hgserve.reponame = repo.slug # TODO: is it Possible to charge the settings just for one time? hgserve.repo.ui.setconfig('web', 'name', smart_str(hgserve.reponame)) hgserve.repo.ui.setconfig('web', 'description', smart_str(repo.description)) hgserve.repo.ui.setconfig('web', 'contact', smart_str(repo.owner.get_full_name())) hgserve.repo.ui.setconfig('web', 'allow_archive', repo.allow_archive) if os.path.exists(hgwebproxy_settings.STYLES_PATH): template_paths = templater.templatepath() template_paths.insert(0, hgwebproxy_settings.STYLES_PATH) hgserve.repo.ui.setconfig('web', 'templates', template_paths) hgserve.templatepath = hgserve.repo.ui.config('web', 'templates', template_paths) if hgwebproxy_settings.ALLOW_CUSTOM_STYLE: hgserve.repo.ui.setconfig('web', 'style', repo.style) else: hgserve.repo.ui.setconfig('web', 'style', hgwebproxy_settings.DEFAULT_STYLE) hgserve.repo.ui.setconfig('web', 'baseurl', repo.get_absolute_url()) hgserve.repo.ui.setconfig('web', 'allow_push', authed) #Allow push to the current user hgserve.repo.ui.setconfig('web', 'staticurl', hgwebproxy_settings.STATIC_URL) if settings.DEBUG: hgserve.repo.ui.setconfig('web', 'push_ssl', 'false') else: hgserve.repo.ui.setconfig('web', 'push_ssl', repo.allow_push_ssl) # Catch hgweb error to show as Django Exceptions try: response.write(''.join(each for each in hgserve.run_wsgi(hgr))) except KeyError: return HttpResponseServerError('Mercurial has crashed', mimetype='text/html') if mercurial_request: return response # make sure we return the response without wrapping if content-type is # either a binary stream or text/plain (for raw changesets). if response['content-type'].split(';')[0] in ('application/octet-stream', 'text/plain'): return response context = { 'content': response.content, 'reponame': hgserve.reponame, 'static_url': hgwebproxy_settings.STATIC_URL, 'slugpath': request.path.replace(repo.get_absolute_url(), ''), 'is_root': request.path == repo.get_absolute_url(), 'repo': repo, } if request.path.endswith(repo_name + '/rss-log') or request.path.endswith(repo_name + '/atom-log'): return HttpResponse(response.content, mimetype='application/xml') else: return render_to_response("hgwebproxy/wrapper.html", context, RequestContext(request))
def repo_detail(request, username, pattern): """ Repository detail view. """ repo_name = pattern.split('/')[0] repo = get_object_or_404(Repository, slug=repo_name, owner__username=username) """ Instance the hgweb wrapper """ response = HttpResponse() hgr = HgRequestWrapper(request, response, script_name=repo.get_absolute_url()) """ Authenticate on all requests. To authenticate only against 'POST' requests """ realm = hgwebproxy_settings.AUTH_REALM mercurial_request = is_mercurial(request) if mercurial_request: """ If a slash is not present, would be added a slash regardless of APPEND_SLASH django setting since hgweb returns 404 if it isn't present. """ if not request.path.endswith('/'): new_url = [request.get_host(), request.path + '/'] if new_url[0]: newurl = "%s://%s%s" % ( request.is_secure() and 'https' or 'http', new_url[0], urlquote(new_url[1])) else: newurl = urlquote(new_url[1]) if request.GET: newurl += '?' + request.META['QUERY_STRING'] return HttpResponseRedirect(newurl) authed = basic_auth(request, realm, repo) else: if not repo.can_browse(request.user): raise PermissionDenied(_("You do not have access to this repository")) authed = request.user.username if not authed: response.status_code = 401 response['WWW-Authenticate'] = '''Basic realm="%s"''' % realm if request.META['REQUEST_METHOD']=='POST' and request.META['QUERY_STRING'].startswith("cmd=unbundle"): # drain request, this is a fix/workaround for http://mercurial.selenic.com/btw/issue1876 hgr.drain() return response else: hgr.set_user(authed) hgserve = hgweb(str(repo.location)) hgserve.reponame = repo.slug # TODO: is it Possible to charge the settings just for one time? hgserve.repo.ui.setconfig('web', 'name', smart_str(hgserve.reponame)) hgserve.repo.ui.setconfig('web', 'description', smart_str(repo.description)) hgserve.repo.ui.setconfig('web', 'contact', smart_str(repo.owner.get_full_name())) hgserve.repo.ui.setconfig('web', 'allow_archive', repo.allow_archive) if os.path.exists(hgwebproxy_settings.STYLES_PATH): template_paths = templater.templatepath() template_paths.insert(0, hgwebproxy_settings.STYLES_PATH) hgserve.repo.ui.setconfig('web', 'templates', template_paths) hgserve.templatepath = hgserve.repo.ui.config('web', 'templates', template_paths) if hgwebproxy_settings.ALLOW_CUSTOM_STYLE: hgserve.repo.ui.setconfig('web', 'style', repo.style) else: hgserve.repo.ui.setconfig('web', 'style', hgwebproxy_settings.DEFAULT_STYLE) hgserve.repo.ui.setconfig('web', 'baseurl', repo.get_absolute_url()) hgserve.repo.ui.setconfig('web', 'allow_push', authed) #Allow push to the current user hgserve.repo.ui.setconfig('web', 'staticurl', hgwebproxy_settings.STATIC_URL) if settings.DEBUG: hgserve.repo.ui.setconfig('web', 'push_ssl', 'false') else: hgserve.repo.ui.setconfig('web', 'push_ssl', repo.allow_push_ssl) # Catch hgweb error to show as Django Exceptions try: response.write(''.join(each for each in hgserve.run_wsgi(hgr))) except KeyError: return HttpResponseServerError('Mercurial has crashed', mimetype='text/html') if mercurial_request: return response # make sure we return the response without wrapping if content-type is # either a binary stream or text/plain (for raw changesets). if response['content-type'].split(';')[0] in ('application/octet-stream', 'text/plain'): return response context = { 'content': response.content, 'reponame' : hgserve.reponame, 'static_url' : hgwebproxy_settings.STATIC_URL, 'slugpath': request.path.replace(repo.get_absolute_url(), ''), 'is_root': request.path == repo.get_absolute_url(), 'repo': repo, } if request.path.endswith(repo_name + '/rss-log') or request.path.endswith(repo_name + '/atom-log'): return HttpResponse(response.content, mimetype='application/xml') else: return render_to_response("hgwebproxy/wrapper.html", context, RequestContext(request))
def hgroot(request, *args): response = Httpresponseonse() hgr = HgRequestWrapper(request, response) """ You want to specify the path to your config file here. Look at `hgweb.conf` for a working example. """ config = os.path.join(settings.BASE_DIR, 'hgwebproxy', 'hgweb.conf') os.environ['HGRCPATH'] = config """ Authenticate on all requests. To authenticate only against 'POST' requests, uncomment the line below the comment. Currently, repositories are only viewable by authenticated users. If authentication is only done on 'POST' request, then repositories are readable by anyone. but only authenticated users can push. """ #if request.method == "POST": realm = 'Basic Auth' # Change if you want. if is_mercurial(request): # This is a request by a mercurial user authed = basic_auth(request, realm) else: # This is a standard web request if not request.user.is_authenticated(): return HttpresponseonseRedirect('%s?next=%s' % (settings.LOGIN_URL,request.path)) else: authed = request.user.username if not authed: response.status_code = 401 response['WWW-Authenticate'] = '''Basic realm="%s"''' % realm return response else: hgr.set_user(authed) """ Run the `hgwebdir` method from Mercurial directly, with our incognito request wrapper, output will be buffered. Wrapped in a try:except: since `hgweb` *can* crash. Mercurial now sends the content through as a generator. We need to iterate over the output in order to get all of the content """ try: response.write(''.join([each for each in hgwrapper(config)])) except KeyError: response['content-type'] = 'text/html' response.write('hgweb crashed.') # if hgweb crashed you can do what you like, throw a 404 or continue on # hgweb tends to throw these on invalid requests..? pass """ In cases of downloading raw files or tarballs, we don't want to pass the output to our template, so instead we just return it as-is. """ if response.has_header('content-type'): if not response['content-type'].startswith("text/html"): return response """ Otherwise, send the content on to the template, for any kind of custom layout you want around it. """ return render_to_responseonse("flat.html", { 'content': response.content, }, RequestContext(request))
def explore(self, request, id, *args): opts = self.model._meta app_label = opts.app_label response = HttpResponse() repo = get_object_or_404(Repository, pk=id) if not self.has_view_permission(request, repo): raise PermissionDenied hgr = HgRequestWrapper( request, response, script_name=repo.get_admin_explore_url(), ) hgr.set_user(request.user.username) """ Run the `hgwebdir` method from Mercurial directly, with our incognito request wrapper, output will be buffered. Wrapped in a try:except: since `hgweb` *can* crash. Mercurial now sends the content through as a generator. We need to iterate over the output in order to get all of the content """ template_dir = os.path.join(os.path.dirname(__file__), 'templates') hgserve = hgweb(str(repo.location)) hgserve.reponame = repo.slug # TODO: A more flexible way to get the default template path of mercurial hgserve.templatepath = (template_dir, '/usr/share/mercurial/templates') hgserve.repo.ui.setconfig('web', 'description', smart_str(repo.description)) hgserve.repo.ui.setconfig('web', 'name', smart_str(hgserve.reponame)) # encode('utf-8') FIX "decoding Unicode is not supported" exception on mercurial hgserve.repo.ui.setconfig('web', 'contact', smart_str(repo.owner.get_full_name())) hgserve.repo.ui.setconfig('web', 'allow_archive', repo.allow_archive) hgserve.repo.ui.setconfig('web', 'style', 'monoblue_plain') hgserve.repo.ui.setconfig('web', 'baseurl', repo.get_admin_explore_url()) hgserve.repo.ui.setconfig('web', 'staticurl', STATIC_URL) try: response.write(''.join([each for each in hgserve.run_wsgi(hgr)])) except KeyError: response['content-type'] = 'text/html' response.write('hgweb crashed.') # if hgweb crashed you can do what you like, throw a 404 or continue on # hgweb tends to throw these on invalid requests..? pass context = { 'app_label': app_label, 'opts': opts, 'has_change_permission': self.has_change_permission(request, repo), 'original': repo, 'content': response.content, 'reponame' : hgserve.reponame, 'static_url' : STATIC_URL, 'slugpath': request.path.replace(repo.get_admin_explore_url(), '') or 'summary', 'is_root': request.path == repo.get_admin_explore_url(), } """ In cases of downloading raw files or tarballs, we don't want to pass the output to our template, so instead we just return it as-is. """ if response.has_header('content-type'): if not response['content-type'].startswith("text/html"): return response """ Otherwise, send the content on to the template, for any kind of custom layout you want around it. """ return render_to_response("admin/hgwebproxy/repository/explore.html", context, RequestContext(request))