##// END OF EJS Templates
assure that we don't have an empty description when creating a repo
marcink -
r1517:142a0559 beta
parent child Browse files
Show More
@@ -1,358 +1,361 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.repo
3 rhodecode.model.repo
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 Repository model for rhodecode
6 Repository model for rhodecode
7
7
8 :created_on: Jun 5, 2010
8 :created_on: Jun 5, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import os
25 import os
26 import shutil
26 import shutil
27 import logging
27 import logging
28 import traceback
28 import traceback
29 from datetime import datetime
29 from datetime import datetime
30
30
31 from sqlalchemy.orm import joinedload, make_transient
31 from sqlalchemy.orm import joinedload, make_transient
32
32
33 from vcs.utils.lazy import LazyProperty
33 from vcs.utils.lazy import LazyProperty
34 from vcs.backends import get_backend
34 from vcs.backends import get_backend
35
35
36 from rhodecode.lib import safe_str
36 from rhodecode.lib import safe_str
37
37
38 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
39 from rhodecode.model.caching_query import FromCache
39 from rhodecode.model.caching_query import FromCache
40 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
40 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, Group
41 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, Group
42 from rhodecode.model.user import UserModel
42 from rhodecode.model.user import UserModel
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46
46
47 class RepoModel(BaseModel):
47 class RepoModel(BaseModel):
48
48
49 @LazyProperty
49 @LazyProperty
50 def repos_path(self):
50 def repos_path(self):
51 """Get's the repositories root path from database
51 """Get's the repositories root path from database
52 """
52 """
53
53
54 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
54 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
55 return q.ui_value
55 return q.ui_value
56
56
57 def get(self, repo_id, cache=False):
57 def get(self, repo_id, cache=False):
58 repo = self.sa.query(Repository)\
58 repo = self.sa.query(Repository)\
59 .filter(Repository.repo_id == repo_id)
59 .filter(Repository.repo_id == repo_id)
60
60
61 if cache:
61 if cache:
62 repo = repo.options(FromCache("sql_cache_short",
62 repo = repo.options(FromCache("sql_cache_short",
63 "get_repo_%s" % repo_id))
63 "get_repo_%s" % repo_id))
64 return repo.scalar()
64 return repo.scalar()
65
65
66 def get_by_repo_name(self, repo_name, cache=False):
66 def get_by_repo_name(self, repo_name, cache=False):
67 repo = self.sa.query(Repository)\
67 repo = self.sa.query(Repository)\
68 .filter(Repository.repo_name == repo_name)
68 .filter(Repository.repo_name == repo_name)
69
69
70 if cache:
70 if cache:
71 repo = repo.options(FromCache("sql_cache_short",
71 repo = repo.options(FromCache("sql_cache_short",
72 "get_repo_%s" % repo_name))
72 "get_repo_%s" % repo_name))
73 return repo.scalar()
73 return repo.scalar()
74
74
75
75
76 def get_users_js(self):
76 def get_users_js(self):
77
77
78 users = self.sa.query(User).filter(User.active == True).all()
78 users = self.sa.query(User).filter(User.active == True).all()
79 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
79 u_tmpl = '''{id:%s, fname:"%s", lname:"%s", nname:"%s"},'''
80 users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
80 users_array = '[%s]' % '\n'.join([u_tmpl % (u.user_id, u.name,
81 u.lastname, u.username)
81 u.lastname, u.username)
82 for u in users])
82 for u in users])
83 return users_array
83 return users_array
84
84
85 def get_users_groups_js(self):
85 def get_users_groups_js(self):
86 users_groups = self.sa.query(UsersGroup)\
86 users_groups = self.sa.query(UsersGroup)\
87 .filter(UsersGroup.users_group_active == True).all()
87 .filter(UsersGroup.users_group_active == True).all()
88
88
89 g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
89 g_tmpl = '''{id:%s, grname:"%s",grmembers:"%s"},'''
90
90
91 users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
91 users_groups_array = '[%s]' % '\n'.join([g_tmpl % \
92 (gr.users_group_id, gr.users_group_name,
92 (gr.users_group_id, gr.users_group_name,
93 len(gr.members))
93 len(gr.members))
94 for gr in users_groups])
94 for gr in users_groups])
95 return users_groups_array
95 return users_groups_array
96
96
97 def update(self, repo_name, form_data):
97 def update(self, repo_name, form_data):
98 try:
98 try:
99 cur_repo = self.get_by_repo_name(repo_name, cache=False)
99 cur_repo = self.get_by_repo_name(repo_name, cache=False)
100
100
101 #update permissions
101 #update permissions
102 for member, perm, member_type in form_data['perms_updates']:
102 for member, perm, member_type in form_data['perms_updates']:
103 if member_type == 'user':
103 if member_type == 'user':
104 r2p = self.sa.query(RepoToPerm)\
104 r2p = self.sa.query(RepoToPerm)\
105 .filter(RepoToPerm.user == User.by_username(member))\
105 .filter(RepoToPerm.user == User.by_username(member))\
106 .filter(RepoToPerm.repository == cur_repo)\
106 .filter(RepoToPerm.repository == cur_repo)\
107 .one()
107 .one()
108
108
109 r2p.permission = self.sa.query(Permission)\
109 r2p.permission = self.sa.query(Permission)\
110 .filter(Permission.permission_name ==
110 .filter(Permission.permission_name ==
111 perm).scalar()
111 perm).scalar()
112 self.sa.add(r2p)
112 self.sa.add(r2p)
113 else:
113 else:
114 g2p = self.sa.query(UsersGroupRepoToPerm)\
114 g2p = self.sa.query(UsersGroupRepoToPerm)\
115 .filter(UsersGroupRepoToPerm.users_group ==
115 .filter(UsersGroupRepoToPerm.users_group ==
116 UsersGroup.get_by_group_name(member))\
116 UsersGroup.get_by_group_name(member))\
117 .filter(UsersGroupRepoToPerm.repository ==
117 .filter(UsersGroupRepoToPerm.repository ==
118 cur_repo).one()
118 cur_repo).one()
119
119
120 g2p.permission = self.sa.query(Permission)\
120 g2p.permission = self.sa.query(Permission)\
121 .filter(Permission.permission_name ==
121 .filter(Permission.permission_name ==
122 perm).scalar()
122 perm).scalar()
123 self.sa.add(g2p)
123 self.sa.add(g2p)
124
124
125 #set new permissions
125 #set new permissions
126 for member, perm, member_type in form_data['perms_new']:
126 for member, perm, member_type in form_data['perms_new']:
127 if member_type == 'user':
127 if member_type == 'user':
128 r2p = RepoToPerm()
128 r2p = RepoToPerm()
129 r2p.repository = cur_repo
129 r2p.repository = cur_repo
130 r2p.user = User.by_username(member)
130 r2p.user = User.by_username(member)
131
131
132 r2p.permission = self.sa.query(Permission)\
132 r2p.permission = self.sa.query(Permission)\
133 .filter(Permission.
133 .filter(Permission.
134 permission_name == perm)\
134 permission_name == perm)\
135 .scalar()
135 .scalar()
136 self.sa.add(r2p)
136 self.sa.add(r2p)
137 else:
137 else:
138 g2p = UsersGroupRepoToPerm()
138 g2p = UsersGroupRepoToPerm()
139 g2p.repository = cur_repo
139 g2p.repository = cur_repo
140 g2p.users_group = UsersGroup.get_by_group_name(member)
140 g2p.users_group = UsersGroup.get_by_group_name(member)
141 g2p.permission = self.sa.query(Permission)\
141 g2p.permission = self.sa.query(Permission)\
142 .filter(Permission.
142 .filter(Permission.
143 permission_name == perm)\
143 permission_name == perm)\
144 .scalar()
144 .scalar()
145 self.sa.add(g2p)
145 self.sa.add(g2p)
146
146
147 #update current repo
147 #update current repo
148 for k, v in form_data.items():
148 for k, v in form_data.items():
149 if k == 'user':
149 if k == 'user':
150 cur_repo.user = User.by_username(v)
150 cur_repo.user = User.by_username(v)
151 elif k == 'repo_name':
151 elif k == 'repo_name':
152 cur_repo.repo_name = form_data['repo_name_full']
152 cur_repo.repo_name = form_data['repo_name_full']
153 elif k == 'repo_group':
153 elif k == 'repo_group':
154 cur_repo.group_id = v
154 cur_repo.group_id = v
155
155
156 else:
156 else:
157 setattr(cur_repo, k, v)
157 setattr(cur_repo, k, v)
158
158
159 self.sa.add(cur_repo)
159 self.sa.add(cur_repo)
160
160
161 if repo_name != form_data['repo_name_full']:
161 if repo_name != form_data['repo_name_full']:
162 # rename repository
162 # rename repository
163 self.__rename_repo(old=repo_name,
163 self.__rename_repo(old=repo_name,
164 new=form_data['repo_name_full'])
164 new=form_data['repo_name_full'])
165
165
166 self.sa.commit()
166 self.sa.commit()
167 except:
167 except:
168 log.error(traceback.format_exc())
168 log.error(traceback.format_exc())
169 self.sa.rollback()
169 self.sa.rollback()
170 raise
170 raise
171
171
172 def create(self, form_data, cur_user, just_db=False, fork=False):
172 def create(self, form_data, cur_user, just_db=False, fork=False):
173
173
174 try:
174 try:
175 if fork:
175 if fork:
176 repo_name = form_data['fork_name']
176 repo_name = form_data['fork_name']
177 org_name = form_data['repo_name']
177 org_name = form_data['repo_name']
178 org_full_name = org_name
178 org_full_name = org_name
179
179
180 else:
180 else:
181 org_name = repo_name = form_data['repo_name']
181 org_name = repo_name = form_data['repo_name']
182 repo_name_full = form_data['repo_name_full']
182 repo_name_full = form_data['repo_name_full']
183
183
184 new_repo = Repository()
184 new_repo = Repository()
185 new_repo.enable_statistics = False
185 new_repo.enable_statistics = False
186 for k, v in form_data.items():
186 for k, v in form_data.items():
187 if k == 'repo_name':
187 if k == 'repo_name':
188 if fork:
188 if fork:
189 v = repo_name
189 v = repo_name
190 else:
190 else:
191 v = repo_name_full
191 v = repo_name_full
192 if k == 'repo_group':
192 if k == 'repo_group':
193 k = 'group_id'
193 k = 'group_id'
194
194
195 if k == 'description':
196 v = v or repo_name
197
195 setattr(new_repo, k, v)
198 setattr(new_repo, k, v)
196
199
197 if fork:
200 if fork:
198 parent_repo = self.sa.query(Repository)\
201 parent_repo = self.sa.query(Repository)\
199 .filter(Repository.repo_name == org_full_name).one()
202 .filter(Repository.repo_name == org_full_name).one()
200 new_repo.fork = parent_repo
203 new_repo.fork = parent_repo
201
204
202 new_repo.user_id = cur_user.user_id
205 new_repo.user_id = cur_user.user_id
203 self.sa.add(new_repo)
206 self.sa.add(new_repo)
204
207
205 #create default permission
208 #create default permission
206 repo_to_perm = RepoToPerm()
209 repo_to_perm = RepoToPerm()
207 default = 'repository.read'
210 default = 'repository.read'
208 for p in UserModel(self.sa).get_by_username('default',
211 for p in UserModel(self.sa).get_by_username('default',
209 cache=False).user_perms:
212 cache=False).user_perms:
210 if p.permission.permission_name.startswith('repository.'):
213 if p.permission.permission_name.startswith('repository.'):
211 default = p.permission.permission_name
214 default = p.permission.permission_name
212 break
215 break
213
216
214 default_perm = 'repository.none' if form_data['private'] else default
217 default_perm = 'repository.none' if form_data['private'] else default
215
218
216 repo_to_perm.permission_id = self.sa.query(Permission)\
219 repo_to_perm.permission_id = self.sa.query(Permission)\
217 .filter(Permission.permission_name == default_perm)\
220 .filter(Permission.permission_name == default_perm)\
218 .one().permission_id
221 .one().permission_id
219
222
220 repo_to_perm.repository = new_repo
223 repo_to_perm.repository = new_repo
221 repo_to_perm.user_id = UserModel(self.sa)\
224 repo_to_perm.user_id = UserModel(self.sa)\
222 .get_by_username('default', cache=False).user_id
225 .get_by_username('default', cache=False).user_id
223
226
224 self.sa.add(repo_to_perm)
227 self.sa.add(repo_to_perm)
225
228
226 if not just_db:
229 if not just_db:
227 self.__create_repo(repo_name, form_data['repo_type'],
230 self.__create_repo(repo_name, form_data['repo_type'],
228 form_data['repo_group'],
231 form_data['repo_group'],
229 form_data['clone_uri'])
232 form_data['clone_uri'])
230
233
231 self.sa.commit()
234 self.sa.commit()
232
235
233 #now automatically start following this repository as owner
236 #now automatically start following this repository as owner
234 from rhodecode.model.scm import ScmModel
237 from rhodecode.model.scm import ScmModel
235 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
238 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
236 cur_user.user_id)
239 cur_user.user_id)
237
240
238 except:
241 except:
239 log.error(traceback.format_exc())
242 log.error(traceback.format_exc())
240 self.sa.rollback()
243 self.sa.rollback()
241 raise
244 raise
242
245
243 def create_fork(self, form_data, cur_user):
246 def create_fork(self, form_data, cur_user):
244 from rhodecode.lib.celerylib import tasks, run_task
247 from rhodecode.lib.celerylib import tasks, run_task
245 run_task(tasks.create_repo_fork, form_data, cur_user)
248 run_task(tasks.create_repo_fork, form_data, cur_user)
246
249
247 def delete(self, repo):
250 def delete(self, repo):
248 try:
251 try:
249 self.sa.delete(repo)
252 self.sa.delete(repo)
250 self.__delete_repo(repo)
253 self.__delete_repo(repo)
251 self.sa.commit()
254 self.sa.commit()
252 except:
255 except:
253 log.error(traceback.format_exc())
256 log.error(traceback.format_exc())
254 self.sa.rollback()
257 self.sa.rollback()
255 raise
258 raise
256
259
257 def delete_perm_user(self, form_data, repo_name):
260 def delete_perm_user(self, form_data, repo_name):
258 try:
261 try:
259 self.sa.query(RepoToPerm)\
262 self.sa.query(RepoToPerm)\
260 .filter(RepoToPerm.repository \
263 .filter(RepoToPerm.repository \
261 == self.get_by_repo_name(repo_name))\
264 == self.get_by_repo_name(repo_name))\
262 .filter(RepoToPerm.user_id == form_data['user_id']).delete()
265 .filter(RepoToPerm.user_id == form_data['user_id']).delete()
263 self.sa.commit()
266 self.sa.commit()
264 except:
267 except:
265 log.error(traceback.format_exc())
268 log.error(traceback.format_exc())
266 self.sa.rollback()
269 self.sa.rollback()
267 raise
270 raise
268
271
269 def delete_perm_users_group(self, form_data, repo_name):
272 def delete_perm_users_group(self, form_data, repo_name):
270 try:
273 try:
271 self.sa.query(UsersGroupRepoToPerm)\
274 self.sa.query(UsersGroupRepoToPerm)\
272 .filter(UsersGroupRepoToPerm.repository \
275 .filter(UsersGroupRepoToPerm.repository \
273 == self.get_by_repo_name(repo_name))\
276 == self.get_by_repo_name(repo_name))\
274 .filter(UsersGroupRepoToPerm.users_group_id \
277 .filter(UsersGroupRepoToPerm.users_group_id \
275 == form_data['users_group_id']).delete()
278 == form_data['users_group_id']).delete()
276 self.sa.commit()
279 self.sa.commit()
277 except:
280 except:
278 log.error(traceback.format_exc())
281 log.error(traceback.format_exc())
279 self.sa.rollback()
282 self.sa.rollback()
280 raise
283 raise
281
284
282 def delete_stats(self, repo_name):
285 def delete_stats(self, repo_name):
283 try:
286 try:
284 self.sa.query(Statistics)\
287 self.sa.query(Statistics)\
285 .filter(Statistics.repository == \
288 .filter(Statistics.repository == \
286 self.get_by_repo_name(repo_name)).delete()
289 self.get_by_repo_name(repo_name)).delete()
287 self.sa.commit()
290 self.sa.commit()
288 except:
291 except:
289 log.error(traceback.format_exc())
292 log.error(traceback.format_exc())
290 self.sa.rollback()
293 self.sa.rollback()
291 raise
294 raise
292
295
293 def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
296 def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
294 """
297 """
295 makes repository on filesystem. It's group aware means it'll create
298 makes repository on filesystem. It's group aware means it'll create
296 a repository within a group, and alter the paths accordingly of
299 a repository within a group, and alter the paths accordingly of
297 group location
300 group location
298
301
299 :param repo_name:
302 :param repo_name:
300 :param alias:
303 :param alias:
301 :param parent_id:
304 :param parent_id:
302 :param clone_uri:
305 :param clone_uri:
303 """
306 """
304 from rhodecode.lib.utils import is_valid_repo
307 from rhodecode.lib.utils import is_valid_repo
305
308
306 if new_parent_id:
309 if new_parent_id:
307 paths = Group.get(new_parent_id).full_path.split(Group.url_sep())
310 paths = Group.get(new_parent_id).full_path.split(Group.url_sep())
308 new_parent_path = os.sep.join(paths)
311 new_parent_path = os.sep.join(paths)
309 else:
312 else:
310 new_parent_path = ''
313 new_parent_path = ''
311
314
312 repo_path = os.path.join(*map(lambda x:safe_str(x),
315 repo_path = os.path.join(*map(lambda x:safe_str(x),
313 [self.repos_path, new_parent_path, repo_name]))
316 [self.repos_path, new_parent_path, repo_name]))
314
317
315 if is_valid_repo(repo_path, self.repos_path) is False:
318 if is_valid_repo(repo_path, self.repos_path) is False:
316 log.info('creating repo %s in %s @ %s', repo_name, repo_path,
319 log.info('creating repo %s in %s @ %s', repo_name, repo_path,
317 clone_uri)
320 clone_uri)
318 backend = get_backend(alias)
321 backend = get_backend(alias)
319
322
320 backend(repo_path, create=True, src_url=clone_uri)
323 backend(repo_path, create=True, src_url=clone_uri)
321
324
322
325
323 def __rename_repo(self, old, new):
326 def __rename_repo(self, old, new):
324 """
327 """
325 renames repository on filesystem
328 renames repository on filesystem
326
329
327 :param old: old name
330 :param old: old name
328 :param new: new name
331 :param new: new name
329 """
332 """
330 log.info('renaming repo from %s to %s', old, new)
333 log.info('renaming repo from %s to %s', old, new)
331
334
332 old_path = os.path.join(self.repos_path, old)
335 old_path = os.path.join(self.repos_path, old)
333 new_path = os.path.join(self.repos_path, new)
336 new_path = os.path.join(self.repos_path, new)
334 if os.path.isdir(new_path):
337 if os.path.isdir(new_path):
335 raise Exception('Was trying to rename to already existing dir %s' \
338 raise Exception('Was trying to rename to already existing dir %s' \
336 % new_path)
339 % new_path)
337 shutil.move(old_path, new_path)
340 shutil.move(old_path, new_path)
338
341
339 def __delete_repo(self, repo):
342 def __delete_repo(self, repo):
340 """
343 """
341 removes repo from filesystem, the removal is acctually made by
344 removes repo from filesystem, the removal is acctually made by
342 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
345 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
343 repository is no longer valid for rhodecode, can be undeleted later on
346 repository is no longer valid for rhodecode, can be undeleted later on
344 by reverting the renames on this repository
347 by reverting the renames on this repository
345
348
346 :param repo: repo object
349 :param repo: repo object
347 """
350 """
348 rm_path = os.path.join(self.repos_path, repo.repo_name)
351 rm_path = os.path.join(self.repos_path, repo.repo_name)
349 log.info("Removing %s", rm_path)
352 log.info("Removing %s", rm_path)
350 #disable hg/git
353 #disable hg/git
351 alias = repo.repo_type
354 alias = repo.repo_type
352 shutil.move(os.path.join(rm_path, '.%s' % alias),
355 shutil.move(os.path.join(rm_path, '.%s' % alias),
353 os.path.join(rm_path, 'rm__.%s' % alias))
356 os.path.join(rm_path, 'rm__.%s' % alias))
354 #disable repo
357 #disable repo
355 shutil.move(rm_path, os.path.join(self.repos_path, 'rm__%s__%s' \
358 shutil.move(rm_path, os.path.join(self.repos_path, 'rm__%s__%s' \
356 % (datetime.today()\
359 % (datetime.today()\
357 .strftime('%Y%m%d_%H%M%S_%f'),
360 .strftime('%Y%m%d_%H%M%S_%f'),
358 repo.repo_name)))
361 repo.repo_name)))
General Comments 0
You need to be logged in to leave comments. Login now