Changeset - e7eef7a1db6a
[Not reviewed]
beta
1 13 1
Marcin Kuzminski - 14 years ago 2011-11-25 23:11:32
marcin@python-works.com
#235 forking page repo group selection
- group is selected as parent repo
- refactoring of session behavior to get more atomic operations in models
14 files changed with 259 insertions and 170 deletions:
0 comments (0 inline, 0 general)
rhodecode/config/routing.py
Show inline comments
 
@@ -456,28 +456,29 @@ def make_map(config):
 
                controller='settings', action="delete",
 
                conditions=dict(method=["DELETE"], function=check_repo))
 

	
 
    rmap.connect('repo_settings_update', '/{repo_name:.*}/settings',
 
                controller='settings', action="update",
 
                conditions=dict(method=["PUT"], function=check_repo))
 

	
 
    rmap.connect('repo_settings_home', '/{repo_name:.*}/settings',
 
                controller='settings', action='index',
 
                conditions=dict(function=check_repo))
 

	
 
    rmap.connect('repo_fork_create_home', '/{repo_name:.*}/fork',
 
                controller='settings', action='fork_create',
 
                controller='forks', action='fork_create',
 
                conditions=dict(function=check_repo, method=["POST"]))
 

	
 
    rmap.connect('repo_fork_home', '/{repo_name:.*}/fork',
 
                controller='settings', action='fork',
 
                controller='forks', action='fork',
 
                conditions=dict(function=check_repo))
 

	
 
    rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
 
                 controller='forks', action='forks',
 
                conditions=dict(function=check_repo))
 

	
 
    rmap.connect('repo_followers_home', '/{repo_name:.*}/followers',
 
                 controller='followers', action='followers',
 
                 conditions=dict(function=check_repo))
 

	
 
    rmap.connect('repo_forks_home', '/{repo_name:.*}/forks',
 
                 controller='forks', action='forks',
 
                 conditions=dict(function=check_repo))
 

	
 
    return rmap
rhodecode/controllers/admin/repos.py
Show inline comments
 
@@ -20,39 +20,40 @@
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

	
 
import logging
 
import traceback
 
import formencode
 
from formencode import htmlfill
 

	
 
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 import request, session, tmpl_context as c, url
 
from pylons.controllers.util import redirect
 
from pylons.i18n.translation import _
 
from sqlalchemy.exc import IntegrityError
 

	
 
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, repo_name_slug
 
from rhodecode.lib.helpers import get_token
 
from rhodecode.model.meta import Session
 
from rhodecode.model.db import User, Repository, UserFollowing, RepoGroup
 
from rhodecode.model.forms import RepoForm
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.repo import RepoModel
 
from sqlalchemy.exc import IntegrityError
 

	
 
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()
 
@@ -118,47 +119,47 @@ class ReposController(BaseController):
 
        # url('repos')
 

	
 
        c.repos_list = ScmModel().get_repos(Repository.query()
 
                                            .order_by(Repository.repo_name)
 
                                            .all(), sort_key='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()
 

	
 
        self.__load_defaults()
 
        form_result = {}
 
        try:
 
            form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
 
                            .to_python(dict(request.POST))
 
            repo_model.create(form_result, self.rhodecode_user)
 
            RepoModel().create(form_result, self.rhodecode_user)
 
            if form_result['clone_uri']:
 
                h.flash(_('created repository %s from %s') \
 
                    % (form_result['repo_name'], form_result['clone_uri']),
 
                    category='success')
 
            else:
 
                h.flash(_('created repository %s') % form_result['repo_name'],
 
                    category='success')
 

	
 
            if request.POST.get('user_created'):
 
                #created by regular non admin user
 
                action_logger(self.rhodecode_user, 'user_created_repo',
 
                              form_result['repo_name_full'], '', self.sa)
 
            else:
 
                action_logger(self.rhodecode_user, 'admin_created_repo',
 
                              form_result['repo_name_full'], '', self.sa)
 

	
 
            Session().commit()
 
        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,
 
@@ -198,25 +199,25 @@ class ReposController(BaseController):
 
        changed_name = repo_name
 
        _form = RepoForm(edit=True, old_data={'repo_name': repo_name},
 
                         repo_groups=c.repo_groups_choices)()
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            repo = 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 = repo.repo_name
 
            action_logger(self.rhodecode_user, 'admin_updated_repo',
 
                              changed_name, '', self.sa)
 

	
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            defaults = self.__load_data(repo_name)
 
            defaults.update(errors.value)
 
            return htmlfill.render(
 
                render('admin/repos/repo_edit.html'),
 
                defaults=defaults,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 

	
 
        except Exception:
 
            log.error(traceback.format_exc())
 
@@ -242,25 +243,25 @@ class ReposController(BaseController):
 
                      ' 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')
 

	
 
            Session().commit()
 
        except IntegrityError, e:
 
            if e.message.find('repositories_fork_id_fkey'):
 
                log.error(traceback.format_exc())
 
                h.flash(_('Cannot delete %s it still contains attached '
 
                          'forks') % repo_name,
 
                        category='warning')
 
            else:
 
                log.error(traceback.format_exc())
 
                h.flash(_('An error occurred during '
 
                          'deletion of %s') % repo_name,
 
                        category='error')
 

	
rhodecode/controllers/forks.py
Show inline comments
 
@@ -14,43 +14,161 @@
 
# it under the terms of the GNU General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
import logging
 
import formencode
 
import traceback
 
from formencode import htmlfill
 

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

	
 
import rhodecode.lib.helpers as h
 

	
 
from rhodecode.lib.helpers import Page
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
 
    NotAnonymous
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.model.db import Repository, User, UserFollowing
 
from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.forms import RepoForkForm
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class ForksController(BaseRepoController):
 

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

	
 
    def __load_defaults(self):
 
        c.repo_groups = RepoGroup.groups_choices()
 
        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
 

	
 
    def __load_data(self, repo_name=None):
 
        """
 
        Load defaults settings for edit, and update
 

	
 
        :param repo_name:
 
        """
 
        self.__load_defaults()
 

	
 
        c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
 
        repo = db_repo.scm_instance
 

	
 
        if c.repo_info is None:
 
            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'))
 

	
 
        c.default_user_id = User.get_by_username('default').user_id
 
        c.in_public_journal = UserFollowing.query()\
 
            .filter(UserFollowing.user_id == c.default_user_id)\
 
            .filter(UserFollowing.follows_repository == c.repo_info).scalar()
 

	
 
        if c.repo_info.stats:
 
            last_rev = c.repo_info.stats.stat_on_revision
 
        else:
 
            last_rev = 0
 
        c.stats_revision = last_rev
 

	
 
        c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
 

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

	
 
        defaults = RepoModel()._get_defaults(repo_name)
 
        # add prefix to fork
 
        defaults['repo_name'] = 'fork-' + defaults['repo_name']
 
        return defaults
 

	
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def forks(self, repo_name):
 
        p = int(request.params.get('page', 1))
 
        repo_id = c.rhodecode_db_repo.repo_id
 
        d = Repository.get_repo_forks(repo_id)
 
        c.forks_pager = Page(d, page=p, items_per_page=20)
 

	
 
        c.forks_data = render('/forks/forks_data.html')
 

	
 
        if request.environ.get('HTTP_X_PARTIAL_XHR'):
 
            return c.forks_data
 

	
 
        return render('/forks/forks.html')
 

	
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def fork(self, repo_name):
 
        c.repo_info = Repository.get_by_repo_name(repo_name)
 
        if not c.repo_info:
 
            h.flash(_('%s repository is not mapped to db perhaps'
 
                      ' it was created or renamed from the file system'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('home'))
 

	
 
        defaults = self.__load_data(repo_name)
 

	
 
        return htmlfill.render(
 
            render('forks/fork.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 

	
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def fork_create(self, repo_name):
 
        self.__load_defaults()
 
        c.repo_info = Repository.get_by_repo_name(repo_name)
 
        _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type},
 
                             repo_groups=c.repo_groups_choices,)()
 
        form_result = {}
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            # add org_path of repo so we can do a clone from it later
 
            form_result['org_path'] = c.repo_info.repo_name
 

	
 
            # create fork is done sometimes async on celery, db transaction
 
            # management is handled there.
 
            RepoModel().create_fork(form_result, self.rhodecode_user)
 
            h.flash(_('forked %s repository as %s') \
 
                      % (repo_name, form_result['repo_name']),
 
                    category='success')
 
        except formencode.Invalid, errors:
 
            c.new_repo = errors.value['repo_name']
 

	
 
            return htmlfill.render(
 
                render('forks/fork.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during repository forking %s') %
 
                    repo_name, category='error')
 

	
 
        return redirect(url('home'))
rhodecode/controllers/journal.py
Show inline comments
 
@@ -14,39 +14,40 @@
 
# 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 itertools import groupby
 

	
 
from sqlalchemy import or_
 
from sqlalchemy.orm import joinedload, make_transient
 
from sqlalchemy.orm import joinedload
 
from webhelpers.paginate import Page
 
from itertools import groupby
 
from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 

	
 
from paste.httpexceptions import HTTPBadRequest
 
from pylons import request, tmpl_context as c, response, url
 
from pylons.i18n.translation import _
 
from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 

	
 
import rhodecode.lib.helpers as h
 
from rhodecode.lib.auth import LoginRequired, NotAnonymous
 
from rhodecode.lib.base import BaseController, render
 
from rhodecode.model.db import UserLog, UserFollowing
 
from rhodecode.model.meta import Session
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class JournalController(BaseController):
 

	
 
    def __before__(self):
 
        super(JournalController, self).__before__()
 
        self.rhodecode_user = self.rhodecode_user
 
        self.title = _('%s public journal %s feed') % (c.rhodecode_name, '%s')
 
        self.language = 'en-us'
 
        self.ttl = "5"
 
@@ -115,33 +116,35 @@ class JournalController(BaseController):
 
    @LoginRequired()
 
    @NotAnonymous()
 
    def toggle_following(self):
 
        cur_token = request.POST.get('auth_token')
 
        token = h.get_token()
 
        if cur_token == token:
 

	
 
            user_id = request.POST.get('follows_user_id')
 
            if user_id:
 
                try:
 
                    self.scm_model.toggle_following_user(user_id,
 
                                                self.rhodecode_user.user_id)
 
                    Session().commit()
 
                    return 'ok'
 
                except:
 
                    raise HTTPBadRequest()
 

	
 
            repo_id = request.POST.get('follows_repo_id')
 
            if repo_id:
 
                try:
 
                    self.scm_model.toggle_following_repo(repo_id,
 
                                                self.rhodecode_user.user_id)
 
                    Session().commit()
 
                    return 'ok'
 
                except:
 
                    raise HTTPBadRequest()
 

	
 
        log.debug('token mismatch %s vs %s', cur_token, token)
 
        raise HTTPBadRequest()
 

	
 
    @LoginRequired()
 
    def public_journal(self):
 
        # Return a rendered template
 
        p = int(request.params.get('page', 1))
 

	
rhodecode/controllers/settings.py
Show inline comments
 
@@ -26,32 +26,32 @@
 
import logging
 
import traceback
 
import formencode
 

	
 
from formencode import htmlfill
 

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

	
 
import rhodecode.lib.helpers as h
 

	
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator, \
 
    HasRepoPermissionAnyDecorator, NotAnonymous
 
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAllDecorator
 
from rhodecode.lib.base import BaseRepoController, render
 
from rhodecode.lib.utils import invalidate_cache, action_logger
 

	
 
from rhodecode.model.forms import RepoSettingsForm, RepoForkForm
 
from rhodecode.model.forms import RepoSettingsForm
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.db import RepoGroup
 
from rhodecode.model.meta import Session
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class SettingsController(BaseRepoController):
 

	
 
    @LoginRequired()
 
    def __before__(self):
 
        super(SettingsController, self).__before__()
 
    
 
    def __load_defaults(self):
 
        c.repo_groups = RepoGroup.groups_choices()
 
@@ -96,24 +96,25 @@ class SettingsController(BaseRepoControl
 
                                 old_data={'repo_name': repo_name},
 
                                 repo_groups=c.repo_groups_choices)()
 
        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_full']
 
            action_logger(self.rhodecode_user, 'user_updated_repo',
 
                          changed_name, '', self.sa)
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            c.repo_info = repo_model.get_by_repo_name(repo_name)
 
            c.users_array = repo_model.get_users_js()
 
            errors.value.update({'user': c.repo_info.user.username})
 
            return htmlfill.render(
 
                render('settings/repo_settings.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except Exception:
 
            log.error(traceback.format_exc())
 
@@ -139,70 +140,19 @@ class SettingsController(BaseRepoControl
 
                      ' 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('home'))
 
        try:
 
            action_logger(self.rhodecode_user, 'user_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')
 
            Session().commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during deletion of %s') % repo_name,
 
                    category='error')
 

	
 
        return redirect(url('home'))
 

	
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def fork(self, repo_name):
 
        repo_model = RepoModel()
 
        c.repo_info = repo = repo_model.get_by_repo_name(repo_name)
 
        if not repo:
 
            h.flash(_('%s repository is not mapped to db perhaps'
 
                      ' it was created or renamed from the file system'
 
                      ' please run the application again'
 
                      ' in order to rescan repositories') % repo_name,
 
                      category='error')
 

	
 
            return redirect(url('home'))
 

	
 
        return render('settings/repo_fork.html')
 

	
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def fork_create(self, repo_name):
 
        repo_model = RepoModel()
 
        c.repo_info = repo_model.get_by_repo_name(repo_name)
 
        _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type})()
 
        form_result = {}
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            form_result.update({'repo_name': repo_name})
 
            repo_model.create_fork(form_result, self.rhodecode_user)
 
            h.flash(_('forked %s repository as %s') \
 
                      % (repo_name, form_result['fork_name']),
 
                    category='success')
 
            action_logger(self.rhodecode_user,
 
                          'user_forked_repo:%s' % form_result['fork_name'],
 
                           repo_name, '', self.sa)
 
        except formencode.Invalid, errors:
 
            c.new_repo = errors.value['fork_name']
 
            r = render('settings/repo_fork.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())
 
            h.flash(_('An error occurred during repository forking %s') %
 
                    repo_name, category='error')
 

	
 
        return redirect(url('home'))
rhodecode/lib/celerylib/tasks.py
Show inline comments
 
@@ -28,105 +28,99 @@ from celery.decorators import task
 
import os
 
import traceback
 
import logging
 
from os.path import join as jn
 

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

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

	
 
from vcs import get_backend
 

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

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

	
 
from vcs.backends import get_repo
 
from rhodecode.model.db import Statistics, Repository, User
 

	
 
from sqlalchemy import engine_from_config
 

	
 

	
 
add_cache(config)
 

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

	
 

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

	
 

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

	
 
def get_logger(cls):
 
    if CELERY_ON:
 
        try:
 
            log = cls.get_logger()
 
        except:
 
            log = logging.getLogger(__name__)
 
    else:
 
        log = logging.getLogger(__name__)
 

	
 
    return log
 

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

	
 

	
 
@task(ignore_result=True)
 
@locked_task
 
def whoosh_index(repo_location, full_index):
 
    from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
 

	
 
    #log = whoosh_index.get_logger()
 
    from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
 

	
 
    index_location = config['index_dir']
 
    WhooshIndexingDaemon(index_location=index_location,
 
                         repo_location=repo_location, sa=get_session())\
 
                         .run(full_index=full_index)
 

	
 

	
 
@task(ignore_result=True)
 
def get_commits_stats(repo_name, ts_min_y, ts_max_y):
 
    log = get_logger(get_commits_stats)
 

	
 
    lockkey = __get_lockkey('get_commits_stats', repo_name, ts_min_y,
 
                            ts_max_y)
 
    lockkey_path = config['here']
 

	
 
    log.info('running task with lockkey %s', lockkey)
 
    try:
 
        sa = get_session()
 
        lock = l = DaemonLock(file_=jn(lockkey_path, lockkey))
 

	
 
        #for js data compatibilty cleans the key for person from '
 
        akc = lambda k: person(k).replace('"', "")
 

	
 
        co_day_auth_aggr = {}
 
        commits_by_day_aggregate = {}
 
        repos_path = get_repos_path()
 
        repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
 
        repo = Repository.get_by_repo_name(repo_name).scm_instance
 
        repo_size = len(repo.revisions)
 
        #return if repo have no revisions
 
        if repo_size < 1:
 
            lock.release()
 
            return True
 

	
 
        skip_date_limit = True
 
        parse_limit = int(config['app_conf'].get('commit_parse_limit'))
 
        last_rev = 0
 
        last_cs = None
 
        timegetter = itemgetter('time')
 

	
 
@@ -246,55 +240,56 @@ def get_commits_stats(repo_name, ts_min_
 
        lock.release()
 

	
 
        #execute another task if celery is enabled
 
        if len(repo.revisions) > 1 and CELERY_ON:
 
            run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
 
        return True
 
    except LockHeld:
 
        log.info('LockHeld')
 
        return 'Task with key %s already running' % lockkey
 

	
 
@task(ignore_result=True)
 
def send_password_link(user_email):
 
    from rhodecode.model.notification import EmailNotificationModel
 

	
 
    log = get_logger(send_password_link)
 

	
 
    try:
 
        from rhodecode.model.notification import EmailNotificationModel
 
        sa = get_session()
 
        user = User.get_by_email(user_email)
 
        if user:
 
            log.debug('password reset user found %s' % user)
 
            link = url('reset_password_confirmation', key=user.api_key,
 
                       qualified=True)
 
            reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
 
            body = EmailNotificationModel().get_email_tmpl(reg_type,
 
                                                **{'user':user.short_contact,
 
                                                   'reset_url':link})
 
            log.debug('sending email')
 
            run_task(send_email, user_email,
 
                     _("password reset link"), body)
 
            log.info('send new password mail to %s', user_email)
 
        else:
 
            log.debug("password reset email %s not found" % user_email)
 
    except:
 
        log.error(traceback.format_exc())
 
        return False
 

	
 
    return True
 

	
 
@task(ignore_result=True)
 
def reset_user_password(user_email):
 
    log = get_logger(reset_user_password)
 
    from rhodecode.lib import auth
 

	
 
    from rhodecode.lib import auth
 
    log = get_logger(reset_user_password)
 

	
 
    try:
 
        try:
 
            sa = get_session()
 
            user = User.get_by_email(user_email)
 
            new_passwd = auth.PasswordGenerator().gen_password(8,
 
                             auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
 
            if user:
 
                user.password = auth.get_crypt_password(new_passwd)
 
                user.api_key = auth.generate_api_key(user.username)
 
                sa.add(user)
 
                sa.commit()
 
@@ -352,45 +347,57 @@ def send_email(recipients, subject, body
 
        m = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth,
 
                       mail_port, ssl, tls, debug=debug)
 
        m.send(recipients, subject, body, html_body)
 
    except:
 
        log.error('Mail sending failed')
 
        log.error(traceback.format_exc())
 
        return False
 
    return True
 

	
 

	
 
@task(ignore_result=True)
 
def create_repo_fork(form_data, cur_user):
 
    """
 
    Creates a fork of repository using interval VCS methods
 
    
 
    :param form_data:
 
    :param cur_user:
 
    """
 
    from rhodecode.model.repo import RepoModel
 

	
 
    log = get_logger(create_repo_fork)
 

	
 
    from rhodecode.model.repo import RepoModel
 
    from vcs import get_backend
 
    Session = get_session()
 
    base_path = Repository.base_path()
 

	
 
    RepoModel(Session).create(form_data, cur_user, just_db=True, fork=True)
 

	
 
    alias = form_data['repo_type']
 
    org_repo_name = form_data['org_path']
 
    source_repo_path = os.path.join(base_path, org_repo_name)
 
    destination_fork_path = os.path.join(base_path, form_data['repo_name_full'])
 

	
 
    repo_model = RepoModel(get_session())
 
    repo_model.create(form_data, cur_user, just_db=True, fork=True)
 
    repo_name = form_data['repo_name']
 
    repos_path = get_repos_path()
 
    repo_path = os.path.join(repos_path, repo_name)
 
    repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
 
    alias = form_data['repo_type']
 

	
 
    log.info('creating repo fork %s as %s', repo_name, repo_path)
 
    log.info('creating fork of %s as %s', source_repo_path,
 
             destination_fork_path)
 
    backend = get_backend(alias)
 
    backend(str(repo_fork_path), create=True, src_url=str(repo_path))
 

	
 
    backend(safe_str(destination_fork_path), create=True,
 
            src_url=safe_str(source_repo_path))
 
    action_logger(cur_user, 'user_forked_repo:%s' % org_repo_name,
 
                   org_repo_name, '', Session)
 
    # finally commit at latest possible stage
 
    Session.commit()
 

	
 
def __get_codes_stats(repo_name):
 
    repos_path = get_repos_path()
 
    repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
 
    repo = Repository.get_by_repo_name(repo_name).scm_instance
 

	
 
    tip = repo.get_changeset()
 
    code_stats = {}
 

	
 
    def aggregate(cs):
 
        for f in cs[2]:
 
            ext = lower(f.extension)
 
            if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
 
                if ext in code_stats:
 
                    code_stats[ext] += 1
 
                else:
 
                    code_stats[ext] = 1
 

	
rhodecode/lib/hooks.py
Show inline comments
 
@@ -24,25 +24,26 @@
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
import os
 
import sys
 

	
 
from mercurial.scmutil import revrange
 
from mercurial.node import nullrev
 

	
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.utils import action_logger
 

	
 

	
 
def repo_size(ui, repo, hooktype=None, **kwargs):
 
    """Presents size of repository after push
 
    """
 
    Presents size of repository after push
 

	
 
    :param ui:
 
    :param repo:
 
    :param hooktype:
 
    """
 

	
 
    if hooktype != 'changegroup':
 
        return False
 
    size_hg, size_root = 0, 0
 
    for path, dirs, files in os.walk(repo.root):
 
        if path.find('.hg') != -1:
 
            for f in files:
 
@@ -56,42 +57,45 @@ def repo_size(ui, repo, hooktype=None, *
 
                    size_root += os.path.getsize(os.path.join(path, f))
 
                except OSError:
 
                    pass
 

	
 
    size_hg_f = h.format_byte_size(size_hg)
 
    size_root_f = h.format_byte_size(size_root)
 
    size_total_f = h.format_byte_size(size_root + size_hg)
 
    sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \
 
                     % (size_hg_f, size_root_f, size_total_f))
 

	
 

	
 
def log_pull_action(ui, repo, **kwargs):
 
    """Logs user last pull action
 
    """
 
    Logs user last pull action
 

	
 
    :param ui:
 
    :param repo:
 
    """
 

	
 
    extra_params = dict(repo.ui.configitems('rhodecode_extras'))
 
    username = extra_params['username']
 
    repository = extra_params['repository']
 
    action = 'pull'
 

	
 
    action_logger(username, action, repository, extra_params['ip'])
 
    action_logger(username, action, repository, extra_params['ip'],
 
                  commit=True)
 

	
 
    return 0
 

	
 

	
 
def log_push_action(ui, repo, **kwargs):
 
    """Maps user last push action to new changeset id, from mercurial
 
    """
 
    Maps user last push action to new changeset id, from mercurial
 

	
 
    :param ui:
 
    :param repo:
 
    """
 

	
 
    extra_params = dict(repo.ui.configitems('rhodecode_extras'))
 
    username = extra_params['username']
 
    repository = extra_params['repository']
 
    action = extra_params['action'] + ':%s'
 
    node = kwargs['node']
 

	
 
    def get_revs(repo, rev_opt):
 
@@ -101,15 +105,16 @@ def log_push_action(ui, repo, **kwargs):
 
            if len(revs) == 0:
 
                return (nullrev, nullrev)
 
            return (max(revs), min(revs))
 
        else:
 
            return (len(repo) - 1, 0)
 

	
 
    stop, start = get_revs(repo, [node + ':'])
 

	
 
    revs = (str(repo[r]) for r in xrange(start, stop + 1))
 

	
 
    action = action % ','.join(revs)
 

	
 
    action_logger(username, action, repository, extra_params['ip'])
 
    action_logger(username, action, repository, extra_params['ip'],
 
                  commit=True)
 

	
 
    return 0
rhodecode/lib/utils.py
Show inline comments
 
@@ -84,25 +84,25 @@ def repo_name_slug(value):
 

	
 
    for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
 
        slug = slug.replace(c, '-')
 
    slug = recursive_replace(slug, '-')
 
    slug = collapse(slug, '-')
 
    return slug
 

	
 

	
 
def get_repo_slug(request):
 
    return request.environ['pylons.routes_dict'].get('repo_name')
 

	
 

	
 
def action_logger(user, action, repo, ipaddr='', sa=None):
 
def action_logger(user, action, repo, ipaddr='', sa=None, commit=False):
 
    """
 
    Action logger for various actions made by users
 

	
 
    :param user: user that made this action, can be a unique username string or
 
        object containing user_id attribute
 
    :param action: action to log, should be on of predefined unique actions for
 
        easy translations
 
    :param repo: string name of repository or object containing repo_id,
 
        that action was made on
 
    :param ipaddr: optional ip address from what the action was made
 
    :param sa: optional sqlalchemy session
 

	
 
@@ -129,30 +129,31 @@ def action_logger(user, action, repo, ip
 
            raise Exception('You have to provide repository to action logger')
 

	
 
        user_log = UserLog()
 
        user_log.user_id = user_obj.user_id
 
        user_log.action = action
 

	
 
        user_log.repository_id = repo_obj.repo_id
 
        user_log.repository_name = repo_name
 

	
 
        user_log.action_date = datetime.datetime.now()
 
        user_log.user_ip = ipaddr
 
        sa.add(user_log)
 
        sa.commit()
 

	
 
        log.info('Adding user %s, action %s on %s', user_obj, action, repo)
 
        if commit:
 
            sa.commit()
 
    except:
 
        log.error(traceback.format_exc())
 
        sa.rollback()
 
        raise
 

	
 

	
 
def get_repos(path, recursive=False):
 
    """
 
    Scans given path for repos and return (name,(type,path)) tuple
 

	
 
    :param path: path to scann for repositories
 
    :param recursive: recursive search and return names with subdirs in front
 
    """
 

	
 
    if path.endswith(os.sep):
 
        #remove ending slash for better results
rhodecode/model/forms.py
Show inline comments
 
@@ -280,42 +280,26 @@ def ValidRepoName(edit, old_data):
 
                                                 error_dict=e_dict)
 

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

	
 
            return value
 

	
 
    return _ValidRepoName
 

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

	
 
            repo_name = value.get('fork_name')
 

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

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

	
 

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

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

	
 
    return _SlugifyName
 

	
 
def ValidCloneUri():
 
    from mercurial.httprepo import httprepository, httpsrepository
 
@@ -596,35 +580,38 @@ def RepoForm(edit=False, old_data={}, su
 
        description = UnicodeString(strip=True, min=1, not_empty=True)
 
        private = StringBoolean(if_missing=False)
 
        enable_statistics = StringBoolean(if_missing=False)
 
        enable_downloads = StringBoolean(if_missing=False)
 

	
 
        if edit:
 
            #this is repo owner
 
            user = All(UnicodeString(not_empty=True), ValidRepoUser)
 

	
 
        chained_validators = [ValidRepoName(edit, old_data), ValidPerms]
 
    return _RepoForm
 

	
 
def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
 
def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                 repo_groups=[]):
 
    class _RepoForkForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        fork_name = All(UnicodeString(strip=True, min=1, not_empty=True),
 
        repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
 
                        SlugifyName())
 
        repo_group = OneOf(repo_groups, hideList=True)
 
        repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
 
        description = UnicodeString(strip=True, min=1, not_empty=True)
 
        private = StringBoolean(if_missing=False)
 
        repo_type = All(ValidForkType(old_data), OneOf(supported_backends))
 

	
 
        chained_validators = [ValidForkName()]
 
        copy_permissions = StringBoolean(if_missing=False)
 
        fork_parent_id = UnicodeString()
 
        chained_validators = [ValidForkName(edit, old_data)]
 

	
 
    return _RepoForkForm
 

	
 
def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                     repo_groups=[]):
 
    class _RepoForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
 
                        SlugifyName())
 
        description = UnicodeString(strip=True, min=1, not_empty=True)
 
        repo_group = OneOf(repo_groups, hideList=True)
rhodecode/model/notification.py
Show inline comments
 
@@ -26,26 +26,24 @@
 

	
 
import os
 
import logging
 
import traceback
 
import datetime
 

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

	
 
from rhodecode.lib import helpers as h
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import Notification, User, UserNotification
 
from rhodecode.lib.celerylib import run_task
 
from rhodecode.lib.celerylib.tasks import send_email
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class NotificationModel(BaseModel):
 

	
 

	
 
    def __get_user(self, user):
 
        if isinstance(user, basestring):
 
            return User.get_by_username(username=user)
 
        else:
 
            return self._get_instance(User, user)
 
@@ -65,24 +63,25 @@ class NotificationModel(BaseModel):
 
               type_=Notification.TYPE_MESSAGE):
 
        """
 
        
 
        Creates notification of given type
 
        
 
        :param created_by: int, str or User instance. User who created this
 
            notification
 
        :param subject:
 
        :param body:
 
        :param recipients: list of int, str or User objects
 
        :param type_: type of notification
 
        """
 
        from rhodecode.lib.celerylib import tasks, run_task
 

	
 
        if not getattr(recipients, '__iter__', False):
 
            raise Exception('recipients must be a list of iterable')
 

	
 
        created_by_obj = self.__get_user(created_by)
 

	
 
        recipients_objs = []
 
        for u in recipients:
 
            obj = self.__get_user(u)
 
            if obj:
 
                recipients_objs.append(obj)
 
        recipients_objs = set(recipients_objs)
 
@@ -91,25 +90,25 @@ class NotificationModel(BaseModel):
 
                                    body=body, recipients=recipients_objs,
 
                                    type_=type_)
 

	
 

	
 
        # send email with notification
 
        for rec in recipients_objs:
 
            email_subject = NotificationModel().make_description(notif, False)
 
            type_ = EmailNotificationModel.TYPE_CHANGESET_COMMENT
 
            email_body = body
 
            email_body_html = EmailNotificationModel()\
 
                            .get_email_tmpl(type_, **{'subject':subject,
 
                                                      'body':h.rst(body)})
 
            run_task(send_email, rec.email, email_subject, email_body,
 
            run_task(tasks.send_email, rec.email, email_subject, email_body,
 
                     email_body_html)
 

	
 
        return notif
 

	
 
    def delete(self, user, notification):
 
        # we don't want to remove actual notification just the assignment
 
        try:
 
            notification = self.__get_notification(notification)
 
            user = self.__get_user(user)
 
            if notification and user:
 
                obj = UserNotification.query()\
 
                        .filter(UserNotification.user == user)\
rhodecode/model/repo.py
Show inline comments
 
@@ -203,54 +203,51 @@ class RepoModel(BaseModel):
 
            if repo_name != new_name:
 
                # rename repository
 
                self.__rename_repo(old=repo_name, new=new_name)
 

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

	
 
    def create(self, form_data, cur_user, just_db=False, fork=False):
 
        from rhodecode.model.scm import ScmModel
 

	
 
        try:
 
            if fork:
 
                repo_name = form_data['fork_name']
 
                org_name = form_data['repo_name']
 
                org_full_name = org_name
 
                fork_parent_id = form_data['fork_parent_id']
 

	
 
            else:
 
                org_name = repo_name = form_data['repo_name']
 
            # repo name is just a name of repository
 
            # while repo_name_full is a full qualified name that is combined
 
            # with name and path of group
 
            repo_name = form_data['repo_name']
 
                repo_name_full = form_data['repo_name_full']
 

	
 
            new_repo = Repository()
 
            new_repo.enable_statistics = False
 

	
 
            for k, v in form_data.items():
 
                if k == 'repo_name':
 
                    if fork:
 
                        v = repo_name
 
                    else:
 
                        v = repo_name_full
 
                if k == 'repo_group':
 
                    k = 'group_id'
 

	
 
                if k == 'description':
 
                    v = v or repo_name
 

	
 
                setattr(new_repo, k, v)
 

	
 
            if fork:
 
                parent_repo = self.sa.query(Repository)\
 
                        .filter(Repository.repo_name == org_full_name).one()
 
                parent_repo = Repository.get(fork_parent_id)
 
                new_repo.fork = parent_repo
 

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

	
 
            #create default permission
 
            repo_to_perm = UserRepoToPerm()
 
            default = 'repository.read'
 
            for p in User.get_by_username('default').user_perms:
 
                if p.permission.permission_name.startswith('repository.'):
 
                    default = p.permission.permission_name
 
                    break
 
@@ -262,37 +259,39 @@ class RepoModel(BaseModel):
 
                    .one().permission_id
 

	
 
            repo_to_perm.repository = new_repo
 
            repo_to_perm.user_id = User.get_by_username('default').user_id
 

	
 
            self.sa.add(repo_to_perm)
 

	
 
            if not just_db:
 
                self.__create_repo(repo_name, form_data['repo_type'],
 
                                   form_data['repo_group'],
 
                                   form_data['clone_uri'])
 

	
 
            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)
 
            return new_repo
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def create_fork(self, form_data, cur_user):
 
        """
 
        Simple wrapper into executing celery task for fork creation
 
        
 
        :param form_data:
 
        :param 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
 
@@ -316,24 +315,29 @@ class RepoModel(BaseModel):
 
                .filter(UsersGroupRepoToPerm.repository \
 
                        == self.get_by_repo_name(repo_name))\
 
                .filter(UsersGroupRepoToPerm.users_group_id
 
                        == form_data['users_group_id']).one()
 
            self.sa.delete(obj)
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def delete_stats(self, repo_name):
 
        """
 
        removes stats for given repo
 
        
 
        :param repo_name:
 
        """
 
        try:
 
            obj = self.sa.query(Statistics)\
 
                    .filter(Statistics.repository == \
 
                        self.get_by_repo_name(repo_name)).one()
 
            self.sa.delete(obj)
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
rhodecode/model/scm.py
Show inline comments
 
@@ -199,75 +199,67 @@ class ScmModel(BaseModel):
 
        :param repo_name: this repo that should invalidation take place
 
        """
 
        CacheInvalidation.set_invalidate(repo_name)
 
        CacheInvalidation.set_invalidate(repo_name + "_README")
 

	
 
    def toggle_following_repo(self, follow_repo_id, user_id):
 

	
 
        f = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.follows_repo_id == follow_repo_id)\
 
            .filter(UserFollowing.user_id == user_id).scalar()
 

	
 
        if f is not None:
 

	
 
            try:
 
                self.sa.delete(f)
 
                self.sa.commit()
 
                action_logger(UserTemp(user_id),
 
                              'stopped_following_repo',
 
                              RepoTemp(follow_repo_id))
 
                return
 
            except:
 
                log.error(traceback.format_exc())
 
                self.sa.rollback()
 
                raise
 

	
 
        try:
 
            f = UserFollowing()
 
            f.user_id = user_id
 
            f.follows_repo_id = follow_repo_id
 
            self.sa.add(f)
 
            self.sa.commit()
 

	
 
            action_logger(UserTemp(user_id),
 
                          'started_following_repo',
 
                          RepoTemp(follow_repo_id))
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def toggle_following_user(self, follow_user_id, user_id):
 
        f = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.follows_user_id == follow_user_id)\
 
            .filter(UserFollowing.user_id == user_id).scalar()
 

	
 
        if f is not None:
 
            try:
 
                self.sa.delete(f)
 
                self.sa.commit()
 
                return
 
            except:
 
                log.error(traceback.format_exc())
 
                self.sa.rollback()
 
                raise
 

	
 
        try:
 
            f = UserFollowing()
 
            f.user_id = user_id
 
            f.follows_user_id = follow_user_id
 
            self.sa.add(f)
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def is_following_repo(self, repo_name, user_id, cache=False):
 
        r = self.sa.query(Repository)\
 
            .filter(Repository.repo_name == repo_name).scalar()
 

	
 
        f = self.sa.query(UserFollowing)\
 
            .filter(UserFollowing.follows_repository == r)\
 
            .filter(UserFollowing.user_id == user_id).scalar()
 

	
 
        return f is not None
 

	
 
@@ -308,26 +300,26 @@ class ScmModel(BaseModel):
 
                      'repository': repo_name}
 

	
 
            #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)
 

	
 
            repo.pull(clone_uri)
 
            self.mark_for_invalidation(repo_name)
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def commit_change(self, repo, repo_name, cs, user, author, message, content,
 
                      f_path):
 
    def commit_change(self, repo, repo_name, cs, user, author, message,
 
                      content, f_path):
 

	
 
        if repo.alias == 'hg':
 
            from vcs.backends.hg import MercurialInMemoryChangeset as IMC
 
        elif repo.alias == 'git':
 
            from vcs.backends.git import GitInMemoryChangeset as IMC
 

	
 
        # decoding here will force that we have proper encoded values
 
        # in any other case this will throw exceptions and deny commit
 
        content = safe_str(content)
 
        message = safe_str(message)
 
        path = safe_str(f_path)
 
        author = safe_str(author)
rhodecode/public/css/style.css
Show inline comments
 
@@ -1781,32 +1781,36 @@ div.form div.fields div.field div.button
 
.journal_highlight {
 
	font-weight: bold;
 
	padding: 0 2px;
 
	vertical-align: bottom;
 
}
 
 
.trending_language_tbl,.trending_language_tbl td {
 
	border: 0 !important;
 
	margin: 0 !important;
 
	padding: 0 !important;
 
}
 
 
.trending_language_tbl,.trending_language_tbl tr {
 
    border-spacing: 1px;
 
}
 
 
.trending_language {
 
	background-color: #003367;
 
	color: #FFF;
 
	display: block;
 
	min-width: 20px;
 
	text-decoration: none;
 
	height: 12px;
 
	margin-bottom: 4px;
 
	margin-bottom: 0px;
 
	margin-left: 5px;
 
	white-space: pre;
 
	padding: 3px;
 
}
 
 
h3.files_location {
 
	font-size: 1.8em;
 
	font-weight: 700;
 
	border-bottom: none !important;
 
	margin: 10px 0 !important;
 
}
 
rhodecode/templates/forks/fork.html
Show inline comments
 
file renamed from rhodecode/templates/settings/repo_fork.html to rhodecode/templates/forks/fork.html
 
@@ -22,40 +22,57 @@
 
    <div class="title">
 
        ${self.breadcrumbs()}      
 
    </div>
 
    ${h.form(url('repo_fork_create_home',repo_name=c.repo_info.repo_name))}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
            <div class="field">
 
	            <div class="label">
 
	                <label for="repo_name">${_('Fork name')}:</label>
 
	            </div>
 
	            <div class="input">
 
	                ${h.text('fork_name',class_="small")}
 
                  ${h.text('repo_name',class_="small")}
 
	                ${h.hidden('repo_type',c.repo_info.repo_type)}
 
                  ${h.hidden('fork_parent_id',c.repo_info.repo_id)}
 
              </div>
 
            </div>
 
            <div class="field">
 
                 <div class="label">
 
                     <label for="repo_group">${_('Repository group')}:</label>
 
                 </div>
 
                 <div class="input">
 
                     ${h.select('repo_group','',c.repo_groups,class_="medium")}
 
	            </div>
 
             </div>
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="description">${_('Description')}:</label>
 
                </div>
 
                <div class="textarea text-area editor">
 
                    ${h.textarea('description',cols=23,rows=5)}
 
                </div>
 
             </div>
 
            <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="private">${_('Private')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
                    ${h.checkbox('private',value="True")}
 
                </div>
 
             </div>
 
            <div class="field">
 
                <div class="label label-checkbox">
 
                    <label for="private">${_('Copy permissions')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
                    ${h.checkbox('copy_permissions',value="True")}
 
                </div>
 
             </div>             
 
	        <div class="buttons">
 
	          ${h.submit('',_('fork this repository'),class_="ui-button")}
 
	        </div>                                                          
 
        </div>
 
    </div>    
 
    ${h.end_form()}    
 
</div>
 
</%def>   
0 comments (0 inline, 0 general)