Changeset - 22c8f23cc75b
[Not reviewed]
Merge default
0 6 0
Mads Kiilerich - 7 years ago 2018-11-05 00:31:07
mads@kiilerich.com
Merge stable
5 files changed with 101 insertions and 12 deletions:
0 comments (0 inline, 0 general)
.hgtags
Show inline comments
 
@@ -22,48 +22,49 @@ d9c8dddb96af521e346f05b88d515c536eef3d17
 
344f748517814ed0408a49e392dc625f4cc37fdc rhodecode-0.0.1.1.1
 
6c01c12eafb8cc72d4c4cbd121400fad755b2862 rhodecode-0.0.1.1.2
 
4fa80e0484ef5c33feaa9c39fc66916f410ba353 rhodecode-0.0.1.1.3
 
cb77867d69d3c5931712aac486c980a42ee90745 rhodecode-0.0.1.1.5
 
cb77867d69d3c5931712aac486c980a42ee90745 rhodecode-0.0.1.1.5
 
008bdfdd95c8bd31ae6d89f76c75c1f49cbcd0bc rhodecode-0.0.1.1.5
 
c5af1d3c861fb36b156224e75c2f55a97f54657d rhodecode-0.0.1.1.6
 
7327a0d1584cf28d33e738048af1f6809d499451 rhodecode-0.0.1.1.7
 
bd102f45950f779995a1beae42b6eb099cdd27b3 rhodecode-0.0.1.1.7
 
c8974135732aa0ceb841cee6df66e29f089b4963 rhodecode-0.0.1.1.8
 
c252049af24cd98eef5f4143fa3abbff3c912e29 rhodecode-0.0.1.2.0
 
0b8fba8ab90b01f811a50e6e7384989cced21d38 rhodecode-0.0.1.2.1
 
22273bec00ba2fd860c60a9277d3d7229e288e18 rhodecode-0.0.1.2.2
 
1ff606a7858dbd8a5f70b3da5cc89524bd0d84f9 rhodecode-0.0.1.2.3
 
a7a282a902b207ce34e830d643c79b7ab52e3b35 rhodecode-0.0.1.2.4
 
b6b611e7722e754abebaae6e265cbb4c823d344d rhodecode-0.0.1.2.5
 
dbc82e3362a25d2aece42060089824c4342efd17 rhodecode-0.0.1.3.0
 
79a95f338fd0115b2cdb77118f39e17d22ff505c rhodecode-0.0.1.3.1
 
9ab21c5ddb84935bea5c743b4e147ed5a398b30c rhodecode-0.0.1.3.2
 
934906f028b582a254e0028ba25e5d20dd32b9cd rhodecode-0.0.1.3.3
 
af21362474e3ab5aa0e2fbb1c872356f2c16c4f3 rhodecode-0.0.1.3.4
 
0e2792e04bd316fe64335cbe6a476031ac60b29b rhodecode-0.0.1.3.5
 
edfff9f37916389144d3a3644d0a7d7adfd79b11 rhodecode-0.0.1.3.6
 
9ae95fdeca184f2404205645f06c6597b74ef2db rhodecode-0.0.1.4.0
 
909143a4dde53c46d4f24abb426ec870471c7de1 rhodecode-0.0.1.4.1
 
d998cc84cf726798486a438763053f0e1dc1b646 rhodecode-0.0.1.4.2
 
3f5d40b9dd99ccb009ea2211ee2d4b594c634946 rhodecode-0.0.1.4.3
 
3148c08cf86f1849917e2d50f7ab7766c1550b0a rhodecode-0.0.1.4.4
 
a5f0bc867edc88be23eb808693e5393a97d4c54a rhodecode-0.0.1.5.0
 
3259dc7caea48687eab018ee646ae6ad7e7ef377 rhodecode-0.0.1.5.1
 
efe23d6c178c11d575a0214181276a3452776e48 rhodecode-0.0.1.5.2
 
1a498b11f1540f5b94b6f6009298f5dc3eaad9e9 rhodecode-0.0.1.5.3
 
3447862ad8c9ceba85857774c526e39fde3a2281 rhodecode-0.0.1.5.4
 
c15d7b336af58df9f1bbc8f8957464e7ea618d4c rhodecode-0.0.1.6.0rc1
 
78b53ee0d247f90d51b028307ff5717851b6c265 rhodecode-0.0.1.6.0
 
351ad34d56321349ff5bd38f537bd768b8efef2e rhodecode-0.0.1.7.0
 
1f71ef689d2a3c9978cea6591a1f4e9107a5ca83 rhodecode-0.0.1.7.1
 
cc48c1541c7e2e84114bf92a0f9cd4b8b1341545 0.0
 
d17e88a1a88a29f6fac948c94498129e405a40d3 0.1
 
ad0ce803b40cb17fc3988373052943e041030b02 0.2
 
c6e32714336345403adf76abb6ebf9b8116fcdc7 0.2.1
 
14f488a5dc4ca6647bc6acf12534fd137e968aa8 0.2.2
 
9b3e9e242f5c97cc0c7657e5ac93dce7de61ca16 0.3
 
9bf8eb837e785b6856ccfac264e977ce3ebe1535 0.3.1
 
a84d40e9481fcea4dafadee86b03f0dd401527d6 0.3.2
 
64ea7ea0923618a0c117acebb816a6f0d162bfdb 0.3.3
 
cf635c823ea059cc3a1581b82d8672e46b682384 0.3.4
 
4cca4cc6a0a97f4c4763317184cd41aca4297630 0.3.5
 
082c9b8f0f17bd34740eb90c69bdc4c80d4b5b31 0.3.6
kallithea/lib/base.py
Show inline comments
 
@@ -283,97 +283,97 @@ class BaseVCSController(object):
 
                paste.httpheaders.REMOTE_USER.update(environ, result)
 
                username = result
 
            else:
 
                return None, result.wsgi_application
 

	
 
        #==============================================================
 
        # CHECK PERMISSIONS FOR THIS REQUEST USING GIVEN USERNAME
 
        #==============================================================
 
        try:
 
            user = User.get_by_username_or_email(username)
 
            if user is None or not user.active:
 
                return None, webob.exc.HTTPForbidden()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            return None, webob.exc.HTTPInternalServerError()
 

	
 
        # check permissions for this repository
 
        perm = self._check_permission(action, user, repo_name, ip_addr)
 
        if not perm:
 
            return None, webob.exc.HTTPForbidden()
 

	
 
        return user, None
 

	
 
    def _handle_request(self, environ, start_response):
 
        raise NotImplementedError()
 

	
 
    def _get_by_id(self, repo_name):
 
        """
 
        Gets a special pattern _<ID> from clone url and tries to replace it
 
        with a repository_name for support of _<ID> permanent URLs
 

	
 
        :param repo_name:
 
        """
 

	
 
        data = repo_name.split('/')
 
        if len(data) >= 2:
 
            from kallithea.lib.utils import get_repo_by_id
 
            by_id_match = get_repo_by_id(repo_name)
 
            if by_id_match:
 
                data[1] = safe_str(by_id_match)
 

	
 
        return '/'.join(data)
 

	
 
    def _check_permission(self, action, user, repo_name, ip_addr=None):
 
        """
 
        Checks permissions using action (push/pull) user and repository
 
        name
 

	
 
        :param action: push or pull action
 
        :param action: 'push' or 'pull' action
 
        :param user: `User` instance
 
        :param repo_name: repository name
 
        """
 
        # check IP
 
        ip_allowed = AuthUser.check_ip_allowed(user, ip_addr)
 
        if ip_allowed:
 
            log.info('Access for IP:%s allowed', ip_addr)
 
        else:
 
            return False
 

	
 
        if action == 'push':
 
            if not HasPermissionAnyMiddleware('repository.write',
 
                                              'repository.admin')(user,
 
                                                                  repo_name):
 
                return False
 

	
 
        else:
 
            #any other action need at least read permission
 
            if not HasPermissionAnyMiddleware('repository.read',
 
                                              'repository.write',
 
                                              'repository.admin')(user,
 
                                                                  repo_name):
 
                return False
 

	
 
        return True
 

	
 
    def _get_ip_addr(self, environ):
 
        return _get_ip_addr(environ)
 

	
 
    def __call__(self, environ, start_response):
 
        start = time.time()
 
        try:
 
            return self._handle_request(environ, start_response)
 
        finally:
 
            log = logging.getLogger('kallithea.' + self.__class__.__name__)
 
            log.debug('Request time: %.3fs', time.time() - start)
 
            meta.Session.remove()
 

	
 

	
 
class BaseController(TGController):
 

	
 
    def _before(self, *args, **kwargs):
 
        """
 
        _before is called before controller methods and after __call__
 
        """
 
        c.kallithea_version = __version__
 
        rc_config = Setting.get_app_settings()
 

	
kallithea/lib/markup_renderer.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.lib.markup_renderer
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
Renderer for markup languages with ability to parse using rst or markdown
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: Oct 27, 2011
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 
"""
 

	
 

	
 
import re
 
import logging
 
import traceback
 

	
 
import markdown as markdown_mod
 
import bleach
 

	
 
from kallithea.lib.utils2 import safe_unicode, MENTIONS_REGEX
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
url_re = re.compile(r'''\bhttps?://(?:[\da-zA-Z0-9@:.-]+)'''
 
                    r'''(?:[/a-zA-Z0-9_=@#~&+%.,:;?!*()-]*[/a-zA-Z0-9_=@#~])?''')
 

	
 

	
 
class MarkupRenderer(object):
 
    RESTRUCTUREDTEXT_DISALLOWED_DIRECTIVES = ['include', 'meta', 'raw']
 

	
 
    MARKDOWN_PAT = re.compile(r'md|mkdn?|mdown|markdown', re.IGNORECASE)
 
    RST_PAT = re.compile(r're?st', re.IGNORECASE)
 
    PLAIN_PAT = re.compile(r'readme', re.IGNORECASE)
 

	
 
    def _detect_renderer(self, source, filename):
 
        """
 
        runs detection of what renderer should be used for generating html
 
        from a markup language
 

	
 
        filename can be also explicitly a renderer name
 

	
 
        :param source:
 
        :param filename:
 
        """
 

	
 
        if self.MARKDOWN_PAT.findall(filename):
 
            return self.markdown
 
        elif self.RST_PAT.findall(filename):
 
            return self.rst
 
        elif self.PLAIN_PAT.findall(filename):
 
            return self.rst
 
        return self.plain
 

	
 
    @classmethod
 
    def _flavored_markdown(cls, text):
 
        """
 
        Github style flavored markdown
 

	
 
        :param text:
 
        """
 
        from hashlib import md5
 

	
 
        # Extract pre blocks.
 
        extractions = {}
 

	
 
        def pre_extraction_callback(matchobj):
 
@@ -93,106 +96,132 @@ class MarkupRenderer(object):
 
        text = re.sub(r'^(?! {4}|\t)\w+_\w+_\w[\w_]*', italic_callback, text)
 

	
 
        # In very clear cases, let newlines become <br /> tags.
 
        def newline_callback(matchobj):
 
            if len(matchobj.group(1)) == 1:
 
                return matchobj.group(0).rstrip() + '  \n'
 
            else:
 
                return matchobj.group(0)
 
        pattern = re.compile(r'^[\w\<][^\n]*(\n+)', re.MULTILINE)
 
        text = re.sub(pattern, newline_callback, text)
 

	
 
        # Insert pre block extractions.
 
        def pre_insert_callback(matchobj):
 
            return '\n\n' + extractions[matchobj.group(1)]
 
        text = re.sub(r'{gfm-extraction-([0-9a-f]{32})\}',
 
                      pre_insert_callback, text)
 

	
 
        return text
 

	
 
    def render(self, source, filename=None):
 
        """
 
        Renders a given filename using detected renderer
 
        it detects renderers based on file extension or mimetype.
 
        At last it will just do a simple html replacing new lines with <br/>
 

	
 
        :param file_name:
 
        :param source:
 
        """
 

	
 
        renderer = self._detect_renderer(source, filename)
 
        readme_data = renderer(source)
 
        return readme_data
 

	
 
    @classmethod
 
    def plain(cls, source, universal_newline=True):
 
        source = safe_unicode(source)
 
        if universal_newline:
 
            newline = '\n'
 
            source = newline.join(source.splitlines())
 

	
 
        def url_func(match_obj):
 
            url_full = match_obj.group(0)
 
            return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
 
        source = url_re.sub(url_func, source)
 
        return '<br />' + source.replace("\n", '<br />')
 

	
 
    @classmethod
 
    def markdown(cls, source, safe=True, flavored=False):
 
        """
 
        Convert Markdown (possibly GitHub Flavored) to XSS safe HTML, possibly
 
        with "safe" fall-back to plaintext.
 

	
 
        >>> MarkupRenderer.markdown('''<img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg">''')
 
        u'<p><img id="a" src="http://example.com/test.jpg" style="color: red;"></p>'
 
        >>> MarkupRenderer.markdown('''<img class="c d" src="file://localhost/test.jpg">''')
 
        u'<p><img class="c d"></p>'
 
        >>> MarkupRenderer.markdown('''<a href="foo">foo</a>''')
 
        u'<p><a href="foo">foo</a></p>'
 
        >>> MarkupRenderer.markdown('''<script>alert(1)</script>''')
 
        u'&lt;script&gt;alert(1)&lt;/script&gt;'
 
        >>> MarkupRenderer.markdown('''<div onclick="alert(2)">yo</div>''')
 
        u'<div>yo</div>'
 
        >>> MarkupRenderer.markdown('''<a href="javascript:alert(3)">yo</a>''')
 
        u'<p><a>yo</a></p>'
 
        """
 
        source = safe_unicode(source)
 
        try:
 
            import markdown as __markdown
 
            if flavored:
 
                source = cls._flavored_markdown(source)
 
            return __markdown.markdown(source,
 
            markdown_html = markdown_mod.markdown(source,
 
                                       extensions=['codehilite', 'extra'],
 
                                       extension_configs={'codehilite': {'css_class': 'code-highlight'}})
 
        except ImportError:
 
            log.warning('Install markdown to use this function')
 
            return cls.plain(source)
 
            # Allow most HTML, while preventing XSS issues:
 
            # no <script> tags, no onclick attributes, no javascript
 
            # "protocol", and also limit styling to prevent defacing.
 
            return bleach.clean(markdown_html,
 
                tags=['a', 'abbr', 'b', 'blockquote', 'br', 'code', 'dd',
 
                      'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5',
 
                      'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'span',
 
                      'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th',
 
                      'thead', 'tr', 'ul'],
 
                attributes=['class', 'id', 'style', 'label', 'title', 'alt', 'href', 'src'],
 
                styles=['color'],
 
                protocols=['http', 'https', 'mailto'],
 
                )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            if safe:
 
                log.debug('Falling back to render in plain mode')
 
                return cls.plain(source)
 
            else:
 
                raise
 

	
 
    @classmethod
 
    def rst(cls, source, safe=True):
 
        source = safe_unicode(source)
 
        try:
 
            from docutils.core import publish_parts
 
            from docutils.parsers.rst import directives
 
            docutils_settings = dict([(alias, None) for alias in
 
                                cls.RESTRUCTUREDTEXT_DISALLOWED_DIRECTIVES])
 

	
 
            docutils_settings.update({'input_encoding': 'unicode',
 
                                      'report_level': 4})
 

	
 
            for k, v in docutils_settings.iteritems():
 
                directives.register_directive(k, v)
 

	
 
            parts = publish_parts(source=source,
 
                                  writer_name="html4css1",
 
                                  settings_overrides=docutils_settings)
 

	
 
            return parts['html_title'] + parts["fragment"]
 
        except ImportError:
 
            log.warning('Install docutils to use this function')
 
            return cls.plain(source)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            if safe:
 
                log.debug('Falling back to render in plain mode')
 
                return cls.plain(source)
 
            else:
 
                raise
 

	
 
    @classmethod
 
    def rst_with_mentions(cls, source):
 

	
 
        def wrapp(match_obj):
 
            uname = match_obj.groups()[0]
 
            return '\ **@%(uname)s**\ ' % {'uname': uname}
 
        mention_hl = MENTIONS_REGEX.sub(wrapp, source).strip()
 
        return cls.rst(mention_hl)
kallithea/lib/middleware/simplehg.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.lib.middleware.simplehg
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
SimpleHg middleware for handling Mercurial protocol requests (push/clone etc.).
 
It's implemented with basic auth function
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: Apr 28, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 

	
 
"""
 

	
 

	
 
import os
 
import logging
 
import traceback
 
import urllib
 

	
 
from webob.exc import HTTPNotFound, HTTPForbidden, HTTPInternalServerError, \
 
    HTTPNotAcceptable, HTTPBadRequest
 

	
 
from kallithea.lib.utils2 import safe_str, safe_unicode, fix_PATH, get_server_url, \
 
    _set_extras
 
from kallithea.lib.base import BaseVCSController, check_locking_state
 
from kallithea.lib.utils import make_ui, is_valid_repo, ui_sections
 
from kallithea.lib.vcs.utils.hgcompat import RepoError, hgweb_mod
 
from kallithea.lib.exceptions import HTTPLockedRC
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def is_mercurial(environ):
 
    """
 
    Returns True if request's target is mercurial server - header
 
    ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
 
    """
 
    http_accept = environ.get('HTTP_ACCEPT')
 
    path_info = environ['PATH_INFO']
 
    if http_accept and http_accept.startswith('application/mercurial'):
 
        ishg_path = True
 
    else:
 
        ishg_path = False
 

	
 
    log.debug('pathinfo: %s detected as Mercurial %s',
 
        path_info, ishg_path
 
    )
 
    return ishg_path
 

	
 

	
 
def get_header_hgarg(environ):
 
    """Decode the special Mercurial encoding of big requests over multiple headers.
 
    >>> get_header_hgarg({})
 
    ''
 
    >>> get_header_hgarg({'HTTP_X_HGARG_0': ' ', 'HTTP_X_HGARG_1': 'a','HTTP_X_HGARG_2': '','HTTP_X_HGARG_3': 'b+c %20'})
 
    'ab+c %20'
 
    """
 
    chunks = []
 
    i = 1
 
    while True:
 
        v = environ.get('HTTP_X_HGARG_%d' % i)
 
        if v is None:
 
            break
 
        chunks.append(v)
 
        i += 1
 
    return ''.join(chunks)
 

	
 

	
 
class SimpleHg(BaseVCSController):
 

	
 
    def _handle_request(self, environ, start_response):
 
        if not is_mercurial(environ):
 
            return self.application(environ, start_response)
 

	
 
        ip_addr = self._get_ip_addr(environ)
 
        # skip passing error to error controller
 
        environ['pylons.status_code_redirect'] = True
 

	
 
        #======================================================================
 
        # EXTRACT REPOSITORY NAME FROM ENV
 
        #======================================================================
 
        try:
 
            str_repo_name = self.__get_repository(environ)
 
            repo_name = safe_unicode(str_repo_name)
 
            log.debug('Extracted repo name is %s', repo_name)
 
        except Exception as e:
 
            log.error('error extracting repo_name: %r', e)
 
            return HTTPInternalServerError()(environ, start_response)
 

	
 
        # quick check if that dir exists...
 
        if not is_valid_repo(repo_name, self.basepath, 'hg'):
 
            return HTTPNotFound()(environ, start_response)
 

	
 
        #======================================================================
 
        # GET ACTION PULL or PUSH
 
        #======================================================================
 
        try:
 
            action = self.__get_action(environ)
 
        except HTTPBadRequest as e:
 
            return e(environ, start_response)
 

	
 
        #======================================================================
 
        # CHECK PERMISSIONS
 
        #======================================================================
 
        user, response_app = self._authorize(environ, start_response, action, repo_name, ip_addr)
 
        if response_app is not None:
 
            return response_app(environ, start_response)
 

	
 
        # extras are injected into Mercurial UI object and later available
 
        # in hooks executed by Kallithea
 
        from kallithea import CONFIG
 
        server_url = get_server_url(environ)
 
        extras = {
 
            'ip': ip_addr,
 
            'username': user.username,
 
            'action': action,
 
@@ -160,69 +179,108 @@ class SimpleHg(BaseVCSController):
 
            log.error(traceback.format_exc())
 
            return HTTPInternalServerError()(environ, start_response)
 

	
 
    def __make_app(self, repo_name, baseui, extras):
 
        """
 
        Make an wsgi application using hgweb, and inject generated baseui
 
        instance, additionally inject some extras into ui object
 
        """
 
        class HgWebWrapper(hgweb_mod.hgweb):
 
            # Work-around for Mercurial 3.6+ causing lock exceptions to be
 
            # thrown late
 
            def _runwsgi(self, *args):
 
                try:
 
                    return super(HgWebWrapper, self)._runwsgi(*args)
 
                except HTTPLockedRC as e:
 
                    log.debug('Locked, response %s: %s', e.code, e.title)
 
                    try:
 
                        req, res, repo = args
 
                        res.status = e.status
 
                        res.headers['Content-Type'] = 'text/plain'
 
                        res.setbodybytes('')
 
                        return res.sendresponse()
 
                    except ValueError: # wsgiresponse was introduced in Mercurial 4.6 (a88d68dc3ee8)
 
                        req, repo = args
 
                        req.respond(e.status, 'text/plain')
 
                        return ''
 

	
 
        return HgWebWrapper(repo_name, name=repo_name, baseui=baseui)
 

	
 
    def __get_repository(self, environ):
 
        """
 
        Gets repository name out of PATH_INFO header
 

	
 
        :param environ: environ where PATH_INFO is stored
 
        """
 
        try:
 
            environ['PATH_INFO'] = self._get_by_id(environ['PATH_INFO'])
 
            repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:])
 
            if repo_name.endswith('/'):
 
                repo_name = repo_name.rstrip('/')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
        return repo_name
 

	
 
    def __get_action(self, environ):
 
        """
 
        Maps Mercurial request commands into a pull or push command.
 
        Maps Mercurial request commands into 'pull' or 'push'.
 

	
 
        Raises HTTPBadRequest if the request environment doesn't look like a hg client.
 
        """
 
        mapping = {'unbundle': 'push',
 
                   'pushkey': 'push'}
 
        mapping = {
 
            # 'batch' is not in this list - it is handled explicitly
 
            'between': 'pull',
 
            'branches': 'pull',
 
            'branchmap': 'pull',
 
            'capabilities': 'pull',
 
            'changegroup': 'pull',
 
            'changegroupsubset': 'pull',
 
            'changesetdata': 'pull',
 
            'clonebundles': 'pull',
 
            'debugwireargs': 'pull',
 
            'filedata': 'pull',
 
            'getbundle': 'pull',
 
            'getlfile': 'pull',
 
            'heads': 'pull',
 
            'hello': 'pull',
 
            'known': 'pull',
 
            'lheads': 'pull',
 
            'listkeys': 'pull',
 
            'lookup': 'pull',
 
            'manifestdata': 'pull',
 
            'narrow_widen': 'pull',
 
            'protocaps': 'pull',
 
            'statlfile': 'pull',
 
            'stream_out': 'pull',
 
            'pushkey': 'push',
 
            'putlfile': 'push',
 
            'unbundle': 'push',
 
            }
 
        for qry in environ['QUERY_STRING'].split('&'):
 
            if qry.startswith('cmd'):
 
                cmd = qry.split('=')[-1]
 
                return mapping.get(cmd, 'pull')
 
            parts = qry.split('=', 1)
 
            if len(parts) == 2 and parts[0] == 'cmd':
 
                cmd = parts[1]
 
                if cmd == 'batch':
 
                    hgarg = get_header_hgarg(environ)
 
                    if not hgarg.startswith('cmds='):
 
                        return 'push' # paranoid and safe
 
                    for cmd_arg in hgarg[5:].split(';'):
 
                        cmd, _args = urllib.unquote_plus(cmd_arg).split(' ', 1)
 
                        op = mapping.get(cmd, 'push')
 
                        if op != 'pull':
 
                            assert op == 'push'
 
                            return 'push'
 
                    return 'pull'
 
                return mapping.get(cmd, 'push')
 

	
 
        # Note: the client doesn't get the helpful error message
 
        raise HTTPBadRequest('Unable to detect pull/push action! Are you using non standard command or client?')
 

	
 
    def _augment_hgrc(self, repo_path, baseui):
 
        """Augment baseui with config settings from the repo_path repo"""
 
        hgrc = os.path.join(repo_path, '.hg', 'hgrc')
 
        repoui = make_ui('file', hgrc)
 
        for section in ui_sections:
 
            for k, v in repoui.configitems(section):
 
                baseui.setconfig(section, k, v)
setup.py
Show inline comments
 
modified file chmod 100755 => 100644
 
@@ -15,96 +15,97 @@ def _get_meta_var(name, data, callback_h
 
    import re
 
    matches = re.compile(r'(?:%s)\s*=\s*(.*)' % name).search(data)
 
    if matches:
 
        if not callable(callback_handler):
 
            callback_handler = lambda v: v
 

	
 
        return callback_handler(eval(matches.groups()[0]))
 

	
 
_meta = open(os.path.join(here, 'kallithea', '__init__.py'), 'rb')
 
_metadata = _meta.read()
 
_meta.close()
 

	
 
callback = lambda V: ('.'.join(map(str, V[:3])) + '.'.join(V[3:]))
 
__version__ = _get_meta_var('VERSION', _metadata, callback)
 
__license__ = _get_meta_var('__license__', _metadata)
 
__author__ = _get_meta_var('__author__', _metadata)
 
__url__ = _get_meta_var('__url__', _metadata)
 
# defines current platform
 
__platform__ = platform.system()
 

	
 
is_windows = __platform__ in ['Windows']
 

	
 
requirements = [
 
    "alembic >= 0.8.0, < 1.1",
 
    "gearbox < 1",
 
    "waitress >= 0.8.8, < 1.2",
 
    "WebOb >= 1.7, < 1.8", # turbogears2 2.3.12 requires WebOb<1.8.0
 
    "backlash >= 0.1.2, < 1",
 
    "TurboGears2 >= 2.3.10, < 3",
 
    "tgext.routes >= 0.2.0, < 1",
 
    "Beaker >= 1.7.0, < 2",
 
    "WebHelpers >= 1.3, < 1.4",
 
    "FormEncode >= 1.2.4, < 1.4",
 
    "SQLAlchemy >= 1.1, < 1.3",
 
    "Mako >= 0.9.0, < 1.1",
 
    "Pygments >= 1.5, < 2.3",
 
    "Whoosh >= 2.5.0, < 2.8",
 
    "celery >= 3.1, < 4.0", # celery 4 doesn't work
 
    "Babel >= 0.9.6, < 2.7",
 
    "python-dateutil >= 1.5.0, < 2.8",
 
    "Markdown >= 2.2.1, < 2.7",
 
    "docutils >= 0.8.1, < 0.15",
 
    "URLObject >= 2.3.4, < 2.5",
 
    "Routes >= 1.13, < 2",
 
    "dulwich >= 0.14.1, < 0.20",
 
    "mercurial >= 4.1.1, < 4.9",
 
    "decorator >= 3.3.2, < 4.4",
 
    "Paste >= 2.0.3, < 3",
 
    "bleach >= 3.0, < 3.1",
 
]
 

	
 
if sys.version_info < (2, 7):
 
    requirements.append("importlib == 1.0.1")
 
    requirements.append("argparse")
 

	
 
if not is_windows:
 
    requirements.append("bcrypt >= 3.1.0, < 3.2")
 

	
 
dependency_links = [
 
]
 

	
 
classifiers = [
 
    'Development Status :: 4 - Beta',
 
    'Environment :: Web Environment',
 
    'Framework :: Pylons',
 
    'Intended Audience :: Developers',
 
    'License :: OSI Approved :: GNU General Public License (GPL)',
 
    'Operating System :: OS Independent',
 
    'Programming Language :: Python',
 
    'Programming Language :: Python :: 2.6',
 
    'Programming Language :: Python :: 2.7',
 
    'Topic :: Software Development :: Version Control',
 
]
 

	
 

	
 
# additional files from project that goes somewhere in the filesystem
 
# relative to sys.prefix
 
data_files = []
 

	
 
description = ('Kallithea is a fast and powerful management tool '
 
               'for Mercurial and Git with a built in push/pull server, '
 
               'full text search and code-review.')
 

	
 
keywords = ' '.join([
 
    'kallithea', 'mercurial', 'git', 'code review',
 
    'repo groups', 'ldap', 'repository management', 'hgweb replacement',
 
    'hgwebdir', 'gitweb replacement', 'serving hgweb',
 
])
 

	
 
# long description
 
README_FILE = 'README.rst'
 
try:
 
    long_description = open(README_FILE).read()
 
except IOError as err:
 
    sys.stderr.write(
 
        "[WARNING] Cannot find file specified as long_description (%s)\n"
 
        % README_FILE
0 comments (0 inline, 0 general)