changeset 3641:b44979649915 beta

recursive forks detach - added API attrs for option to delete or detach forks - deleting repos with attached forks raises an special Exception
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 31 Mar 2013 16:18:09 +0200
parents 4f80df0d45c8
children 749dfd6b6e95
files docs/api/api.rst rhodecode/controllers/admin/repos.py rhodecode/controllers/api/api.py rhodecode/lib/exceptions.py rhodecode/model/repo.py
diffstat 5 files changed, 58 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/docs/api/api.rst	Sat Mar 30 16:17:56 2013 +0100
+++ b/docs/api/api.rst	Sun Mar 31 16:18:09 2013 +0200
@@ -848,8 +848,10 @@
 delete_repo
 -----------
 
-Deletes a repository. This command can be executed only using api_key belonging to user with admin
-rights or regular user that have admin access to repository.
+Deletes a repository. This command can be executed only using api_key belonging
+to user with admin rights or regular user that have admin access to repository.
+When `forks` param is set it's possible to detach or delete forks of deleting
+repository
 
 
 INPUT::
@@ -858,7 +860,8 @@
     api_key : "<api_key>"
     method :  "delete_repo"
     args:     {
-                "repoid" : "<reponame or repo_id>"
+                "repoid" : "<reponame or repo_id>",
+                "forks"  : "`delete` or `detach` = Optional(None)"
               }
 
 OUTPUT::
--- a/rhodecode/controllers/admin/repos.py	Sat Mar 30 16:17:56 2013 +0100
+++ b/rhodecode/controllers/admin/repos.py	Sun Mar 31 16:18:09 2013 +0200
@@ -50,6 +50,7 @@
 from rhodecode.model.repo import RepoModel
 from rhodecode.lib.compat import json
 from sqlalchemy.sql.expression import func
+from rhodecode.lib.exceptions import AttachedForksError
 
 log = logging.getLogger(__name__)
 
@@ -302,38 +303,26 @@
             return redirect(url('repos'))
         try:
             _forks = repo.forks.count()
+            handle_forks = None
             if _forks and request.POST.get('forks'):
                 do = request.POST['forks']
                 if do == 'detach_forks':
-                    for r in repo.forks:
-                        log.debug('Detaching fork %s from repo %s' % (r, repo))
-                        r.fork = None
-                        Session().add(r)
+                    handle_forks = 'detach'
                     h.flash(_('Detached %s forks') % _forks, category='success')
                 elif do == 'delete_forks':
-                    for r in repo.forks:
-                        log.debug('Deleting fork %s of repo %s' % (r, repo))
-                        repo_model.delete(r)
+                    handle_forks = 'delete'
                     h.flash(_('Deleted %s forks') % _forks, category='success')
+            repo_model.delete(repo, forks=handle_forks)
             action_logger(self.rhodecode_user, 'admin_deleted_repo',
-                              repo_name, self.ip_addr, self.sa)
-            repo_model.delete(repo)
+                  repo_name, self.ip_addr, self.sa)
             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') != -1:
-                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')
+        except AttachedForksError:
+            h.flash(_('Cannot delete %s it still contains attached forks')
+                        % repo_name, category='warning')
 
-        except Exception, e:
+        except Exception:
             log.error(traceback.format_exc())
             h.flash(_('An error occurred during deletion of %s') % repo_name,
                     category='error')
--- a/rhodecode/controllers/api/api.py	Sat Mar 30 16:17:56 2013 +0100
+++ b/rhodecode/controllers/api/api.py	Sun Mar 31 16:18:09 2013 +0200
@@ -853,12 +853,13 @@
                                                             fork_name)
             )
 
-    def delete_repo(self, apiuser, repoid):
+    def delete_repo(self, apiuser, repoid, forks=Optional(None)):
         """
         Deletes a given repository
 
         :param apiuser:
         :param repoid:
+        :param forks: detach or delete, what do do with attached forks for repo
         """
         repo = get_repo_or_error(repoid)
 
@@ -866,13 +867,26 @@
             # check if we have admin permission for this repo !
             if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
                                             repo_name=repo.repo_name) is False:
-                 raise JSONRPCError('repository `%s` does not exist' % (repoid))
+                raise JSONRPCError('repository `%s` does not exist' % (repoid))
 
         try:
-            RepoModel().delete(repo)
+            handle_forks = Optional.extract(forks)
+            _forks_msg = ''
+            _forks = [f for f in repo.forks]
+            if handle_forks == 'detach':
+                _forks_msg = ' ' + _('Detached %s forks') % len(_forks)
+            elif handle_forks == 'delete':
+                _forks_msg = ' ' + _('Deleted %s forks') % len(_forks)
+            elif _forks:
+                raise JSONRPCError(
+                    'Cannot delete `%s` it still contains attached forks'
+                    % repo.repo_name
+                )
+
+            RepoModel().delete(repo, forks=forks)
             Session().commit()
             return dict(
-                msg='Deleted repository `%s`' % repo.repo_name,
+                msg='Deleted repository `%s`%s' % (repo.repo_name, _forks_msg),
                 success=True
             )
         except Exception:
--- a/rhodecode/lib/exceptions.py	Sat Mar 30 16:17:56 2013 +0100
+++ b/rhodecode/lib/exceptions.py	Sun Mar 31 16:18:09 2013 +0200
@@ -58,6 +58,10 @@
     pass
 
 
+class AttachedForksError(Exception):
+    pass
+
+
 class HTTPLockedRC(HTTPClientError):
     """
     Special Exception For locked Repos in RhodeCode, the return code can
--- a/rhodecode/model/repo.py	Sat Mar 30 16:17:56 2013 +0100
+++ b/rhodecode/model/repo.py	Sun Mar 31 16:18:09 2013 +0200
@@ -42,6 +42,7 @@
     RhodeCodeSetting, RepositoryField
 from rhodecode.lib import helpers as h
 from rhodecode.lib.auth import HasRepoPermissionAny
+from rhodecode.lib.exceptions import AttachedForksError
 
 log = logging.getLogger(__name__)
 
@@ -465,9 +466,27 @@
         from rhodecode.lib.celerylib import tasks, run_task
         run_task(tasks.create_repo_fork, form_data, cur_user)
 
-    def delete(self, repo):
+    def delete(self, repo, forks=None):
+        """
+        Delete given repository, forks parameter defines what do do with
+        attached forks. Throws AttachedForksError if deleted repo has attached
+        forks
+
+        :param repo:
+        :param forks: str 'delete' or 'detach'
+        """
         repo = self._get_repo(repo)
         if repo:
+            if forks == 'detach':
+                for r in repo.forks:
+                    r.fork = None
+                    self.sa.add(r)
+            elif forks == 'delete':
+                for r in repo.forks:
+                    self.delete(r, forks='delete')
+            elif [f for f in repo.forks]:
+                raise AttachedForksError()
+
             old_repo_dict = repo.get_dict()
             owner = repo.user
             try: