##// END OF EJS Templates
repositories: enabled support for maintenance commands....
marcink -
r1555:9d1f0e57 default
parent child Browse files
Show More
@@ -0,0 +1,33 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 def includeme(config):
23
24 config.add_route(
25 name='repo_maintenance',
26 pattern='/{repo_name:.*?[^/]}/maintenance', repo_route=True)
27
28 config.add_route(
29 name='repo_maintenance_execute',
30 pattern='/{repo_name:.*?[^/]}/maintenance/execute', repo_route=True)
31
32 # Scan module for configuration decorators.
33 config.scan()
@@ -0,0 +1,19 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
@@ -0,0 +1,70 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 from pyramid.view import view_config
24
25 from rhodecode.apps._base import RepoAppView
26 from rhodecode.lib.auth import (LoginRequired, HasRepoPermissionAnyDecorator,
27 NotAnonymous)
28 from rhodecode.lib import repo_maintenance
29
30 log = logging.getLogger(__name__)
31
32
33 class RepoMaintenanceView(RepoAppView):
34 def load_default_context(self):
35 c = self._get_local_tmpl_context()
36
37 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
38 c.repo_info = self.db_repo
39
40 self._register_global_c(c)
41 return c
42
43 @LoginRequired()
44 @NotAnonymous()
45 @HasRepoPermissionAnyDecorator('repository.admin')
46 @view_config(
47 route_name='repo_maintenance', request_method='GET',
48 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
49 def repo_maintenance(self):
50 c = self.load_default_context()
51 c.active = 'maintenance'
52 maintenance = repo_maintenance.RepoMaintenance()
53 c.executable_tasks = maintenance.get_tasks_for_repo(self.db_repo)
54 return self._get_template_context(c)
55
56 @LoginRequired()
57 @NotAnonymous()
58 @HasRepoPermissionAnyDecorator('repository.admin')
59 @view_config(
60 route_name='repo_maintenance_execute', request_method='GET',
61 renderer='json', xhr=True)
62 def repo_maintenance_execute(self):
63 c = self.load_default_context()
64 c.active = 'maintenance'
65 _ = self.request.translate
66
67 maintenance = repo_maintenance.RepoMaintenance()
68 executed_types = maintenance.execute(self.db_repo)
69
70 return executed_types
@@ -0,0 +1,109 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2017-2017 RhodeCode GmbH
4 #
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
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
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/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 import logging
21
22 log = logging.getLogger(__name__)
23
24
25 class MaintenanceTask(object):
26 human_name = 'undefined'
27
28 def __init__(self, db_repo):
29 self.db_repo = db_repo
30
31 def run(self):
32 """Execute task and return task human value"""
33 raise NotImplementedError()
34
35
36 class GitGC(MaintenanceTask):
37 human_name = 'GIT Garbage collect'
38
39 def _count_objects(self, repo):
40 stdout, stderr = repo.run_git_command(
41 ['count-objects', '-v'], fail_on_stderr=False)
42
43 errors = ' '
44 objects = ' '.join(stdout.splitlines())
45
46 if stderr:
47 errors = '\nSTD ERR:' + '\n'.join(stderr.splitlines())
48 return objects + errors
49
50 def run(self):
51 output = []
52 instance = self.db_repo.scm_instance()
53
54 objects = 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
61 out = 'executed git gc --aggressive'
62 if stderr:
63 out = ''.join(stderr.splitlines())
64
65 elif stdout:
66 out = ''.join(stdout.splitlines())
67
68 output.append(out)
69
70 objects = self._count_objects(instance)
71 log.debug('GIT objects:%s', objects)
72 output.append(objects)
73
74 return '\n'.join(output)
75
76
77 class HGVerify(MaintenanceTask):
78 human_name = 'HG Verify repo'
79
80 def run(self):
81 instance = self.db_repo.scm_instance()
82 res = instance.verify()
83 return res
84
85
86 class RepoMaintenance(object):
87 """
88 Performs maintenance of repository based on it's type
89 """
90 tasks = {
91 'hg': [HGVerify],
92 'git': [GitGC],
93 'svn': [],
94 }
95
96 def get_tasks_for_repo(self, db_repo):
97 """
98 fetches human names of tasks pending for execution for given type of repo
99 """
100 tasks = []
101 for task in self.tasks[db_repo.repo_type]:
102 tasks.append(task.human_name)
103 return tasks
104
105 def execute(self, db_repo):
106 executed_tasks = []
107 for task in self.tasks[db_repo.repo_type]:
108 executed_tasks.append(task(db_repo).run())
109 return executed_tasks
@@ -0,0 +1,58 b''
1 <div class="panel panel-default">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Maintenance')}</h3>
4 </div>
5 <div class="panel-body">
6
7 <p>
8 % if c.executable_tasks:
9 ${_('Perform maintenance tasks for this repo, following tasks will be performed')}:
10 <ol>
11 % for task in c.executable_tasks:
12 <li>${task}</li>
13 % endfor
14 </ol>
15 % else:
16 ${_('No maintenance tasks for this repo available')}
17 % endif
18 </p>
19
20 <div id="results" style="display:none; padding: 10px 0px;"></div>
21
22 % if c.executable_tasks:
23 <div class="form">
24 <div class="fields">
25 <button class="btn btn-small btn-primary" onclick="executeTask();return false">
26 ${_('Run Maintenance')}
27 </button>
28 </div>
29 </div>
30 % endif
31
32 </div>
33 </div>
34
35
36 <script>
37
38 executeTask = function() {
39 var btn = $(this);
40 $('#results').show();
41 $('#results').html('<h4>${_('Performing Maintenance')}...</h4>');
42
43 btn.attr('disabled', 'disabled');
44 btn.addClass('disabled');
45
46 var url = "${h.route_path('repo_maintenance_execute', repo_name=c.repo_info.repo_name)}";
47 var success = function (data) {
48 var displayHtml = $('<pre></pre>');
49
50 $(displayHtml).append(data);
51 $('#results').html(displayHtml);
52 btn.removeAttr('disabled');
53 btn.removeClass('disabled');
54 };
55 ajaxGET(url, success, null);
56
57 }
58 </script>
@@ -288,6 +288,7 b' def includeme(config):'
288 config.include('rhodecode.apps.admin')
288 config.include('rhodecode.apps.admin')
289 config.include('rhodecode.apps.channelstream')
289 config.include('rhodecode.apps.channelstream')
290 config.include('rhodecode.apps.login')
290 config.include('rhodecode.apps.login')
291 config.include('rhodecode.apps.repository')
291 config.include('rhodecode.apps.user_profile')
292 config.include('rhodecode.apps.user_profile')
292 config.include('rhodecode.apps.my_account')
293 config.include('rhodecode.apps.my_account')
293 config.include('rhodecode.apps.svn_support')
294 config.include('rhodecode.apps.svn_support')
@@ -71,6 +71,9 b''
71 <li class="${'active' if c.active=='integrations' else ''}">
71 <li class="${'active' if c.active=='integrations' else ''}">
72 <a href="${h.route_path('repo_integrations_home', repo_name=c.repo_name)}">${_('Integrations')}</a>
72 <a href="${h.route_path('repo_integrations_home', repo_name=c.repo_name)}">${_('Integrations')}</a>
73 </li>
73 </li>
74 <li class="${'active' if c.active=='maintenance' else ''}">
75 <a href="${h.route_path('repo_maintenance', repo_name=c.repo_name)}">${_('Maintenance')}</a>
76 </li>
74 ## TODO: dan: replace repo navigation with navlist registry like with
77 ## TODO: dan: replace repo navigation with navlist registry like with
75 ## admin menu. First must find way to allow runtime configuration
78 ## admin menu. First must find way to allow runtime configuration
76 ## it to account for the c.repo_info.repo_type != 'svn' call above
79 ## it to account for the c.repo_info.repo_type != 'svn' call above
@@ -209,7 +209,7 b''
209 <%text filter="h">
209 <%text filter="h">
210 <script>
210 <script>
211 // Server announcement displayed on the top of the page.
211 // Server announcement displayed on the top of the page.
212 // This can be used to send a global maintainance messages or other
212 // This can be used to send a global maintenance messages or other
213 // important messages to all users of the RhodeCode Enterprise system.
213 // important messages to all users of the RhodeCode Enterprise system.
214
214
215 $(document).ready(function(e){
215 $(document).ready(function(e){
General Comments 0
You need to be logged in to leave comments. Login now