Mercurial > kallithea
diff rhodecode/model/hg.py @ 665:070f32743632 beta
Moved out reposcan into hg Model.
Rewrote repo scann and caching of repositories, all is in hgModel.
Changed invalidate cache calls.
mergeds main repo list and repo switcher list into one new based on hgModel.
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Sun, 07 Nov 2010 15:02:56 +0100 |
parents | ffd07396d315 |
children | 4685f3eafd35 |
line wrap: on
line diff
--- a/rhodecode/model/hg.py Sat Nov 06 16:19:01 2010 +0100 +++ b/rhodecode/model/hg.py Sun Nov 07 15:02:56 2010 +0100 @@ -22,57 +22,25 @@ Model for RhodeCode @author: marcink """ -from beaker.cache import cache_region +from beaker.cache import cache_region, region_invalidate from mercurial import ui from rhodecode.lib import helpers as h -from rhodecode.lib.utils import invalidate_cache from rhodecode.lib.auth import HasRepoPermissionAny +from rhodecode.lib.utils import get_repos from rhodecode.model import meta -from rhodecode.model.db import Repository, User +from rhodecode.model.caching_query import FromCache +from rhodecode.model.db import Repository, User, RhodeCodeUi from sqlalchemy.orm import joinedload +from vcs import get_repo as vcs_get_repo, get_backend +from vcs.backends.hg import MercurialRepository from vcs.exceptions import RepositoryError, VCSError +from vcs.utils.lazy import LazyProperty import logging -import sys +import os import time log = logging.getLogger(__name__) -try: - from vcs.backends.hg import MercurialRepository - from vcs.backends.git import GitRepository -except ImportError: - sys.stderr.write('You have to import vcs module') - raise Exception('Unable to import vcs') - -def _get_repos_cached_initial(app_globals, initial): - """return cached dict with repos - """ - g = app_globals - return HgModel().repo_scan(g.paths[0][1], g.baseui, initial) - -@cache_region('long_term', 'cached_repo_list') -def _get_repos_cached(): - """return cached dict with repos - """ - log.info('getting all repositories list') - from pylons import app_globals as g - return HgModel().repo_scan(g.paths[0][1], g.baseui) - -@cache_region('super_short_term', 'cached_repos_switcher_list') -def _get_repos_switcher_cached(cached_repo_list): - repos_lst = [] - for repo in [x for x in cached_repo_list.values()]: - if HasRepoPermissionAny('repository.write', 'repository.read', - 'repository.admin')(repo.name, 'main page check'): - repos_lst.append((repo.name, repo.dbrepo.private,)) - - return sorted(repos_lst, key=lambda k:k[0].lower()) - -@cache_region('long_term', 'full_changelog') -def _full_changelog_cached(repo_name): - log.info('getting full changelog for %s', repo_name) - return list(reversed(list(HgModel().get_repo(repo_name)))) - class HgModel(object): """ Mercurial Model @@ -84,6 +52,16 @@ else: self.sa = sa + + @LazyProperty + def repos_path(self): + """ + Get's the repositories root path from database + """ + q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one() + + return q.ui_value + def repo_scan(self, repos_path, baseui, initial=False): """ Listing of repositories in given path. This path should not be a @@ -91,93 +69,100 @@ :param repos_path: path to directory containing repositories :param baseui - :param initial: initial scann + :param initial: initial scan """ log.info('scanning for repositories in %s', repos_path) if not isinstance(baseui, ui.ui): baseui = ui.ui() - - from rhodecode.lib.utils import get_repos - repos = get_repos(repos_path) - - repos_list = {} - for name, path in repos: + for name, path in get_repos(repos_path): try: - #name = name.split('/')[-1] if repos_list.has_key(name): - raise RepositoryError('Duplicate repository name %s found in' - ' %s' % (name, path)) + raise RepositoryError('Duplicate repository name %s ' + 'found in %s' % (name, path)) else: + + klass = get_backend(path[0]) + if path[0] == 'hg': - repos_list[name] = MercurialRepository(path[1], baseui=baseui) - repos_list[name].name = name + repos_list[name] = klass(path[1], baseui=baseui) if path[0] == 'git': - repos_list[name] = GitRepository(path[1]) - repos_list[name].name = name - - dbrepo = None - if not initial: - #for initial scann on application first run we don't - #have db repos yet. - dbrepo = self.sa.query(Repository)\ - .options(joinedload(Repository.fork))\ - .filter(Repository.repo_name == name)\ - .scalar() - - if dbrepo: - log.info('Adding db instance to cached list') - repos_list[name].dbrepo = dbrepo - repos_list[name].description = dbrepo.description - if dbrepo.user: - repos_list[name].contact = dbrepo.user.full_contact - else: - repos_list[name].contact = self.sa.query(User)\ - .filter(User.admin == True).first().full_contact + repos_list[name] = klass(path[1]) except OSError: continue return repos_list - def get_repos(self): - for name, repo in _get_repos_cached().items(): + def get_repos(self, all_repos=None): + """ + Get all repos from db and for each such repo make backend and + fetch dependent data from db + """ + if not all_repos: + all_repos = self.sa.query(Repository).all() - if isinstance(repo, MercurialRepository) and repo._get_hidden(): - #skip hidden web repository - continue + for r in all_repos: + + repo = self.get(r.repo_name) - last_change = repo.last_change - tip = h.get_changeset_safe(repo, 'tip') + if repo is not None: + last_change = repo.last_change + tip = h.get_changeset_safe(repo, 'tip') - tmp_d = {} - tmp_d['name'] = repo.name - tmp_d['name_sort'] = tmp_d['name'].lower() - tmp_d['description'] = repo.description - tmp_d['description_sort'] = tmp_d['description'] - tmp_d['last_change'] = last_change - tmp_d['last_change_sort'] = time.mktime(last_change.timetuple()) - tmp_d['tip'] = tip.raw_id - tmp_d['tip_sort'] = tip.revision - tmp_d['rev'] = tip.revision - tmp_d['contact'] = repo.contact - tmp_d['contact_sort'] = tmp_d['contact'] - tmp_d['repo_archives'] = list(repo._get_archives()) - tmp_d['last_msg'] = tip.message - tmp_d['repo'] = repo - yield tmp_d + tmp_d = {} + tmp_d['name'] = repo.name + tmp_d['name_sort'] = tmp_d['name'].lower() + tmp_d['description'] = repo.dbrepo.description + tmp_d['description_sort'] = tmp_d['description'] + tmp_d['last_change'] = last_change + tmp_d['last_change_sort'] = time.mktime(last_change.timetuple()) + tmp_d['tip'] = tip.raw_id + tmp_d['tip_sort'] = tip.revision + tmp_d['rev'] = tip.revision + tmp_d['contact'] = repo.dbrepo.user.full_contact + tmp_d['contact_sort'] = tmp_d['contact'] + tmp_d['repo_archives'] = list(repo._get_archives()) + tmp_d['last_msg'] = tip.message + tmp_d['repo'] = repo + yield tmp_d def get_repo(self, repo_name): - try: - repo = _get_repos_cached()[repo_name] - return repo - except KeyError: - #i we're here and we got key errors let's try to invalidate the - #cahce and try again - invalidate_cache('cached_repo_list') - repo = _get_repos_cached()[repo_name] + return self.get(repo_name) + + def get(self, repo_name): + """ + Get's repository from given name, creates BackendInstance and + propagates it's data from database with all additional information + :param repo_name: + """ + if not HasRepoPermissionAny('repository.read', 'repository.write', + 'repository.admin')(repo_name, 'get repo check'): + return + + @cache_region('long_term', 'get_repo_cached_%s' % repo_name) + def _get_repo(repo_name): + + repo = vcs_get_repo(os.path.join(self.repos_path, repo_name), + alias=None, create=False) + + #skip hidden web repository + if isinstance(repo, MercurialRepository) and repo._get_hidden(): + return + + dbrepo = self.sa.query(Repository)\ + .options(joinedload(Repository.fork))\ + .options(joinedload(Repository.user))\ + .filter(Repository.repo_name == repo_name)\ + .scalar() + repo.dbrepo = dbrepo return repo + invalidate = False + if invalidate: + log.info('INVALIDATING CACHE FOR %s', repo_name) + region_invalidate(_get_repo, None, repo_name) + return _get_repo(repo_name)