diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py
--- a/rhodecode/config/routing.py
+++ b/rhodecode/config/routing.py
@@ -465,19 +465,20 @@ def make_map(config):
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
diff --git a/rhodecode/controllers/admin/repos.py b/rhodecode/controllers/admin/repos.py
--- a/rhodecode/controllers/admin/repos.py
+++ b/rhodecode/controllers/admin/repos.py
@@ -29,9 +29,10 @@ 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, \
@@ -39,11 +40,11 @@ from rhodecode.lib.auth import LoginRequ
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__)
@@ -65,7 +66,7 @@ class ReposController(BaseController):
def __load_defaults(self):
c.repo_groups = RepoGroup.groups_choices()
c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
-
+
repo_model = RepoModel()
c.users_array = repo_model.get_users_js()
c.users_groups_array = repo_model.get_users_groups_js()
@@ -127,13 +128,13 @@ class ReposController(BaseController):
"""
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']),
@@ -143,13 +144,13 @@ class ReposController(BaseController):
category='success')
if request.POST.get('user_created'):
- #created by regular non admin user
+ # 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']
@@ -207,7 +208,7 @@ class ReposController(BaseController):
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)
@@ -251,7 +252,7 @@ class ReposController(BaseController):
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())
diff --git a/rhodecode/controllers/forks.py b/rhodecode/controllers/forks.py
--- a/rhodecode/controllers/forks.py
+++ b/rhodecode/controllers/forks.py
@@ -23,13 +23,23 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
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__)
@@ -37,11 +47,59 @@ 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
@@ -54,3 +112,63 @@ class ForksController(BaseRepoController
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'))
diff --git a/rhodecode/controllers/journal.py b/rhodecode/controllers/journal.py
--- a/rhodecode/controllers/journal.py
+++ b/rhodecode/controllers/journal.py
@@ -23,21 +23,22 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
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__)
@@ -124,6 +125,7 @@ class JournalController(BaseController):
try:
self.scm_model.toggle_following_user(user_id,
self.rhodecode_user.user_id)
+ Session().commit()
return 'ok'
except:
raise HTTPBadRequest()
@@ -133,6 +135,7 @@ class JournalController(BaseController):
try:
self.scm_model.toggle_following_repo(repo_id,
self.rhodecode_user.user_id)
+ Session().commit()
return 'ok'
except:
raise HTTPBadRequest()
diff --git a/rhodecode/controllers/settings.py b/rhodecode/controllers/settings.py
--- a/rhodecode/controllers/settings.py
+++ b/rhodecode/controllers/settings.py
@@ -35,14 +35,14 @@ 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__)
@@ -52,15 +52,15 @@ class SettingsController(BaseRepoControl
@LoginRequired()
def __before__(self):
super(SettingsController, 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)
-
+
repo_model = RepoModel()
c.users_array = repo_model.get_users_js()
c.users_groups_array = repo_model.get_users_groups_js()
-
+
@HasRepoPermissionAllDecorator('repository.admin')
def index(self, repo_name):
repo_model = RepoModel()
@@ -89,15 +89,15 @@ class SettingsController(BaseRepoControl
def update(self, repo_name):
repo_model = RepoModel()
changed_name = repo_name
-
+
self.__load_defaults()
-
+
_form = RepoSettingsForm(edit=True,
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),
@@ -105,6 +105,7 @@ class SettingsController(BaseRepoControl
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()
@@ -148,61 +149,10 @@ class SettingsController(BaseRepoControl
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'))
diff --git a/rhodecode/lib/celerylib/tasks.py b/rhodecode/lib/celerylib/tasks.py
--- a/rhodecode/lib/celerylib/tasks.py
+++ b/rhodecode/lib/celerylib/tasks.py
@@ -37,29 +37,28 @@ 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'))
@@ -81,17 +80,13 @@ def get_logger(cls):
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())\
@@ -111,13 +106,12 @@ def get_commits_stats(repo_name, ts_min_
sa = get_session()
lock = l = DaemonLock(file_=jn(lockkey_path, lockkey))
- #for js data compatibilty cleans the key for person from '
+ # 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:
@@ -139,9 +133,9 @@ def get_commits_stats(repo_name, ts_min_
last_rev = cur_stats.stat_on_revision
if last_rev == repo.get_changeset().revision and repo_size > 1:
- #pass silently without any work if we're not on first revision or
- #current state of parsing revision(from db marker) is the
- #last revision
+ # pass silently without any work if we're not on first revision or
+ # current state of parsing revision(from db marker) is the
+ # last revision
lock.release()
return True
@@ -255,10 +249,11 @@ def get_commits_stats(repo_name, ts_min_
@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:
@@ -283,9 +278,9 @@ def send_password_link(user_email):
@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:
@@ -361,27 +356,39 @@ def send_email(recipients, subject, body
@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 = {}
diff --git a/rhodecode/lib/hooks.py b/rhodecode/lib/hooks.py
--- a/rhodecode/lib/hooks.py
+++ b/rhodecode/lib/hooks.py
@@ -33,7 +33,8 @@ from rhodecode.lib.utils import action_l
def repo_size(ui, repo, hooktype=None, **kwargs):
- """Presents size of repository after push
+ """
+ Presents size of repository after push
:param ui:
:param repo:
@@ -65,7 +66,8 @@ def repo_size(ui, repo, hooktype=None, *
def log_pull_action(ui, repo, **kwargs):
- """Logs user last pull action
+ """
+ Logs user last pull action
:param ui:
:param repo:
@@ -76,13 +78,15 @@ def log_pull_action(ui, repo, **kwargs):
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:
@@ -110,6 +114,7 @@ def log_push_action(ui, repo, **kwargs):
action = action % ','.join(revs)
- action_logger(username, action, repository, extra_params['ip'])
+ action_logger(username, action, repository, extra_params['ip'],
+ commit=True)
return 0
diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py
--- a/rhodecode/lib/utils.py
+++ b/rhodecode/lib/utils.py
@@ -93,7 +93,7 @@ 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
@@ -138,12 +138,13 @@ def action_logger(user, action, repo, ip
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):
diff --git a/rhodecode/model/forms.py b/rhodecode/model/forms.py
--- a/rhodecode/model/forms.py
+++ b/rhodecode/model/forms.py
@@ -185,7 +185,7 @@ class ValidPassword(formencode.validator
class ValidPasswordsMatch(formencode.validators.FancyValidator):
def validate_python(self, value, state):
-
+
pass_val = value.get('password') or value.get('new_password')
if pass_val != value['password_confirmation']:
e_dict = {'password_confirmation':
@@ -198,7 +198,7 @@ class ValidAuth(formencode.validators.Fa
'invalid_login':_('invalid user name'),
'disabled_account':_('Your account is disabled')
}
-
+
# error mapping
e_dict = {'username':messages['invalid_login'],
'password':messages['invalid_password']}
@@ -208,7 +208,7 @@ class ValidAuth(formencode.validators.Fa
password = value['password']
username = value['username']
user = User.get_by_username(username)
-
+
if authenticate(username, password):
return value
else:
@@ -254,7 +254,7 @@ def ValidRepoName(edit, old_data):
# db key This is an actual just the name to store in the
# database
repo_name_full = group_path + RepoGroup.url_sep() + repo_name
-
+
else:
group_path = ''
repo_name_full = repo_name
@@ -289,24 +289,8 @@ def ValidRepoName(edit, old_data):
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():
@@ -513,7 +497,7 @@ def UserForm(edit=False, old_data={}):
else:
password = All(UnicodeString(strip=True, min=6, not_empty=True))
password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False))
-
+
active = StringBoolean(if_missing=False)
name = UnicodeString(strip=True, min=1, not_empty=True)
lastname = UnicodeString(strip=True, min=1, not_empty=True)
@@ -605,17 +589,20 @@ def RepoForm(edit=False, old_data={}, su
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
@@ -630,7 +617,7 @@ def RepoSettingsForm(edit=False, old_dat
repo_group = OneOf(repo_groups, hideList=True)
private = StringBoolean(if_missing=False)
- chained_validators = [ValidRepoName(edit, old_data), ValidPerms,
+ chained_validators = [ValidRepoName(edit, old_data), ValidPerms,
ValidSettings]
return _RepoForm
diff --git a/rhodecode/model/notification.py b/rhodecode/model/notification.py
--- a/rhodecode/model/notification.py
+++ b/rhodecode/model/notification.py
@@ -35,8 +35,6 @@ 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__)
@@ -74,6 +72,7 @@ class NotificationModel(BaseModel):
: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')
@@ -100,7 +99,7 @@ class NotificationModel(BaseModel):
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
diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py
--- a/rhodecode/model/repo.py
+++ b/rhodecode/model/repo.py
@@ -212,36 +212,33 @@ class RepoModel(BaseModel):
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_full = form_data['repo_name_full']
+ # 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
+ 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
@@ -271,19 +268,21 @@ class RepoModel(BaseModel):
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
+ # now automatically start following this repository as owner
ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
- cur_user.user_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)
@@ -325,6 +324,11 @@ class RepoModel(BaseModel):
raise
def delete_stats(self, repo_name):
+ """
+ removes stats for given repo
+
+ :param repo_name:
+ """
try:
obj = self.sa.query(Statistics)\
.filter(Statistics.repository == \
diff --git a/rhodecode/model/scm.py b/rhodecode/model/scm.py
--- a/rhodecode/model/scm.py
+++ b/rhodecode/model/scm.py
@@ -208,17 +208,14 @@ class ScmModel(BaseModel):
.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:
@@ -226,13 +223,12 @@ class ScmModel(BaseModel):
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):
@@ -243,11 +239,9 @@ class ScmModel(BaseModel):
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:
@@ -255,10 +249,8 @@ class ScmModel(BaseModel):
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):
@@ -317,8 +309,8 @@ class ScmModel(BaseModel):
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
diff --git a/rhodecode/public/css/style.css b/rhodecode/public/css/style.css
--- a/rhodecode/public/css/style.css
+++ b/rhodecode/public/css/style.css
@@ -1790,6 +1790,10 @@ div.form div.fields div.field div.button
padding: 0 !important;
}
+.trending_language_tbl,.trending_language_tbl tr {
+ border-spacing: 1px;
+}
+
.trending_language {
background-color: #003367;
color: #FFF;
@@ -1797,7 +1801,7 @@ div.form div.fields div.field div.button
min-width: 20px;
text-decoration: none;
height: 12px;
- margin-bottom: 4px;
+ margin-bottom: 0px;
margin-left: 5px;
white-space: pre;
padding: 3px;
diff --git a/rhodecode/templates/settings/repo_fork.html b/rhodecode/templates/forks/fork.html
rename from rhodecode/templates/settings/repo_fork.html
rename to rhodecode/templates/forks/fork.html
--- a/rhodecode/templates/settings/repo_fork.html
+++ b/rhodecode/templates/forks/fork.html
@@ -27,14 +27,23 @@
-
-
-
-
- ${h.text('fork_name',class_="small")}
- ${h.hidden('repo_type',c.repo_info.repo_type)}
-
-
+
+
+
+
+ ${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)}
+
+
+
+
+
+
+
+ ${h.select('repo_group','',c.repo_groups,class_="medium")}
+
+
@@ -50,7 +59,15 @@
${h.checkbox('private',value="True")}
-
+
+
+
+
+
+
+ ${h.checkbox('copy_permissions',value="True")}
+
+
${h.submit('',_('fork this repository'),class_="ui-button")}