diff --git a/rhodecode/apps/repository/views/repo_settings_advanced.py b/rhodecode/apps/repository/views/repo_settings_advanced.py --- a/rhodecode/apps/repository/views/repo_settings_advanced.py +++ b/rhodecode/apps/repository/views/repo_settings_advanced.py @@ -29,7 +29,7 @@ from rhodecode.lib import audit_logger from rhodecode.lib.auth import ( LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired, HasRepoPermissionAny) -from rhodecode.lib.exceptions import AttachedForksError +from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError from rhodecode.lib.utils2 import safe_int from rhodecode.lib.vcs import RepositoryError from rhodecode.model.db import Session, UserFollowing, User, Repository @@ -80,22 +80,23 @@ class RepoSettingsView(RepoAppView): """ _ = self.request.translate handle_forks = self.request.POST.get('forks', None) + if handle_forks == 'detach_forks': + handle_forks = 'detach' + elif handle_forks == 'delete_forks': + handle_forks = 'delete' try: + old_data = self.db_repo.get_api_data() + RepoModel().delete(self.db_repo, forks=handle_forks) + _forks = self.db_repo.forks.count() if _forks and handle_forks: if handle_forks == 'detach_forks': - handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif handle_forks == 'delete_forks': - handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') - old_data = self.db_repo.get_api_data() - RepoModel().delete(self.db_repo, forks=handle_forks) - - repo = audit_logger.RepoWrap(repo_id=None, - repo_name=self.db_repo.repo_name) + repo = audit_logger.RepoWrap(repo_id=None, repo_name=self.db_repo.repo_name) audit_logger.store_web( 'repo.delete', action_data={'old_data': old_data}, user=self._rhodecode_user, repo=repo) @@ -118,6 +119,20 @@ class RepoSettingsView(RepoAppView): # redirect to advanced for forks handle action ? raise HTTPFound(repo_advanced_url) + except AttachedPullRequestsError: + repo_advanced_url = h.route_path( + 'edit_repo_advanced', repo_name=self.db_repo_name, + _anchor='advanced-delete') + attached_prs = len(self.db_repo.pull_requests_source + + self.db_repo.pull_requests_target) + h.flash( + _('Cannot delete `{repo}` it still contains {num} attached pull requests. ' + 'Consider archiving the repository instead.').format( + repo=self.db_repo_name, num=attached_prs), category='warning') + + # redirect to advanced for forks handle action ? + raise HTTPFound(repo_advanced_url) + except Exception: log.exception("Exception during deletion of repository") h.flash(_('An error occurred during deletion of `%s`') diff --git a/rhodecode/lib/exceptions.py b/rhodecode/lib/exceptions.py --- a/rhodecode/lib/exceptions.py +++ b/rhodecode/lib/exceptions.py @@ -70,6 +70,10 @@ class AttachedForksError(Exception): pass +class AttachedPullRequestsError(Exception): + pass + + class RepoGroupAssignmentError(Exception): pass diff --git a/rhodecode/model/repo.py b/rhodecode/model/repo.py --- a/rhodecode/model/repo.py +++ b/rhodecode/model/repo.py @@ -32,7 +32,7 @@ from zope.cachedescriptors.property impo from rhodecode import events from rhodecode.lib.auth import HasUserGroupPermissionAny from rhodecode.lib.caching_query import FromCache -from rhodecode.lib.exceptions import AttachedForksError +from rhodecode.lib.exceptions import AttachedForksError, AttachedPullRequestsError from rhodecode.lib.hooks_base import log_delete_repository from rhodecode.lib.user_log_filter import user_log_filter from rhodecode.lib.utils import make_db_config @@ -608,7 +608,7 @@ class RepoModel(BaseModel): from rhodecode.lib.celerylib import tasks, run_task return run_task(tasks.create_repo_fork, form_data, cur_user) - def delete(self, repo, forks=None, fs_remove=True, cur_user=None): + def delete(self, repo, forks=None, pull_requests=None, fs_remove=True, cur_user=None): """ Delete given repository, forks parameter defines what do do with attached forks. Throws AttachedForksError if deleted repo has attached @@ -632,6 +632,12 @@ class RepoModel(BaseModel): elif [f for f in repo.forks]: raise AttachedForksError() + # check for pull requests + pr_sources = repo.pull_requests_source + pr_targets = repo.pull_requests_target + if pull_requests != 'delete' and (pr_sources or pr_targets): + raise AttachedPullRequestsError() + old_repo_dict = repo.get_dict() events.trigger(events.RepoPreDeleteEvent(repo)) try: diff --git a/rhodecode/templates/admin/repos/repo_edit_advanced.mako b/rhodecode/templates/admin/repos/repo_edit_advanced.mako --- a/rhodecode/templates/admin/repos/repo_edit_advanced.mako +++ b/rhodecode/templates/admin/repos/repo_edit_advanced.mako @@ -7,6 +7,8 @@ (_('Updated on'), h.format_date(c.rhodecode_db_repo.updated_on), '', ''), (_('Cached Commit id'), lambda: h.link_to(c.rhodecode_db_repo.changeset_cache.get('short_id'), h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.rhodecode_db_repo.changeset_cache.get('raw_id'))), '', ''), (_('Attached scoped tokens'), len(c.rhodecode_db_repo.scoped_tokens), '', [x.user for x in c.rhodecode_db_repo.scoped_tokens]), + (_('Pull requests source'), len(c.rhodecode_db_repo.pull_requests_source), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.source_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_source]), + (_('Pull requests target'), len(c.rhodecode_db_repo.pull_requests_target), '', ['pr_id:{}, repo:{}'.format(x.pull_request_id,x.target_repo.repo_name) for x in c.rhodecode_db_repo.pull_requests_target]), ] %> @@ -131,6 +133,18 @@ %endif + <% attached_prs = len(c.rhodecode_db_repo.pull_requests_source + c.rhodecode_db_repo.pull_requests_target) %> + % if c.rhodecode_db_repo.pull_requests_source or c.rhodecode_db_repo.pull_requests_target: + + + ${_ungettext('This repository has %s attached pull request.', 'This repository has %s attached pull requests.', attached_prs) % attached_prs} +
+ ${_('Consider to archive this repository instead.')} + + + + + % endif
diff --git a/rhodecode/tests/fixture.py b/rhodecode/tests/fixture.py --- a/rhodecode/tests/fixture.py +++ b/rhodecode/tests/fixture.py @@ -226,7 +226,7 @@ class Fixture(object): return r def destroy_repo(self, repo_name, **kwargs): - RepoModel().delete(repo_name, **kwargs) + RepoModel().delete(repo_name, pull_requests='delete', **kwargs) Session().commit() def destroy_repo_on_filesystem(self, repo_name):