diff --git a/rhodecode/config/routing.py b/rhodecode/config/routing.py --- a/rhodecode/config/routing.py +++ b/rhodecode/config/routing.py @@ -116,19 +116,21 @@ def make_map(config): #settings actions m.connect('repo_stats', "/repos_stats/{repo_name:.*}", - action="repo_stats", conditions=dict(method=["DELETE"], - function=check_repo)) + action="repo_stats", conditions=dict(method=["DELETE"], + function=check_repo)) m.connect('repo_cache', "/repos_cache/{repo_name:.*}", - action="repo_cache", conditions=dict(method=["DELETE"], + action="repo_cache", conditions=dict(method=["DELETE"], + function=check_repo)) + m.connect('repo_public_journal',"/repos_public_journal/{repo_name:.*}", + action="repo_public_journal", conditions=dict(method=["PUT"], function=check_repo)) - m.connect('repo_public_journal', - "/repos_public_journal/{repo_name:.*}", - action="repo_public_journal", conditions=dict(method=["PUT"], - function=check_repo)) m.connect('repo_pull', "/repo_pull/{repo_name:.*}", - action="repo_pull", conditions=dict(method=["PUT"], - function=check_repo)) - + action="repo_pull", conditions=dict(method=["PUT"], + function=check_repo)) + m.connect('repo_as_fork', "/repo_as_fork/{repo_name:.*}", + action="repo_as_fork", conditions=dict(method=["PUT"], + function=check_repo)) + with rmap.submapper(path_prefix=ADMIN_PREFIX, controller='admin/repos_groups') as m: m.connect("repos_groups", "/repos_groups", 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 @@ -111,6 +111,10 @@ class ReposController(BaseController): c.repo_last_rev) * 100) defaults = RepoModel()._get_defaults(repo_name) + + c.repos_list = [('', _('--REMOVE FORK--'))] + c.repos_list += [(x.repo_id, x.repo_name) for x in + Repository.query().order_by(Repository.repo_name).all()] return defaults @HasPermissionAllDecorator('hg.admin') @@ -380,6 +384,28 @@ class ReposController(BaseController): return redirect(url('edit_repo', repo_name=repo_name)) @HasPermissionAllDecorator('hg.admin') + def repo_as_fork(self, repo_name): + """ + Mark given repository as a fork of another + + :param repo_name: + """ + try: + fork_id = request.POST.get('id_fork_of') + repo = ScmModel().mark_as_fork(repo_name, fork_id, + self.rhodecode_user.username) + fork = repo.fork.repo_name if repo.fork else _('Nothing') + Session.commit() + h.flash(_('Marked repo %s as fork of %s' % (repo_name,fork)), + category='success') + except Exception, e: + raise + h.flash(_('An error occurred during this operation'), + category='error') + + return redirect(url('edit_repo', repo_name=repo_name)) + + @HasPermissionAllDecorator('hg.admin') def show(self, repo_name, format='html'): """GET /repos/repo_name: Show a specific item""" # url('repo', repo_name=ID) diff --git a/rhodecode/model/__init__.py b/rhodecode/model/__init__.py --- a/rhodecode/model/__init__.py +++ b/rhodecode/model/__init__.py @@ -89,5 +89,4 @@ class BaseModel(object): else: if instance: raise Exception('given object must be int or Instance' - ' of %s got %s' % (type(cls), - type(instance))) + ' of %s got %s' % (type(cls), type(instance))) diff --git a/rhodecode/model/scm.py b/rhodecode/model/scm.py --- a/rhodecode/model/scm.py +++ b/rhodecode/model/scm.py @@ -117,6 +117,18 @@ class ScmModel(BaseModel): Generic Scm Model """ + def __get_repo(self, instance): + cls = Repository + if isinstance(instance, cls): + return instance + elif isinstance(instance, int) or str(instance).isdigit(): + return cls.get(instance) + elif isinstance(instance, basestring): + return cls.get_by_repo_name(instance) + elif instance: + raise Exception('given object must be int, basestr or Instance' + ' of %s got %s' % (type(cls), type(instance))) + @LazyProperty def repos_path(self): """ @@ -279,6 +291,13 @@ class ScmModel(BaseModel): return self.sa.query(Repository)\ .filter(Repository.fork_id == repo_id).count() + def mark_as_fork(self, repo, fork, user): + repo = self.__get_repo(repo) + fork = self.__get_repo(fork) + repo.fork = fork + self.sa.add(repo) + return repo + def pull_changes(self, repo_name, username): dbrepo = Repository.get_by_repo_name(repo_name) clone_uri = dbrepo.clone_uri diff --git a/rhodecode/templates/admin/repos/repo_edit.html b/rhodecode/templates/admin/repos/repo_edit.html --- a/rhodecode/templates/admin/repos/repo_edit.html +++ b/rhodecode/templates/admin/repos/repo_edit.html @@ -131,14 +131,13 @@ ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')} <div class="form"> <div class="fields"> - ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="refresh_icon action_button",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")} - <div class="field" style="border:none"> + ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="ui-btn",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")} + <div class="field" style="border:none;color:#888"> <ul> <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li> <li>${_('Percentage of stats gathered')}: ${c.stats_percentage} %</li> </ul> </div> - </div> </div> ${h.end_form()} @@ -148,7 +147,7 @@ ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')} <div class="form"> <div class="fields"> - ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="pull_icon action_button",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")} + ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="ui-btn",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")} <div class="field" style="border:none"> <ul> <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li> @@ -163,7 +162,7 @@ ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')} <div class="form"> <div class="fields"> - ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="refresh_icon action_button",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")} + ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="ui-btn",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")} </div> </div> ${h.end_form()} @@ -171,14 +170,20 @@ <h3>${_('Public journal')}</h3> ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')} <div class="form"> - <div class="fields"> ${h.hidden('auth_token',str(h.get_token()))} + <div class="field"> %if c.in_public_journal: - ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="stop_following_icon action_button")} + ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="ui-btn")} %else: - ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="start_following_icon action_button")} + ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="ui-btn")} %endif - </div> + </div> + <div class="field" style="border:none;color:#888"> + <ul> + <li>${_('''All actions made on this repository will be accessible to everyone in public journal''')} + </li> + </ul> + </div> </div> ${h.end_form()} @@ -186,8 +191,30 @@ ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')} <div class="form"> <div class="fields"> - ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="delete_icon action_button",onclick="return confirm('"+_('Confirm to delete this repository')+"');")} + ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="ui-btn red",onclick="return confirm('"+_('Confirm to delete this repository')+"');")} </div> + <div class="field" style="border:none;color:#888"> + <ul> + <li>${_('''This repository will be renamed in a special way in order to be unaccesible for RhodeCode and VCS systems. + If you need fully delete it from filesystem please do it manually''')} + </li> + </ul> + </div> + </div> + ${h.end_form()} + + <h3>${_('Set as fork')}</h3> + ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')} + <div class="form"> + <div class="fields"> + ${h.select('id_fork_of','',c.repos_list,class_="medium")} + ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('set'),class_="ui-btn",)} + </div> + <div class="field" style="border:none;color:#888"> + <ul> + <li>${_('''Manually set this repository as a fork of another''')}</li> + </ul> + </div> </div> ${h.end_form()}