comparison rhodecode/lib/utils.py @ 2776:63e58ef80ef1

Merge beta branch into stable
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 02 Sep 2012 21:19:54 +0200
parents a437a986d399 dd240b2b7a12
children 9ae95fdeca18
comparison
equal deleted inserted replaced
2301:9d097c2592d3 2776:63e58ef80ef1
49 49
50 from rhodecode.lib.caching_query import FromCache 50 from rhodecode.lib.caching_query import FromCache
51 51
52 from rhodecode.model import meta 52 from rhodecode.model import meta
53 from rhodecode.model.db import Repository, User, RhodeCodeUi, \ 53 from rhodecode.model.db import Repository, User, RhodeCodeUi, \
54 UserLog, RepoGroup, RhodeCodeSetting, UserRepoGroupToPerm,\ 54 UserLog, RepoGroup, RhodeCodeSetting, CacheInvalidation
55 CacheInvalidation
56 from rhodecode.model.meta import Session 55 from rhodecode.model.meta import Session
57 from rhodecode.model.repos_group import ReposGroupModel 56 from rhodecode.model.repos_group import ReposGroupModel
58 from rhodecode.lib.utils2 import safe_str, safe_unicode 57 from rhodecode.lib.utils2 import safe_str, safe_unicode
59 from rhodecode.lib.vcs.utils.fakemod import create_module 58 from rhodecode.lib.vcs.utils.fakemod import create_module
60 59
127 :param sa: optional sqlalchemy session 126 :param sa: optional sqlalchemy session
128 127
129 """ 128 """
130 129
131 if not sa: 130 if not sa:
132 sa = meta.Session 131 sa = meta.Session()
133 132
134 try: 133 try:
135 if hasattr(user, 'user_id'): 134 if hasattr(user, 'user_id'):
136 user_obj = user 135 user_obj = user
137 elif isinstance(user, basestring): 136 elif isinstance(user, basestring):
144 repo_name = repo_obj.repo_name 143 repo_name = repo_obj.repo_name
145 elif isinstance(repo, basestring): 144 elif isinstance(repo, basestring):
146 repo_name = repo.lstrip('/') 145 repo_name = repo.lstrip('/')
147 repo_obj = Repository.get_by_repo_name(repo_name) 146 repo_obj = Repository.get_by_repo_name(repo_name)
148 else: 147 else:
149 raise Exception('You have to provide repository to action logger') 148 repo_obj = None
149 repo_name = ''
150 150
151 user_log = UserLog() 151 user_log = UserLog()
152 user_log.user_id = user_obj.user_id 152 user_log.user_id = user_obj.user_id
153 user_log.action = safe_unicode(action) 153 user_log.action = safe_unicode(action)
154 154
155 user_log.repository_id = repo_obj.repo_id 155 user_log.repository = repo_obj
156 user_log.repository_name = repo_name 156 user_log.repository_name = repo_name
157 157
158 user_log.action_date = datetime.datetime.now() 158 user_log.action_date = datetime.datetime.now()
159 user_log.user_ip = ipaddr 159 user_log.user_ip = ipaddr
160 sa.add(user_log) 160 sa.add(user_log)
201 yield inner_scm 201 yield inner_scm
202 202
203 return _get_repos(path) 203 return _get_repos(path)
204 204
205 205
206 def is_valid_repo(repo_name, base_path): 206 def is_valid_repo(repo_name, base_path, scm=None):
207 """ 207 """
208 Returns True if given path is a valid repository False otherwise 208 Returns True if given path is a valid repository False otherwise.
209 If scm param is given also compare if given scm is the same as expected
210 from scm parameter
209 211
210 :param repo_name: 212 :param repo_name:
211 :param base_path: 213 :param base_path:
214 :param scm:
212 215
213 :return True: if given path is a valid repository 216 :return True: if given path is a valid repository
214 """ 217 """
215 full_path = os.path.join(safe_str(base_path), safe_str(repo_name)) 218 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
216 219
217 try: 220 try:
218 get_scm(full_path) 221 scm_ = get_scm(full_path)
222 if scm:
223 return scm_[0] == scm
219 return True 224 return True
220 except VCSError: 225 except VCSError:
221 return False 226 return False
222 227
223 228
231 full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name)) 236 full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name))
232 237
233 # check if it's not a repo 238 # check if it's not a repo
234 if is_valid_repo(repos_group_name, base_path): 239 if is_valid_repo(repos_group_name, base_path):
235 return False 240 return False
241
242 try:
243 # we need to check bare git repos at higher level
244 # since we might match branches/hooks/info/objects or possible
245 # other things inside bare git repo
246 get_scm(os.path.dirname(full_path))
247 return False
248 except VCSError:
249 pass
236 250
237 # check if it's a valid path 251 # check if it's a valid path
238 if os.path.isdir(full_path): 252 if os.path.isdir(full_path):
239 return True 253 return True
240 254
264 'paths', 'profiling', 278 'paths', 'profiling',
265 'server', 'trusted', 279 'server', 'trusted',
266 'ui', 'web', ] 280 'ui', 'web', ]
267 281
268 282
269 def make_ui(read_from='file', path=None, checkpaths=True): 283 def make_ui(read_from='file', path=None, checkpaths=True, clear_session=True):
270 """ 284 """
271 A function that will read python rc files or database 285 A function that will read python rc files or database
272 and make an mercurial ui object from read options 286 and make an mercurial ui object from read options
273 287
274 :param path: path to mercurial config file 288 :param path: path to mercurial config file
294 for k, v in cfg.items(section): 308 for k, v in cfg.items(section):
295 log.debug('settings ui from file[%s]%s:%s' % (section, k, v)) 309 log.debug('settings ui from file[%s]%s:%s' % (section, k, v))
296 baseui.setconfig(section, k, v) 310 baseui.setconfig(section, k, v)
297 311
298 elif read_from == 'db': 312 elif read_from == 'db':
299 sa = meta.Session 313 sa = meta.Session()
300 ret = sa.query(RhodeCodeUi)\ 314 ret = sa.query(RhodeCodeUi)\
301 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\ 315 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
302 .all() 316 .all()
303 317
304 hg_ui = ret 318 hg_ui = ret
305 for ui_ in hg_ui: 319 for ui_ in hg_ui:
306 if ui_.ui_active: 320 if ui_.ui_active:
307 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section, 321 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
308 ui_.ui_key, ui_.ui_value) 322 ui_.ui_key, ui_.ui_value)
309 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value) 323 baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
310 324 if ui_.ui_key == 'push_ssl':
311 meta.Session.remove() 325 # force set push_ssl requirement to False, rhodecode
326 # handles that
327 baseui.setconfig(ui_.ui_section, ui_.ui_key, False)
328 if clear_session:
329 meta.Session.remove()
312 return baseui 330 return baseui
313 331
314 332
315 def set_rhodecode_config(config): 333 def set_rhodecode_config(config):
316 """ 334 """
335 if cache_key.startswith('get_repo_cached_'): 353 if cache_key.startswith('get_repo_cached_'):
336 name = cache_key.split('get_repo_cached_')[-1] 354 name = cache_key.split('get_repo_cached_')[-1]
337 ScmModel().mark_for_invalidation(name) 355 ScmModel().mark_for_invalidation(name)
338 356
339 357
340 class EmptyChangeset(BaseChangeset):
341 """
342 An dummy empty changeset. It's possible to pass hash when creating
343 an EmptyChangeset
344 """
345
346 def __init__(self, cs='0' * 40, repo=None, requested_revision=None,
347 alias=None):
348 self._empty_cs = cs
349 self.revision = -1
350 self.message = ''
351 self.author = ''
352 self.date = ''
353 self.repository = repo
354 self.requested_revision = requested_revision
355 self.alias = alias
356
357 @LazyProperty
358 def raw_id(self):
359 """
360 Returns raw string identifying this changeset, useful for web
361 representation.
362 """
363
364 return self._empty_cs
365
366 @LazyProperty
367 def branch(self):
368 return get_backend(self.alias).DEFAULT_BRANCH_NAME
369
370 @LazyProperty
371 def short_id(self):
372 return self.raw_id[:12]
373
374 def get_file_changeset(self, path):
375 return self
376
377 def get_file_content(self, path):
378 return u''
379
380 def get_file_size(self, path):
381 return 0
382
383
384 def map_groups(path): 358 def map_groups(path):
385 """ 359 """
386 Given a full path to a repository, create all nested groups that this 360 Given a full path to a repository, create all nested groups that this
387 repo is inside. This function creates parent-child relationships between 361 repo is inside. This function creates parent-child relationships between
388 groups and creates default perms for all new groups. 362 groups and creates default perms for all new groups.
389 363
390 :param paths: full path to repository 364 :param paths: full path to repository
391 """ 365 """
392 sa = meta.Session 366 sa = meta.Session()
393 groups = path.split(Repository.url_sep()) 367 groups = path.split(Repository.url_sep())
394 parent = None 368 parent = None
395 group = None 369 group = None
396 370
397 # last element is repo in nested groups structure 371 # last element is repo in nested groups structure
416 sa.flush() 390 sa.flush()
417 parent = group 391 parent = group
418 return group 392 return group
419 393
420 394
421 def repo2db_mapper(initial_repo_list, remove_obsolete=False): 395 def repo2db_mapper(initial_repo_list, remove_obsolete=False,
396 install_git_hook=False):
422 """ 397 """
423 maps all repos given in initial_repo_list, non existing repositories 398 maps all repos given in initial_repo_list, non existing repositories
424 are created, if remove_obsolete is True it also check for db entries 399 are created, if remove_obsolete is True it also check for db entries
425 that are not in initial_repo_list and removes them. 400 that are not in initial_repo_list and removes them.
426 401
427 :param initial_repo_list: list of repositories found by scanning methods 402 :param initial_repo_list: list of repositories found by scanning methods
428 :param remove_obsolete: check for obsolete entries in database 403 :param remove_obsolete: check for obsolete entries in database
404 :param install_git_hook: if this is True, also check and install githook
405 for a repo if missing
429 """ 406 """
430 from rhodecode.model.repo import RepoModel 407 from rhodecode.model.repo import RepoModel
431 sa = meta.Session 408 from rhodecode.model.scm import ScmModel
409 sa = meta.Session()
432 rm = RepoModel() 410 rm = RepoModel()
433 user = sa.query(User).filter(User.admin == True).first() 411 user = sa.query(User).filter(User.admin == True).first()
434 if user is None: 412 if user is None:
435 raise Exception('Missing administrative account !') 413 raise Exception('Missing administrative account !')
436 added = [] 414 added = []
437 415
438 for name, repo in initial_repo_list.items(): 416 for name, repo in initial_repo_list.items():
439 group = map_groups(name) 417 group = map_groups(name)
440 if not rm.get_by_repo_name(name, cache=False): 418 db_repo = rm.get_by_repo_name(name)
441 log.info('repository %s not found creating default' % name) 419 # found repo that is on filesystem not in RhodeCode database
420 if not db_repo:
421 log.info('repository %s not found creating now' % name)
442 added.append(name) 422 added.append(name)
443 form_data = { 423 desc = (repo.description
444 'repo_name': name, 424 if repo.description != 'unknown'
445 'repo_name_full': name, 425 else '%s repository' % name)
446 'repo_type': repo.alias, 426 new_repo = rm.create_repo(
447 'description': repo.description \ 427 repo_name=name,
448 if repo.description != 'unknown' else '%s repository' % name, 428 repo_type=repo.alias,
449 'private': False, 429 description=desc,
450 'group_id': getattr(group, 'group_id', None) 430 repos_group=getattr(group, 'group_id', None),
451 } 431 owner=user,
452 rm.create(form_data, user, just_db=True) 432 just_db=True
433 )
434 # we added that repo just now, and make sure it has githook
435 # installed
436 if new_repo.repo_type == 'git':
437 ScmModel().install_git_hook(new_repo.scm_instance)
438 elif install_git_hook:
439 if db_repo.repo_type == 'git':
440 ScmModel().install_git_hook(db_repo.scm_instance)
453 sa.commit() 441 sa.commit()
454 removed = [] 442 removed = []
455 if remove_obsolete: 443 if remove_obsolete:
456 # remove from database those repositories that are not in the filesystem 444 # remove from database those repositories that are not in the filesystem
457 for repo in sa.query(Repository).all(): 445 for repo in sa.query(Repository).all():
458 if repo.repo_name not in initial_repo_list.keys(): 446 if repo.repo_name not in initial_repo_list.keys():
459 log.debug("Removing non existing repository found in db %s" % 447 log.debug("Removing non existing repository found in db `%s`" %
460 repo.repo_name) 448 repo.repo_name)
461 removed.append(repo.repo_name) 449 try:
462 sa.delete(repo) 450 sa.delete(repo)
463 sa.commit() 451 sa.commit()
452 removed.append(repo.repo_name)
453 except:
454 #don't hold further removals on error
455 log.error(traceback.format_exc())
456 sa.rollback()
464 457
465 # clear cache keys 458 # clear cache keys
466 log.debug("Clearing cache keys now...") 459 log.debug("Clearing cache keys now...")
467 CacheInvalidation.clear_cache() 460 CacheInvalidation.clear_cache()
468 sa.commit() 461 sa.commit()
555 """ 548 """
556 Makes a fresh database and 549 Makes a fresh database and
557 install test repository into tmp dir 550 install test repository into tmp dir
558 """ 551 """
559 from rhodecode.lib.db_manage import DbManage 552 from rhodecode.lib.db_manage import DbManage
560 from rhodecode.tests import HG_REPO, TESTS_TMP_PATH 553 from rhodecode.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH
561 554
562 # PART ONE create db 555 # PART ONE create db
563 dbconf = config['sqlalchemy.db1.url'] 556 dbconf = config['sqlalchemy.db1.url']
564 log.debug('making test db %s' % dbconf) 557 log.debug('making test db %s' % dbconf)
565 558
574 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path)) 567 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
575 dbmanage.create_default_user() 568 dbmanage.create_default_user()
576 dbmanage.admin_prompt() 569 dbmanage.admin_prompt()
577 dbmanage.create_permissions() 570 dbmanage.create_permissions()
578 dbmanage.populate_default_permissions() 571 dbmanage.populate_default_permissions()
579 Session.commit() 572 Session().commit()
580 # PART TWO make test repo 573 # PART TWO make test repo
581 log.debug('making test vcs repositories') 574 log.debug('making test vcs repositories')
582 575
583 idx_path = config['app_conf']['index_dir'] 576 idx_path = config['app_conf']['index_dir']
584 data_path = config['app_conf']['cache_dir'] 577 data_path = config['app_conf']['cache_dir']
590 583
591 if data_path and os.path.exists(data_path): 584 if data_path and os.path.exists(data_path):
592 log.debug('remove %s' % data_path) 585 log.debug('remove %s' % data_path)
593 shutil.rmtree(data_path) 586 shutil.rmtree(data_path)
594 587
595 #CREATE DEFAULT HG REPOSITORY 588 #CREATE DEFAULT TEST REPOS
596 cur_dir = dn(dn(abspath(__file__))) 589 cur_dir = dn(dn(abspath(__file__)))
597 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz")) 590 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
598 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO)) 591 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
599 tar.close() 592 tar.close()
593
594 cur_dir = dn(dn(abspath(__file__)))
595 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_git.tar.gz"))
596 tar.extractall(jn(TESTS_TMP_PATH, GIT_REPO))
597 tar.close()
598
599 #LOAD VCS test stuff
600 from rhodecode.tests.vcs import setup_package
601 setup_package()
600 602
601 603
602 #============================================================================== 604 #==============================================================================
603 # PASTER COMMANDS 605 # PASTER COMMANDS
604 #============================================================================== 606 #==============================================================================