aboutsummaryrefslogtreecommitdiff
path: root/rhodecode/model/db.py
diff options
context:
space:
mode:
Diffstat (limited to 'rhodecode/model/db.py')
-rw-r--r--rhodecode/model/db.py141
1 files changed, 139 insertions, 2 deletions
diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py
index c253b879..6421a072 100644
--- a/rhodecode/model/db.py
+++ b/rhodecode/model/db.py
@@ -26,13 +26,23 @@
import os
import logging
import datetime
+import traceback
from datetime import date
from sqlalchemy import *
from sqlalchemy.exc import DatabaseError
-from sqlalchemy.orm import relationship, backref
+from sqlalchemy.orm import relationship, backref, joinedload
from sqlalchemy.orm.interfaces import MapperExtension
+from beaker.cache import cache_region, region_invalidate
+
+
+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 vcs.nodes import FileNode
+
from rhodecode.lib import str2bool
from rhodecode.model.meta import Base, Session
from rhodecode.model.caching_query import FromCache
@@ -150,6 +160,7 @@ class User(Base):
return self.admin
def __repr__(self):
+ return 'ahmmm'
return "<%s('id:%s:%s')>" % (self.__class__.__name__,
self.user_id, self.username)
@@ -266,8 +277,13 @@ class Repository(Base):
@classmethod
def by_repo_name(cls, repo_name):
- return Session.query(cls).filter(cls.repo_name == repo_name).one()
+ q = Session.query(cls).filter(cls.repo_name == repo_name)
+
+ q = q.options(joinedload(Repository.fork))\
+ .options(joinedload(Repository.user))\
+ .options(joinedload(Repository.group))\
+ return q.one()
@classmethod
def get_repo_forks(cls, repo_id):
@@ -298,6 +314,127 @@ class Repository(Base):
def groups_and_repo(self):
return self.groups_with_parents, self.just_name
+ @LazyProperty
+ def repo_path(self):
+ """
+ Returns base full path for that repository means where it actually
+ exists on a filesystem
+ """
+
+ q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
+ return q.ui_value
+
+ @property
+ def repo_full_path(self):
+ p = [self.repo_path]
+ # we need to split the name by / since this is how we store the
+ # names in the database, but that eventually needs to be converted
+ # into a valid system path
+ p += self.repo_name.split('/')
+ return os.path.join(*p)
+
+ @property
+ def _ui(self):
+ """
+ Creates an db based ui object for this repository
+ """
+ from mercurial import ui
+ from mercurial import config
+ baseui = ui.ui()
+
+ #clean the baseui object
+ baseui._ocfg = config.config()
+ baseui._ucfg = config.config()
+ baseui._tcfg = config.config()
+
+
+ ret = Session.query(RhodeCodeUi)\
+ .options(FromCache("sql_cache_short",
+ "repository_repo_ui")).all()
+
+ hg_ui = ret
+ for ui_ in hg_ui:
+ if ui_.ui_active:
+ log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
+ ui_.ui_key, ui_.ui_value)
+ baseui.setconfig(ui_.ui_section, ui_.ui_key, ui_.ui_value)
+
+ return baseui
+
+ #==========================================================================
+ # SCM CACHE INSTANCE
+ #==========================================================================
+
+ @property
+ def invalidate(self):
+ """
+ Returns Invalidation object if this repo should be invalidated
+ None otherwise. `cache_active = False` means that this cache
+ state is not valid and needs to be invalidated
+ """
+ return Session.query(CacheInvalidation)\
+ .filter(CacheInvalidation.cache_key == self.repo_name)\
+ .filter(CacheInvalidation.cache_active == False)\
+ .scalar()
+
+ @property
+ def set_invalidate(self):
+ """
+ set a cache for invalidation for this instance
+ """
+ inv = Session.query(CacheInvalidation)\
+ .filter(CacheInvalidation.cache_key == self.repo_name)\
+ .scalar()
+
+ if inv is None:
+ inv = CacheInvalidation(self.repo_name)
+ inv.cache_active = True
+ Session.add(inv)
+ Session.commit()
+
+ @property
+ def scm_instance(self):
+ return self.__get_instance(self.repo_name)
+
+ @property
+ def scm_instance_cached(self):
+ @cache_region('long_term')
+ def _c(repo_name):
+ return self.__get_instance(repo_name)
+
+ inv = self.invalidate
+ if inv:
+ region_invalidate(_c, None, self.repo_name)
+ #update our cache
+ inv.cache_key.cache_active = True
+ Session.add(inv)
+ Session.commit()
+
+ return _c(self.repo_name)
+
+ def __get_instance(self, repo_name):
+ try:
+ alias = get_scm(self.repo_full_path)[0]
+ log.debug('Creating instance of %s repository', alias)
+ backend = get_backend(alias)
+ except VCSError:
+ log.error(traceback.format_exc())
+ log.error('Perhaps this repository is in db and not in '
+ 'filesystem run rescan repositories with '
+ '"destroy old data " option from admin panel')
+ return
+
+ if alias == 'hg':
+ repo = backend(self.repo_full_path, create=False,
+ baseui=self._ui)
+ #skip hidden web repository
+ if repo._get_hidden():
+ return
+ else:
+ repo = backend(self.repo_full_path, create=False)
+
+ return repo
+
class Group(Base):
__tablename__ = 'groups'