##// END OF EJS Templates
maintainance: add repack and fsck for git maintainance execution list.
marcink -
r3009:ae9279cb default
parent child Browse files
Show More
@@ -1,64 +1,62 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 from pyramid.view import view_config
23 from pyramid.view import view_config
24
24
25 from rhodecode.apps._base import RepoAppView
25 from rhodecode.apps._base import RepoAppView
26 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
26 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
27 from rhodecode.lib import repo_maintenance
27 from rhodecode.lib import repo_maintenance
28
28
29 log = logging.getLogger(__name__)
29 log = logging.getLogger(__name__)
30
30
31
31
32 class RepoMaintenanceView(RepoAppView):
32 class RepoMaintenanceView(RepoAppView):
33 def load_default_context(self):
33 def load_default_context(self):
34 c = self._get_local_tmpl_context()
34 c = self._get_local_tmpl_context()
35
36
37 return c
35 return c
38
36
39 @LoginRequired()
37 @LoginRequired()
40 @HasRepoPermissionAnyDecorator('repository.admin')
38 @HasRepoPermissionAnyDecorator('repository.admin')
41 @view_config(
39 @view_config(
42 route_name='edit_repo_maintenance', request_method='GET',
40 route_name='edit_repo_maintenance', request_method='GET',
43 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
41 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
44 def repo_maintenance(self):
42 def repo_maintenance(self):
45 c = self.load_default_context()
43 c = self.load_default_context()
46 c.active = 'maintenance'
44 c.active = 'maintenance'
47 maintenance = repo_maintenance.RepoMaintenance()
45 maintenance = repo_maintenance.RepoMaintenance()
48 c.executable_tasks = maintenance.get_tasks_for_repo(self.db_repo)
46 c.executable_tasks = maintenance.get_tasks_for_repo(self.db_repo)
49 return self._get_template_context(c)
47 return self._get_template_context(c)
50
48
51 @LoginRequired()
49 @LoginRequired()
52 @HasRepoPermissionAnyDecorator('repository.admin')
50 @HasRepoPermissionAnyDecorator('repository.admin')
53 @view_config(
51 @view_config(
54 route_name='edit_repo_maintenance_execute', request_method='GET',
52 route_name='edit_repo_maintenance_execute', request_method='GET',
55 renderer='json', xhr=True)
53 renderer='json', xhr=True)
56 def repo_maintenance_execute(self):
54 def repo_maintenance_execute(self):
57 c = self.load_default_context()
55 c = self.load_default_context()
58 c.active = 'maintenance'
56 c.active = 'maintenance'
59 _ = self.request.translate
57 _ = self.request.translate
60
58
61 maintenance = repo_maintenance.RepoMaintenance()
59 maintenance = repo_maintenance.RepoMaintenance()
62 executed_types = maintenance.execute(self.db_repo)
60 executed_types = maintenance.execute(self.db_repo)
63
61
64 return executed_types
62 return executed_types
@@ -1,118 +1,175 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2017-2018 RhodeCode GmbH
3 # Copyright (C) 2017-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import logging
20 import logging
21
21
22 log = logging.getLogger(__name__)
22 log = logging.getLogger(__name__)
23
23
24
24
25 class MaintenanceTask(object):
25 class MaintenanceTask(object):
26 human_name = 'undefined'
26 human_name = 'undefined'
27
27
28 def __init__(self, db_repo):
28 def __init__(self, db_repo):
29 self.db_repo = db_repo
29 self.db_repo = db_repo
30
30
31 def run(self):
31 def run(self):
32 """Execute task and return task human value"""
32 """Execute task and return task human value"""
33 raise NotImplementedError()
33 raise NotImplementedError()
34
34
35
35
36 class GitGC(MaintenanceTask):
36 class GitGC(MaintenanceTask):
37 human_name = 'GIT Garbage collect'
37 human_name = 'GIT Garbage collect'
38
38
39 def _count_objects(self, repo):
39 def _count_objects(self, repo):
40 stdout, stderr = repo.run_git_command(
40 stdout, stderr = repo.run_git_command(
41 ['count-objects', '-v'], fail_on_stderr=False)
41 ['count-objects', '-v'], fail_on_stderr=False)
42
42
43 errors = ' '
43 errors = ' '
44 objects = ' '.join(stdout.splitlines())
44 objects = ' '.join(stdout.splitlines())
45
45
46 if stderr:
46 if stderr:
47 errors = '\nSTD ERR:' + '\n'.join(stderr.splitlines())
47 errors = '\nSTD ERR:' + '\n'.join(stderr.splitlines())
48 return objects + errors
48 return objects + errors
49
49
50 def run(self):
50 def run(self):
51 output = []
51 output = []
52 instance = self.db_repo.scm_instance()
52 instance = self.db_repo.scm_instance()
53
53
54 objects = self._count_objects(instance)
54 objects_before = self._count_objects(instance)
55 output.append(objects)
56 log.debug('GIT objects:%s', objects)
57
58 stdout, stderr = instance.run_git_command(
59 ['gc', '--aggressive'], fail_on_stderr=False)
60
55
61 out = 'executed git gc --aggressive'
56 log.debug('GIT objects:%s', objects_before)
62 if stderr:
57 cmd = ['gc', '--aggressive']
63 out = ''.join(stderr.splitlines())
58 stdout, stderr = instance.run_git_command(cmd, fail_on_stderr=False)
64
59
65 elif stdout:
60 out = 'executed {}'.format(' '.join(cmd))
66 out = ''.join(stdout.splitlines())
67
68 output.append(out)
61 output.append(out)
69
62
70 objects = self._count_objects(instance)
63 out = ''
71 log.debug('GIT objects:%s', objects)
64 if stderr:
72 output.append(objects)
65 out += ''.join(stderr.splitlines())
66
67 if stdout:
68 out += ''.join(stdout.splitlines())
69
70 if out:
71 output.append(out)
72
73 objects_after = self._count_objects(instance)
74 log.debug('GIT objects:%s', objects_after)
75 output.append('objects before :' + objects_before)
76 output.append('objects after :' + objects_after)
77
78 return '\n'.join(output)
79
80
81 class GitFSCK(MaintenanceTask):
82 human_name = 'GIT FSCK'
83
84 def run(self):
85 output = []
86 instance = self.db_repo.scm_instance()
87
88 cmd = ['fsck', '--full']
89 stdout, stderr = instance.run_git_command(cmd, fail_on_stderr=False)
90
91 out = 'executed {}'.format(' '.join(cmd))
92 output.append(out)
93
94 out = ''
95 if stderr:
96 out += ''.join(stderr.splitlines())
97
98 if stdout:
99 out += ''.join(stdout.splitlines())
100
101 if out:
102 output.append(out)
103
104 return '\n'.join(output)
105
106
107 class GitRepack(MaintenanceTask):
108 human_name = 'GIT Repack'
109
110 def run(self):
111 output = []
112 instance = self.db_repo.scm_instance()
113 cmd = ['repack', '-a', '-d',
114 '--window-memory', '10m', '--max-pack-size', '100m']
115 stdout, stderr = instance.run_git_command(cmd, fail_on_stderr=False)
116
117 out = 'executed {}'.format(' '.join(cmd))
118 output.append(out)
119 out = ''
120
121 if stderr:
122 out += ''.join(stderr.splitlines())
123
124 if stdout:
125 out += ''.join(stdout.splitlines())
126
127 if out:
128 output.append(out)
73
129
74 return '\n'.join(output)
130 return '\n'.join(output)
75
131
76
132
77 class HGVerify(MaintenanceTask):
133 class HGVerify(MaintenanceTask):
78 human_name = 'HG Verify repo'
134 human_name = 'HG Verify repo'
79
135
80 def run(self):
136 def run(self):
81 instance = self.db_repo.scm_instance()
137 instance = self.db_repo.scm_instance()
82 res = instance.verify()
138 res = instance.verify()
83 return res
139 return res
84
140
85
141
86 class SVNVerify(MaintenanceTask):
142 class SVNVerify(MaintenanceTask):
87 human_name = 'SVN Verify repo'
143 human_name = 'SVN Verify repo'
88
144
89 def run(self):
145 def run(self):
90 instance = self.db_repo.scm_instance()
146 instance = self.db_repo.scm_instance()
91 res = instance.verify()
147 res = instance.verify()
92 return res
148 return res
93
149
94
150
95 class RepoMaintenance(object):
151 class RepoMaintenance(object):
96 """
152 """
97 Performs maintenance of repository based on it's type
153 Performs maintenance of repository based on it's type
98 """
154 """
99 tasks = {
155 tasks = {
100 'hg': [HGVerify],
156 'hg': [HGVerify],
101 'git': [GitGC],
157 'git': [GitFSCK, GitGC, GitRepack],
102 'svn': [SVNVerify],
158 'svn': [SVNVerify],
103 }
159 }
104
160
105 def get_tasks_for_repo(self, db_repo):
161 def get_tasks_for_repo(self, db_repo):
106 """
162 """
107 fetches human names of tasks pending for execution for given type of repo
163 fetches human names of tasks pending for execution for given type of repo
108 """
164 """
109 tasks = []
165 tasks = []
110 for task in self.tasks[db_repo.repo_type]:
166 for task in self.tasks[db_repo.repo_type]:
111 tasks.append(task.human_name)
167 tasks.append(task.human_name)
112 return tasks
168 return tasks
113
169
114 def execute(self, db_repo):
170 def execute(self, db_repo):
115 executed_tasks = []
171 executed_tasks = []
116 for task in self.tasks[db_repo.repo_type]:
172 for task in self.tasks[db_repo.repo_type]:
117 executed_tasks.append(task(db_repo).run())
173 output = task.human_name + ':\n' + task(db_repo).run() + '\n--\n'
174 executed_tasks.append(output)
118 return executed_tasks
175 return executed_tasks
General Comments 0
You need to be logged in to leave comments. Login now