Changeset - 8182ebed2922
[Not reviewed]
beta
0 9 0
Marcin Kuzminski - 13 years ago 2013-01-05 01:58:29
marcin@python-works.com
Added full last changeset info to lightweight dashboard
9 files changed with 79 insertions and 12 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/home.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.controllers.home
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    Home controller for Rhodecode
 

	
 
    :created_on: Feb 18, 2010
 
    :author: marcink
 
    :copyright: (C) 2010-2012 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, request
 
from pylons.i18n.translation import _
 
from webob.exc import HTTPBadRequest
 

	
 
import rhodecode
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.ext_json import json
 
from rhodecode.lib.auth import LoginRequired
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.model.db import Repository
 
from sqlalchemy.sql.expression import func
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class HomeController(BaseController):
 

	
 
    @LoginRequired()
 
    def __before__(self):
 
        super(HomeController, self).__before__()
 

	
 
    def index(self):
 
        c.groups = self.scm_model.get_repos_groups()
 
        c.group = None
 

	
 
        if c.visual.lightweight_dashboard is False:
 
            c.repos_list = self.scm_model.get_repos()
 
        ## lightweight version of dashboard
 
        else:
 
            c.repos_list = Repository.query()\
 
                            .filter(Repository.group_id == None)\
 
                            .order_by(func.lower(Repository.repo_name))\
 
                            .all()
 
            repos_data = []
 
            total_records = len(c.repos_list)
 

	
 
            _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
 
            template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 

	
 
            quick_menu = lambda repo_name: (template.get_def("quick_menu")
 
                                            .render(repo_name, _=_, h=h, c=c))
 
            repo_lnk = lambda name, rtype, private, fork_of: (
 
                template.get_def("repo_name")
 
                .render(name, rtype, private, fork_of, short_name=False,
 
                        admin=False, _=_, h=h, c=c))
 
            last_change = lambda last_change:  (template.get_def("last_change")
 
                                           .render(last_change, _=_, h=h, c=c))
 
            rss_lnk = lambda repo_name: (template.get_def("rss")
 
                                           .render(repo_name, _=_, h=h, c=c))
 
            atom_lnk = lambda repo_name: (template.get_def("atom")
 
                                           .render(repo_name, _=_, h=h, c=c))
 
            tip = lambda repo_name, cs_cache: (template.get_def("revision")
 
                                    .render(repo_name,
 
                                            cs_cache.get('revision'),
 
                                            cs_cache.get('raw_id'),
 
                                            cs_cache.get('author'),
 
                                            cs_cache.get('message'), _=_, h=h,
 
                                            c=c))
 

	
 
            def desc(desc):
 
                if c.visual.stylify_metatags:
 
                    return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
 
                else:
 
                    return h.urlify_text(h.truncate(desc, 60))
 

	
 
            for repo in c.repos_list:
 
                repos_data.append({
 
                    "menu": quick_menu(repo.repo_name),
 
                    "raw_name": repo.repo_name.lower(),
 
                    "name": repo_lnk(repo.repo_name, repo.repo_type,
 
                                     repo.private, repo.fork),
 
                    "last_change": last_change(repo.last_db_change),
 
                    "tip": tip(repo.repo_name, repo.changeset_cache),
 
                    "desc": desc(repo.description),
 
                    "owner": h.person(repo.user.username),
 
                    "rss": rss_lnk(repo.repo_name),
 
                    "atom": atom_lnk(repo.repo_name),
 
                })
 

	
 
            c.data = json.dumps({
 
                "totalRecords": total_records,
 
                "startIndex": 0,
 
                "sort": "name",
 
                "dir": "asc",
 
                "records": repos_data
 
            })
 

	
 
        return render('/index.html')
 

	
 
    def repo_switcher(self):
 
        if request.is_xhr:
 
            all_repos = Repository.query().order_by(Repository.repo_name).all()
 
            c.repos_list = self.scm_model.get_repos(all_repos,
 
                                                    sort_key='name_sort',
 
                                                    simple=True)
 
            return render('/repo_switcher_list.html')
 
        else:
 
            raise HTTPBadRequest()
 

	
 
    def branch_tag_switcher(self, repo_name):
 
        if request.is_xhr:
 
            c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
 
            c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
 
            return render('/switch_to_list.html')
 
        else:
 
            raise HTTPBadRequest()
rhodecode/lib/base.py
Show inline comments
 
@@ -226,107 +226,107 @@ class BaseVCSController(object):
 
            log.debug('Repository %s do not have locking enabled' % (repo))
 
        log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s'
 
                  % (make_lock, locked, locked_by))
 
        return make_lock, locked, locked_by
 

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

	
 

	
 
class BaseController(WSGIController):
 

	
 
    def __before__(self):
 
        """
 
        __before__ is called before controller methods and after __call__
 
        """
 
        c.rhodecode_version = __version__
 
        c.rhodecode_instanceid = config.get('instance_id')
 
        c.rhodecode_name = config.get('rhodecode_title')
 
        c.use_gravatar = str2bool(config.get('use_gravatar'))
 
        c.ga_code = config.get('rhodecode_ga_code')
 
        # Visual options
 
        c.visual = AttributeDict({})
 
        rc_config = RhodeCodeSetting.get_app_settings()
 

	
 
        c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
 
        c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
 
        c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
 
        c.visual.lightweight_dashboard = str2bool(rc_config.get('rhodecode_lightweight_dashboard'))
 
        c.visual.lightweight_dashboard_items = safe_int(config.get('dashboard_items', 100))
 

	
 
        c.repo_name = get_repo_slug(request)
 
        c.backends = BACKENDS.keys()
 
        c.unread_notifications = NotificationModel()\
 
                        .get_unread_cnt_for_user(c.rhodecode_user.user_id)
 
        self.cut_off_limit = int(config.get('cut_off_limit'))
 

	
 
        self.sa = meta.Session
 
        self.scm_model = ScmModel(self.sa)
 

	
 
    def __call__(self, environ, start_response):
 
        """Invoke the Controller"""
 
        # WSGIController.__call__ dispatches to the Controller method
 
        # the request is routed to. This routing information is
 
        # available in environ['pylons.routes_dict']
 
        start = time.time()
 
        try:
 
            self.ip_addr = _get_ip_addr(environ)
 
            # make sure that we update permissions each time we call controller
 
            api_key = request.GET.get('api_key')
 
            cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
 
            user_id = cookie_store.get('user_id', None)
 
            username = get_container_username(environ, config)
 
            auth_user = AuthUser(user_id, api_key, username, self.ip_addr)
 
            request.user = auth_user
 
            self.rhodecode_user = c.rhodecode_user = auth_user
 
            if not self.rhodecode_user.is_authenticated and \
 
                       self.rhodecode_user.user_id is not None:
 
                self.rhodecode_user.set_authenticated(
 
                    cookie_store.get('is_authenticated')
 
                )
 
            log.info('IP: %s User: %s accessed %s' % (
 
               self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
 
            )
 
            return WSGIController.__call__(self, environ, start_response)
 
        finally:
 
            log.info('IP: %s Request to %s time: %.3fs' % (
 
                _get_ip_addr(environ),
 
                safe_unicode(_get_access_path(environ)), time.time() - start)
 
            )
 
            meta.Session.remove()
 

	
 

	
 
class BaseRepoController(BaseController):
 
    """
 
    Base class for controllers responsible for loading all needed data for
 
    repository loaded items are
 

	
 
    c.rhodecode_repo: instance of scm repository
 
    c.rhodecode_db_repo: instance of db
 
    c.repository_followers: number of followers
 
    c.repository_forks: number of forks
 
    """
 

	
 
    def __before__(self):
 
        super(BaseRepoController, self).__before__()
 
        if c.repo_name:
 

	
 
            dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
 
            c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
 
            # update last change according to VCS data
 
            dbr.update_last_change(c.rhodecode_repo.last_change)
 
            dbr.update_changeset_cache(dbr.get_changeset())
 
            if c.rhodecode_repo is None:
 
                log.error('%s this repository is present in database but it '
 
                          'cannot be created as an scm instance', c.repo_name)
 

	
 
                redirect(url('home'))
 

	
 
            # some globals counter for menu
 
            c.repository_followers = self.scm_model.get_followers(dbr)
 
            c.repository_forks = self.scm_model.get_forks(dbr)
 
            c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
rhodecode/lib/dbmigrate/versions/010_version_1_5_2.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper, joinedload
 
from sqlalchemy.orm.session import Session
 
from sqlalchemy.ext.declarative import declarative_base
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 
from rhodecode.model import meta
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """
 
    Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 
    #==========================================================================
 
    # USER LOGS
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_5_0 import UserIpMap
 
    tbl = UserIpMap.__table__
 
    tbl.create()
 

	
 
    #==========================================================================
 
    # REPOSITORIES
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_5_0 import Repository
 
    tbl = Repository.__table__
 
    changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True)
 
    # create username column
 
    changeset_cache.create(table=tbl)
 

	
 
    #fix cache data
 
    _Session = Session()
 
    ## after adding that column fix all usernames
 
    repositories = _Session.query(Repository).all()
 
    for entry in repositories:
 
        entry.update_changeset_cache()
 
    _Session.commit()
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
rhodecode/lib/update_repoinfo.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    package.rhodecode.lib.cleanup
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    :created_on: Jul 14, 2012
 
    :author: marcink
 
    :copyright: (C) 2010-2012 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/>.
 
from __future__ import with_statement
 

	
 
import os
 
import sys
 
import re
 
import shutil
 
import logging
 
import datetime
 
import string
 

	
 
from os.path import dirname as dn, join as jn
 
from rhodecode.model import init_model
 
from rhodecode.lib.utils2 import engine_from_config, safe_str
 
from rhodecode.model.db import RhodeCodeUi, Repository
 
from rhodecode.lib.vcs.backends.base import EmptyChangeset
 

	
 

	
 
#to get the rhodecode import
 
sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
 

	
 
from rhodecode.lib.utils import BasePasterCommand, Command, add_cache
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UpdateCommand(BasePasterCommand):
 

	
 
    max_args = 1
 
    min_args = 1
 

	
 
    usage = "CONFIG_FILE"
 
    summary = "Cleanup deleted repos"
 
    group_name = "RhodeCode"
 
    takes_config_file = -1
 
    parser = Command.standard_parser(verbose=True)
 

	
 
    def command(self):
 
        logging.config.fileConfig(self.path_to_ini_file)
 
        from pylons import config
 

	
 
        #get to remove repos !!
 
        add_cache(config)
 
        engine = engine_from_config(config, 'sqlalchemy.db1.')
 
        init_model(engine)
 

	
 
        repo_update_list = map(string.strip,
 
                               self.options.repo_update_list.split(',')) \
 
                               if self.options.repo_update_list else None
 

	
 
        if repo_update_list:
 
            repo_list = Repository.query().filter(Repository.repo_name.in_(repo_update_list))
 
        else:
 
            repo_list = Repository.getAll()
 
        for repo in repo_list:
 
            last_change = (repo.scm_instance.last_change if repo.scm_instance
 
                           else datetime.datetime.utcfromtimestamp(0))
 
            repo.update_last_change(last_change)
 
            last_cs = (repo.scm_instance.get_changeset() if repo.scm_instance
 
                           else EmptyChangeset())
 
            repo.update_changeset_cache(last_cs)
 

	
 
    def update_parser(self):
 
        self.parser.add_option('--update-only',
 
                          action='store',
 
                          dest='repo_update_list',
 
                          help="Specifies a comma separated list of repositores "
 
                                "to update last commit info for. OPTIONAL",
 
                          )
rhodecode/lib/utils.py
Show inline comments
 
@@ -362,192 +362,193 @@ def map_groups(path):
 
    """
 
    Given a full path to a repository, create all nested groups that this
 
    repo is inside. This function creates parent-child relationships between
 
    groups and creates default perms for all new groups.
 

	
 
    :param paths: full path to repository
 
    """
 
    sa = meta.Session()
 
    groups = path.split(Repository.url_sep())
 
    parent = None
 
    group = None
 

	
 
    # last element is repo in nested groups structure
 
    groups = groups[:-1]
 
    rgm = ReposGroupModel(sa)
 
    for lvl, group_name in enumerate(groups):
 
        group_name = '/'.join(groups[:lvl] + [group_name])
 
        group = RepoGroup.get_by_group_name(group_name)
 
        desc = '%s group' % group_name
 

	
 
        # skip folders that are now removed repos
 
        if REMOVED_REPO_PAT.match(group_name):
 
            break
 

	
 
        if group is None:
 
            log.debug('creating group level: %s group_name: %s' % (lvl,
 
                                                                   group_name))
 
            group = RepoGroup(group_name, parent)
 
            group.group_description = desc
 
            sa.add(group)
 
            rgm._create_default_perms(group)
 
            sa.flush()
 
        parent = group
 
    return group
 

	
 

	
 
def repo2db_mapper(initial_repo_list, remove_obsolete=False,
 
                   install_git_hook=False):
 
    """
 
    maps all repos given in initial_repo_list, non existing repositories
 
    are created, if remove_obsolete is True it also check for db entries
 
    that are not in initial_repo_list and removes them.
 

	
 
    :param initial_repo_list: list of repositories found by scanning methods
 
    :param remove_obsolete: check for obsolete entries in database
 
    :param install_git_hook: if this is True, also check and install githook
 
        for a repo if missing
 
    """
 
    from rhodecode.model.repo import RepoModel
 
    from rhodecode.model.scm import ScmModel
 
    sa = meta.Session()
 
    rm = RepoModel()
 
    user = sa.query(User).filter(User.admin == True).first()
 
    if user is None:
 
        raise Exception('Missing administrative account!')
 
    added = []
 

	
 
#    # clear cache keys
 
#    log.debug("Clearing cache keys now...")
 
#    CacheInvalidation.clear_cache()
 
#    sa.commit()
 

	
 
    ##creation defaults
 
    defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
 
    enable_statistics = defs.get('repo_enable_statistics')
 
    enable_locking = defs.get('repo_enable_locking')
 
    enable_downloads = defs.get('repo_enable_downloads')
 
    private = defs.get('repo_private')
 

	
 
    for name, repo in initial_repo_list.items():
 
        group = map_groups(name)
 
        db_repo = rm.get_by_repo_name(name)
 
        # found repo that is on filesystem not in RhodeCode database
 
        if not db_repo:
 
            log.info('repository %s not found, creating now' % name)
 
            added.append(name)
 
            desc = (repo.description
 
                    if repo.description != 'unknown'
 
                    else '%s repository' % name)
 

	
 
            new_repo = rm.create_repo(
 
                repo_name=name,
 
                repo_type=repo.alias,
 
                description=desc,
 
                repos_group=getattr(group, 'group_id', None),
 
                owner=user,
 
                just_db=True,
 
                enable_locking=enable_locking,
 
                enable_downloads=enable_downloads,
 
                enable_statistics=enable_statistics,
 
                private=private
 
            )
 
            # we added that repo just now, and make sure it has githook
 
            # installed
 
            if new_repo.repo_type == 'git':
 
                ScmModel().install_git_hook(new_repo.scm_instance)
 
            new_repo.update_changeset_cache()
 
        elif install_git_hook:
 
            if db_repo.repo_type == 'git':
 
                ScmModel().install_git_hook(db_repo.scm_instance)
 
        # during starting install all cache keys for all repositories in the
 
        # system, this will register all repos and multiple instances
 
        key, _prefix, _org_key = CacheInvalidation._get_key(name)
 
        CacheInvalidation.invalidate(name)
 
        log.debug("Creating a cache key for %s, instance_id %s"
 
                  % (name, _prefix or 'unknown'))
 

	
 
    sa.commit()
 
    removed = []
 
    if remove_obsolete:
 
        # remove from database those repositories that are not in the filesystem
 
        for repo in sa.query(Repository).all():
 
            if repo.repo_name not in initial_repo_list.keys():
 
                log.debug("Removing non-existing repository found in db `%s`" %
 
                          repo.repo_name)
 
                try:
 
                    sa.delete(repo)
 
                    sa.commit()
 
                    removed.append(repo.repo_name)
 
                except:
 
                    #don't hold further removals on error
 
                    log.error(traceback.format_exc())
 
                    sa.rollback()
 

	
 
    return added, removed
 

	
 

	
 
# set cache regions for beaker so celery can utilise it
 
def add_cache(settings):
 
    cache_settings = {'regions': None}
 
    for key in settings.keys():
 
        for prefix in ['beaker.cache.', 'cache.']:
 
            if key.startswith(prefix):
 
                name = key.split(prefix)[1].strip()
 
                cache_settings[name] = settings[key].strip()
 
    if cache_settings['regions']:
 
        for region in cache_settings['regions'].split(','):
 
            region = region.strip()
 
            region_settings = {}
 
            for key, value in cache_settings.items():
 
                if key.startswith(region):
 
                    region_settings[key.split('.')[1]] = value
 
            region_settings['expire'] = int(region_settings.get('expire',
 
                                                                60))
 
            region_settings.setdefault('lock_dir',
 
                                       cache_settings.get('lock_dir'))
 
            region_settings.setdefault('data_dir',
 
                                       cache_settings.get('data_dir'))
 

	
 
            if 'type' not in region_settings:
 
                region_settings['type'] = cache_settings.get('type',
 
                                                             'memory')
 
            beaker.cache.cache_regions[region] = region_settings
 

	
 

	
 
def load_rcextensions(root_path):
 
    import rhodecode
 
    from rhodecode.config import conf
 

	
 
    path = os.path.join(root_path, 'rcextensions', '__init__.py')
 
    if os.path.isfile(path):
 
        rcext = create_module('rc', path)
 
        EXT = rhodecode.EXTENSIONS = rcext
 
        log.debug('Found rcextensions now loading %s...' % rcext)
 

	
 
        # Additional mappings that are not present in the pygments lexers
 
        conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
 

	
 
        #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
 

	
 
        if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
 
            log.debug('settings custom INDEX_EXTENSIONS')
 
            conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
 

	
 
        #ADDITIONAL MAPPINGS
 
        log.debug('adding extra into INDEX_EXTENSIONS')
 
        conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
 

	
 

	
 
#==============================================================================
 
# TEST FUNCTIONS AND CREATORS
 
#==============================================================================
 
def create_test_index(repo_location, config, full_index):
 
    """
 
    Makes default test index
 

	
 
    :param config: test config
 
    :param full_index:
 
    """
 

	
 
    from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
 
    from rhodecode.lib.pidlock import DaemonLock, LockHeld
 

	
rhodecode/lib/vcs/backends/base.py
Show inline comments
 
@@ -283,192 +283,193 @@ class BaseRepository(object):
 
        raise NotImplementedError
 

	
 
    def get_user_name(self, config_file=None):
 
        """
 
        Returns user's name from global configuration file.
 

	
 
        :param config_file: A path to file which should be used to retrieve
 
          configuration from (might also be a list of file paths)
 
        """
 
        raise NotImplementedError
 

	
 
    def get_user_email(self, config_file=None):
 
        """
 
        Returns user's email from global configuration file.
 

	
 
        :param config_file: A path to file which should be used to retrieve
 
          configuration from (might also be a list of file paths)
 
        """
 
        raise NotImplementedError
 

	
 
    # =========== #
 
    # WORKDIR API #
 
    # =========== #
 

	
 
    @LazyProperty
 
    def workdir(self):
 
        """
 
        Returns ``Workdir`` instance for this repository.
 
        """
 
        raise NotImplementedError
 

	
 

	
 
class BaseChangeset(object):
 
    """
 
    Each backend should implement it's changeset representation.
 

	
 
    **Attributes**
 

	
 
        ``repository``
 
            repository object within which changeset exists
 

	
 
        ``id``
 
            may be ``raw_id`` or i.e. for mercurial's tip just ``tip``
 

	
 
        ``raw_id``
 
            raw changeset representation (i.e. full 40 length sha for git
 
            backend)
 

	
 
        ``short_id``
 
            shortened (if apply) version of ``raw_id``; it would be simple
 
            shortcut for ``raw_id[:12]`` for git/mercurial backends or same
 
            as ``raw_id`` for subversion
 

	
 
        ``revision``
 
            revision number as integer
 

	
 
        ``files``
 
            list of ``FileNode`` (``Node`` with NodeKind.FILE) objects
 

	
 
        ``dirs``
 
            list of ``DirNode`` (``Node`` with NodeKind.DIR) objects
 

	
 
        ``nodes``
 
            combined list of ``Node`` objects
 

	
 
        ``author``
 
            author of the changeset, as unicode
 

	
 
        ``message``
 
            message of the changeset, as unicode
 

	
 
        ``parents``
 
            list of parent changesets
 

	
 
        ``last``
 
            ``True`` if this is last changeset in repository, ``False``
 
            otherwise; trying to access this attribute while there is no
 
            changesets would raise ``EmptyRepositoryError``
 
    """
 
    def __str__(self):
 
        return '<%s at %s:%s>' % (self.__class__.__name__, self.revision,
 
            self.short_id)
 

	
 
    def __repr__(self):
 
        return self.__str__()
 

	
 
    def __unicode__(self):
 
        return u'%s:%s' % (self.revision, self.short_id)
 

	
 
    def __eq__(self, other):
 
        return self.raw_id == other.raw_id
 

	
 
    def __json__(self):
 
        return dict(
 
            short_id=self.short_id,
 
            raw_id=self.raw_id,
 
            revision=self.revision,
 
            message=self.message,
 
            date=self.date,
 
            author=self.author,
 
        )
 

	
 
    @LazyProperty
 
    def last(self):
 
        if self.repository is None:
 
            raise ChangesetError("Cannot check if it's most recent revision")
 
        return self.raw_id == self.repository.revisions[-1]
 

	
 
    @LazyProperty
 
    def parents(self):
 
        """
 
        Returns list of parents changesets.
 
        """
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def children(self):
 
        """
 
        Returns list of children changesets.
 
        """
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def id(self):
 
        """
 
        Returns string identifying this changeset.
 
        """
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def raw_id(self):
 
        """
 
        Returns raw string identifying this changeset.
 
        """
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def short_id(self):
 
        """
 
        Returns shortened version of ``raw_id`` attribute, as string,
 
        identifying this changeset, useful for web representation.
 
        """
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def revision(self):
 
        """
 
        Returns integer identifying this changeset.
 

	
 
        """
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def commiter(self):
 
        """
 
        Returns Commiter for given commit
 
        """
 

	
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def commiter_name(self):
 
        """
 
        Returns Author name for given commit
 
        """
 

	
 
        return author_name(self.commiter)
 

	
 
    @LazyProperty
 
    def commiter_email(self):
 
        """
 
        Returns Author email address for given commit
 
        """
 

	
 
        return author_email(self.commiter)
 

	
 
    @LazyProperty
 
    def author(self):
 
        """
 
        Returns Author for given commit
 
        """
 

	
 
        raise NotImplementedError
 

	
 
    @LazyProperty
 
    def author_name(self):
 
        """
 
        Returns Author name for given commit
 
        """
 

	
 
        return author_name(self.author)
 

	
 
    @LazyProperty
rhodecode/model/db.py
Show inline comments
 
@@ -578,238 +578,256 @@ class UserLog(Base, BaseModel):
 
class UsersGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    def get_api_data(self):
 
        users_group = self
 

	
 
        data = dict(
 
            users_group_id=users_group.users_group_id,
 
            group_name=users_group.users_group_name,
 
            active=users_group.users_group_active,
 
        )
 

	
 
        return data
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        Index('r_repo_name_idx', 'repo_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
    _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    #changeset_cache = Column("changeset_cache", LargeBinary(), nullable=False) #JSON data
 
    _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing',
 
                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
 
                             cascade='all')
 

	
 
    logs = relationship('UserLog')
 
    comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_org = relationship('PullRequest',
 
                    primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_other = relationship('PullRequest',
 
                    primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
 
                                   self.repo_name)
 

	
 
    @hybrid_property
 
    def locked(self):
 
        # always should return [user_id, timelocked]
 
        if self._locked:
 
            _lock_info = self._locked.split(':')
 
            return int(_lock_info[0]), _lock_info[1]
 
        return [None, None]
 

	
 
    @locked.setter
 
    def locked(self, val):
 
        if val and isinstance(val, (list, tuple)):
 
            self._locked = ':'.join(map(str, val))
 
        else:
 
            self._locked = None
 

	
 
    @hybrid_property
 
    def changeset_cache(self):
 
        from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
        dummy = EmptyChangeset().__json__()
 
        if not self._changeset_cache:
 
            return dummy
 
        try:
 
            return json.loads(self._changeset_cache)
 
        except TypeError:
 
            return dummy
 

	
 
    @changeset_cache.setter
 
    def changeset_cache(self, val):
 
        try:
 
            self._changeset_cache = json.dumps(val)
 
        except:
 
            log.error(traceback.format_exc())
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_full_path(cls, repo_full_path):
 
        repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
 
        return cls.get_by_repo_name(repo_name.strip(URL_SEP))
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session().query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def forks(self):
 
        """
 
        Return forks of this repo
 
        """
 
        return Repository.get_repo_forks(self.repo_id)
 

	
 
    @property
 
    def parent(self):
 
        """
 
        Returns fork parent
 
        """
 
        return self.fork
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    def groups_with_parents(self):
 
        groups = []
 
        if self.group is None:
 
            return groups
 

	
 
        cur_gr = self.group
 
        groups.insert(0, cur_gr)
 
        while 1:
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            groups.insert(0, gr)
 

	
 
        return groups
 

	
 
    @property
 
    def groups_and_repo(self):
 
        return self.groups_with_parents, self.just_name
 

	
 
    @LazyProperty
 
    def repo_path(self):
 
        """
 
        Returns base full path for that repository means where it actually
 
        exists on a filesystem
 
        """
 
        q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              Repository.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def repo_full_path(self):
 
        p = [self.repo_path]
 
        # we need to split the name by / since this is how we store the
 
        # names in the database, but that eventually needs to be converted
 
        # into a valid system path
 
        p += self.repo_name.split(Repository.url_sep())
 
        return os.path.join(*p)
 

	
 
    @property
 
    def cache_keys(self):
 
        """
 
        Returns associated cache keys for that repo
 
@@ -821,198 +839,216 @@ class Repository(Base, BaseModel):
 

	
 
    def get_new_name(self, repo_name):
 
        """
 
        returns new full repository name based on assigned group and new new
 

	
 
        :param group_name:
 
        """
 
        path_prefix = self.group.full_path_splitted if self.group else []
 
        return Repository.url_sep().join(path_prefix + [repo_name])
 

	
 
    @property
 
    def _ui(self):
 
        """
 
        Creates an db based ui object for this repository
 
        """
 
        from rhodecode.lib.utils import make_ui
 
        return make_ui('db', clear_session=False)
 

	
 
    @classmethod
 
    def inject_ui(cls, repo, extras={}):
 
        from rhodecode.lib.vcs.backends.hg import MercurialRepository
 
        from rhodecode.lib.vcs.backends.git import GitRepository
 
        required = (MercurialRepository, GitRepository)
 
        if not isinstance(repo, required):
 
            raise Exception('repo must be instance of %s' % required)
 

	
 
        # inject ui extra param to log this action via push logger
 
        for k, v in extras.items():
 
            repo._repo.ui.setconfig('rhodecode_extras', k, v)
 

	
 
    @classmethod
 
    def is_valid(cls, repo_name):
 
        """
 
        returns True if given repo name is a valid filesystem repository
 

	
 
        :param cls:
 
        :param repo_name:
 
        """
 
        from rhodecode.lib.utils import is_valid_repo
 

	
 
        return is_valid_repo(repo_name, cls.base_path())
 

	
 
    def get_api_data(self):
 
        """
 
        Common function for generating repo api data
 

	
 
        """
 
        repo = self
 
        data = dict(
 
            repo_id=repo.repo_id,
 
            repo_name=repo.repo_name,
 
            repo_type=repo.repo_type,
 
            clone_uri=repo.clone_uri,
 
            private=repo.private,
 
            created_on=repo.created_on,
 
            description=repo.description,
 
            landing_rev=repo.landing_rev,
 
            owner=repo.user.username,
 
            fork_of=repo.fork.repo_name if repo.fork else None,
 
            enable_statistics=repo.enable_statistics,
 
            enable_locking=repo.enable_locking,
 
            enable_downloads=repo.enable_downloads
 
        )
 

	
 
        return data
 

	
 
    @classmethod
 
    def lock(cls, repo, user_id):
 
        repo.locked = [user_id, time.time()]
 
        Session().add(repo)
 
        Session().commit()
 

	
 
    @classmethod
 
    def unlock(cls, repo):
 
        repo.locked = None
 
        Session().add(repo)
 
        Session().commit()
 

	
 
    @property
 
    def last_db_change(self):
 
        return self.updated_on
 

	
 
    #==========================================================================
 
    # SCM PROPERTIES
 
    #==========================================================================
 

	
 
    def get_changeset(self, rev=None):
 
        return get_changeset_safe(self.scm_instance, rev)
 

	
 
    def get_landing_changeset(self):
 
        """
 
        Returns landing changeset, or if that doesn't exist returns the tip
 
        """
 
        cs = self.get_changeset(self.landing_rev) or self.get_changeset()
 
        return cs
 

	
 
    def update_last_change(self, last_change=None):
 
        if last_change is None:
 
            last_change = datetime.datetime.now()
 
        if self.updated_on is None or self.updated_on != last_change:
 
            log.debug('updated repo %s with new date %s' % (self, last_change))
 
    def update_changeset_cache(self, cs_cache=None):
 
        """
 
        Update cache of last changeset for repository, keys should be::
 

	
 
            short_id
 
            raw_id
 
            revision
 
            message
 
            date
 
            author
 

	
 
        :param cs_cache:
 
        """
 
        from rhodecode.lib.vcs.backends.base import BaseChangeset
 
        if cs_cache is None:
 
            cs_cache = self.get_changeset()
 
        if isinstance(cs_cache, BaseChangeset):
 
            cs_cache = cs_cache.__json__()
 

	
 
        if cs_cache != self.changeset_cache:
 
            last_change = cs_cache.get('date') or self.last_change
 
            log.debug('updated repo %s with new cs cache %s' % (self, cs_cache))
 
            self.updated_on = last_change
 
            self.changeset_cache = cs_cache
 
            Session().add(self)
 
            Session().commit()
 

	
 
    @property
 
    def tip(self):
 
        return self.get_changeset('tip')
 

	
 
    @property
 
    def author(self):
 
        return self.tip.author
 

	
 
    @property
 
    def last_change(self):
 
        return self.scm_instance.last_change
 

	
 
    def get_comments(self, revisions=None):
 
        """
 
        Returns comments for this repository grouped by revisions
 

	
 
        :param revisions: filter query by revisions only
 
        """
 
        cmts = ChangesetComment.query()\
 
            .filter(ChangesetComment.repo == self)
 
        if revisions:
 
            cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
 
        grouped = defaultdict(list)
 
        for cmt in cmts.all():
 
            grouped[cmt.revision].append(cmt)
 
        return grouped
 

	
 
    def statuses(self, revisions=None):
 
        """
 
        Returns statuses for this repository
 

	
 
        :param revisions: list of revisions to get statuses for
 
        :type revisions: list
 
        """
 

	
 
        statuses = ChangesetStatus.query()\
 
            .filter(ChangesetStatus.repo == self)\
 
            .filter(ChangesetStatus.version == 0)
 
        if revisions:
 
            statuses = statuses.filter(ChangesetStatus.revision.in_(revisions))
 
        grouped = {}
 

	
 
        #maybe we have open new pullrequest without a status ?
 
        stat = ChangesetStatus.STATUS_UNDER_REVIEW
 
        status_lbl = ChangesetStatus.get_status_lbl(stat)
 
        for pr in PullRequest.query().filter(PullRequest.org_repo == self).all():
 
            for rev in pr.revisions:
 
                pr_id = pr.pull_request_id
 
                pr_repo = pr.other_repo.repo_name
 
                grouped[rev] = [stat, status_lbl, pr_id, pr_repo]
 

	
 
        for stat in statuses.all():
 
            pr_id = pr_repo = None
 
            if stat.pull_request:
 
                pr_id = stat.pull_request.pull_request_id
 
                pr_repo = stat.pull_request.other_repo.repo_name
 
            grouped[stat.revision] = [str(stat.status), stat.status_lbl,
 
                                      pr_id, pr_repo]
 
        return grouped
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(repo_name=self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        import rhodecode
 
        full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, cache_map=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 

	
 
        if cache_map:
 
            # get using prefilled cache_map
 
            invalidate_repo = cache_map[self.repo_name]
 
            if invalidate_repo:
rhodecode/templates/index_base.html
Show inline comments
 
@@ -140,192 +140,195 @@
 

	
 
      var myDataSource = new YAHOO.util.DataSource(YUD.get("groups_list"));
 

	
 
      myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
 
      myDataSource.responseSchema = {
 
          fields: [
 
              {key:"name"},
 
              {key:"desc"},
 
          ]
 
      };
 

	
 
      var myDataTable = new YAHOO.widget.DataTable("groups_list_wrap", myColumnDefs, myDataSource,{
 
          sortedBy:{key:"name",dir:"asc"},
 
          paginator: new YAHOO.widget.Paginator({
 
              rowsPerPage: 5,
 
              alwaysVisible: false,
 
              template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
 
              pageLinks: 5,
 
              containerClass: 'pagination-wh',
 
              currentPageClass: 'pager_curpage',
 
              pageLinkClass: 'pager_link',
 
              nextPageLinkLabel: '&gt;',
 
              previousPageLinkLabel: '&lt;',
 
              firstPageLinkLabel: '&lt;&lt;',
 
              lastPageLinkLabel: '&gt;&gt;',
 
              containers:['user-paginator']
 
          }),
 
          MSG_SORTASC:"${_('Click to sort ascending')}",
 
          MSG_SORTDESC:"${_('Click to sort descending')}"
 
      });
 

	
 
      // main table sorting
 
      var myColumnDefs = [
 
          {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
 
          {key:"name",label:"${_('Name')}",sortable:true,
 
              sortOptions: { sortFunction: nameSort }},
 
          {key:"desc",label:"${_('Description')}",sortable:true},
 
          {key:"last_change",label:"${_('Last Change')}",sortable:true,
 
              sortOptions: { sortFunction: ageSort }},
 
          {key:"tip",label:"${_('Tip')}",sortable:true,
 
        	  sortOptions: { sortFunction: revisionSort }},
 
          {key:"owner",label:"${_('Owner')}",sortable:true},
 
          {key:"rss",label:"",sortable:false},
 
          {key:"atom",label:"",sortable:false},
 
      ];
 

	
 
      var myDataSource = new YAHOO.util.DataSource(YUD.get("repos_list"));
 

	
 
      myDataSource.responseType = YAHOO.util.DataSource.TYPE_HTMLTABLE;
 

	
 
      myDataSource.responseSchema = {
 
          fields: [
 
              {key:"menu"},
 
              //{key:"raw_name"},
 
              {key:"name"},
 
              {key:"desc"},
 
              {key:"last_change"},
 
              {key:"tip"},
 
              {key:"owner"},
 
              {key:"rss"},
 
              {key:"atom"},
 
          ]
 
      };
 

	
 
      var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,
 
              {
 
    	       sortedBy:{key:"name",dir:"asc"},
 
               MSG_SORTASC:"${_('Click to sort ascending')}",
 
               MSG_SORTDESC:"${_('Click to sort descending')}",
 
               MSG_EMPTY:"${_('No records found.')}",
 
               MSG_ERROR:"${_('Data error.')}",
 
               MSG_LOADING:"${_('Loading...')}",
 
              }
 
      );
 
      myDataTable.subscribe('postRenderEvent',function(oArgs) {
 
          tooltip_activate();
 
          quick_repo_menu();
 
          q_filter('q_filter',YUQ('div.table tr td a.repo_name'),func);
 
      });
 

	
 
    </script>
 
    % else:
 
      <script>
 
        //var url = "${h.url('formatted_users', format='json')}";
 
        var data = ${c.data|n};
 
        var myDataSource = new YAHOO.util.DataSource(data);
 
        myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
 

	
 
        myDataSource.responseSchema = {
 
            resultsList: "records",
 
            fields: [
 
               {key:"menu"},
 
               {key:"raw_name"},
 
               {key:"name"},
 
               {key:"desc"},
 
               {key:"last_change"},
 
               {key: "tip"},
 
               {key:"owner"},
 
               {key:"rss"},
 
               {key:"atom"},
 
            ]
 
         };
 
        myDataSource.doBeforeCallback = function(req,raw,res,cb) {
 
            // This is the filter function
 
            var data     = res.results || [],
 
                filtered = [],
 
                i,l;
 

	
 
            if (req) {
 
                req = req.toLowerCase();
 
                for (i = 0; i<data.length; i++) {
 
                    var pos = data[i].raw_name.toLowerCase().indexOf(req)
 
                    if (pos != -1) {
 
                        filtered.push(data[i]);
 
                    }
 
                }
 
                res.results = filtered;
 
            }
 
            YUD.get('repo_count').innerHTML = res.results.length;
 
            return res;
 
        }
 

	
 
        // main table sorting
 
        var myColumnDefs = [
 
            {key:"menu",label:"",sortable:false,className:"quick_repo_menu hidden"},
 
            {key:"name",label:"${_('Name')}",sortable:true,
 
                sortOptions: { sortFunction: nameSort }},
 
            {key:"desc",label:"${_('Description')}",sortable:true},
 
            {key:"last_change",label:"${_('Last Change')}",sortable:true,
 
                sortOptions: { sortFunction: ageSort }},
 
            {key:"tip",label:"${_('Tip')}",sortable:true,
 
                sortOptions: { sortFunction: revisionSort }},                
 
            {key:"owner",label:"${_('Owner')}",sortable:true},
 
            {key:"rss",label:"",sortable:false},
 
            {key:"atom",label:"",sortable:false},
 
        ];
 

	
 
        var myDataTable = new YAHOO.widget.DataTable("repos_list_wrap", myColumnDefs, myDataSource,{
 
          sortedBy:{key:"name",dir:"asc"},
 
          paginator: new YAHOO.widget.Paginator({
 
              rowsPerPage: ${c.visual.lightweight_dashboard_items},
 
              alwaysVisible: false,
 
              template : "{PreviousPageLink} {FirstPageLink} {PageLinks} {LastPageLink} {NextPageLink}",
 
              pageLinks: 5,
 
              containerClass: 'pagination-wh',
 
              currentPageClass: 'pager_curpage',
 
              pageLinkClass: 'pager_link',
 
              nextPageLinkLabel: '&gt;',
 
              previousPageLinkLabel: '&lt;',
 
              firstPageLinkLabel: '&lt;&lt;',
 
              lastPageLinkLabel: '&gt;&gt;',
 
              containers:['user-paginator']
 
          }),
 

	
 
          MSG_SORTASC:"${_('Click to sort ascending')}",
 
          MSG_SORTDESC:"${_('Click to sort descending')}",
 
          MSG_EMPTY:"${_('No records found.')}",
 
          MSG_ERROR:"${_('Data error.')}",
 
          MSG_LOADING:"${_('Loading...')}",
 
        }
 
        );
 
        myDataTable.subscribe('postRenderEvent',function(oArgs) {
 
            tooltip_activate();
 
            quick_repo_menu();
 
        });
 

	
 
        var filterTimeout = null;
 

	
 
        updateFilter  = function () {
 
            // Reset timeout
 
            filterTimeout = null;
 

	
 
            // Reset sort
 
            var state = myDataTable.getState();
 
                state.sortedBy = {key:'name', dir:YAHOO.widget.DataTable.CLASS_ASC};
 

	
 
            // Get filtered data
 
            myDataSource.sendRequest(YUD.get('q_filter').value,{
 
                success : myDataTable.onDataReturnInitializeTable,
 
                failure : myDataTable.onDataReturnInitializeTable,
 
                scope   : myDataTable,
 
                argument: state
 
            });
 

	
 
        };
 
        YUE.on('q_filter','click',function(){
 
            YUD.get('q_filter').value = '';
 
         });
 

	
 
        YUE.on('q_filter','keyup',function (e) {
 
            clearTimeout(filterTimeout);
 
            filterTimeout = setTimeout(updateFilter,600);
 
        });
 
      </script>
 
    % endif
setup.cfg
Show inline comments
 
[egg_info]
 
tag_build =
 
tag_svn_revision = true
 

	
 
[easy_install]
 
find_links = http://www.pylonshq.com/download/
 

	
 
[nosetests]
 
verbose=True
 
verbosity=2
 
with-pylons=test.ini
 
detailed-errors=1
 
nologcapture=1
 
#pdb=1
 
#pdb-failures=1
 
pdb=1
 
pdb-failures=1
 

	
 
# Babel configuration
 
[compile_catalog]
 
domain = rhodecode
 
directory = rhodecode/i18n
 
statistics = true
 

	
 
[extract_messages]
 
add_comments = TRANSLATORS:
 
output_file = rhodecode/i18n/rhodecode.pot
 
width = 80
 

	
 
[init_catalog]
 
domain = rhodecode
 
input_file = rhodecode/i18n/rhodecode.pot
 
output_dir = rhodecode/i18n
 

	
 
[update_catalog]
 
domain = rhodecode
 
input_file = rhodecode/i18n/rhodecode.pot
 
output_dir = rhodecode/i18n
 
previous = true
 

	
 
[build_sphinx]
 
source-dir = docs/
 
build-dir  = docs/_build
 
all_files  = 1
 

	
 
[upload_sphinx]
 
upload-dir = docs/_build/html
 
\ No newline at end of file
0 comments (0 inline, 0 general)