Changeset - 81e8dfa3beb5
[Not reviewed]
Merge beta
0 4 0
Marcin Kuzminski - 15 years ago 2010-12-09 19:32:16
marcin@python-works.com
merge
4 files changed with 38 insertions and 24 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/admin/repos.py
Show inline comments
 
#!/usr/bin/env python
 
# encoding: utf-8
 
# repos controller for pylons
 
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
 
#
 
# 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.
 
"""
 
Created on April 7, 2010
 
admin controller for pylons
 
@author: marcink
 
"""
 
from formencode import htmlfill
 
from operator import itemgetter
 
from paste.httpexceptions import HTTPInternalServerError
 
from pylons import request, response, session, tmpl_context as c, url
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
 
    HasPermissionAnyDecorator
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger
 
from rhodecode.model.db import User
 
from rhodecode.model.forms import RepoForm
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.repo import RepoModel
 
import formencode
 
import logging
 
import traceback
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ReposController(BaseController):
 
    """REST Controller styled on the Atom Publishing Protocol"""
 
    # To properly map this controller, ensure your config/routing.py
 
    # file has a resource setup:
 
    #     map.resource('repo', 'repos')
 

	
 
    @LoginRequired()
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(ReposController, self).__before__()
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def index(self, format='html'):
 
        """GET /repos: All items in the collection"""
 
        # url('repos')
 
        cached_repo_list = ScmModel().get_repos()
 
        c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
 
        return render('admin/repos/repos.html')
 

	
 
    @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
 
    def create(self):
 
        """POST /repos: Create a new item"""
 
        # url('repos')
 
        repo_model = RepoModel()
 
        _form = RepoForm()()
 
        form_result = {}
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.create(form_result, c.rhodecode_user)
 
            h.flash(_('created repository %s') % form_result['repo_name'],
 
                    category='success')
 

	
 
            if request.POST.get('user_created'):
 
                action_logger(self.rhodecode_user, 'user_created_repo',
 
                              form_result['repo_name'], '', self.sa)
 
            else:
 
                action_logger(self.rhodecode_user, 'admin_created_repo',
 
                              form_result['repo_name'], '', self.sa)
 

	
 
        except formencode.Invalid, errors:
 
            c.new_repo = errors.value['repo_name']
 

	
 
            if request.POST.get('user_created'):
 
                r = render('admin/repos/repo_add_create_repository.html')
 
            else:
 
                r = render('admin/repos/repo_add.html')
 

	
 
            return htmlfill.render(
 
                r,
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            msg = _('error occured during creation of repository %s') \
 
                    % form_result.get('repo_name')
 
            h.flash(msg, category='error')
 
        if request.POST.get('user_created'):
 
            return redirect(url('home'))
 
        return redirect(url('repos'))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def new(self, format='html'):
 
        """GET /repos/new: Form to create a new item"""
 
        new_repo = request.GET.get('repo', '')
 
        c.new_repo = h.repo_name_slug(new_repo)
 

	
 
        return render('admin/repos/repo_add.html')
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def update(self, repo_name):
 
        """PUT /repos/repo_name: Update an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="PUT" />
 
        # Or using helpers:
 
        #    h.form(url('repo', repo_name=ID),
 
        #           method='put')
 
        # url('repo', repo_name=ID)
 
        repo_model = RepoModel()
 
        changed_name = repo_name
 
        _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
 

	
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo_model.update(repo_name, form_result)
 
            invalidate_cache('get_repo_cached_%s' % repo_name)
 
            h.flash(_('Repository %s updated successfully' % repo_name),
 
                    category='success')
 
            changed_name = form_result['repo_name']
 
            action_logger(self.rhodecode_user, 'admin_updated_repo',
 
                              changed_name, '', self.sa)
 

	
 
        except formencode.Invalid, errors:
 
            c.repo_info = repo_model.get_by_repo_name(repo_name)
 
            if c.repo_info.stats:
 
                last_rev = c.repo_info.stats.stat_on_revision
 
            else:
 
                last_rev = 0
 
            c.stats_revision = last_rev
 
            r = ScmModel().get(repo_name)
 
            c.repo_last_rev = r.revisions[-1] if r.revisions else 0
 

	
 
            if last_rev == 0:
 
                c.stats_percentage = 0
 
            else:
 
                c.stats_percentage = '%.2f' % ((float((last_rev)) /
 
                                                c.repo_last_rev) * 100)
 

	
 
            c.users_array = repo_model.get_users_js()
 
            errors.value.update({'user':c.repo_info.user.username})
 
            return htmlfill.render(
 
                render('admin/repos/repo_edit.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('error occurred during update of repository %s') \
 
                    % repo_name, category='error')
 

	
 
        return redirect(url('edit_repo', repo_name=changed_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete(self, repo_name):
 
        """DELETE /repos/repo_name: Delete an existing item"""
 
        # Forms posted to this method should contain a hidden field:
 
        #    <input type="hidden" name="_method" value="DELETE" />
 
        # Or using helpers:
 
        #    h.form(url('repo', repo_name=ID),
 
        #           method='delete')
 
        # url('repo', repo_name=ID)
 

	
 
        repo_model = RepoModel()
 
        repo = repo_model.get_by_repo_name(repo_name)
 
        if not repo:
 
            h.flash(_('%s repository is not mapped to db perhaps'
 
                      ' it was moved or renamed  from the filesystem'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('repos'))
 
        try:
 
            action_logger(self.rhodecode_user, 'admin_deleted_repo',
 
                              repo_name, '', self.sa)
 
            repo_model.delete(repo)
 
            invalidate_cache('get_repo_cached_%s' % repo_name)
 
            h.flash(_('deleted repository %s') % repo_name, category='success')
 

	
 
        except Exception, e:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occured during deletion of %s') % repo_name,
 
                    category='error')
 

	
 
        return redirect(url('repos'))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete_perm_user(self, repo_name):
 
        """
 
        DELETE an existing repository permission user
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            repo_model = RepoModel()
 
            repo_model.delete_perm_user(request.POST, repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occured during deletion of repository user'),
 
                    category='error')
 
            raise HTTPInternalServerError()
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_stats(self, repo_name):
 
        """
 
        DELETE an existing repository statistics
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            repo_model = RepoModel()
 
            repo_model.delete_stats(repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occured during deletion of repository stats'),
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def repo_cache(self, repo_name):
 
        """
 
        INVALIDATE exisitings repository cache
 
        :param repo_name:
 
        """
 

	
 
        try:
 
            ScmModel().mark_for_invalidation(repo_name)
 
        except Exception, e:
 
            h.flash(_('An error occurred during cache invalidation'),
 
                    category='error')
 
        return redirect(url('edit_repo', repo_name=repo_name))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def show(self, repo_name, format='html'):
 
        """GET /repos/repo_name: Show a specific item"""
 
        # url('repo', repo_name=ID)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def edit(self, repo_name, format='html'):
 
        """GET /repos/repo_name/edit: Form to edit an existing item"""
 
        # url('edit_repo', repo_name=ID)
 
        repo_model = RepoModel()
 
        c.repo_info = repo = repo_model.get_by_repo_name(repo_name)
 
        if repo.stats:
 
            last_rev = repo.stats.stat_on_revision
 
        c.repo_info = repo_model.get_by_repo_name(repo_name)
 
        if c.repo_info.stats:
 
            last_rev = c.repo_info.stats.stat_on_revision
 
        else:
 
            last_rev = 0
 
        c.stats_revision = last_rev
 
        r = ScmModel().get(repo_name)
 
        c.repo_last_rev = r.revisions[-1] if r.revisions else 0
 

	
 
        if last_rev == 0:
 
            c.stats_percentage = 0
 
        else:
 
            c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100)
 
            c.stats_percentage = '%.2f' % ((float((last_rev)) /
 
                                            c.repo_last_rev) * 100)
 

	
 

	
 
        if not repo:
 
        if not c.repo_info:
 
            h.flash(_('%s repository is not mapped to db perhaps'
 
                      ' it was created or renamed from the filesystem'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('repos'))
 
        defaults = c.repo_info.__dict__
 
        if c.repo_info.user:
 
            defaults.update({'user':c.repo_info.user.username})
 
        else:
 
            replacement_user = self.sa.query(User)\
 
            .filter(User.admin == True).first().username
 
            defaults.update({'user':replacement_user})
 

	
 
        c.users_array = repo_model.get_users_js()
 

	
 
        for p in c.repo_info.repo_to_perm:
 
            defaults.update({'perm_%s' % p.user.username:
 
                             p.permission.permission_name})
 

	
 
        return htmlfill.render(
 
            render('admin/repos/repo_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
rhodecode/controllers/summary.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    package.rhodecode.controllers.summary
 
    ~~~~~~~~~~~~~~
 

	
 
    Summary controller for Rhodecode
 
    
 
    :created_on: Apr 18, 2010
 
    :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 calendar
 
import logging
 
from time import mktime
 
from datetime import datetime, timedelta
 

	
 
from vcs.exceptions import ChangesetError
 

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

	
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.db import Statistics
 

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

	
 
from rhodecode.lib.celerylib import run_task
 
from rhodecode.lib.celerylib.tasks import get_commits_stats
 

	
 
from webhelpers.paginate import Page
 

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

	
 
class SummaryController(BaseController):
 

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

	
 
    def index(self):
 
        scm_model = ScmModel()
 
        c.repo_info = scm_model.get_repo(c.repo_name)
 
        c.following = scm_model.is_following_repo(c.repo_name,
 
                                             c.rhodecode_user.user_id)
 
        def url_generator(**kw):
 
            return url('shortlog_home', repo_name=c.repo_name, **kw)
 

	
 
        c.repo_changesets = Page(c.repo_info, page=1, items_per_page=10,
 
                                 url=url_generator)
 

	
 
        e = request.environ
 

	
 
        if self.rhodecode_user.username == 'default':
 
            password = ':default'
 
        else:
 
            password = ''
 

	
 
        uri = u'%(protocol)s://%(user)s%(password)s@%(host)s%(prefix)s/%(repo_name)s' % {
 
                                        'protocol': e.get('wsgi.url_scheme'),
 
                                        'user':str(c.rhodecode_user.username),
 
                                        'password':password,
 
                                        'host':e.get('HTTP_HOST'),
 
                                        'prefix':e.get('SCRIPT_NAME'),
 
                                        'repo_name':c.repo_name, }
 
        c.clone_repo_url = uri
 
        c.repo_tags = OrderedDict()
 
        for name, hash in c.repo_info.tags.items()[:10]:
 
            try:
 
                c.repo_tags[name] = c.repo_info.get_changeset(hash)
 
            except ChangesetError:
 
                c.repo_tags[name] = EmptyChangeset(hash)
 

	
 
        c.repo_branches = OrderedDict()
 
        for name, hash in c.repo_info.branches.items()[:10]:
 
            try:
 
                c.repo_branches[name] = c.repo_info.get_changeset(hash)
 
            except ChangesetError:
 
                c.repo_branches[name] = EmptyChangeset(hash)
 

	
 
        td = datetime.today() + timedelta(days=1)
 
        y, m, d = td.year, td.month, td.day
 

	
 
        ts_min_y = mktime((y - 1, (td - timedelta(days=calendar.mdays[m])).month,
 
                            d, 0, 0, 0, 0, 0, 0,))
 
        ts_min_m = mktime((y, (td - timedelta(days=calendar.mdays[m])).month,
 
                            d, 0, 0, 0, 0, 0, 0,))
 

	
 
        ts_max_y = mktime((y, m, d, 0, 0, 0, 0, 0, 0,))
 
        if c.repo_info.dbrepo.enable_statistics:
 
            c.no_data_msg = _('No data loaded yet')
 
            run_task(get_commits_stats, c.repo_info.name, ts_min_y, ts_max_y)
 
        else:
 
            c.no_data_msg = _('Statistics are disabled for this repository')
 
            c.no_data_msg = _('Statistics update 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 == c.repo_info.dbrepo)\
 
            .scalar()
 

	
 

	
 
        if stats and stats.languages:
 
            c.no_data = False
 
            c.no_data = False is c.repo_info.dbrepo.enable_statistics
 
            lang_stats = json.loads(stats.languages)
 
            c.commit_data = stats.commit_activity
 
            c.overview_data = stats.commit_activity_combined
 
            c.trending_languages = json.dumps(OrderedDict(
 
                                       sorted(lang_stats.items(), reverse=True,
 
                                            key=lambda k: k[1])[:10]
 
                                        )
 
                                    )
 
        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
 

	
 
        return render('summary/summary.html')
 

	
rhodecode/model/repo.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.repo
 
    ~~~~~~~~~~~~~~~~~~~~
 

	
 
    Repository model for rhodecode
 
    
 
    :created_on: Jun 5, 2010
 
    :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 os
 
import shutil
 
import logging
 
import traceback
 
from datetime import datetime
 

	
 
from pylons import app_globals as g
 

	
 
from rhodecode.model import BaseModel
 
from rhodecode.model.caching_query import FromCache
 
from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
 
    Statistics
 
from rhodecode.model.user import UserModel
 

	
 
from vcs.backends import get_backend
 

	
 
log = logging.getLogger(__name__)
 

	
 
class RepoModel(BaseModel):
 

	
 
    def get(self, repo_id, cache=False):
 
        repo = self.sa.query(Repository)\
 
            .filter(Repository.repo_id == repo_id)
 

	
 
        if cache:
 
            repo = repo.options(FromCache("sql_cache_short",
 
                                          "get_repo_%s" % repo_id))
 
        return repo.scalar()
 

	
 

	
 
    def get_by_repo_name(self, repo_name, cache=False):
 
        repo = self.sa.query(Repository)\
 
            .filter(Repository.repo_name == repo_name)
 

	
 
        if cache:
 
            repo = repo.options(FromCache("sql_cache_short",
 
                                          "get_repo_%s" % repo_name))
 
        return repo.scalar()
 

	
 
    def get_users_js(self):
 

	
 
        users = self.sa.query(User).filter(User.active == True).all()
 
        u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
 
        users_array = '[%s];' % '\n'.join([u_tmpl % (u.user_id, u.name,
 
                                                    u.lastname, u.username)
 
                                        for u in users])
 
        return users_array
 

	
 

	
 
    def update(self, repo_name, form_data):
 
        try:
 
            cur_repo = self.get_by_repo_name(repo_name, cache=False)
 
            user_model = UserModel(self.sa)
 

	
 
            #update permissions
 
            for username, perm in form_data['perms_updates']:
 
                r2p = self.sa.query(RepoToPerm)\
 
                        .filter(RepoToPerm.user == UserModel(self.sa)\
 
                                .get_by_username(username, cache=False))\
 
                        .filter(RepoToPerm.repository == \
 
                                self.get_by_repo_name(repo_name))\
 
                        .filter(RepoToPerm.user == user_model.get_by_username(username))\
 
                        .filter(RepoToPerm.repository == cur_repo)\
 
                        .one()
 

	
 
                r2p.permission_id = self.sa.query(Permission).filter(
 
                                                Permission.permission_name ==
 
                                                perm).one().permission_id
 
                r2p.permission = self.sa.query(Permission)\
 
                                    .filter(Permission.permission_name == perm)\
 
                                    .scalar()
 
                self.sa.add(r2p)
 

	
 
            #set new permissions
 
            for username, perm in form_data['perms_new']:
 
                r2p = RepoToPerm()
 
                r2p.repository = self.get_by_repo_name(repo_name)
 
                r2p.user = UserModel(self.sa).get_by_username(username, cache=False)
 
                r2p.repository = cur_repo
 
                r2p.user = user_model.get_by_username(username, cache=False)
 

	
 
                r2p.permission_id = self.sa.query(Permission).filter(
 
                                        Permission.permission_name == perm)\
 
                                        .one().permission_id
 
                r2p.permission = self.sa.query(Permission)\
 
                                    .filter(Permission.permission_name == perm)\
 
                                    .scalar()
 
                self.sa.add(r2p)
 

	
 
            #update current repo
 
            cur_repo = self.get_by_repo_name(repo_name, cache=False)
 

	
 
            for k, v in form_data.items():
 
                if k == 'user':
 
                    cur_repo.user_id = v
 
                    cur_repo.user = user_model.get(v)
 
                else:
 
                    setattr(cur_repo, k, v)
 

	
 
            self.sa.add(cur_repo)
 

	
 
            if repo_name != form_data['repo_name']:
 
                #rename our data
 
                self.__rename_repo(repo_name, form_data['repo_name'])
 

	
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def create(self, form_data, cur_user, just_db=False, fork=False):
 
        try:
 
            if fork:
 
                #force str since hg doesn't go with unicode
 
                repo_name = str(form_data['fork_name'])
 
                org_name = str(form_data['repo_name'])
 

	
 
            else:
 
                org_name = repo_name = str(form_data['repo_name'])
 
            new_repo = Repository()
 
            for k, v in form_data.items():
 
                if k == 'repo_name':
 
                    v = repo_name
 
                setattr(new_repo, k, v)
 

	
 
            if fork:
 
                parent_repo = self.sa.query(Repository)\
 
                        .filter(Repository.repo_name == org_name).scalar()
 
                new_repo.fork = parent_repo
 

	
 
            new_repo.user_id = cur_user.user_id
 
            self.sa.add(new_repo)
 

	
 
            #create default permission
 
            repo_to_perm = RepoToPerm()
 
            default = 'repository.read'
 
            for p in UserModel(self.sa).get_by_username('default', cache=False).user_perms:
 
                if p.permission.permission_name.startswith('repository.'):
 
                    default = p.permission.permission_name
 
                    break
 

	
 
            default_perm = 'repository.none' if form_data['private'] else default
 

	
 
            repo_to_perm.permission_id = self.sa.query(Permission)\
 
                    .filter(Permission.permission_name == default_perm)\
 
                    .one().permission_id
 

	
 
            repo_to_perm.repository_id = new_repo.repo_id
 
            repo_to_perm.user_id = UserModel(self.sa)\
 
                .get_by_username('default', cache=False).user_id
 

	
 
            self.sa.add(repo_to_perm)
 
            self.sa.commit()
 

	
 

	
 
            #now automatically start following this repository as owner
 
            from rhodecode.model.scm import ScmModel
 
            ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
 
                                             cur_user.user_id)
 

	
 
            if not just_db:
 
                self.__create_repo(repo_name, form_data['repo_type'])
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def create_fork(self, form_data, cur_user):
 
        from rhodecode.lib.celerylib import tasks, run_task
 
        run_task(tasks.create_repo_fork, form_data, cur_user)
 

	
 
    def delete(self, repo):
 
        try:
 
            self.sa.delete(repo)
 
            self.__delete_repo(repo)
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def delete_perm_user(self, form_data, repo_name):
 
        try:
 
            self.sa.query(RepoToPerm)\
 
                .filter(RepoToPerm.repository \
 
                        == self.get_by_repo_name(repo_name))\
 
                .filter(RepoToPerm.user_id == form_data['user_id']).delete()
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def delete_stats(self, repo_name):
 
        try:
 
            self.sa.query(Statistics)\
 
                .filter(Statistics.repository == \
 
                        self.get_by_repo_name(repo_name)).delete()
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 

	
 
    def __create_repo(self, repo_name, alias):
 
        """
 
        makes repository on filesystem
 
        :param repo_name:
 
        :param alias:
 
        """
 
        from rhodecode.lib.utils import check_repo
 
        repo_path = os.path.join(g.base_path, repo_name)
 
        if check_repo(repo_name, g.base_path):
 
            log.info('creating repo %s in %s', repo_name, repo_path)
 
            backend = get_backend(alias)
 
            backend(repo_path, create=True)
 

	
 
    def __rename_repo(self, old, new):
 
        """
 
        renames repository on filesystem
 
        :param old: old name
 
        :param new: new name
 
        """
 
        log.info('renaming repo from %s to %s', old, new)
 

	
 
        old_path = os.path.join(g.base_path, old)
 
        new_path = os.path.join(g.base_path, new)
 
        if os.path.isdir(new_path):
 
            raise Exception('Was trying to rename to already existing dir %s',
 
                            new_path)
 
        shutil.move(old_path, new_path)
 

	
 
    def __delete_repo(self, repo):
 
        """
 
        removes repo from filesystem, the removal is acctually made by
 
        added rm__ prefix into dir, and rename internat .hg/.git dirs so this
 
        repository is no longer valid for rhodecode, can be undeleted later on
 
        by reverting the renames on this repository
 
        :param repo: repo object
 
        """
 
        rm_path = os.path.join(g.base_path, repo.repo_name)
 
        log.info("Removing %s", rm_path)
 
        #disable hg/git
 
        alias = repo.repo_type
 
        shutil.move(os.path.join(rm_path, '.%s' % alias),
 
                    os.path.join(rm_path, 'rm__.%s' % alias))
 
        #disable repo
 
        shutil.move(rm_path, os.path.join(g.base_path, 'rm__%s__%s' \
 
                                          % (datetime.today(), repo.repo_name)))
rhodecode/templates/summary/summary.html
Show inline comments
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${c.repo_name} ${_('Summary')} - ${c.rhodecode_name}
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    &raquo; 
 
    ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
 
    &raquo;
 
    ${_('summary')}
 
</%def>
 

	
 
<%def name="page_nav()">
 
	${self.menu('summary')}    
 
</%def>
 

	
 
<%def name="main()">
 
<div class="box box-left">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <!-- end box / title -->
 
	<div class="form">
 
	  <div class="fields">
 
		 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Name')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
		         %if c.repo_info.dbrepo.repo_type =='hg':
 
		           <img style="margin-bottom:2px" class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="/images/icons/hgicon.png"/>
 
		         %endif
 
		         %if c.repo_info.dbrepo.repo_type =='git':
 
		           <img style="margin-bottom:2px" class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="/images/icons/giticon.png"/>
 
		         %endif 
 
                                 			  
 
	             %if c.repo_info.dbrepo.private:
 
	                <img style="margin-bottom:2px" class="icon" title="${_('private repository')}" alt="${_('private repository')}" src="/images/icons/lock.png"/>
 
	             %else:
 
	                <img style="margin-bottom:2px" class="icon" title="${_('public repository')}" alt="${_('public repository')}" src="/images/icons/lock_open.png"/>
 
	             %endif
 
			      <span style="font-size: 1.6em;font-weight: bold;vertical-align: baseline;">${c.repo_info.name}</span>
 
			      %if c.rhodecode_user.username != 'default':
 
				      %if c.following:
 
	                  <span id="follow_toggle" class="following" title="${_('Stop following this repository')}"
 
	                        onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
 
	                  </span>			      
 
				      %else:
 
				      <span id="follow_toggle" class="follow" title="${_('Start following this repository')}"
 
				            onclick="javascript:toggleFollowingRepo(${c.repo_info.dbrepo.repo_id},'${str(h.get_token())}')">
 
				      </span>
 
				      %endif
 
				  %endif:
 
			      <br/>
 
		            %if c.repo_info.dbrepo.fork:
 
		            	<span style="margin-top:5px">
 
		            	<a href="${h.url('summary_home',repo_name=c.repo_info.dbrepo.fork.repo_name)}">
 
		            	<img class="icon" alt="${_('public')}"
 
		            	title="${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}" 
 
		            	src="/images/icons/arrow_divide.png"/>
 
		            	${_('Fork of')} ${c.repo_info.dbrepo.fork.repo_name}
 
		            	</a>
 
		            	</span>
 
		            %endif			      
 
			  </div>
 
			 </div>
 
			
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Description')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      ${c.repo_info.dbrepo.description}
 
			  </div>
 
			 </div>
 
			
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Contact')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			  	<div class="gravatar">
 
			  		<img alt="gravatar" src="${h.gravatar_url(c.repo_info.dbrepo.user.email)}"/>
 
			  	</div>
 
			  		${_('Username')}: ${c.repo_info.dbrepo.user.username}<br/>
 
			  		${_('Name')}: ${c.repo_info.dbrepo.user.name} ${c.repo_info.dbrepo.user.lastname}<br/>
 
			  		${_('Email')}: <a href="mailto:${c.repo_info.dbrepo.user.email}">${c.repo_info.dbrepo.user.email}</a>
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Last change')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      ${h.age(c.repo_info.last_change)} - ${c.repo_info.last_change} 
 
			      ${_('by')} ${h.get_changeset_safe(c.repo_info,'tip').author} 
 
			      
 
			  </div>
 
			 </div>
 
			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Clone url')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			      <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Trending source files')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
			    <div id="lang_stats">
 
			    
 
			    </div> 			  
 
			  	<script type="text/javascript">
 
				  	YUE.onDOMReady(function(e){
 
				  	    id = 'clone_url';
 
				  	    YUE.on(id,'click',function(e){
 
				  	        YUD.get('clone_url').select();
 
				  	    })
 
				  	})
 
			  		var data = ${c.trending_languages|n};
 
			  		var total = 0;
 
			  		var no_data = true;
 
			  		for (k in data){
 
			  		    total += data[k];
 
			  		    no_data = false;
 
			  		} 
 
					var tbl = document.createElement('table');
 
					tbl.setAttribute('class','trending_language_tbl');
 
					var cnt =0;
 
			  		for (k in data){
 
			  			cnt+=1;
 
			  			var hide = cnt>2;
 
				  		var tr = document.createElement('tr');
 
				  		if (hide){
 
				  			tr.setAttribute('style','display:none');
 
				  			tr.setAttribute('class','stats_hidden');
 
				  		}
 
				  		var percentage = Math.round((data[k]/total*100),2);
 
						var value = data[k];
 
				  		var td1 = document.createElement('td');
 
				  		td1.width=150;
 
				  		var trending_language_label = document.createElement('div');
 
				  		trending_language_label.innerHTML = k;
 
				  		td1.appendChild(trending_language_label);
 

	
 
				  		var td2 = document.createElement('td');
 
				  		td2.setAttribute('style','padding-right:14px !important');
 
			  		    var trending_language = document.createElement('div');
 
			  		    var nr_files = value+" ${_('files')}";
 
			  		    
 
			  		    trending_language.title = k+" "+nr_files;
 
			  		    
 
			  		    if (percentage>20){
 
			  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"% "+nr_files+ "</b>";	
 
			  		    }
 
			  		    else{
 
			  		    	trending_language.innerHTML = "<b style='font-size:0.8em'>"+percentage+"%</b>";
 
			  		    }
 
			  		    
 
			  		    trending_language.setAttribute("class", 'trending_language top-right-rounded-corner bottom-right-rounded-corner');
 
			  		    trending_language.style.width=percentage+"%";
 
						td2.appendChild(trending_language);
 
						
 
						tr.appendChild(td1);
 
						tr.appendChild(td2);
 
			  		    tbl.appendChild(tr);
 
			  		    if(cnt == 2){
 
			  		    	var show_more = document.createElement('tr');
 
			  		    	var td=document.createElement('td');
 
			  		    	lnk = document.createElement('a');
 
			  		    	lnk.href='#';
 
			  		    	lnk.innerHTML = "${_("show more")}";
 
			  		    	lnk.id='code_stats_show_more';
 
			  		        td.appendChild(lnk);
 
			  		    	show_more.appendChild(td);
 
			  		    	show_more.appendChild(document.createElement('td'));
 
			  		    	tbl.appendChild(show_more);
 
			  		    }
 
			  		    
 
			  		}
 
			  		if(no_data){
 
			  			var tr = document.createElement('tr');
 
			  			var td1 = document.createElement('td');
 
			  			td1.innerHTML = "${c.no_data_msg}";
 
			  			tr.appendChild(td1);
 
			  			tbl.appendChild(tr);
 
					}
 
			  		YUD.get('lang_stats').appendChild(tbl);
 
			  		YUE.on('code_stats_show_more','click',function(){
 
			  			l = YUD.getElementsByClassName('stats_hidden')
 
			  			for (e in l){
 
			  			    YUD.setStyle(l[e],'display','');
 
			  			};
 
			  			YUD.setStyle(YUD.get('code_stats_show_more'),
 
			  					'display','none');
 
			  		})
 
			  		
 
			  	</script>
 
 
 
			  </div>
 
			 </div>
 
			 			
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Download')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
		        %for cnt,archive in enumerate(c.repo_info._get_archives()):
 
		             %if cnt >=1:
 
		             |
 
		             %endif
 
		             ${h.link_to(c.repo_info.name+'.'+archive['type'],
 
		                h.url('files_archive_home',repo_name=c.repo_info.name,
 
		                revision='tip',fileformat=archive['extension']),class_="archive_icon")}
 
		        %endfor
 
			  </div>
 
			 </div>
 
			 
 
			 <div class="field">
 
			  <div class="label">
 
			      <label>${_('Feeds')}:</label>
 
			  </div>
 
			  <div class="input-short">
 
	            ${h.link_to(_('RSS'),h.url('rss_feed_home',repo_name=c.repo_info.name),class_='rss_icon')}
 
	            ${h.link_to(_('Atom'),h.url('atom_feed_home',repo_name=c.repo_info.name),class_='atom_icon')}
 
			  </div>
 
			 </div>				 			 			 
 
	  </div>		 
 
	</div>				
 
</div>
 
        
 
<div class="box box-right"  style="min-height:455px">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Commit activity by day / author')}</h5>
 
    </div>
 
    
 
    <div class="table">
 
        
 
         %if c.no_data:
 
           <div style="padding:0 10px 10px 15px;font-size: 1.2em;">${c.no_data_msg}</div>
 
        %endif:  
 
        <div id="commit_history" style="width:460px;height:300px;float:left"></div>
 
        <div style="clear: both;height: 10px"></div>
 
        <div id="overview" style="width:460px;height:100px;float:left"></div>
 
        
 
    	<div id="legend_data" style="clear:both;margin-top:10px;">
 
	    	<div id="legend_container"></div>
 
	    	<div id="legend_choices">
 
				<table id="legend_choices_tables" style="font-size:smaller;color:#545454"></table>
 
	    	</div>
 
    	</div>
 
		<script type="text/javascript">
 
		/**
 
		 * Plots summary graph
 
		 *
 
		 * @class SummaryPlot
 
		 * @param {from} initial from for detailed graph
 
		 * @param {to} initial to for detailed graph
 
		 * @param {dataset}
 
		 * @param {overview_dataset}
 
		 */
 
		function SummaryPlot(from,to,dataset,overview_dataset) {
 
			var initial_ranges = {
 
			    "xaxis":{
 
				    "from":from,
 
				   	"to":to,
 
				},
 
			};
 
		    var dataset = dataset;
 
		    var overview_dataset = [overview_dataset];
 
		    var choiceContainer = YUD.get("legend_choices");
 
		    var choiceContainerTable = YUD.get("legend_choices_tables");
 
		    var plotContainer = YUD.get('commit_history');
 
		    var overviewContainer = YUD.get('overview');
 
		    
 
		    var plot_options = {
 
				bars: {show:true,align:'center',lineWidth:4},
 
				legend: {show:true, container:"legend_container"},
 
				points: {show:true,radius:0,fill:false},
 
				yaxis: {tickDecimals:0,},
 
				xaxis: {
 
					mode: "time", 
 
					timeformat: "%d/%m",
 
				    min:from,
 
				    max:to,	
 
				}, 
 
				grid: {
 
					hoverable: true, 
 
				    clickable: true,
 
				    autoHighlight:true,
 
				    color: "#999"
 
				},
 
				//selection: {mode: "x"}
 
		    };
 
		    var overview_options = {
 
				legend:{show:false},
 
			    bars: {show:true,barWidth: 2,},
 
			    shadowSize: 0,
 
			    xaxis: {mode: "time", timeformat: "%d/%m/%y",},
 
			    yaxis: {ticks: 3, min: 0,tickDecimals:0,},
 
			    grid: {color: "#999",},
 
			    selection: {mode: "x"}
 
			};
 

	
 
			/**
 
			*get dummy data needed in few places
 
			*/
 
		    function getDummyData(label){
 
		    	return {"label":label,
 
               	 "data":[{"time":0,
 
               		 "commits":0,
 
	                     "added":0,
 
	                     "changed":0,
 
	                     "removed":0,
 
                    }],
 
                    "schema":["commits"],
 
                    "color":'#ffffff',
 
           		}
 
			}
 
			
 
		    /**
 
		     * generate checkboxes accordindly to data
 
		     * @param keys
 
		     * @returns
 
		     */
 
		    function generateCheckboxes(data) {
 
			    //append checkboxes
 
			    var i = 0;
 
			    choiceContainerTable.innerHTML = '';
 
			    for(var pos in data) {
 
			    	
 
			    	data[pos].color = i;
 
			        i++;
 
			        if(data[pos].label != ''){
 
				        choiceContainerTable.innerHTML += '<tr><td>'+
 
				        '<input type="checkbox" name="' + data[pos].label +'" checked="checked" />'
 
				        +data[pos].label+
 
				        '</td></tr>';
 
			        }
 
			    }	
 
		    }
 
		    
 
		    /**
 
		     * ToolTip show
 
		     */
 
		    function showTooltip(x, y, contents) {
 
		        var div=document.getElementById('tooltip');
 
		        if(!div) {
 
		            div = document.createElement('div');
 
		            div.id="tooltip";
 
		            div.style.position="absolute";
 
		            div.style.border='1px solid #fdd';
 
		            div.style.padding='2px';
 
		            div.style.backgroundColor='#fee';
 
		            document.body.appendChild(div);
 
		        }
 
		        YUD.setStyle(div, 'opacity', 0);
 
		        div.innerHTML = contents;
 
		        div.style.top=(y + 5) + "px";
 
		        div.style.left=(x + 5) + "px";
 

	
 
		        var anim = new YAHOO.util.Anim(div, {opacity: {to: 0.8}}, 0.2);
 
		        anim.animate();
 
		    }
 
		    
 
			/**
 
			 * This function will detect if selected period has some changesets 
 
			   for this user if it does this data is then pushed for displaying
 
			   Additionally it will only display users that are selected by the checkbox
 
			*/
 
		    function getDataAccordingToRanges(ranges) {
 
		    	
 
		        var data = [];
 
		        var keys = [];
 
				for(var key in dataset){
 
					var push = false;
 
					
 
					//method1 slow !!
 
		            //*
 
		            for(var ds in dataset[key].data){
 
			            commit_data = dataset[key].data[ds];
 
			            if (commit_data.time >= ranges.xaxis.from && commit_data.time <= ranges.xaxis.to){
 
			            	push = true;
 
			            	break;
 
					    }
 
				    }
 
					//*/
 
				    
 
				    /*//method2 sorted commit data !!!
 
				    
 
				    var first_commit = dataset[key].data[0].time;
 
				    var last_commit = dataset[key].data[dataset[key].data.length-1].time;
 
				    
 
				    if (first_commit >= ranges.xaxis.from && last_commit <= ranges.xaxis.to){
 
						push = true;
 
					}
 
				    //*/
 
				    
 
				    if(push){			
 
				    	data.push(dataset[key]);
 
				    }
 
				}
 
				if(data.length >= 1){
 
					return data;
 
				} 
 
				else{
 
					//just return dummy data for graph to plot itself
 
					return [getDummyData('')];	
 
				}
 
				
 
		    }
 
		    
 
			/**
 
			* redraw using new checkbox data
 
			*/
 
		    function plotchoiced(e,args){
 
			    var cur_data = args[0];
 
			    var cur_ranges = args[1];
 
		    	
 
				var new_data = [];
 
		    	var inputs = choiceContainer.getElementsByTagName("input");
 

	
 
		    	//show only checked labels
 
		        for(var i=0; i<inputs.length; i++) {
 
		            var checkbox_key = inputs[i].name;
 
		            
 
	                if(inputs[i].checked){
 
						for(var d in cur_data){
 
							if(cur_data[d].label == checkbox_key){
 
								new_data.push(cur_data[d]);
 
							}
 
						}			                
 
	    	        }
 
	                else{
 
		                //push dummy data to not hide the label
 
						new_data.push(getDummyData(checkbox_key));
 
			        }
 
		        }
 
					        
 
		    	var new_options = YAHOO.lang.merge(plot_options, {
 
		            xaxis: { 
 
		  	      		min: cur_ranges.xaxis.from, 
 
		  	      		max: cur_ranges.xaxis.to,
 
		  	      		mode:"time",
 
		  	      		timeformat: "%d/%m",
 
		        	},
 
		    	});
 
		    	if (!new_data){
 
					new_data = [[0,1]];
 
				}
 
		    	// do the zooming
 
		       plot = YAHOO.widget.Flot(plotContainer, new_data, new_options);
 
		       
 
		       plot.subscribe("plotselected", plotselected);
 
	
 
		       //resubscribe plothover
 
		       plot.subscribe("plothover", plothover);
 
		        
 
		       // don't fire event on the overview to prevent eternal loop
 
		       overview.setSelection(cur_ranges, true);
 
	
 
		    }
 
		    
 
			/**
 
		     * plot only selected items from overview
 
		     * @param ranges
 
		     * @returns
 
		     */
 
		    function plotselected(ranges,cur_data) {
 
			    //updates the data for new plot
 
	    		data = getDataAccordingToRanges(ranges);
 
	    		generateCheckboxes(data);
 
	    		
 
		    	var new_options = YAHOO.lang.merge(plot_options, {
 
		            xaxis: { 
 
		  	      		min: ranges.xaxis.from, 
 
		  	      		max: ranges.xaxis.to,
 
		  	      		mode:"time",
 
		  	      		timeformat: "%d/%m",
 
		        	},
 
		        	yaxis: { 
 
                        min: ranges.yaxis.from, 
 
                        max: ranges.yaxis.to,
 
                    },
 
                    		        	
 
		    	});
 
		    	// do the zooming
 
		        plot = YAHOO.widget.Flot(plotContainer, data, new_options);
 

	
 
		        plot.subscribe("plotselected", plotselected);
 

	
 
		        //resubscribe plothover
 
		        plot.subscribe("plothover", plothover);
 
		        
 
		        // don't fire event on the overview to prevent eternal loop
 
		        overview.setSelection(ranges, true);
 

	
 
		        //resubscribe choiced
 
		        YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, ranges]);
 
		    }
 
		    
 
		    var previousPoint = null;
 

	
 
			function plothover(o) {
 
		        var pos = o.pos;
 
		        var item = o.item;
 
		        
 
		        //YUD.get("x").innerHTML = pos.x.toFixed(2);
 
		        //YUD.get("y").innerHTML = pos.y.toFixed(2);
 
		        if (item) {
 
		            if (previousPoint != item.datapoint) {
 
		                previousPoint = item.datapoint;
 
		                
 
		                var tooltip = YUD.get("tooltip");
 
		                if(tooltip) {
 
		                	  tooltip.parentNode.removeChild(tooltip);
 
		                }
 
		                var x = item.datapoint.x.toFixed(2);
 
		                var y = item.datapoint.y.toFixed(2);
 
						
 
		                if (!item.series.label){
 
		                    item.series.label = 'commits';
 
		                }
 
		                var d = new Date(x*1000);
 
		                var fd = d.toDateString()
 
		                var nr_commits = parseInt(y);
 
		                
 
		                var cur_data = dataset[item.series.label].data[item.dataIndex];
 
		                var added = cur_data.added;
 
		                var changed = cur_data.changed;
 
		                var removed = cur_data.removed;
 
		                
 
		                var nr_commits_suffix = " ${_('commits')} ";
 
		                var added_suffix = " ${_('files added')} ";
 
		                var changed_suffix = " ${_('files changed')} ";
 
		                var removed_suffix = " ${_('files removed')} ";
 

	
 
		                
 
		                if(nr_commits == 1){nr_commits_suffix = " ${_('commit')} ";}
 
						if(added==1){added_suffix=" ${_('file added')} ";}
 
						if(changed==1){changed_suffix=" ${_('file changed')} ";}
 
						if(removed==1){removed_suffix=" ${_('file removed')} ";}
 
										                
 
		                showTooltip(item.pageX, item.pageY, item.series.label + " on " + fd
 
								 +'<br/>'+
 
		                         nr_commits + nr_commits_suffix+'<br/>'+
 
		                         added + added_suffix +'<br/>'+
 
		                         changed + changed_suffix + '<br/>'+
 
		                         removed + removed_suffix + '<br/>');
 
		            }
 
		        }
 
		        else {
 
		        	  var tooltip = YUD.get("tooltip");
 
		        	  
 
			          if(tooltip) {
 
			                tooltip.parentNode.removeChild(tooltip);
 
			          }
 
		            previousPoint = null;
 
		        }
 
		    }
 
			
 
		    /**
 
		     * MAIN EXECUTION
 
		     */
 
			
 
			var data = getDataAccordingToRanges(initial_ranges);
 
			generateCheckboxes(data);
 
			
 
		    //main plot
 
		    var plot = YAHOO.widget.Flot(plotContainer,data,plot_options);
 
		    
 
			//overview
 
			var overview = YAHOO.widget.Flot(overviewContainer, overview_dataset, overview_options);
 
			
 
			//show initial selection on overview
 
			overview.setSelection(initial_ranges);    
 
			
 
		    plot.subscribe("plotselected", plotselected);
 
		    
 
		    overview.subscribe("plotselected", function (ranges) {
 
		        plot.setSelection(ranges);
 
		    });		
 
				
 
		    plot.subscribe("plothover", plothover);
 

	
 
		    YUE.on(choiceContainer.getElementsByTagName("input"), "click", plotchoiced, [data, initial_ranges]);
 
		}
 
			SummaryPlot(${c.ts_min},${c.ts_max},${c.commit_data|n},${c.overview_data|n});		
 
		</script>
 

	
 
    </div>
 
</div>    
 

	
 
<div class="box">    
 
    <div class="title">
 
        <div class="breadcrumbs">${h.link_to(_('Shortlog'),h.url('shortlog_home',repo_name=c.repo_name))}</div>
 
    </div>    
 
    <div class="table">
 
        <div id="shortlog_data">
 
            <%include file='../shortlog/shortlog_data.html'/>
 
        </div>
 
        ##%if c.repo_changesets:
 
        ##	${h.link_to(_('show more'),h.url('changelog_home',repo_name=c.repo_name))}
 
        ##%endif
 
    </div>
 
</div>
 
<div class="box">    
 
    <div class="title">
 
        <div class="breadcrumbs">${h.link_to(_('Last ten tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
 
        <div class="breadcrumbs">${h.link_to(_('Tags'),h.url('tags_home',repo_name=c.repo_name))}</div>
 
    </div>    
 
    <div class="table">
 
        <%include file='../tags/tags_data.html'/>
 
        %if c.repo_changesets:
 
        	${h.link_to(_('show more'),h.url('tags_home',repo_name=c.repo_name))}
 
        %endif
 
    </div>
 
</div>
 
<div class="box">
 
    <div class="title">
 
        <div class="breadcrumbs">${h.link_to(_('Last ten branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
 
        <div class="breadcrumbs">${h.link_to(_('Branches'),h.url('branches_home',repo_name=c.repo_name))}</div>
 
    </div>    
 
    <div class="table">
 
        <%include file='../branches/branches_data.html'/>
 
        %if c.repo_changesets:
 
        	${h.link_to(_('show more'),h.url('branches_home',repo_name=c.repo_name))}
 
        %endif
 
    </div>      
 
</div> 
 

	
 
</%def>    
 
\ No newline at end of file
0 comments (0 inline, 0 general)