Changeset - da8f1d1b22de
[Not reviewed]
rhodecode/controllers/api/__init__.py
Show inline comments
 
@@ -5,54 +5,54 @@
 

	
 
    JSON RPC controller
 
    
 
    :created_on: Aug 20, 2011
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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; version 2
 
# of the License or (at your opinion) any later version of the license.
 
# 
 
# 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, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
import inspect
 
import json
 
import logging
 
import types
 
import urllib
 
import traceback
 
from itertools import izip_longest
 

	
 
from rhodecode.lib.compat import izip_longest, json
 

	
 
from paste.response import replace_header
 

	
 
from pylons.controllers import WSGIController
 
from pylons.controllers.util import Response
 

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

	
 
from rhodecode.model.db import User
 
from rhodecode.lib.auth import AuthUser
 

	
 
log = logging.getLogger('JSONRPC')
 

	
 
class JSONRPCError(BaseException):
 

	
 
    def __init__(self, message):
 
        self.message = message
 

	
 
    def __str__(self):
 
        return str(self.message)
 

	
 

	
 
def jsonrpc_error(message, code=None):
 
@@ -82,150 +82,151 @@ class JSONRPCController(WSGIController):
 
        """
 
        return self._rpc_args
 

	
 
    def __call__(self, environ, start_response):
 
        """
 
        Parse the request body as JSON, look up the method on the
 
        controller and if it exists, dispatch to it.
 
        """
 
        if 'CONTENT_LENGTH' not in environ:
 
            log.debug("No Content-Length")
 
            return jsonrpc_error(message="No Content-Length in request")
 
        else:
 
            length = environ['CONTENT_LENGTH'] or 0
 
            length = int(environ['CONTENT_LENGTH'])
 
            log.debug('Content-Length: %s', length)
 

	
 
        if length == 0:
 
            log.debug("Content-Length is 0")
 
            return jsonrpc_error(message="Content-Length is 0")
 

	
 
        raw_body = environ['wsgi.input'].read(length)
 

	
 
        try:
 
            json_body = json.loads(urllib.unquote_plus(raw_body))
 
        except ValueError as e:
 
        except ValueError, e:
 
            #catch JSON errors Here
 
            return jsonrpc_error(message="JSON parse error ERR:%s RAW:%r" \
 
                                 % (e, urllib.unquote_plus(raw_body)))
 

	
 
        #check AUTH based on API KEY
 
        try:
 
            self._req_api_key = json_body['api_key']
 
            self._req_method = json_body['method']
 
            self._req_params = json_body['args']
 
            log.debug('method: %s, params: %s',
 
                      self._req_method,
 
                      self._req_params)
 
        except KeyError as e:
 
        except KeyError, e:
 
            return jsonrpc_error(message='Incorrect JSON query missing %s' % e)
 

	
 
        #check if we can find this session using api_key
 
        try:
 
            u = User.get_by_api_key(self._req_api_key)
 
            auth_u = AuthUser(u.user_id, self._req_api_key)
 
        except Exception as e:
 
        except Exception, e:
 
            return jsonrpc_error(message='Invalid API KEY')
 

	
 
        self._error = None
 
        try:
 
            self._func = self._find_method()
 
        except AttributeError, e:
 
            return jsonrpc_error(message=str(e))
 

	
 
        # now that we have a method, add self._req_params to
 
        # self.kargs and dispatch control to WGIController
 
        argspec = inspect.getargspec(self._func)
 
        arglist = argspec[0][1:]
 
        defaults = argspec[3] or []
 
        default_empty = types.NotImplementedType
 
        
 
        kwarglist = list(izip_longest(reversed(arglist),reversed(defaults),
 

	
 
        kwarglist = list(izip_longest(reversed(arglist), reversed(defaults),
 
                                fillvalue=default_empty))
 

	
 
        # this is little trick to inject logged in user for 
 
        # perms decorators to work they expect the controller class to have
 
        # rhodecode_user attribute set
 
        self.rhodecode_user = auth_u
 

	
 
        # This attribute will need to be first param of a method that uses
 
        # api_key, which is translated to instance of user at that name
 
        USER_SESSION_ATTR = 'apiuser'
 

	
 
        if USER_SESSION_ATTR not in arglist:
 
            return jsonrpc_error(message='This method [%s] does not support '
 
                                 'authentication (missing %s param)' %
 
                                 (self._func.__name__, USER_SESSION_ATTR))
 

	
 
        # get our arglist and check if we provided them as args
 
        for arg,default in kwarglist:
 
        for arg, default in kwarglist:
 
            if arg == USER_SESSION_ATTR:
 
                # USER_SESSION_ATTR is something translated from api key and 
 
                # this is checked before so we don't need validate it
 
                continue
 
            
 

	
 
            # skip the required param check if it's default value is 
 
            # NotImplementedType (default_empty)
 
            if not self._req_params or (type(default) == default_empty
 
                                        and arg not in self._req_params):
 
                return jsonrpc_error(message=('Missing non optional %s arg '
 
                                              'in JSON DATA') % arg)
 

	
 
        self._rpc_args = {USER_SESSION_ATTR:u}
 
        self._rpc_args.update(self._req_params)
 

	
 
        self._rpc_args['action'] = self._req_method
 
        self._rpc_args['environ'] = environ
 
        self._rpc_args['start_response'] = start_response
 

	
 
        status = []
 
        headers = []
 
        exc_info = []
 
        def change_content(new_status, new_headers, new_exc_info=None):
 
            status.append(new_status)
 
            headers.extend(new_headers)
 
            exc_info.append(new_exc_info)
 

	
 
        output = WSGIController.__call__(self, environ, change_content)
 
        output = list(output)
 
        headers.append(('Content-Length', str(len(output[0]))))
 
        replace_header(headers, 'Content-Type', 'application/json')
 
        start_response(status[0], headers, exc_info[0])
 

	
 
        return output
 

	
 
    def _dispatch_call(self):
 
        """
 
        Implement dispatch interface specified by WSGIController
 
        """
 
        try:
 
            raw_response = self._inspect_call(self._func)
 
            if isinstance(raw_response, HTTPError):
 
                self._error = str(raw_response)
 
        except JSONRPCError as e:
 
        except JSONRPCError, e:
 
            self._error = str(e)
 
        except Exception as e:
 
            log.error('Encountered unhandled exception: %s' % traceback.format_exc())
 
        except Exception, e:
 
            log.error('Encountered unhandled exception: %s' \
 
                      % traceback.format_exc())
 
            json_exc = JSONRPCError('Internal server error')
 
            self._error = str(json_exc)
 

	
 
        if self._error is not None:
 
            raw_response = None
 

	
 
        response = dict(result=raw_response, error=self._error)
 

	
 
        try:
 
            return json.dumps(response)
 
        except TypeError, e:
 
            log.debug('Error encoding response: %s', e)
 
            return json.dumps(dict(result=None,
 
                                   error="Error encoding response"))
 

	
 
    def _find_method(self):
 
        """
 
        Return method named by `self._req_method` in controller if able
 
        """
 
        log.debug('Trying to find JSON-RPC method: %s', self._req_method)
 
        if self._req_method.startswith('_'):
 
            raise AttributeError("Method not allowed")
 

	
 
        try:
rhodecode/controllers/branches.py
Show inline comments
 
@@ -9,49 +9,49 @@
 
    :author: marcink
 
    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 

	
 
import logging
 

	
 
from pylons import tmpl_context as c
 
import binascii
 

	
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.odict import OrderedDict
 
from rhodecode.lib.compat import OrderedDict
 
from rhodecode.lib import safe_unicode
 
log = logging.getLogger(__name__)
 

	
 

	
 
class BranchesController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def __before__(self):
 
        super(BranchesController, self).__before__()
 

	
 
    def index(self):
 

	
 
        def _branchtags(localrepo):
 

	
 
            bt = {}
 
            bt_closed = {}
 

	
 
            for bn, heads in localrepo.branchmap().iteritems():
 
                tip = heads[-1]
 
                if 'close' not in localrepo.changelog.read(tip)[5]:
 
                    bt[bn] = tip
 
                else:
rhodecode/controllers/changelog.py
Show inline comments
 
@@ -4,60 +4,55 @@
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    changelog controller for rhodecode
 

	
 
    :created_on: Apr 21, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 

	
 
import logging
 

	
 
try:
 
    import json
 
except ImportError:
 
    #python 2.5 compatibility
 
    import simplejson as json
 

	
 
from mercurial import graphmod
 
from pylons import request, session, tmpl_context as c
 

	
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.helpers import RepoPage
 
from rhodecode.lib.compat import json
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class ChangelogController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def __before__(self):
 
        super(ChangelogController, self).__before__()
 
        c.affected_files_cut_off = 60
 

	
 
    def index(self):
 
        limit = 100
 
        default = 20
 
        if request.params.get('size'):
 
            try:
 
                int_size = int(request.params.get('size'))
 
            except ValueError:
 
                int_size = default
 
            int_size = int_size if int_size <= limit else limit
 
            c.size = int_size
 
            session['changelog_size'] = c.size
rhodecode/controllers/changeset.py
Show inline comments
 
@@ -13,49 +13,49 @@
 
"""
 
# 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/>.
 
import logging
 
import traceback
 

	
 
from pylons import tmpl_context as c, url, request, response
 
from pylons.i18n.translation import _
 
from pylons.controllers.util import redirect
 

	
 
import rhodecode.lib.helpers as h
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.utils import EmptyChangeset
 
from rhodecode.lib.odict import OrderedDict
 
from rhodecode.lib.compat import OrderedDict
 

	
 
from vcs.exceptions import RepositoryError, ChangesetError, \
 
ChangesetDoesNotExistError
 
from vcs.nodes import FileNode
 
from vcs.utils import diffs as differ
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class ChangesetController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def __before__(self):
 
        super(ChangesetController, self).__before__()
 
        c.affected_files_cut_off = 60
 

	
 
    def index(self, revision):
 

	
 
        def wrap_to_table(str):
 

	
 
            return '''<table class="code-difftable">
 
                        <tr class="line">
rhodecode/controllers/files.py
Show inline comments
 
@@ -295,48 +295,55 @@ class FilesController(BaseRepoController
 
    @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
 
    def add(self, repo_name, revision, f_path):
 
        r_post = request.POST
 
        c.cs = self.__get_cs_or_redirect(revision, repo_name,
 
                                         redirect_after=False)
 
        if c.cs is None:
 
            c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias)
 

	
 
        c.f_path = f_path
 

	
 
        if r_post:
 
            unix_mode = 0
 
            content = convert_line_endings(r_post.get('content'), unix_mode)
 

	
 
            message = r_post.get('message') or (_('Added %s via RhodeCode')
 
                                                % (f_path))
 
            location = r_post.get('location')
 
            filename = r_post.get('filename')
 
            file_obj = r_post.get('upload_file', None)
 

	
 
            if file_obj is not None and hasattr(file_obj, 'filename'):
 
                filename = file_obj.filename
 
                content = file_obj.file
 

	
 
            #TODO: REMOVE THIS !!
 
            ################################
 
            import ipdb;ipdb.set_trace()
 
            print 'setting ipdb debuggin for rhodecode.controllers.files.FilesController.add'
 
            ################################
 

	
 

	
 
            node_path = os.path.join(location, filename)
 
            author = self.rhodecode_user.full_contact
 

	
 
            if not content:
 
                h.flash(_('No content'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 
            if not filename:
 
                h.flash(_('No filename'), category='warning')
 
                return redirect(url('changeset_home', repo_name=c.repo_name,
 
                                    revision='tip'))
 

	
 
            try:
 
                self.scm_model.create_node(repo=c.rhodecode_repo,
 
                                             repo_name=repo_name, cs=c.cs,
 
                                             user=self.rhodecode_user,
 
                                             author=author, message=message,
 
                                             content=content, f_path=node_path)
 
                h.flash(_('Successfully committed to %s' % node_path),
 
                        category='success')
 
            except NodeAlreadyExistsError, e:
 
                h.flash(_(e), category='error')
 
            except Exception:
 
                log.error(traceback.format_exc())
rhodecode/controllers/summary.py
Show inline comments
 
@@ -18,61 +18,55 @@
 
# 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/>.
 

	
 
import calendar
 
import logging
 
from time import mktime
 
from datetime import datetime, timedelta, date
 

	
 
from vcs.exceptions import ChangesetError
 

	
 
from pylons import tmpl_context as c, request, url
 
from pylons.i18n.translation import _
 

	
 
from rhodecode.model.db import Statistics, Repository
 
from rhodecode.model.repo import RepoModel
 

	
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.utils import EmptyChangeset
 
from rhodecode.lib.odict import OrderedDict
 

	
 
from rhodecode.lib.celerylib import run_task
 
from rhodecode.lib.celerylib.tasks import get_commits_stats, \
 
    LANGUAGES_EXTENSIONS_MAP
 
from rhodecode.lib.helpers import RepoPage
 
from rhodecode.lib.compat import json, OrderedDict
 

	
 
try:
 
    import json
 
except ImportError:
 
    #python 2.5 compatibility
 
    import simplejson as json
 
    
 
log = logging.getLogger(__name__)
 

	
 

	
 
class SummaryController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def __before__(self):
 
        super(SummaryController, self).__before__()
 

	
 
    def index(self, repo_name):
 

	
 
        e = request.environ
 
        c.dbrepo = dbrepo = c.rhodecode_db_repo
 

	
 
        c.following = self.scm_model.is_following_repo(repo_name,
 
                                                self.rhodecode_user.user_id)
 

	
 
        def url_generator(**kw):
 
            return url('shortlog_home', repo_name=repo_name, size=10, **kw)
 

	
 
        c.repo_changesets = RepoPage(c.rhodecode_repo, page=1,
 
                                     items_per_page=10, url=url_generator)
 
@@ -118,72 +112,72 @@ class SummaryController(BaseRepoControll
 

	
 
        ts_min_m = mktime(td_1m.timetuple())
 
        ts_min_y = mktime(td_1y.timetuple())
 
        ts_max_y = mktime(td.timetuple())
 

	
 
        if dbrepo.enable_statistics:
 
            c.no_data_msg = _('No data loaded yet')
 
            run_task(get_commits_stats, c.dbrepo.repo_name, ts_min_y, ts_max_y)
 
        else:
 
            c.no_data_msg = _('Statistics are disabled for this repository')
 
        c.ts_min = ts_min_m
 
        c.ts_max = ts_max_y
 

	
 
        stats = self.sa.query(Statistics)\
 
            .filter(Statistics.repository == dbrepo)\
 
            .scalar()
 

	
 
        c.stats_percentage = 0
 

	
 
        if stats and stats.languages:
 
            c.no_data = False is dbrepo.enable_statistics
 
            lang_stats_d = json.loads(stats.languages)
 
            c.commit_data = stats.commit_activity
 
            c.overview_data = stats.commit_activity_combined
 
            
 

	
 
            lang_stats = ((x, {"count": y,
 
                               "desc": LANGUAGES_EXTENSIONS_MAP.get(x)})
 
                          for x, y in lang_stats_d.items())
 

	
 
            c.trending_languages = json.dumps(OrderedDict(
 
                                       sorted(lang_stats, reverse=True,
 
                                            key=lambda k: k[1])[:10]
 
                                        )
 
                                    )
 
            last_rev = stats.stat_on_revision
 
            c.repo_last_rev = c.rhodecode_repo.count() - 1 \
 
                if c.rhodecode_repo.revisions else 0
 
            if last_rev == 0 or c.repo_last_rev == 0:
 
                pass
 
            else:
 
                c.stats_percentage = '%.2f' % ((float((last_rev)) /
 
                                                c.repo_last_rev) * 100)
 
        else:
 
            c.commit_data = json.dumps({})
 
            c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 10]])
 
            c.trending_languages = json.dumps({})
 
            c.no_data = True
 
            
 

	
 
        c.enable_downloads = dbrepo.enable_downloads
 
        if c.enable_downloads:
 
            c.download_options = self._get_download_links(c.rhodecode_repo)
 

	
 
        return render('summary/summary.html')
 

	
 
    def _get_download_links(self, repo):
 

	
 
        download_l = []
 

	
 
        branches_group = ([], _("Branches"))
 
        tags_group = ([], _("Tags"))
 

	
 
        for name, chs in c.rhodecode_repo.branches.items():
 
            #chs = chs.split(':')[-1]
 
            branches_group[0].append((chs, name),)
 
        download_l.append(branches_group)
 

	
 
        for name, chs in c.rhodecode_repo.tags.items():
 
            #chs = chs.split(':')[-1]
 
            tags_group[0].append((chs, name),)
 
        download_l.append(tags_group)
 

	
 
        return download_l
rhodecode/controllers/tags.py
Show inline comments
 
@@ -7,47 +7,47 @@
 

	
 
    :created_on: Apr 21, 2010
 
    :author: marcink
 
    :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 
import logging
 

	
 
from pylons import tmpl_context as c
 

	
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.odict import OrderedDict
 
from rhodecode.lib.compat import OrderedDict
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class TagsController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def __before__(self):
 
        super(TagsController, self).__before__()
 

	
 
    def index(self):
 
        c.repo_tags = OrderedDict()
 

	
 
        tags = [(name, c.rhodecode_repo.get_changeset(hash_)) for \
 
                 name, hash_ in c.rhodecode_repo.tags.items()]
 
        ordered_tags = sorted(tags, key=lambda x: x[1].date, reverse=True)
 
        for name, cs_tag in ordered_tags:
 
            c.repo_tags[name] = cs_tag
 

	
 
        return render('tags/tags.html')
rhodecode/lib/__init__.py
Show inline comments
 
@@ -2,56 +2,48 @@
 
"""
 
    rhodecode.lib.__init__
 
    ~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    Some simple helper functions
 

	
 
    :created_on: Jan 5, 2011
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 

	
 

	
 
try:
 
    import json
 
except ImportError:
 
    #python 2.5 compatibility
 
    import simplejson as json
 

	
 

	
 
def __get_lem():
 
    from pygments import lexers
 
    from string import lower
 
    from collections import defaultdict
 

	
 
    d = defaultdict(lambda: [])
 

	
 
    def __clean(s):
 
        s = s.lstrip('*')
 
        s = s.lstrip('.')
 

	
 
        if s.find('[') != -1:
 
            exts = []
 
            start, stop = s.find('['), s.find(']')
 

	
 
            for suffix in s[start + 1:stop]:
 
                exts.append(s[:s.find('[')] + suffix)
 
            return map(lower, exts)
 
        else:
 
            return map(lower, [s])
 

	
 
    for lx, t in sorted(lexers.LEXERS.items()):
 
        m = map(__clean, t[-2])
 
        if m:
 
@@ -188,56 +180,56 @@ def safe_unicode(str_, from_encoding='ut
 
            raise Exception()
 
        return str_.decode(encoding)
 
    except (ImportError, UnicodeDecodeError, Exception):
 
        return unicode(str_, from_encoding, 'replace')
 

	
 
def safe_str(unicode_, to_encoding='utf8'):
 
    """
 
    safe str function. Does few trick to turn unicode_ into string
 
     
 
    In case of UnicodeEncodeError we try to return it with encoding detected
 
    by chardet library if it fails fallback to string with errors replaced
 

	
 
    :param unicode_: unicode to encode
 
    :rtype: str
 
    :returns: str object
 
    """
 

	
 
    if isinstance(unicode_, str):
 
        return unicode_
 

	
 
    try:
 
        return unicode_.encode(to_encoding)
 
    except UnicodeEncodeError:
 
        pass
 
    
 

	
 
    try:
 
        import chardet
 
        encoding = chardet.detect(unicode_)['encoding']
 
        print encoding
 
        if encoding is None:
 
            raise UnicodeEncodeError()
 
        
 

	
 
        return unicode_.encode(encoding)
 
    except (ImportError, UnicodeEncodeError):
 
        return unicode_.encode(to_encoding, 'replace')
 

	
 
    return safe_str
 

	
 

	
 

	
 
def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
 
    """
 
    Custom engine_from_config functions that makes sure we use NullPool for
 
    file based sqlite databases. This prevents errors on sqlite. This only 
 
    applies to sqlalchemy versions < 0.7.0
 

	
 
    """
 
    import sqlalchemy
 
    from sqlalchemy import engine_from_config as efc
 
    import logging
 

	
 
    if int(sqlalchemy.__version__.split('.')[1]) < 7:
 

	
 
        # This solution should work for sqlalchemy < 0.7.0, and should use
 
        # proxy=TimerProxy() for execution time profiling
 

	
 
@@ -365,25 +357,25 @@ def credentials_filter(uri):
 
    if len(uri) > 2 and uri[2]:
 
        uri[2] = ':' + uri[2]
 

	
 
    return ''.join(uri)
 

	
 
def get_changeset_safe(repo, rev):
 
    """
 
    Safe version of get_changeset if this changeset doesn't exists for a 
 
    repo it returns a Dummy one instead
 
    
 
    :param repo:
 
    :param rev:
 
    """
 
    from vcs.backends.base import BaseRepository
 
    from vcs.exceptions import RepositoryError
 
    if not isinstance(repo, BaseRepository):
 
        raise Exception('You must pass an Repository '
 
                        'object as first argument got %s', type(repo))
 

	
 
    try:
 
        cs = repo.get_changeset(rev)
 
    except RepositoryError:
 
        from rhodecode.lib.utils import EmptyChangeset
 
        cs = EmptyChangeset(requested_revision=rev)
 
    return cs
 
\ No newline at end of file
 
    return cs
rhodecode/lib/celerylib/tasks.py
Show inline comments
 
@@ -22,64 +22,61 @@
 
# 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/>.
 
from celery.decorators import task
 

	
 
import os
 
import traceback
 
import logging
 
from os.path import dirname as dn, join as jn
 

	
 
from time import mktime
 
from operator import itemgetter
 
from string import lower
 

	
 
from pylons import config, url
 
from pylons.i18n.translation import _
 

	
 
from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, safe_str
 
from rhodecode.lib.celerylib import run_task, locked_task, str2bool, \
 
    __get_lockkey, LockHeld, DaemonLock
 
from rhodecode.lib.helpers import person
 
from rhodecode.lib.smtp_mailer import SmtpMailer
 
from rhodecode.lib.utils import add_cache
 
from rhodecode.lib.odict import OrderedDict
 
from rhodecode.lib.compat import json, OrderedDict
 

	
 
from rhodecode.model import init_model
 
from rhodecode.model import meta
 
from rhodecode.model.db import RhodeCodeUi, Statistics, Repository
 

	
 
from vcs.backends import get_repo
 

	
 
from sqlalchemy import engine_from_config
 

	
 
add_cache(config)
 

	
 
try:
 
    import json
 
except ImportError:
 
    #python 2.5 compatibility
 
    import simplejson as json
 

	
 

	
 
__all__ = ['whoosh_index', 'get_commits_stats',
 
           'reset_user_password', 'send_email']
 

	
 
CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
 

	
 

	
 
def get_session():
 
    if CELERY_ON:
 
        engine = engine_from_config(config, 'sqlalchemy.db1.')
 
        init_model(engine)
 
    sa = meta.Session()
 
    return sa
 

	
 

	
 
def get_repos_path():
 
    sa = get_session()
 
    q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
 
    return q.ui_value
 

	
 

	
 
@task(ignore_result=True)
 
@locked_task
 
def whoosh_index(repo_location, full_index):
rhodecode/lib/compat.py
Show inline comments
 
new file 100644
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.lib.compat
 
    ~~~~~~~~~~~~~~~~~~~~
 

	
 
    Python backward compatibility functions and common libs
 
    
 
    
 
    :created_on: Oct 7, 2011
 
    :author: marcink
 
    :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>    
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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/>.
 

	
 
#==============================================================================
 
# json
 
#==============================================================================
 
try:
 
    import json
 
except ImportError:
 
    import simplejson as json
 

	
 

	
 
#==============================================================================
 
# izip_longest
 
#==============================================================================
 
try:
 
    from itertools import izip_longest
 
except ImportError:
 
    import itertools
 

	
 
    def izip_longest(*args, **kwds): # noqa
 
        fillvalue = kwds.get("fillvalue")
 

	
 
        def sentinel(counter=([fillvalue] * (len(args) - 1)).pop):
 
            yield counter() # yields the fillvalue, or raises IndexError
 

	
 
        fillers = itertools.repeat(fillvalue)
 
        iters = [itertools.chain(it, sentinel(), fillers)
 
                    for it in args]
 
        try:
 
            for tup in itertools.izip(*iters):
 
                yield tup
 
        except IndexError:
 
            pass
 

	
 

	
 
#==============================================================================
 
# OrderedDict
 
#==============================================================================
 

	
 
# Python Software Foundation License
 

	
 
# XXX: it feels like using the class with "is" and "is not" instead of "==" and
 
# "!=" should be faster.
 
class _Nil(object):
 

	
 
    def __repr__(self):
 
        return "nil"
 

	
 
    def __eq__(self, other):
 
        if (isinstance(other, _Nil)):
 
            return True
 
        else:
 
            return NotImplemented
 

	
 
    def __ne__(self, other):
 
        if (isinstance(other, _Nil)):
 
            return False
 
        else:
 
            return NotImplemented
 

	
 
_nil = _Nil()
 

	
 
class _odict(object):
 
    """Ordered dict data structure, with O(1) complexity for dict operations
 
    that modify one element.
 
    
 
    Overwriting values doesn't change their original sequential order.
 
    """
 

	
 
    def _dict_impl(self):
 
        return None
 

	
 
    def __init__(self, data=(), **kwds):
 
        """This doesn't accept keyword initialization as normal dicts to avoid
 
        a trap - inside a function or method the keyword args are accessible
 
        only as a dict, without a defined order, so their original order is
 
        lost.
 
        """
 
        if kwds:
 
            raise TypeError("__init__() of ordered dict takes no keyword "
 
                            "arguments to avoid an ordering trap.")
 
        self._dict_impl().__init__(self)
 
        # If you give a normal dict, then the order of elements is undefined
 
        if hasattr(data, "iteritems"):
 
            for key, val in data.iteritems():
 
                self[key] = val
 
        else:
 
            for key, val in data:
 
                self[key] = val
 

	
 
    # Double-linked list header
 
    def _get_lh(self):
 
        dict_impl = self._dict_impl()
 
        if not hasattr(self, '_lh'):
 
            dict_impl.__setattr__(self, '_lh', _nil)
 
        return dict_impl.__getattribute__(self, '_lh')
 

	
 
    def _set_lh(self, val):
 
        self._dict_impl().__setattr__(self, '_lh', val)
 

	
 
    lh = property(_get_lh, _set_lh)
 

	
 
    # Double-linked list tail
 
    def _get_lt(self):
 
        dict_impl = self._dict_impl()
 
        if not hasattr(self, '_lt'):
 
            dict_impl.__setattr__(self, '_lt', _nil)
 
        return dict_impl.__getattribute__(self, '_lt')
 

	
 
    def _set_lt(self, val):
 
        self._dict_impl().__setattr__(self, '_lt', val)
 

	
 
    lt = property(_get_lt, _set_lt)
 

	
 
    def __getitem__(self, key):
 
        return self._dict_impl().__getitem__(self, key)[1]
 

	
 
    def __setitem__(self, key, val):
 
        dict_impl = self._dict_impl()
 
        try:
 
            dict_impl.__getitem__(self, key)[1] = val
 
        except KeyError, e:
 
            new = [dict_impl.__getattribute__(self, 'lt'), val, _nil]
 
            dict_impl.__setitem__(self, key, new)
 
            if dict_impl.__getattribute__(self, 'lt') == _nil:
 
                dict_impl.__setattr__(self, 'lh', key)
 
            else:
 
                dict_impl.__getitem__(
 
                    self, dict_impl.__getattribute__(self, 'lt'))[2] = key
 
            dict_impl.__setattr__(self, 'lt', key)
 

	
 
    def __delitem__(self, key):
 
        dict_impl = self._dict_impl()
 
        pred, _ , succ = self._dict_impl().__getitem__(self, key)
 
        if pred == _nil:
 
            dict_impl.__setattr__(self, 'lh', succ)
 
        else:
 
            dict_impl.__getitem__(self, pred)[2] = succ
 
        if succ == _nil:
 
            dict_impl.__setattr__(self, 'lt', pred)
 
        else:
 
            dict_impl.__getitem__(self, succ)[0] = pred
 
        dict_impl.__delitem__(self, key)
 

	
 
    def __contains__(self, key):
 
        return key in self.keys()
 

	
 
    def __len__(self):
 
        return len(self.keys())
 

	
 
    def __str__(self):
 
        pairs = ("%r: %r" % (k, v) for k, v in self.iteritems())
 
        return "{%s}" % ", ".join(pairs)
 

	
 
    def __repr__(self):
 
        if self:
 
            pairs = ("(%r, %r)" % (k, v) for k, v in self.iteritems())
 
            return "odict([%s])" % ", ".join(pairs)
 
        else:
 
            return "odict()"
 

	
 
    def get(self, k, x=None):
 
        if k in self:
 
            return self._dict_impl().__getitem__(self, k)[1]
 
        else:
 
            return x
 

	
 
    def __iter__(self):
 
        dict_impl = self._dict_impl()
 
        curr_key = dict_impl.__getattribute__(self, 'lh')
 
        while curr_key != _nil:
 
            yield curr_key
 
            curr_key = dict_impl.__getitem__(self, curr_key)[2]
 

	
 
    iterkeys = __iter__
 

	
 
    def keys(self):
 
        return list(self.iterkeys())
 

	
 
    def itervalues(self):
 
        dict_impl = self._dict_impl()
 
        curr_key = dict_impl.__getattribute__(self, 'lh')
 
        while curr_key != _nil:
 
            _, val, curr_key = dict_impl.__getitem__(self, curr_key)
 
            yield val
 

	
 
    def values(self):
 
        return list(self.itervalues())
 

	
 
    def iteritems(self):
 
        dict_impl = self._dict_impl()
 
        curr_key = dict_impl.__getattribute__(self, 'lh')
 
        while curr_key != _nil:
 
            _, val, next_key = dict_impl.__getitem__(self, curr_key)
 
            yield curr_key, val
 
            curr_key = next_key
 

	
 
    def items(self):
 
        return list(self.iteritems())
 

	
 
    def sort(self, cmp=None, key=None, reverse=False):
 
        items = [(k, v) for k, v in self.items()]
 
        if cmp is not None:
 
            items = sorted(items, cmp=cmp)
 
        elif key is not None:
 
            items = sorted(items, key=key)
 
        else:
 
            items = sorted(items, key=lambda x: x[1])
 
        if reverse:
 
            items.reverse()
 
        self.clear()
 
        self.__init__(items)
 

	
 
    def clear(self):
 
        dict_impl = self._dict_impl()
 
        dict_impl.clear(self)
 
        dict_impl.__setattr__(self, 'lh', _nil)
 
        dict_impl.__setattr__(self, 'lt', _nil)
 

	
 
    def copy(self):
 
        return self.__class__(self)
 

	
 
    def update(self, data=(), **kwds):
 
        if kwds:
 
            raise TypeError("update() of ordered dict takes no keyword "
 
                            "arguments to avoid an ordering trap.")
 
        if hasattr(data, "iteritems"):
 
            data = data.iteritems()
 
        for key, val in data:
 
            self[key] = val
 

	
 
    def setdefault(self, k, x=None):
 
        try:
 
            return self[k]
 
        except KeyError:
 
            self[k] = x
 
            return x
 

	
 
    def pop(self, k, x=_nil):
 
        try:
 
            val = self[k]
 
            del self[k]
 
            return val
 
        except KeyError:
 
            if x == _nil:
 
                raise
 
            return x
 

	
 
    def popitem(self):
 
        try:
 
            dict_impl = self._dict_impl()
 
            key = dict_impl.__getattribute__(self, 'lt')
 
            return key, self.pop(key)
 
        except KeyError:
 
            raise KeyError("'popitem(): ordered dictionary is empty'")
 

	
 
    def riterkeys(self):
 
        """To iterate on keys in reversed order.
 
        """
 
        dict_impl = self._dict_impl()
 
        curr_key = dict_impl.__getattribute__(self, 'lt')
 
        while curr_key != _nil:
 
            yield curr_key
 
            curr_key = dict_impl.__getitem__(self, curr_key)[0]
 

	
 
    __reversed__ = riterkeys
 

	
 
    def rkeys(self):
 
        """List of the keys in reversed order.
 
        """
 
        return list(self.riterkeys())
 

	
 
    def ritervalues(self):
 
        """To iterate on values in reversed order.
 
        """
 
        dict_impl = self._dict_impl()
 
        curr_key = dict_impl.__getattribute__(self, 'lt')
 
        while curr_key != _nil:
 
            curr_key, val, _ = dict_impl.__getitem__(self, curr_key)
 
            yield val
 

	
 
    def rvalues(self):
 
        """List of the values in reversed order.
 
        """
 
        return list(self.ritervalues())
 

	
 
    def riteritems(self):
 
        """To iterate on (key, value) in reversed order.
 
        """
 
        dict_impl = self._dict_impl()
 
        curr_key = dict_impl.__getattribute__(self, 'lt')
 
        while curr_key != _nil:
 
            pred_key, val, _ = dict_impl.__getitem__(self, curr_key)
 
            yield curr_key, val
 
            curr_key = pred_key
 

	
 
    def ritems(self):
 
        """List of the (key, value) in reversed order.
 
        """
 
        return list(self.riteritems())
 

	
 
    def firstkey(self):
 
        if self:
 
            return self._dict_impl().__getattribute__(self, 'lh')
 
        else:
 
            raise KeyError("'firstkey(): ordered dictionary is empty'")
 

	
 
    def lastkey(self):
 
        if self:
 
            return self._dict_impl().__getattribute__(self, 'lt')
 
        else:
 
            raise KeyError("'lastkey(): ordered dictionary is empty'")
 

	
 
    def as_dict(self):
 
        return self._dict_impl()(self.items())
 

	
 
    def _repr(self):
 
        """_repr(): low level repr of the whole data contained in the odict.
 
        Useful for debugging.
 
        """
 
        dict_impl = self._dict_impl()
 
        form = "odict low level repr lh,lt,data: %r, %r, %s"
 
        return form % (dict_impl.__getattribute__(self, 'lh'),
 
                       dict_impl.__getattribute__(self, 'lt'),
 
                       dict_impl.__repr__(self))
 

	
 
class OrderedDict(_odict, dict):
 

	
 
    def _dict_impl(self):
 
        return dict
 

	
 

	
 
#==============================================================================
 
# OrderedSet
 
#==============================================================================
 
from sqlalchemy.util import OrderedSet
rhodecode/lib/odict.py
Show inline comments
 
deleted file
rhodecode/lib/oset.py
Show inline comments
 
deleted file
rhodecode/model/db.py
Show inline comments
 
@@ -20,51 +20,52 @@
 
# 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/>.
 

	
 
import os
 
import logging
 
import datetime
 
import traceback
 
from datetime import date
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relationship, backref, joinedload, class_mapper
 
from sqlalchemy.orm.interfaces import MapperExtension
 

	
 
from beaker.cache import cache_region, region_invalidate
 

	
 
from vcs import get_backend
 
from vcs.utils.helpers import get_scm
 
from vcs.exceptions import VCSError
 
from vcs.utils.lazy import LazyProperty
 

	
 
from rhodecode.lib import str2bool, safe_str, get_changeset_safe, \
 
    generate_api_key
 
from rhodecode.lib.exceptions import UsersGroupsAssignedException
 
from rhodecode.lib import str2bool, json, safe_str, get_changeset_safe,\
 
    generate_api_key
 
from rhodecode.lib.compat import json
 

	
 
from rhodecode.model.meta import Base, Session
 
from rhodecode.model.caching_query import FromCache
 

	
 
log = logging.getLogger(__name__)
 

	
 
#==============================================================================
 
# BASE CLASSES
 
#==============================================================================
 

	
 
class ModelSerializer(json.JSONEncoder):
 
    """
 
    Simple Serializer for JSON,
 
    
 
    usage::
 
        
 
        to make object customized for serialization implement a __json__
 
        method that will return a dict for serialization into json
 
        
 
    example::
 
        
 
        class Task(object):
 
        
 
            def __init__(self, name, value):
 
@@ -281,49 +282,49 @@ class User(Base, BaseModel):
 

	
 
    @classmethod
 
    def by_username(cls, username, case_insensitive=False):
 
        if case_insensitive:
 
            return Session.query(cls).filter(cls.username.like(username)).one()
 
        else:
 
            return Session.query(cls).filter(cls.username == username).one()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key):
 
        return Session.query(cls).filter(cls.api_key == api_key).one()
 

	
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 

	
 
        self.last_login = datetime.datetime.now()
 
        Session.add(self)
 
        Session.commit()
 
        log.debug('updated user %s lastlogin', self.username)
 

	
 
    @classmethod
 
    def create(cls, form_data):
 
        from rhodecode.lib.auth import get_crypt_password
 
        
 

	
 
        try:
 
            new_user = cls()
 
            for k, v in form_data.items():
 
                if k == 'password':
 
                    v = get_crypt_password(v)
 
                setattr(new_user, k, v)
 

	
 
            new_user.api_key = generate_api_key(form_data['username'])
 
            Session.add(new_user)
 
            Session.commit()
 
            return new_user
 
        except:
 
            log.error(traceback.format_exc())
 
            Session.rollback()
 
            raise
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = {'extend_existing':True}
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 
    repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
rhodecode/model/forms.py
Show inline comments
 
@@ -262,48 +262,61 @@ def ValidRepoName(edit, old_data):
 
            if old_data.get('repo_name') != repo_name_full or not edit:
 

	
 
                if group_path != '':
 
                    if RepoModel().get_by_repo_name(repo_name_full,):
 
                        e_dict = {'repo_name':_('This repository already '
 
                                                'exists in group "%s"') %
 
                                  gr.group_name}
 
                        raise formencode.Invalid('', value, state,
 
                                                 error_dict=e_dict)
 

	
 
                else:
 
                    if RepoModel().get_by_repo_name(repo_name_full):
 
                        e_dict = {'repo_name':_('This repository '
 
                                                'already exists')}
 
                        raise formencode.Invalid('', value, state,
 
                                                 error_dict=e_dict)
 
            return value
 

	
 

	
 
    return _ValidRepoName
 

	
 
def ValidForkName():
 
    class _ValidForkName(formencode.validators.FancyValidator):
 
        def to_python(self, value, state):
 

	
 
            repo_name = value.get('fork_name')
 

	
 
            slug = repo_name_slug(repo_name)
 
            if slug in ['_admin', '']:
 
                e_dict = {'repo_name': _('This repository name is disallowed')}
 
                raise formencode.Invalid('', value, state, error_dict=e_dict)
 

	
 
            if RepoModel().get_by_repo_name(repo_name):
 
                e_dict = {'fork_name':_('This repository '
 
                                        'already exists')}
 
                raise formencode.Invalid('', value, state,
 
                                         error_dict=e_dict)
 
            return value
 
    return _ValidForkName
 

	
 

	
 
def SlugifyName():
 
    class _SlugifyName(formencode.validators.FancyValidator):
 

	
 
        def to_python(self, value, state):
 
            return repo_name_slug(value)
 

	
 
    return _SlugifyName
 

	
 
def ValidCloneUri():
 
    from mercurial.httprepo import httprepository, httpsrepository
 
    from rhodecode.lib.utils import make_ui
 

	
 
    class _ValidCloneUri(formencode.validators.FancyValidator):
 

	
 
        def to_python(self, value, state):
 
            if not value:
 
                pass
 
            elif value.startswith('https'):
 
                try:
 
                    httpsrepository(make_ui('db'), value).capabilities
rhodecode/tests/rhodecode_crawler.py
Show inline comments
 
@@ -81,49 +81,49 @@ def test_changeset_walk(limit=None):
 
    for i in repo:
 
        cnt += 1
 
        raw_cs = '/'.join((PROJECT, 'changeset', i.raw_id))
 
        if limit and limit == cnt:
 
            break
 

	
 
        full_uri = (BASE_URI % raw_cs)
 
        s = time.time()
 
        f = o.open(full_uri)
 
        size = len(f.read())
 
        e = time.time() - s
 
        total_time += e
 
        print '%s visited %s\%s size:%s req:%s ms' % (cnt, full_uri, i, size, e)
 

	
 
    print 'total_time', total_time
 
    print 'average on req', total_time / float(cnt)
 

	
 

	
 
def test_files_walk(limit=100):
 
    print 'processing', jn(PROJECT_PATH, PROJECT)
 
    total_time = 0
 

	
 
    repo = vcs.get_repo(jn(PROJECT_PATH, PROJECT))
 

	
 
    from rhodecode.lib.oset import OrderedSet
 
    from rhodecode.lib.compat import OrderedSet
 

	
 
    paths_ = OrderedSet([''])
 
    try:
 
        tip = repo.get_changeset('tip')
 
        for topnode, dirs, files in tip.walk('/'):
 

	
 
            for dir in dirs:
 
                paths_.add(dir.path)
 
                for f in dir:
 
                    paths_.add(f.path)
 

	
 
            for f in files:
 
                paths_.add(f.path)
 

	
 
    except vcs.exception.RepositoryError, e:
 
        pass
 

	
 
    cnt = 0
 
    for f in paths_:
 
        cnt += 1
 
        if limit and limit == cnt:
 
            break
 

	
 
        file_path = '/'.join((PROJECT, 'files', 'tip', f))
0 comments (0 inline, 0 general)