##// END OF EJS Templates
fixes for stable
fixes for stable

File last commit:

r1216:8363b0d2 default
r1216:8363b0d2 default
Show More
scm.py
380 lines | 12.6 KiB | text/x-python | PythonLexer
rolled back to make transient since got some exceptions on expunge...
r757 # -*- coding: utf-8 -*-
"""
docs updates
r811 rhodecode.model.scm
~~~~~~~~~~~~~~~~~~~
rolled back to make transient since got some exceptions on expunge...
r757
docs updates
r811 Scm model for RhodeCode
rolled back to make transient since got some exceptions on expunge...
r757 :created_on: Apr 9, 2010
:author: marcink
fixes for stable
r1216 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
rolled back to make transient since got some exceptions on expunge...
r757 :license: GPLv3, see COPYING for more details.
"""
fixes for stable
r1216 # 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, either version 3 of the License, or
# (at your option) any later version.
#
Refactor codes for scm model...
r691 # 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.
fixes for stable
r1216 #
Refactor codes for scm model...
r691 # You should have received a copy of the GNU General Public License
fixes for stable
r1216 # along with this program. If not, see <http://www.gnu.org/licenses/>.
rolled back to make transient since got some exceptions on expunge...
r757 import os
import time
import traceback
import logging
from vcs import get_backend
from vcs.utils.helpers import get_scm
from vcs.exceptions import RepositoryError, VCSError
from vcs.utils.lazy import LazyProperty
from mercurial import ui
Refactor codes for scm model...
r691 from beaker.cache import cache_region, region_invalidate
rolled back to make transient since got some exceptions on expunge...
r757
Disable git support due to large problems with dulwich....
r710 from rhodecode import BACKENDS
Refactor codes for scm model...
r691 from rhodecode.lib import helpers as h
from rhodecode.lib.auth import HasRepoPermissionAny
added action loggers to following repositories,...
r735 from rhodecode.lib.utils import get_repos, make_ui, action_logger
fixed Example celery config to ampq,...
r752 from rhodecode.model import BaseModel
code cleanups
r758 from rhodecode.model.user import UserModel
from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
Implemented fancier top menu for logged and anonymous users...
r784 UserFollowing, UserLog
#50 on point cache invalidation changes....
r692 from rhodecode.model.caching_query import FromCache
rolled back to make transient since got some exceptions on expunge...
r757
Refactor codes for scm model...
r691 from sqlalchemy.orm import joinedload
#50 on point cache invalidation changes....
r692 from sqlalchemy.orm.session import make_transient
code cleanups
r758 from sqlalchemy.exc import DatabaseError
Refactor codes for scm model...
r691
log = logging.getLogger(__name__)
rolled back to make transient since got some exceptions on expunge...
r757
added action loggers to following repositories,...
r735 class UserTemp(object):
def __init__(self, user_id):
self.user_id = user_id
fixes for stable
r1216
def __repr__(self):
return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
added action loggers to following repositories,...
r735 class RepoTemp(object):
def __init__(self, repo_id):
self.repo_id = repo_id
Added icons with numbers of followers and number of forks
r747
fixes for stable
r1216 def __repr__(self):
return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
fixed Example celery config to ampq,...
r752 class ScmModel(BaseModel):
docs updates
r811 """Generic Scm Model
Refactor codes for scm model...
r691 """
@LazyProperty
def repos_path(self):
docs updates
r811 """Get's the repositories root path from database
Refactor codes for scm model...
r691 """
docs updates
r811
Refactor codes for scm model...
r691 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
return q.ui_value
rolled back to make transient since got some exceptions on expunge...
r757 def repo_scan(self, repos_path, baseui):
fixes for stable
r1216 """Listing of repositories in given path. This path should not be a
Refactor codes for scm model...
r691 repository itself. Return a dictionary of repository objects
fixes for stable
r1216
Refactor codes for scm model...
r691 :param repos_path: path to directory containing repositories
fixed scm model docs
r851 :param baseui: baseui instance to instantiate MercurialRepostitory with
Refactor codes for scm model...
r691 """
docs updates
r811
Refactor codes for scm model...
r691 log.info('scanning for repositories in %s', repos_path)
if not isinstance(baseui, ui.ui):
fixed nasty bug with ui()
r724 baseui = make_ui('db')
Refactor codes for scm model...
r691 repos_list = {}
for name, path in get_repos(repos_path):
try:
fixes for stable
r1216 if name in repos_list:
Refactor codes for scm model...
r691 raise RepositoryError('Duplicate repository name %s '
'found in %s' % (name, path))
else:
klass = get_backend(path[0])
Disable git support due to large problems with dulwich....
r710 if path[0] == 'hg' and path[0] in BACKENDS.keys():
Refactor codes for scm model...
r691 repos_list[name] = klass(path[1], baseui=baseui)
Disable git support due to large problems with dulwich....
r710 if path[0] == 'git' and path[0] in BACKENDS.keys():
Refactor codes for scm model...
r691 repos_list[name] = klass(path[1])
except OSError:
continue
return repos_list
def get_repos(self, all_repos=None):
fixes for stable
r1216 """Get all repos from db and for each repo create it's
backend instance.and fill that backed with information from database
Refactor codes for scm model...
r691 :param all_repos: give specific repositories list, good for filtering
"""
docs updates
r811
bugfix, when user had no repos he would see all repos in my account, (correct commit)
r767 if all_repos is None:
fixed sorting for repo switcher, fixed length for code stats
r693 all_repos = self.sa.query(Repository)\
.order_by(Repository.repo_name).all()
Refactor codes for scm model...
r691
fixed bug when invalidation was making to many queries when there was no list of invalidation
r791 #get the repositories that should be invalidated
cache list speed improvement
r726 invalidation_list = [str(x.cache_key) for x in \
self.sa.query(CacheInvalidation.cache_key)\
.filter(CacheInvalidation.cache_active == False)\
.all()]
Refactor codes for scm model...
r691 for r in all_repos:
cache list speed improvement
r726 repo = self.get(r.repo_name, invalidation_list)
Refactor codes for scm model...
r691
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.dbrepo.description
tmp_d['description_sort'] = tmp_d['description']
tmp_d['last_change'] = last_change
fixes for stable
r1216 tmp_d['last_change_sort'] = time.mktime(last_change \
.timetuple())
Refactor codes for scm model...
r691 tmp_d['tip'] = tip.raw_id
tmp_d['tip_sort'] = tip.revision
tmp_d['rev'] = tip.revision
removed dirty fix for #87 since it,s a no fix after all.
r828 tmp_d['contact'] = repo.dbrepo.user.full_contact
Refactor codes for scm model...
r691 tmp_d['contact_sort'] = tmp_d['contact']
changes for release 1.1.5
r1136 tmp_d['owner_sort'] = tmp_d['contact']
Refactor codes for scm model...
r691 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):
return self.get(repo_name)
cache list speed improvement
r726 def get(self, repo_name, invalidation_list=None):
docs updates
r811 """Get's repository from given name, creates BackendInstance and
Refactor codes for scm model...
r691 propagates it's data from database with all additional information
fixes for stable
r1216
Refactor codes for scm model...
r691 :param repo_name:
fixed bug when invalidation was making to many queries when there was no list of invalidation
r791 :param invalidation_list: if a invalidation list is given the get
fixes for stable
r1216 method should not manually check if this repository needs
fixed bug when invalidation was making to many queries when there was no list of invalidation
r791 invalidation and just invalidate the repositories in list
fixes for stable
r1216
Refactor codes for scm model...
r691 """
if not HasRepoPermissionAny('repository.read', 'repository.write',
'repository.admin')(repo_name, 'get repo check'):
return
fixed bug when invalidation was making to many queries when there was no list of invalidation
r791 #======================================================================
# CACHE FUNCTION
#======================================================================
#50 on point cache invalidation changes....
r692 @cache_region('long_term')
Refactor codes for scm model...
r691 def _get_repo(repo_name):
repo_path = os.path.join(self.repos_path, repo_name)
rolled back to make transient since got some exceptions on expunge...
r757
try:
alias = get_scm(repo_path)[0]
Refactor codes for scm model...
r691
rolled back to make transient since got some exceptions on expunge...
r757 log.debug('Creating instance of %s repository', alias)
backend = get_backend(alias)
except VCSError:
log.error(traceback.format_exc())
return
Refactor codes for scm model...
r691
if alias == 'hg':
Fixed archivals by passing baseui to scm get method for hg....
r715 from pylons import app_globals as g
repo = backend(repo_path, create=False, baseui=g.baseui)
Refactor codes for scm model...
r691 #skip hidden web repository
if repo._get_hidden():
return
else:
repo = backend(repo_path, create=False)
dbrepo = self.sa.query(Repository)\
.options(joinedload(Repository.fork))\
.options(joinedload(Repository.user))\
.filter(Repository.repo_name == repo_name)\
.scalar()
changes transient to expunge on cached repo instances, due to odd very rare problems with previos approach.
r753
rolled back to make transient since got some exceptions on expunge...
r757 make_transient(dbrepo)
if dbrepo.user:
make_transient(dbrepo.user)
if dbrepo.fork:
make_transient(dbrepo.fork)
changes transient to expunge on cached repo instances, due to odd very rare problems with previos approach.
r753
Refactor codes for scm model...
r691 repo.dbrepo = dbrepo
return repo
fixed bug introduced in latest commit
r792 pre_invalidate = True
if invalidation_list is not None:
pre_invalidate = repo_name in invalidation_list
if pre_invalidate:
invalidate = self._should_invalidate(repo_name)
if invalidate:
log.info('invalidating cache for repository %s', repo_name)
region_invalidate(_get_repo, None, repo_name)
self._mark_invalidated(invalidate)
Refactor codes for scm model...
r691 return _get_repo(repo_name)
fixes for stable
r1216 def mark_for_invalidation(self, repo_name):
"""Puts cache invalidation task into db for
further global cache invalidation
#50 on point cache invalidation changes....
r692
:param repo_name: this repo that should invalidation take place
"""
docs updates
r811
#50 on point cache invalidation changes....
r692 log.debug('marking %s for invalidation', repo_name)
cache = self.sa.query(CacheInvalidation)\
.filter(CacheInvalidation.cache_key == repo_name).scalar()
if cache:
#mark this cache as inactive
cache.cache_active = False
else:
log.debug('cache key not found in invalidation db -> creating one')
cache = CacheInvalidation(repo_name)
try:
self.sa.add(cache)
self.sa.commit()
code cleanups
r758 except (DatabaseError,):
#50 on point cache invalidation changes....
r692 log.error(traceback.format_exc())
self.sa.rollback()
implemented user dashboards, and following system.
r734 def toggle_following_repo(self, follow_repo_id, user_id):
#50 on point cache invalidation changes....
r692
implemented user dashboards, and following system.
r734 f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_repo_id == follow_repo_id)\
.filter(UserFollowing.user_id == user_id).scalar()
if f is not None:
Added icons with numbers of followers and number of forks
r747
implemented user dashboards, and following system.
r734 try:
self.sa.delete(f)
self.sa.commit()
added action loggers to following repositories,...
r735 action_logger(UserTemp(user_id),
'stopped_following_repo',
Added icons with numbers of followers and number of forks
r747 RepoTemp(follow_repo_id))
implemented user dashboards, and following system.
r734 return
except:
log.error(traceback.format_exc())
self.sa.rollback()
raise
try:
f = UserFollowing()
f.user_id = user_id
f.follows_repo_id = follow_repo_id
self.sa.add(f)
self.sa.commit()
added action loggers to following repositories,...
r735 action_logger(UserTemp(user_id),
'started_following_repo',
Added icons with numbers of followers and number of forks
r747 RepoTemp(follow_repo_id))
implemented user dashboards, and following system.
r734 except:
log.error(traceback.format_exc())
self.sa.rollback()
raise
fixes for stable
r1216 def toggle_following_user(self, follow_user_id, user_id):
implemented user dashboards, and following system.
r734 f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_user_id == follow_user_id)\
.filter(UserFollowing.user_id == user_id).scalar()
if f is not None:
try:
self.sa.delete(f)
self.sa.commit()
return
except:
log.error(traceback.format_exc())
self.sa.rollback()
raise
try:
f = UserFollowing()
f.user_id = user_id
f.follows_user_id = follow_user_id
self.sa.add(f)
self.sa.commit()
except:
log.error(traceback.format_exc())
self.sa.rollback()
raise
def is_following_repo(self, repo_name, user_id):
r = self.sa.query(Repository)\
.filter(Repository.repo_name == repo_name).scalar()
f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_repository == r)\
.filter(UserFollowing.user_id == user_id).scalar()
return f is not None
def is_following_user(self, username, user_id):
code cleanups
r758 u = UserModel(self.sa).get_by_username(username)
implemented user dashboards, and following system.
r734
f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_user == u)\
.filter(UserFollowing.user_id == user_id).scalar()
return f is not None
#50 on point cache invalidation changes....
r692
Added icons with numbers of followers and number of forks
r747 def get_followers(self, repo_id):
return self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_repo_id == repo_id).count()
def get_forks(self, repo_id):
return self.sa.query(Repository)\
.filter(Repository.fork_id == repo_id).count()
#50 on point cache invalidation changes....
r692
Implemented fancier top menu for logged and anonymous users...
r784 def get_unread_journal(self):
return self.sa.query(UserLog).count()
#50 on point cache invalidation changes....
r692 def _should_invalidate(self, repo_name):
docs updates
r811 """Looks up database for invalidation signals for this repo_name
fixes for stable
r1216
#50 on point cache invalidation changes....
r692 :param repo_name:
"""
ret = self.sa.query(CacheInvalidation)\
.options(FromCache('sql_cache_short',
'get_invalidation_%s' % repo_name))\
.filter(CacheInvalidation.cache_key == repo_name)\
.filter(CacheInvalidation.cache_active == False)\
.scalar()
return ret
def _mark_invalidated(self, cache_key):
fixes for stable
r1216 """ Marks all occurences of cache to invaldation as
already invalidated
docs updates
r811 :param cache_key:
#50 on point cache invalidation changes....
r692 """
docs updates
r811
#50 on point cache invalidation changes....
r692 if cache_key:
log.debug('marking %s as already invalidated', cache_key)
try:
cache_key.cache_active = True
self.sa.add(cache_key)
self.sa.commit()
code cleanups
r758 except (DatabaseError,):
#50 on point cache invalidation changes....
r692 log.error(traceback.format_exc())
self.sa.rollback()