hg.py
183 lines
| 6.5 KiB
| text/x-python
|
PythonLexer
r629 | #!/usr/bin/env python | |||
# encoding: utf-8 | ||||
# Model for RhodeCode | ||||
# Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com> | ||||
# | ||||
# This program is free software; you can redistribute it and/or | ||||
# modify it under the terms of the GNU General Public License | ||||
# as published by the Free Software Foundation; version 2 | ||||
# of the License or (at your opinion) any later version of the license. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU General Public License | ||||
# along with this program; if not, write to the Free Software | ||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||||
# MA 02110-1301, USA. | ||||
""" | ||||
Created on April 9, 2010 | ||||
Model for RhodeCode | ||||
@author: marcink | ||||
""" | ||||
from beaker.cache import cache_region | ||||
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.model import meta | ||||
from rhodecode.model.db import Repository, User | ||||
from sqlalchemy.orm import joinedload | ||||
from vcs.exceptions import RepositoryError, VCSError | ||||
import logging | ||||
import sys | ||||
r633 | import time | |||
r629 | log = logging.getLogger(__name__) | |||
try: | ||||
from vcs.backends.hg import MercurialRepository | ||||
r631 | from vcs.backends.git import GitRepository | |||
r629 | 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 | ||||
r631 | return HgModel().repo_scan(g.paths[0][1], g.baseui, initial) | |||
r629 | ||||
@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 | ||||
r631 | return HgModel().repo_scan(g.paths[0][1], g.baseui) | |||
r629 | ||||
@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): | ||||
r631 | """ | |||
Mercurial Model | ||||
r629 | """ | |||
r631 | def __init__(self, sa=None): | |||
if not sa: | ||||
self.sa = meta.Session() | ||||
else: | ||||
self.sa = sa | ||||
r629 | ||||
r631 | def repo_scan(self, repos_path, baseui, initial=False): | |||
r629 | """ | |||
Listing of repositories in given path. This path should not be a | ||||
repository itself. Return a dictionary of repository objects | ||||
r631 | ||||
:param repos_path: path to directory containing repositories | ||||
:param baseui | ||||
:param initial: initial scann | ||||
r629 | """ | |||
r631 | log.info('scanning for repositories in %s', repos_path) | |||
r629 | ||||
if not isinstance(baseui, ui.ui): | ||||
baseui = ui.ui() | ||||
r631 | from rhodecode.lib.utils import get_repos | |||
repos = get_repos(repos_path) | ||||
r629 | repos_list = {} | |||
for name, path in repos: | ||||
try: | ||||
#name = name.split('/')[-1] | ||||
if repos_list.has_key(name): | ||||
raise RepositoryError('Duplicate repository name %s found in' | ||||
' %s' % (name, path)) | ||||
else: | ||||
r631 | if path[0] == 'hg': | |||
repos_list[name] = MercurialRepository(path[1], baseui=baseui) | ||||
repos_list[name].name = name | ||||
r629 | ||||
r631 | if path[0] == 'git': | |||
repos_list[name] = GitRepository(path[1]) | ||||
repos_list[name].name = name | ||||
r629 | ||||
dbrepo = None | ||||
if not initial: | ||||
#for initial scann on application first run we don't | ||||
#have db repos yet. | ||||
r631 | dbrepo = self.sa.query(Repository)\ | |||
r629 | .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: | ||||
r631 | repos_list[name].contact = self.sa.query(User)\ | |||
r629 | .filter(User.admin == True).first().full_contact | |||
except OSError: | ||||
continue | ||||
r631 | ||||
r629 | return repos_list | |||
def get_repos(self): | ||||
for name, repo in _get_repos_cached().items(): | ||||
r631 | ||||
if isinstance(repo, MercurialRepository) and repo._get_hidden(): | ||||
r629 | #skip hidden web repository | |||
continue | ||||
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 | ||||
r633 | tmp_d['last_change_sort'] = time.mktime(last_change.timetuple()) | |||
r636 | tmp_d['tip'] = tip.raw_id | |||
r629 | 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 | ||||
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 repo | ||||