changeset 2602:17083006a33d beta

Added cleanup repos script that allows to cleanup removed repos from rhodecode older than given amount of time units.
author Marcin Kuzminski <marcin@python-works.com>
date Sat, 14 Jul 2012 18:53:39 +0200
parents aa90719e8520
children 370ed7829168
files rhodecode/lib/cleanup.py setup.py
diffstat 2 files changed, 144 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/lib/cleanup.py	Sat Jul 14 18:53:39 2012 +0200
@@ -0,0 +1,143 @@
+# -*- coding: utf-8 -*-
+"""
+    package.rhodecode.lib.cleanup
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    :created_on: Jul 14, 2012
+    :author: marcink
+    :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
+    :license: GPLv3, see COPYING for more details.
+"""
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+from __future__ import with_statement
+
+import os
+import sys
+import re
+import shutil
+import logging
+import datetime
+
+from os.path import dirname as dn, join as jn
+from rhodecode.model import init_model
+from rhodecode.lib.utils2 import engine_from_config
+from rhodecode.model.db import RhodeCodeUi
+
+
+#to get the rhodecode import
+sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
+
+from rhodecode.lib.utils import BasePasterCommand, Command, ask_ok,\
+    REMOVED_REPO_PAT, add_cache
+
+log = logging.getLogger(__name__)
+
+
+class CleanupCommand(BasePasterCommand):
+
+    max_args = 1
+    min_args = 1
+
+    usage = "CONFIG_FILE"
+    summary = "Cleanup deleted repos"
+    group_name = "RhodeCode"
+    takes_config_file = -1
+    parser = Command.standard_parser(verbose=True)
+
+    def _parse_older_than(self, val):
+        regex = re.compile(r'((?P<days>\d+?)d)?((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')
+        parts = regex.match(val)
+        if not parts:
+            return
+        parts = parts.groupdict()
+        time_params = {}
+        for (name, param) in parts.iteritems():
+            if param:
+                time_params[name] = int(param)
+        return datetime.timedelta(**time_params)
+
+    def _extract_date(self, name):
+        """
+        Extract the date part from rm__<date> pattern of removed repos,
+        and convert it to datetime object
+
+        :param name:
+        """
+        date_part = name[4:19]  # 4:19 since we don't parse milisecods
+        return datetime.datetime.strptime(date_part, '%Y%m%d_%H%M%S')
+
+    def command(self):
+        logging.config.fileConfig(self.path_to_ini_file)
+        from pylons import config
+
+        #get to remove repos !!
+        add_cache(config)
+        engine = engine_from_config(config, 'sqlalchemy.db1.')
+        init_model(engine)
+
+        repos_location = RhodeCodeUi.get_repos_location()
+        to_remove = []
+        for loc in os.listdir(repos_location):
+            if REMOVED_REPO_PAT.match(loc):
+                to_remove.append([loc, self._extract_date(loc)])
+
+        #filter older than (if present)!
+        now = datetime.datetime.now()
+        older_than = self.options.older_than
+        if older_than:
+            to_remove_filtered = []
+            older_than_date = self._parse_older_than(older_than)
+            for name, date_ in to_remove:
+                repo_age = now - date_
+                if repo_age > older_than_date:
+                    to_remove_filtered.append([name, date_])
+
+            to_remove = to_remove_filtered
+            print >> sys.stdout, 'removing [%s] deleted repos older than %s[%s]' \
+                % (len(to_remove), older_than, older_than_date)
+        else:
+            print >> sys.stdout, 'removing all [%s] deleted repos' \
+                % len(to_remove)
+        if self.options.dont_ask or not to_remove:
+            # don't ask just remove !
+            remove = True
+        else:
+            remove = ask_ok('are you sure to remove listed repos \n%s [y/n]?'
+                            % ', \n'.join(['%s removed on %s' % (x[0], x[1])
+                                           for x in to_remove]))
+
+        if remove:
+            for name, date_ in to_remove:
+                print >> sys.stdout, 'removing repository %s' % name
+                shutil.rmtree(os.path.join(repos_location, name))
+        else:
+            print 'nothing done exiting...'
+            sys.exit(0)
+
+    def update_parser(self):
+        self.parser.add_option('--older-than',
+                          action='store',
+                          dest='older_than',
+                          help=(
+                            "only remove repos that have been removed "
+                            "at least given time ago "
+                            "ex. --older-than=30d deletes repositores "
+                            "removed more than 30days ago. Possible options "
+                            "d[ays]/h[ours]/m[inutes]/s[seconds]. OPTIONAL"),
+                          )
+        self.parser.add_option('--dont-ask',
+                               action='store_true',
+                               dest='dont_ask',
+                               help=("Don't ask to remove repos"))
+        
\ No newline at end of file
--- a/setup.py	Sat Jul 14 13:03:34 2012 +0200
+++ b/setup.py	Sat Jul 14 18:53:39 2012 +0200
@@ -157,6 +157,7 @@
 
     [paste.global_paster_command]
     setup-rhodecode=rhodecode.config.setup_rhodecode:SetupCommand
+    cleanup-repos=rhodecode.lib.cleanup:CleanupCommand
     make-index=rhodecode.lib.indexers:MakeIndex
     make-rcext=rhodecode.config.rcextensions.make_rcextensions:MakeRcExt
     upgrade-db=rhodecode.lib.dbmigrate:UpgradeDb