##// END OF EJS Templates
Added friendly message about removing a group that still contains subgroups....
marcink -
r1543:ada6926c beta
parent child Browse files
Show More
@@ -1,225 +1,237
1 1 import logging
2 2 import traceback
3 3 import formencode
4 4
5 5 from formencode import htmlfill
6 6 from operator import itemgetter
7 7
8 8 from pylons import request, response, session, tmpl_context as c, url
9 9 from pylons.controllers.util import abort, redirect
10 10 from pylons.i18n.translation import _
11 11
12 from sqlalchemy.exc import IntegrityError
13
12 14 from rhodecode.lib import helpers as h
13 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
14 HasPermissionAnyDecorator
15 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator
15 16 from rhodecode.lib.base import BaseController, render
16 17 from rhodecode.model.db import Group
17 18 from rhodecode.model.repos_group import ReposGroupModel
18 19 from rhodecode.model.forms import ReposGroupForm
19 20
20 21 log = logging.getLogger(__name__)
21 22
22 23
23 24 class ReposGroupsController(BaseController):
24 25 """REST Controller styled on the Atom Publishing Protocol"""
25 26 # To properly map this controller, ensure your config/routing.py
26 27 # file has a resource setup:
27 28 # map.resource('repos_group', 'repos_groups')
28 29
29 30 @LoginRequired()
30 31 def __before__(self):
31 32 super(ReposGroupsController, self).__before__()
32 33
33 34 def __load_defaults(self):
34 35
35 36 c.repo_groups = [('', '')]
36 37 parents_link = lambda k: h.literal('»'.join(k))
37 38
38 39 c.repo_groups.extend([(x.group_id, parents_link(x.full_path_splitted))
39 40 for x in self.sa.query(Group).all()])
40 41
41 42 c.repo_groups = sorted(c.repo_groups,
42 43 key=lambda t: t[1].split('»')[0])
43 44 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
44 45
45 46 def __load_data(self, group_id):
46 47 """
47 48 Load defaults settings for edit, and update
48 49
49 50 :param group_id:
50 51 """
51 52 self.__load_defaults()
52 53
53 54 repo_group = Group.get(group_id)
54 55
55 56 data = repo_group.get_dict()
56 57
57 58 data['group_name'] = repo_group.name
58 59
59 60 return data
60 61
61 62 @HasPermissionAnyDecorator('hg.admin')
62 63 def index(self, format='html'):
63 64 """GET /repos_groups: All items in the collection"""
64 65 # url('repos_groups')
65 66
66 67 sk = lambda g:g.parents[0].group_name if g.parents else g.group_name
67 68 c.groups = sorted(Group.query().all(), key=sk)
68 69 return render('admin/repos_groups/repos_groups_show.html')
69 70
70 71 @HasPermissionAnyDecorator('hg.admin')
71 72 def create(self):
72 73 """POST /repos_groups: Create a new item"""
73 74 # url('repos_groups')
74 75 self.__load_defaults()
75 76 repos_group_model = ReposGroupModel()
76 77 repos_group_form = ReposGroupForm(available_groups=
77 78 c.repo_groups_choices)()
78 79 try:
79 80 form_result = repos_group_form.to_python(dict(request.POST))
80 81 repos_group_model.create(form_result)
81 82 h.flash(_('created repos group %s') \
82 83 % form_result['group_name'], category='success')
83 84 #TODO: in futureaction_logger(, '', '', '', self.sa)
84 85 except formencode.Invalid, errors:
85 86
86 87 return htmlfill.render(
87 88 render('admin/repos_groups/repos_groups_add.html'),
88 89 defaults=errors.value,
89 90 errors=errors.error_dict or {},
90 91 prefix_error=False,
91 92 encoding="UTF-8")
92 93 except Exception:
93 94 log.error(traceback.format_exc())
94 95 h.flash(_('error occurred during creation of repos group %s') \
95 96 % request.POST.get('group_name'), category='error')
96 97
97 98 return redirect(url('repos_groups'))
98 99
99 100
100 101 @HasPermissionAnyDecorator('hg.admin')
101 102 def new(self, format='html'):
102 103 """GET /repos_groups/new: Form to create a new item"""
103 104 # url('new_repos_group')
104 105 self.__load_defaults()
105 106 return render('admin/repos_groups/repos_groups_add.html')
106 107
107 108 @HasPermissionAnyDecorator('hg.admin')
108 109 def update(self, id):
109 110 """PUT /repos_groups/id: Update an existing item"""
110 111 # Forms posted to this method should contain a hidden field:
111 112 # <input type="hidden" name="_method" value="PUT" />
112 113 # Or using helpers:
113 114 # h.form(url('repos_group', id=ID),
114 115 # method='put')
115 116 # url('repos_group', id=ID)
116 117
117 118 self.__load_defaults()
118 119 c.repos_group = Group.get(id)
119 120
120 121 repos_group_model = ReposGroupModel()
121 122 repos_group_form = ReposGroupForm(edit=True,
122 123 old_data=c.repos_group.get_dict(),
123 124 available_groups=
124 125 c.repo_groups_choices)()
125 126 try:
126 127 form_result = repos_group_form.to_python(dict(request.POST))
127 128 repos_group_model.update(id, form_result)
128 129 h.flash(_('updated repos group %s') \
129 130 % form_result['group_name'], category='success')
130 131 #TODO: in futureaction_logger(, '', '', '', self.sa)
131 132 except formencode.Invalid, errors:
132 133
133 134 return htmlfill.render(
134 135 render('admin/repos_groups/repos_groups_edit.html'),
135 136 defaults=errors.value,
136 137 errors=errors.error_dict or {},
137 138 prefix_error=False,
138 139 encoding="UTF-8")
139 140 except Exception:
140 141 log.error(traceback.format_exc())
141 142 h.flash(_('error occurred during update of repos group %s') \
142 143 % request.POST.get('group_name'), category='error')
143 144
144 145 return redirect(url('repos_groups'))
145 146
146 147
147 148 @HasPermissionAnyDecorator('hg.admin')
148 149 def delete(self, id):
149 150 """DELETE /repos_groups/id: Delete an existing item"""
150 151 # Forms posted to this method should contain a hidden field:
151 152 # <input type="hidden" name="_method" value="DELETE" />
152 153 # Or using helpers:
153 154 # h.form(url('repos_group', id=ID),
154 155 # method='delete')
155 156 # url('repos_group', id=ID)
156 157
157 158 repos_group_model = ReposGroupModel()
158 159 gr = Group.get(id)
159 160 repos = gr.repositories.all()
160 161 if repos:
161 162 h.flash(_('This group contains %s repositores and cannot be '
162 163 'deleted' % len(repos)),
163 164 category='error')
164 165 return redirect(url('repos_groups'))
165 166
166 167 try:
167 168 repos_group_model.delete(id)
168 169 h.flash(_('removed repos group %s' % gr.group_name), category='success')
169 170 #TODO: in future action_logger(, '', '', '', self.sa)
171 except IntegrityError, e:
172 if e.message.find('groups_group_parent_id_fkey'):
173 log.error(traceback.format_exc())
174 h.flash(_('Cannot delete this group it still contains '
175 'subgroups'),
176 category='warning')
177 else:
178 log.error(traceback.format_exc())
179 h.flash(_('error occurred during deletion of repos '
180 'group %s' % gr.group_name), category='error')
181
170 182 except Exception:
171 183 log.error(traceback.format_exc())
172 h.flash(_('error occurred during deletion of repos group %s' % gr.group_name),
173 category='error')
184 h.flash(_('error occurred during deletion of repos '
185 'group %s' % gr.group_name), category='error')
174 186
175 187 return redirect(url('repos_groups'))
176 188
177 189 def show_by_name(self, group_name):
178 190 id_ = Group.get_by_group_name(group_name).group_id
179 191 return self.show(id_)
180 192
181 193 def show(self, id, format='html'):
182 194 """GET /repos_groups/id: Show a specific item"""
183 195 # url('repos_group', id=ID)
184 196
185 197 c.group = Group.get(id)
186 198
187 199 if c.group:
188 200 c.group_repos = c.group.repositories.all()
189 201 else:
190 202 return redirect(url('home'))
191 203
192 204 #overwrite our cached list with current filter
193 205 gr_filter = c.group_repos
194 206 c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter)
195 207
196 208 c.repos_list = c.cached_repo_list
197 209
198 210 c.repo_cnt = 0
199 211
200 212 c.groups = self.sa.query(Group).order_by(Group.group_name)\
201 213 .filter(Group.group_parent_id == id).all()
202 214
203 215 return render('admin/repos_groups/repos_groups.html')
204 216
205 217 @HasPermissionAnyDecorator('hg.admin')
206 218 def edit(self, id, format='html'):
207 219 """GET /repos_groups/id/edit: Form to edit an existing item"""
208 220 # url('edit_repos_group', id=ID)
209 221
210 222 id_ = int(id)
211 223
212 224 c.repos_group = Group.get(id_)
213 225 defaults = self.__load_data(id_)
214 226
215 227 # we need to exclude this group from the group list for editing
216 228 c.repo_groups = filter(lambda x:x[0] != id_, c.repo_groups)
217 229
218 230 return htmlfill.render(
219 231 render('admin/repos_groups/repos_groups_edit.html'),
220 232 defaults=defaults,
221 233 encoding="UTF-8",
222 234 force_defaults=False
223 235 )
224 236
225 237
@@ -1,162 +1,164
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.user_group
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 users groups model for RhodeCode
7 7
8 8 :created_on: Jan 25, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import os
27 27 import logging
28 28 import traceback
29 29 import shutil
30 30
31 31 from pylons.i18n.translation import _
32 32
33 33 from vcs.utils.lazy import LazyProperty
34 34
35 35 from rhodecode.model import BaseModel
36 36 from rhodecode.model.caching_query import FromCache
37 37 from rhodecode.model.db import Group, RhodeCodeUi
38 38
39 39 log = logging.getLogger(__name__)
40 40
41 41
42 42 class ReposGroupModel(BaseModel):
43 43
44 44 @LazyProperty
45 45 def repos_path(self):
46 46 """
47 47 Get's the repositories root path from database
48 48 """
49 49
50 50 q = RhodeCodeUi.get_by_key('/').one()
51 51 return q.ui_value
52 52
53 53 def __create_group(self, group_name):
54 54 """
55 55 makes repositories group on filesystem
56 56
57 57 :param repo_name:
58 58 :param parent_id:
59 59 """
60 60
61 61 create_path = os.path.join(self.repos_path, group_name)
62 62 log.debug('creating new group in %s', create_path)
63 63
64 64 if os.path.isdir(create_path):
65 65 raise Exception('That directory already exists !')
66 66
67 67 os.makedirs(create_path)
68 68
69 69 def __rename_group(self, old, new):
70 70 """
71 71 Renames a group on filesystem
72 72
73 73 :param group_name:
74 74 """
75 75
76 76 if old == new:
77 77 log.debug('skipping group rename')
78 78 return
79 79
80 80 log.debug('renaming repos group from %s to %s', old, new)
81 81
82 82
83 83 old_path = os.path.join(self.repos_path, old)
84 84 new_path = os.path.join(self.repos_path, new)
85 85
86 86 log.debug('renaming repos paths from %s to %s', old_path, new_path)
87 87
88 88 if os.path.isdir(new_path):
89 89 raise Exception('Was trying to rename to already '
90 90 'existing dir %s' % new_path)
91 91 shutil.move(old_path, new_path)
92 92
93 93 def __delete_group(self, group):
94 94 """
95 95 Deletes a group from a filesystem
96 96
97 97 :param group: instance of group from database
98 98 """
99 99 paths = group.full_path.split(Group.url_sep())
100 100 paths = os.sep.join(paths)
101 101
102 102 rm_path = os.path.join(self.repos_path, paths)
103 if os.path.isdir(rm_path):
104 # delete only if that path really exists
103 105 os.rmdir(rm_path)
104 106
105 107 def create(self, form_data):
106 108 try:
107 109 new_repos_group = Group()
108 110 new_repos_group.group_description = form_data['group_description']
109 111 new_repos_group.parent_group = Group.get(form_data['group_parent_id'])
110 112 new_repos_group.group_name = new_repos_group.get_new_name(form_data['group_name'])
111 113
112 114 self.sa.add(new_repos_group)
113 115
114 116 self.__create_group(new_repos_group.group_name)
115 117
116 118 self.sa.commit()
117 119 return new_repos_group
118 120 except:
119 121 log.error(traceback.format_exc())
120 122 self.sa.rollback()
121 123 raise
122 124
123 125 def update(self, repos_group_id, form_data):
124 126
125 127 try:
126 128 repos_group = Group.get(repos_group_id)
127 129 old_path = repos_group.full_path
128 130
129 131 #change properties
130 132 repos_group.group_description = form_data['group_description']
131 133 repos_group.parent_group = Group.get(form_data['group_parent_id'])
132 134 repos_group.group_name = repos_group.get_new_name(form_data['group_name'])
133 135
134 136 new_path = repos_group.full_path
135 137
136 138 self.sa.add(repos_group)
137 139
138 140 self.__rename_group(old_path, new_path)
139 141
140 142 # we need to get all repositories from this new group and
141 143 # rename them accordingly to new group path
142 144 for r in repos_group.repositories:
143 145 r.repo_name = r.get_new_name(r.just_name)
144 146 self.sa.add(r)
145 147
146 148 self.sa.commit()
147 149 return repos_group
148 150 except:
149 151 log.error(traceback.format_exc())
150 152 self.sa.rollback()
151 153 raise
152 154
153 155 def delete(self, users_group_id):
154 156 try:
155 157 users_group = Group.get(users_group_id)
156 158 self.sa.delete(users_group)
157 159 self.__delete_group(users_group)
158 160 self.sa.commit()
159 161 except:
160 162 log.error(traceback.format_exc())
161 163 self.sa.rollback()
162 164 raise
General Comments 0
You need to be logged in to leave comments. Login now