##// END OF EJS Templates
init bare repos for git now by default. This is recommended setup for remotes repositories
marcink -
r2321:75280665 beta
parent child Browse files
Show More
@@ -1,499 +1,503 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.repo
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Repository model for rhodecode
7 7
8 8 :created_on: Jun 5, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 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 import os
26 26 import shutil
27 27 import logging
28 28 import traceback
29 29 from datetime import datetime
30 30
31 31 from rhodecode.lib.vcs.backends import get_backend
32 32 from rhodecode.lib.compat import json
33 33 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode
34 34 from rhodecode.lib.caching_query import FromCache
35 35 from rhodecode.lib.hooks import log_create_repository
36 36
37 37 from rhodecode.model import BaseModel
38 38 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
39 39 Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup
40 40 from rhodecode.lib import helpers as h
41 41
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46 46 class RepoModel(BaseModel):
47 47
48 48 def __get_user(self, user):
49 49 return self._get_instance(User, user, callback=User.get_by_username)
50 50
51 51 def __get_users_group(self, users_group):
52 52 return self._get_instance(UsersGroup, users_group,
53 53 callback=UsersGroup.get_by_group_name)
54 54
55 55 def __get_repos_group(self, repos_group):
56 56 return self._get_instance(RepoGroup, repos_group,
57 57 callback=RepoGroup.get_by_group_name)
58 58
59 59 def __get_repo(self, repository):
60 60 return self._get_instance(Repository, repository,
61 61 callback=Repository.get_by_repo_name)
62 62
63 63 def __get_perm(self, permission):
64 64 return self._get_instance(Permission, permission,
65 65 callback=Permission.get_by_key)
66 66
67 67 @LazyProperty
68 68 def repos_path(self):
69 69 """
70 70 Get's the repositories root path from database
71 71 """
72 72
73 73 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
74 74 return q.ui_value
75 75
76 76 def get(self, repo_id, cache=False):
77 77 repo = self.sa.query(Repository)\
78 78 .filter(Repository.repo_id == repo_id)
79 79
80 80 if cache:
81 81 repo = repo.options(FromCache("sql_cache_short",
82 82 "get_repo_%s" % repo_id))
83 83 return repo.scalar()
84 84
85 85 def get_repo(self, repository):
86 86 return self.__get_repo(repository)
87 87
88 88 def get_by_repo_name(self, repo_name, cache=False):
89 89 repo = self.sa.query(Repository)\
90 90 .filter(Repository.repo_name == repo_name)
91 91
92 92 if cache:
93 93 repo = repo.options(FromCache("sql_cache_short",
94 94 "get_repo_%s" % repo_name))
95 95 return repo.scalar()
96 96
97 97 def get_users_js(self):
98 98 users = self.sa.query(User).filter(User.active == True).all()
99 99 return json.dumps([
100 100 {
101 101 'id': u.user_id,
102 102 'fname': u.name,
103 103 'lname': u.lastname,
104 104 'nname': u.username,
105 105 'gravatar_lnk': h.gravatar_url(u.email, 14)
106 106 } for u in users]
107 107 )
108 108
109 109 def get_users_groups_js(self):
110 110 users_groups = self.sa.query(UsersGroup)\
111 111 .filter(UsersGroup.users_group_active == True).all()
112 112
113 113 return json.dumps([
114 114 {
115 115 'id': gr.users_group_id,
116 116 'grname': gr.users_group_name,
117 117 'grmembers': len(gr.members),
118 118 } for gr in users_groups]
119 119 )
120 120
121 121 def _get_defaults(self, repo_name):
122 122 """
123 123 Get's information about repository, and returns a dict for
124 124 usage in forms
125 125
126 126 :param repo_name:
127 127 """
128 128
129 129 repo_info = Repository.get_by_repo_name(repo_name)
130 130
131 131 if repo_info is None:
132 132 return None
133 133
134 134 defaults = repo_info.get_dict()
135 135 group, repo_name = repo_info.groups_and_repo
136 136 defaults['repo_name'] = repo_name
137 137 defaults['repo_group'] = getattr(group[-1] if group else None,
138 138 'group_id', None)
139 139
140 140 # fill owner
141 141 if repo_info.user:
142 142 defaults.update({'user': repo_info.user.username})
143 143 else:
144 144 replacement_user = User.query().filter(User.admin ==
145 145 True).first().username
146 146 defaults.update({'user': replacement_user})
147 147
148 148 # fill repository users
149 149 for p in repo_info.repo_to_perm:
150 150 defaults.update({'u_perm_%s' % p.user.username:
151 151 p.permission.permission_name})
152 152
153 153 # fill repository groups
154 154 for p in repo_info.users_group_to_perm:
155 155 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
156 156 p.permission.permission_name})
157 157
158 158 return defaults
159 159
160 160 def update(self, repo_name, form_data):
161 161 try:
162 162 cur_repo = self.get_by_repo_name(repo_name, cache=False)
163 163
164 164 # update permissions
165 165 for member, perm, member_type in form_data['perms_updates']:
166 166 if member_type == 'user':
167 167 # this updates existing one
168 168 RepoModel().grant_user_permission(
169 169 repo=cur_repo, user=member, perm=perm
170 170 )
171 171 else:
172 172 RepoModel().grant_users_group_permission(
173 173 repo=cur_repo, group_name=member, perm=perm
174 174 )
175 175 # set new permissions
176 176 for member, perm, member_type in form_data['perms_new']:
177 177 if member_type == 'user':
178 178 RepoModel().grant_user_permission(
179 179 repo=cur_repo, user=member, perm=perm
180 180 )
181 181 else:
182 182 RepoModel().grant_users_group_permission(
183 183 repo=cur_repo, group_name=member, perm=perm
184 184 )
185 185
186 186 # update current repo
187 187 for k, v in form_data.items():
188 188 if k == 'user':
189 189 cur_repo.user = User.get_by_username(v)
190 190 elif k == 'repo_name':
191 191 pass
192 192 elif k == 'repo_group':
193 193 cur_repo.group = RepoGroup.get(v)
194 194
195 195 else:
196 196 setattr(cur_repo, k, v)
197 197
198 198 new_name = cur_repo.get_new_name(form_data['repo_name'])
199 199 cur_repo.repo_name = new_name
200 200
201 201 self.sa.add(cur_repo)
202 202
203 203 if repo_name != new_name:
204 204 # rename repository
205 205 self.__rename_repo(old=repo_name, new=new_name)
206 206
207 207 return cur_repo
208 208 except:
209 209 log.error(traceback.format_exc())
210 210 raise
211 211
212 212 def create(self, form_data, cur_user, just_db=False, fork=False):
213 213 from rhodecode.model.scm import ScmModel
214 214
215 215 try:
216 216 if fork:
217 217 fork_parent_id = form_data['fork_parent_id']
218 218
219 219 # repo name is just a name of repository
220 220 # while repo_name_full is a full qualified name that is combined
221 221 # with name and path of group
222 222 repo_name = form_data['repo_name']
223 223 repo_name_full = form_data['repo_name_full']
224 224
225 225 new_repo = Repository()
226 226 new_repo.enable_statistics = False
227 227
228 228 for k, v in form_data.items():
229 229 if k == 'repo_name':
230 230 v = repo_name_full
231 231 if k == 'repo_group':
232 232 k = 'group_id'
233 233 if k == 'description':
234 234 v = v or repo_name
235 235
236 236 setattr(new_repo, k, v)
237 237
238 238 if fork:
239 239 parent_repo = Repository.get(fork_parent_id)
240 240 new_repo.fork = parent_repo
241 241
242 242 new_repo.user_id = cur_user.user_id
243 243 self.sa.add(new_repo)
244 244
245 245 def _create_default_perms():
246 246 # create default permission
247 247 repo_to_perm = UserRepoToPerm()
248 248 default = 'repository.read'
249 249 for p in User.get_by_username('default').user_perms:
250 250 if p.permission.permission_name.startswith('repository.'):
251 251 default = p.permission.permission_name
252 252 break
253 253
254 254 default_perm = 'repository.none' if form_data['private'] else default
255 255
256 256 repo_to_perm.permission_id = self.sa.query(Permission)\
257 257 .filter(Permission.permission_name == default_perm)\
258 258 .one().permission_id
259 259
260 260 repo_to_perm.repository = new_repo
261 261 repo_to_perm.user_id = User.get_by_username('default').user_id
262 262
263 263 self.sa.add(repo_to_perm)
264 264
265 265 if fork:
266 266 if form_data.get('copy_permissions'):
267 267 repo = Repository.get(fork_parent_id)
268 268 user_perms = UserRepoToPerm.query()\
269 269 .filter(UserRepoToPerm.repository == repo).all()
270 270 group_perms = UsersGroupRepoToPerm.query()\
271 271 .filter(UsersGroupRepoToPerm.repository == repo).all()
272 272
273 273 for perm in user_perms:
274 274 UserRepoToPerm.create(perm.user, new_repo,
275 275 perm.permission)
276 276
277 277 for perm in group_perms:
278 278 UsersGroupRepoToPerm.create(perm.users_group, new_repo,
279 279 perm.permission)
280 280 else:
281 281 _create_default_perms()
282 282 else:
283 283 _create_default_perms()
284 284
285 285 if not just_db:
286 286 self.__create_repo(repo_name, form_data['repo_type'],
287 287 form_data['repo_group'],
288 288 form_data['clone_uri'])
289 289 log_create_repository(new_repo.get_dict(),
290 290 created_by=cur_user.username)
291 291
292 292 # now automatically start following this repository as owner
293 293 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
294 294 cur_user.user_id)
295 295 return new_repo
296 296 except:
297 297 log.error(traceback.format_exc())
298 298 raise
299 299
300 300 def create_fork(self, form_data, cur_user):
301 301 """
302 302 Simple wrapper into executing celery task for fork creation
303 303
304 304 :param form_data:
305 305 :param cur_user:
306 306 """
307 307 from rhodecode.lib.celerylib import tasks, run_task
308 308 run_task(tasks.create_repo_fork, form_data, cur_user)
309 309
310 310 def delete(self, repo):
311 311 repo = self.__get_repo(repo)
312 312 try:
313 313 self.sa.delete(repo)
314 314 self.__delete_repo(repo)
315 315 except:
316 316 log.error(traceback.format_exc())
317 317 raise
318 318
319 319 def grant_user_permission(self, repo, user, perm):
320 320 """
321 321 Grant permission for user on given repository, or update existing one
322 322 if found
323 323
324 324 :param repo: Instance of Repository, repository_id, or repository name
325 325 :param user: Instance of User, user_id or username
326 326 :param perm: Instance of Permission, or permission_name
327 327 """
328 328 user = self.__get_user(user)
329 329 repo = self.__get_repo(repo)
330 330 permission = self.__get_perm(perm)
331 331
332 332 # check if we have that permission already
333 333 obj = self.sa.query(UserRepoToPerm)\
334 334 .filter(UserRepoToPerm.user == user)\
335 335 .filter(UserRepoToPerm.repository == repo)\
336 336 .scalar()
337 337 if obj is None:
338 338 # create new !
339 339 obj = UserRepoToPerm()
340 340 obj.repository = repo
341 341 obj.user = user
342 342 obj.permission = permission
343 343 self.sa.add(obj)
344 344
345 345 def revoke_user_permission(self, repo, user):
346 346 """
347 347 Revoke permission for user on given repository
348 348
349 349 :param repo: Instance of Repository, repository_id, or repository name
350 350 :param user: Instance of User, user_id or username
351 351 """
352 352
353 353 user = self.__get_user(user)
354 354 repo = self.__get_repo(repo)
355 355
356 356 obj = self.sa.query(UserRepoToPerm)\
357 357 .filter(UserRepoToPerm.repository == repo)\
358 358 .filter(UserRepoToPerm.user == user)\
359 359 .one()
360 360 self.sa.delete(obj)
361 361
362 362 def grant_users_group_permission(self, repo, group_name, perm):
363 363 """
364 364 Grant permission for users group on given repository, or update
365 365 existing one if found
366 366
367 367 :param repo: Instance of Repository, repository_id, or repository name
368 368 :param group_name: Instance of UserGroup, users_group_id,
369 369 or users group name
370 370 :param perm: Instance of Permission, or permission_name
371 371 """
372 372 repo = self.__get_repo(repo)
373 373 group_name = self.__get_users_group(group_name)
374 374 permission = self.__get_perm(perm)
375 375
376 376 # check if we have that permission already
377 377 obj = self.sa.query(UsersGroupRepoToPerm)\
378 378 .filter(UsersGroupRepoToPerm.users_group == group_name)\
379 379 .filter(UsersGroupRepoToPerm.repository == repo)\
380 380 .scalar()
381 381
382 382 if obj is None:
383 383 # create new
384 384 obj = UsersGroupRepoToPerm()
385 385
386 386 obj.repository = repo
387 387 obj.users_group = group_name
388 388 obj.permission = permission
389 389 self.sa.add(obj)
390 390
391 391 def revoke_users_group_permission(self, repo, group_name):
392 392 """
393 393 Revoke permission for users group on given repository
394 394
395 395 :param repo: Instance of Repository, repository_id, or repository name
396 396 :param group_name: Instance of UserGroup, users_group_id,
397 397 or users group name
398 398 """
399 399 repo = self.__get_repo(repo)
400 400 group_name = self.__get_users_group(group_name)
401 401
402 402 obj = self.sa.query(UsersGroupRepoToPerm)\
403 403 .filter(UsersGroupRepoToPerm.repository == repo)\
404 404 .filter(UsersGroupRepoToPerm.users_group == group_name)\
405 405 .one()
406 406 self.sa.delete(obj)
407 407
408 408 def delete_stats(self, repo_name):
409 409 """
410 410 removes stats for given repo
411 411
412 412 :param repo_name:
413 413 """
414 414 try:
415 415 obj = self.sa.query(Statistics)\
416 416 .filter(Statistics.repository ==
417 417 self.get_by_repo_name(repo_name))\
418 418 .one()
419 419 self.sa.delete(obj)
420 420 except:
421 421 log.error(traceback.format_exc())
422 422 raise
423 423
424 424 def __create_repo(self, repo_name, alias, new_parent_id, clone_uri=False):
425 425 """
426 426 makes repository on filesystem. It's group aware means it'll create
427 427 a repository within a group, and alter the paths accordingly of
428 428 group location
429 429
430 430 :param repo_name:
431 431 :param alias:
432 432 :param parent_id:
433 433 :param clone_uri:
434 434 """
435 435 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
436 436
437 437 if new_parent_id:
438 438 paths = RepoGroup.get(new_parent_id)\
439 439 .full_path.split(RepoGroup.url_sep())
440 440 new_parent_path = os.sep.join(paths)
441 441 else:
442 442 new_parent_path = ''
443 443
444 444 # we need to make it str for mercurial
445 445 repo_path = os.path.join(*map(lambda x: safe_str(x),
446 446 [self.repos_path, new_parent_path, repo_name]))
447 447
448 448 # check if this path is not a repository
449 449 if is_valid_repo(repo_path, self.repos_path):
450 450 raise Exception('This path %s is a valid repository' % repo_path)
451 451
452 452 # check if this path is a group
453 453 if is_valid_repos_group(repo_path, self.repos_path):
454 454 raise Exception('This path %s is a valid group' % repo_path)
455 455
456 456 log.info('creating repo %s in %s @ %s' % (
457 457 repo_name, safe_unicode(repo_path), clone_uri
458 458 )
459 459 )
460 460 backend = get_backend(alias)
461
462 backend(repo_path, create=True, src_url=clone_uri)
461 if alias == 'hg':
462 backend(repo_path, create=True, src_url=clone_uri)
463 elif alias == 'git':
464 backend(repo_path, create=True, src_url=clone_uri, bare=True)
465 else:
466 raise Exception('Undefined alias %s' % alias)
463 467
464 468 def __rename_repo(self, old, new):
465 469 """
466 470 renames repository on filesystem
467 471
468 472 :param old: old name
469 473 :param new: new name
470 474 """
471 475 log.info('renaming repo from %s to %s' % (old, new))
472 476
473 477 old_path = os.path.join(self.repos_path, old)
474 478 new_path = os.path.join(self.repos_path, new)
475 479 if os.path.isdir(new_path):
476 480 raise Exception(
477 481 'Was trying to rename to already existing dir %s' % new_path
478 482 )
479 483 shutil.move(old_path, new_path)
480 484
481 485 def __delete_repo(self, repo):
482 486 """
483 487 removes repo from filesystem, the removal is acctually made by
484 488 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
485 489 repository is no longer valid for rhodecode, can be undeleted later on
486 490 by reverting the renames on this repository
487 491
488 492 :param repo: repo object
489 493 """
490 494 rm_path = os.path.join(self.repos_path, repo.repo_name)
491 495 log.info("Removing %s" % (rm_path))
492 496 # disable hg/git
493 497 alias = repo.repo_type
494 498 shutil.move(os.path.join(rm_path, '.%s' % alias),
495 499 os.path.join(rm_path, 'rm__.%s' % alias))
496 500 # disable repo
497 501 _d = 'rm__%s__%s' % (datetime.now().strftime('%Y%m%d_%H%M%S_%f'),
498 502 repo.repo_name)
499 503 shutil.move(rm_path, os.path.join(self.repos_path, _d))
General Comments 0
You need to be logged in to leave comments. Login now