##// END OF EJS Templates
fix unicode issues on cleanup-repos script
marcink -
r2925:381eea23 beta
parent child Browse files
Show More
@@ -1,142 +1,142 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 package.rhodecode.lib.cleanup
3 package.rhodecode.lib.cleanup
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 :created_on: Jul 14, 2012
6 :created_on: Jul 14, 2012
7 :author: marcink
7 :author: marcink
8 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
8 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
9 :license: GPLv3, see COPYING for more details.
9 :license: GPLv3, see COPYING for more details.
10 """
10 """
11 # This program is free software: you can redistribute it and/or modify
11 # This program is free software: you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation, either version 3 of the License, or
13 # the Free Software Foundation, either version 3 of the License, or
14 # (at your option) any later version.
14 # (at your option) any later version.
15 #
15 #
16 # This program is distributed in the hope that it will be useful,
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
19 # GNU General Public License for more details.
20 #
20 #
21 # You should have received a copy of the GNU General Public License
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 from __future__ import with_statement
23 from __future__ import with_statement
24
24
25 import os
25 import os
26 import sys
26 import sys
27 import re
27 import re
28 import shutil
28 import shutil
29 import logging
29 import logging
30 import datetime
30 import datetime
31
31
32 from os.path import dirname as dn, join as jn
32 from os.path import dirname as dn, join as jn
33 from rhodecode.model import init_model
33 from rhodecode.model import init_model
34 from rhodecode.lib.utils2 import engine_from_config
34 from rhodecode.lib.utils2 import engine_from_config, safe_str
35 from rhodecode.model.db import RhodeCodeUi
35 from rhodecode.model.db import RhodeCodeUi
36
36
37
37
38 #to get the rhodecode import
38 #to get the rhodecode import
39 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
39 sys.path.append(dn(dn(dn(os.path.realpath(__file__)))))
40
40
41 from rhodecode.lib.utils import BasePasterCommand, Command, ask_ok,\
41 from rhodecode.lib.utils import BasePasterCommand, Command, ask_ok,\
42 REMOVED_REPO_PAT, add_cache
42 REMOVED_REPO_PAT, add_cache
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46
46
47 class CleanupCommand(BasePasterCommand):
47 class CleanupCommand(BasePasterCommand):
48
48
49 max_args = 1
49 max_args = 1
50 min_args = 1
50 min_args = 1
51
51
52 usage = "CONFIG_FILE"
52 usage = "CONFIG_FILE"
53 summary = "Cleanup deleted repos"
53 summary = "Cleanup deleted repos"
54 group_name = "RhodeCode"
54 group_name = "RhodeCode"
55 takes_config_file = -1
55 takes_config_file = -1
56 parser = Command.standard_parser(verbose=True)
56 parser = Command.standard_parser(verbose=True)
57
57
58 def _parse_older_than(self, val):
58 def _parse_older_than(self, val):
59 regex = re.compile(r'((?P<days>\d+?)d)?((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')
59 regex = re.compile(r'((?P<days>\d+?)d)?((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')
60 parts = regex.match(val)
60 parts = regex.match(val)
61 if not parts:
61 if not parts:
62 return
62 return
63 parts = parts.groupdict()
63 parts = parts.groupdict()
64 time_params = {}
64 time_params = {}
65 for (name, param) in parts.iteritems():
65 for (name, param) in parts.iteritems():
66 if param:
66 if param:
67 time_params[name] = int(param)
67 time_params[name] = int(param)
68 return datetime.timedelta(**time_params)
68 return datetime.timedelta(**time_params)
69
69
70 def _extract_date(self, name):
70 def _extract_date(self, name):
71 """
71 """
72 Extract the date part from rm__<date> pattern of removed repos,
72 Extract the date part from rm__<date> pattern of removed repos,
73 and convert it to datetime object
73 and convert it to datetime object
74
74
75 :param name:
75 :param name:
76 """
76 """
77 date_part = name[4:19] # 4:19 since we don't parse milisecods
77 date_part = name[4:19] # 4:19 since we don't parse milisecods
78 return datetime.datetime.strptime(date_part, '%Y%m%d_%H%M%S')
78 return datetime.datetime.strptime(date_part, '%Y%m%d_%H%M%S')
79
79
80 def command(self):
80 def command(self):
81 logging.config.fileConfig(self.path_to_ini_file)
81 logging.config.fileConfig(self.path_to_ini_file)
82 from pylons import config
82 from pylons import config
83
83
84 #get to remove repos !!
84 #get to remove repos !!
85 add_cache(config)
85 add_cache(config)
86 engine = engine_from_config(config, 'sqlalchemy.db1.')
86 engine = engine_from_config(config, 'sqlalchemy.db1.')
87 init_model(engine)
87 init_model(engine)
88
88
89 repos_location = RhodeCodeUi.get_repos_location()
89 repos_location = RhodeCodeUi.get_repos_location()
90 to_remove = []
90 to_remove = []
91 for loc in os.listdir(repos_location):
91 for loc in os.listdir(repos_location):
92 if REMOVED_REPO_PAT.match(loc):
92 if REMOVED_REPO_PAT.match(loc):
93 to_remove.append([loc, self._extract_date(loc)])
93 to_remove.append([loc, self._extract_date(loc)])
94
94
95 #filter older than (if present)!
95 #filter older than (if present)!
96 now = datetime.datetime.now()
96 now = datetime.datetime.now()
97 older_than = self.options.older_than
97 older_than = self.options.older_than
98 if older_than:
98 if older_than:
99 to_remove_filtered = []
99 to_remove_filtered = []
100 older_than_date = self._parse_older_than(older_than)
100 older_than_date = self._parse_older_than(older_than)
101 for name, date_ in to_remove:
101 for name, date_ in to_remove:
102 repo_age = now - date_
102 repo_age = now - date_
103 if repo_age > older_than_date:
103 if repo_age > older_than_date:
104 to_remove_filtered.append([name, date_])
104 to_remove_filtered.append([name, date_])
105
105
106 to_remove = to_remove_filtered
106 to_remove = to_remove_filtered
107 print >> sys.stdout, 'removing [%s] deleted repos older than %s[%s]' \
107 print >> sys.stdout, 'removing [%s] deleted repos older than %s[%s]' \
108 % (len(to_remove), older_than, older_than_date)
108 % (len(to_remove), older_than, older_than_date)
109 else:
109 else:
110 print >> sys.stdout, 'removing all [%s] deleted repos' \
110 print >> sys.stdout, 'removing all [%s] deleted repos' \
111 % len(to_remove)
111 % len(to_remove)
112 if self.options.dont_ask or not to_remove:
112 if self.options.dont_ask or not to_remove:
113 # don't ask just remove !
113 # don't ask just remove !
114 remove = True
114 remove = True
115 else:
115 else:
116 remove = ask_ok('are you sure to remove listed repos \n%s [y/n]?'
116 remove = ask_ok('are you sure to remove listed repos \n%s [y/n]?'
117 % ', \n'.join(['%s removed on %s' % (x[0], x[1])
117 % ', \n'.join(['%s removed on %s'
118 for x in to_remove]))
118 % (safe_str(x[0]), safe_str(x[1])) for x in to_remove]))
119
119
120 if remove:
120 if remove:
121 for name, date_ in to_remove:
121 for name, date_ in to_remove:
122 print >> sys.stdout, 'removing repository %s' % name
122 print >> sys.stdout, 'removing repository %s' % name
123 shutil.rmtree(os.path.join(repos_location, name))
123 shutil.rmtree(os.path.join(repos_location, name))
124 else:
124 else:
125 print 'nothing done exiting...'
125 print 'nothing done exiting...'
126 sys.exit(0)
126 sys.exit(0)
127
127
128 def update_parser(self):
128 def update_parser(self):
129 self.parser.add_option('--older-than',
129 self.parser.add_option('--older-than',
130 action='store',
130 action='store',
131 dest='older_than',
131 dest='older_than',
132 help=(
132 help=(
133 "only remove repos that have been removed "
133 "only remove repos that have been removed "
134 "at least given time ago "
134 "at least given time ago "
135 "ex. --older-than=30d deletes repositores "
135 "ex. --older-than=30d deletes repositores "
136 "removed more than 30days ago. Possible options "
136 "removed more than 30days ago. Possible options "
137 "d[ays]/h[ours]/m[inutes]/s[seconds]. OPTIONAL"),
137 "d[ays]/h[ours]/m[inutes]/s[seconds]. OPTIONAL"),
138 )
138 )
139 self.parser.add_option('--dont-ask',
139 self.parser.add_option('--dont-ask',
140 action='store_true',
140 action='store_true',
141 dest='dont_ask',
141 dest='dont_ask',
142 help=("Don't ask to remove repos"))
142 help=("Don't ask to remove repos"))
General Comments 0
You need to be logged in to leave comments. Login now