@@ -39,18 +39,17 @@ 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, repo_name_slug
from rhodecode.lib.helpers import get_token
from rhodecode.model.db import User, Repository, UserFollowing
from rhodecode.model.db import User, Repository, UserFollowing, Group
from rhodecode.model.forms import RepoForm
from rhodecode.model.scm import ScmModel
from rhodecode.model.repo import RepoModel
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
@@ -61,12 +60,88 @@ class ReposController(BaseController):
@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__()
def __load_data(self, repo_name):
Load defaults settings for edit, and update
:param repo_name:
repo, dbrepo = ScmModel().get(repo_name, retval='repo')
repo_model = RepoModel()
c.repo_info = repo_model.get_by_repo_name(repo_name)
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.repo_groups = [('', '')]
c.repo_groups.extend([(x.group_id, x.group_name) for x in self.sa.query(Group).all()])
c.default_user_id = User.by_username('default').user_id
c.in_public_journal = self.sa.query(UserFollowing)\
.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
c.stats_percentage = '%.2f' % ((float((last_rev)) /
c.repo_last_rev) * 100)
c.users_array = repo_model.get_users_js()
c.users_groups_array = repo_model.get_users_groups_js()
defaults = c.repo_info.get_dict()
group, repo_name = c.repo_info.groups_and_repo
defaults['repo_name'] = repo_name
defaults['repo_group'] = getattr(group, 'group_id', None)
#fill owner
if c.repo_info.user:
defaults.update({'user':c.repo_info.user.username})
replacement_user = self.sa.query(User)\
.filter(User.admin == True).first().username
defaults.update({'user':replacement_user})
#fill repository users
for p in c.repo_info.repo_to_perm:
defaults.update({'u_perm_%s' % p.user.username:
p.permission.permission_name})
#fill repository groups
for p in c.repo_info.users_group_to_perm:
defaults.update({'g_perm_%s' % p.users_group.users_group_name:
return defaults
@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'))
@@ -75,29 +150,38 @@ class ReposController(BaseController):
def create(self):
POST /repos: Create a new item"""
_form = RepoForm()()
form_result = {}
try:
form_result = _form.to_python(dict(request.POST))
form_result = RepoForm()(repo_groups=c.repo_groups).to_python(dict(request.POST))
repo_model.create(form_result, c.rhodecode_user)
h.flash(_('created repository %s') % form_result['repo_name'],
if form_result['clone_uri']:
h.flash(_('created repository %s from %s') \
% (form_result['repo_name'], form_result['clone_uri']),
category='success')
if request.POST.get('user_created'):
action_logger(self.rhodecode_user, 'user_created_repo',
form_result['repo_name'], '', self.sa)
action_logger(self.rhodecode_user, 'admin_created_repo',
except formencode.Invalid, errors:
c.new_repo = errors.value['repo_name']
r = render('admin/repos/repo_add_create_repository.html')
r = render('admin/repos/repo_add.html')
@@ -119,13 +203,14 @@ class ReposController(BaseController):
def new(self, format='html'):
"""GET /repos/new: Form to create a new item"""
new_repo = request.GET.get('repo', '')
c.new_repo = repo_name_slug(new_repo)
return render('admin/repos/repo_add.html')
def update(self, repo_name):
PUT /repos/repo_name: Update an existing item"""
@@ -135,61 +220,36 @@ class ReposController(BaseController):
# h.form(url('repo', repo_name=ID),
# method='put')
# url('repo', repo_name=ID)
changed_name = repo_name
_form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
repo_model.update(repo_name, form_result)
invalidate_cache('get_repo_cached_%s' % repo_name)
h.flash(_('Repository %s updated successfully' % repo_name),
changed_name = form_result['repo_name']
action_logger(self.rhodecode_user, 'admin_updated_repo',
changed_name, '', self.sa)
if last_rev == 0:
errors.value.update({'user':c.repo_info.user.username})
defaults = self.__load_data(repo_name)
defaults.update(errors.value)
return htmlfill.render(
render('admin/repos/repo_edit.html'),
defaults=errors.value,
defaults=defaults,
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))
def delete(self, repo_name):
DELETE /repos/repo_name: Delete an existing item"""
@@ -322,68 +382,13 @@ class ReposController(BaseController):
def edit(self, repo_name, format='html'):
"""GET /repos/repo_name/edit: Form to edit an existing item"""
# url('edit_repo', repo_name=ID)
encoding="UTF-8",
force_defaults=False
@@ -39,13 +39,13 @@ from rhodecode.lib import helpers as h
HasPermissionAnyDecorator, NotAnonymous
from rhodecode.lib.celerylib import tasks, run_task
from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
set_rhodecode_config, repo_name_slug
from rhodecode.model.db import RhodeCodeUi, Repository
from rhodecode.model.db import RhodeCodeUi, Repository, Group
from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
ApplicationUiSettingsForm
from rhodecode.model.settings import SettingsModel
from rhodecode.model.user import UserModel
@@ -318,13 +318,14 @@ class SettingsController(BaseController)
@NotAnonymous()
def create_repository(self):
"""GET /_admin/create_repository: Form to create a new item"""
return render('admin/repos/repo_add_create_repository.html')
def get_hg_ui_settings(self):
ret = self.sa.query(RhodeCodeUi).all()
if not ret:
@@ -447,23 +447,27 @@ def PasswordResetForm():
class _PasswordResetForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
email = All(ValidSystemEmail(), Email(not_empty=True))
return _PasswordResetForm
def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys()):
def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
repo_groups=[]):
class _RepoForm(formencode.Schema):
filter_extra_fields = False
repo_name = All(UnicodeString(strip=True, min=1, not_empty=True),
ValidRepoName(edit, old_data))
clone_uri = UnicodeString(strip=True, min=1, not_empty=False)
repo_group = OneOf(repo_groups)
repo_type = OneOf(supported_backends)
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(Int(not_empty=True), ValidRepoUser)
chained_validators = [ValidPerms]
return _RepoForm
@@ -231,13 +231,14 @@ class RepoModel(BaseModel):
repo_to_perm.user_id = UserModel(self.sa)\
.get_by_username('default', cache=False).user_id
self.sa.add(repo_to_perm)
if not just_db:
self.__create_repo(repo_name, form_data['repo_type'])
self.__create_repo(repo_name, form_data['repo_type'],
form_data['clone_uri'])
self.sa.commit()
#now automatically start following this repository as owner
ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
@@ -296,24 +297,25 @@ class RepoModel(BaseModel):
except:
self.sa.rollback()
raise
def __create_repo(self, repo_name, alias):
def __create_repo(self, repo_name, alias, clone_uri=False):
makes repository on filesystem
:param alias:
from rhodecode.lib.utils import check_repo
repo_path = os.path.join(self.repos_path, repo_name)
if check_repo(repo_name, self.repos_path):
log.info('creating repo %s in %s', repo_name, repo_path)
log.info('creating repo %s in %s @ %s', repo_name, repo_path,
clone_uri)
backend = get_backend(alias)
backend(repo_path, create=True)
backend(repo_path, create=True, src_url=clone_uri)
def __rename_repo(self, old, new):
renames repository on filesystem
:param old: old name
:param new: new name
@@ -11,18 +11,27 @@ ${h.form(url('repos'))}
<div class="input">
${h.text('repo_name',c.new_repo,class_="small")}
</div>
<div class="field">
<div class="label">
<label for="repo_name">${_('Clone from')}:</label>
<label for="clone_uri">${_('Clone from')}:</label>
${h.text('clone_uri',c.new_repo,class_="small")}
${h.text('clone_uri',class_="small")}
<label for="repo_group">${_('Repository group')}:</label>
${h.select('repo_group','',c.repo_groups,class_="medium")}
<span>${h.link_to(_('add new group'),h.url(''))}</span>
<label for="repo_type">${_('Type')}:</label>
${h.select('repo_type','hg',c.backends,class_="small")}
@@ -31,21 +31,38 @@
<label for="repo_name">${_('Name')}:</label>
${h.text('repo_name',class_="medium")}
<label for="clone_uri">${_('Clone uri')}:</label>
${h.select('repo_type','hg',c.backends,class_="medium")}
<div class="label label-textarea">
<label for="description">${_('Description')}:</label>
<div class="textarea text-area editor">
${h.textarea('description',cols=23,rows=5)}
@@ -62,13 +62,23 @@
<img class="icon" alt="${_('public')}"
title="${_('Fork of')} ${c.dbrepo.fork.repo_name}"
src="${h.url("/images/icons/arrow_divide.png")}"/>
${_('Fork of')} ${c.dbrepo.fork.repo_name}
</a>
</span>
%endif
%if c.dbrepo.clone_uri:
<span style="margin-top:5px">
<a href="${h.url(str(c.dbrepo.clone_uri))}">
<img class="icon" alt="${_('remote clone')}"
title="${_('Clone from')} ${c.dbrepo.clone_uri}"
src="${h.url("/images/icons/connect.png")}"/>
${_('Clone from')} ${c.dbrepo.clone_uri}
Status change: