##// END OF EJS Templates
fixes issue #271...
fixes issue #271 - OrderedDict serialization sometimes failed due to how odict is implemented. Dropped usage of it for a simple tuple

File last commit:

r1886:50e32940 beta
r1890:a3efaaa6 beta
Show More
db.py
1138 lines | 43.1 KiB | text/x-python | PythonLexer
Models code cleanups
r759 # -*- coding: utf-8 -*-
"""
new improved models with helper functions for easier data fetching
r832 rhodecode.model.db
~~~~~~~~~~~~~~~~~~
source code cleanup: remove trailing white space, normalize file endings
r1203
added current db version into rhodecode,...
r834 Database Models for RhodeCode
source code cleanup: remove trailing white space, normalize file endings
r1203
Models code cleanups
r759 :created_on: Apr 08, 2010
:author: marcink
2012 copyrights
r1824 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
Models code cleanups
r759 :license: GPLv3, see COPYING for more details.
"""
fixed license issue #149
r1206 # 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.
source code cleanup: remove trailing white space, normalize file endings
r1203 #
Models code cleanups
r759 # 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.
source code cleanup: remove trailing white space, normalize file endings
r1203 #
Models code cleanups
r759 # You should have received a copy of the GNU General Public License
fixed license issue #149
r1206 # along with this program. If not, see <http://www.gnu.org/licenses/>.
Added os.sep in models for better win support...
r1199
import os
Models code cleanups
r759 import logging
import datetime
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 import traceback
Added number of comments in changelog for each changeset...
r1884 from collections import defaultdict
Models code cleanups
r759
fixed imports
r658 from sqlalchemy import *
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 from sqlalchemy.ext.hybrid import hybrid_property
fixes #288...
r1594 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 from beaker.cache import cache_region, region_invalidate
from vcs import get_backend
from vcs.utils.helpers import get_scm
Extended API...
r1500 from vcs.exceptions import VCSError
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 from vcs.utils.lazy import LazyProperty
- refactoring to overcome poor usage of global pylons config...
r1723 from rhodecode.lib import str2bool, safe_str, get_changeset_safe, safe_unicode
removed users_group controller in replace for model methods,...
r1436 from rhodecode.lib.exceptions import UsersGroupsAssignedException
fixed issues with python2.5...
r1514 from rhodecode.lib.compat import json
moved caching query to libs
r1669 from rhodecode.lib.caching_query import FromCache
Extended API...
r1500
fixed Session problems in model class functions...
r1081 from rhodecode.model.meta import Base, Session
moved caching query to libs
r1669
Nicolas VINOT
Correct code style
r1593 log = logging.getLogger(__name__)
renamed project to rhodecode
r547
fixed Session problems in model class functions...
r1081 #==============================================================================
Added basic JsonSerialization into models....
r1388 # BASE CLASSES
fixed Session problems in model class functions...
r1081 #==============================================================================
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class ModelSerializer(json.JSONEncoder):
Added basic JsonSerialization into models....
r1388 """
Simple Serializer for JSON,
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 usage::
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 to make object customized for serialization implement a __json__
method that will return a dict for serialization into json
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 example::
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 class Task(object):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 def __init__(self, name, value):
self.name = name
self.value = value
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584
Added basic JsonSerialization into models....
r1388 def __json__(self):
return dict(name=self.name,
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 value=self.value)
Added basic JsonSerialization into models....
r1388 """
Nicolas VINOT
Correct code style
r1593 def default(self, obj):
Added basic JsonSerialization into models....
r1388
Nicolas VINOT
Correct code style
r1593 if hasattr(obj, '__json__'):
Added basic JsonSerialization into models....
r1388 return obj.__json__()
else:
Nicolas VINOT
Correct code style
r1593 return json.JSONEncoder.default(self, obj)
Added basic JsonSerialization into models....
r1388
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class BaseModel(object):
fixed repo_create permission by adding missing commit statements...
r1758 """
Base Model for all classess
Added basic JsonSerialization into models....
r1388 """
@classmethod
Nicolas VINOT
Correct code style
r1593 def _get_keys(cls):
Added basic JsonSerialization into models....
r1388 """return column names for this model """
Nicolas VINOT
Correct code style
r1593 return class_mapper(cls).c.keys()
Added basic JsonSerialization into models....
r1388
fixed repo_create permission by adding missing commit statements...
r1758 def get_dict(self, serialized=False):
"""
return dict with keys and values corresponding
auto white-space removal
r1818 to this model data
fixed repo_create permission by adding missing commit statements...
r1758 """
Added basic JsonSerialization into models....
r1388
d = {}
for k in self._get_keys():
Nicolas VINOT
Correct code style
r1593 d[k] = getattr(self, k)
pep8ify
r1800
fixed repo_create permission by adding missing commit statements...
r1758 # also use __json__() if present to get additional fields
if hasattr(self, '__json__'):
pep8ify
r1800 for k, val in self.__json__().iteritems():
auto white-space removal
r1818 d[k] = val
Added basic JsonSerialization into models....
r1388 return d
Nicolas VINOT
Correct code style
r1593 def get_appstruct(self):
Added basic JsonSerialization into models....
r1388 """return list with keys and values tupples corresponding
to this model data """
l = []
for k in self._get_keys():
Nicolas VINOT
Correct code style
r1593 l.append((k, getattr(self, k),))
Added basic JsonSerialization into models....
r1388 return l
Nicolas VINOT
Correct code style
r1593 def populate_obj(self, populate_dict):
Added basic JsonSerialization into models....
r1388 """populate model with data from given populate_dict"""
for k in self._get_keys():
if k in populate_dict:
Nicolas VINOT
Correct code style
r1593 setattr(self, k, populate_dict[k])
Added basic JsonSerialization into models....
r1388
@classmethod
Nicolas VINOT
Correct code style
r1593 def query(cls):
commit less models...
r1749 return Session.query(cls)
Added basic JsonSerialization into models....
r1388
@classmethod
Nicolas VINOT
Correct code style
r1593 def get(cls, id_):
fixes #288...
r1594 if id_:
return cls.query().get(id_)
Code cleanup...
r1466
Added more advanced hook management into rhodecode admin settings
r1460 @classmethod
Nicolas VINOT
Correct code style
r1593 def getAll(cls):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return cls.query().all()
Code cleanup...
r1466
Added more advanced hook management into rhodecode admin settings
r1460 @classmethod
Nicolas VINOT
Correct code style
r1593 def delete(cls, id_):
obj = cls.query().get(id_)
commit less models...
r1749 Session.delete(obj)
Code cleanup...
r1466
fixed Session problems in model class functions...
r1081
refactoring of models names for repoGroup permissions
r1633 class RhodeCodeSetting(Base, BaseModel):
renamed hg_app to rhodecode
r548 __tablename__ = 'rhodecode_settings'
code garden
r1886 __table_args__ = (UniqueConstraint('app_settings_name'), {'extend_existing': True})
fixes #288...
r1594 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
app_settings_name = Column("app_settings_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
_app_settings_value = Column("app_settings_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
renamed project to rhodecode
r547
fixes #288...
r1594 def __init__(self, k='', v=''):
Added settings model, and Exceptions lib....
r704 self.app_settings_name = k
self.app_settings_value = v
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
Nicolas VINOT
Correct code style
r1593 @validates('_app_settings_value')
def validate_settings_value(self, key, val):
assert type(val) == unicode
added validation of params on settings table
r1561 return val
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 @hybrid_property
Nicolas VINOT
Correct code style
r1593 def app_settings_value(self):
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 v = self._app_settings_value
if v == 'ldap_active':
Nicolas VINOT
Correct code style
r1593 v = str2bool(v)
Nicolas VINOT
Merge with upstream
r1591 return v
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
@app_settings_value.setter
Nicolas VINOT
Correct code style
r1593 def app_settings_value(self, val):
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 """
Setter that will always make sure we use unicode in app_settings_value
Nicolas VINOT
Merge with upstream
r1591
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546 :param val:
"""
Nicolas VINOT
Correct code style
r1593 self._app_settings_value = safe_unicode(val)
fixes #265 ldap save fails sometimes on converting attributes to booleans, added getter and setter...
r1546
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.app_settings_name, self.app_settings_value)
Added settings model, and Exceptions lib....
r704
Fixed #161 form saves the create repository permission....
r1266 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_name(cls, ldap_key):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.app_settings_name == ldap_key).scalar()
added some fixes to LDAP form re-submition, new simples ldap-settings getter....
r1292
@classmethod
fixes #288...
r1594 def get_app_settings(cls, cache=False):
Fixed #161 form saves the create repository permission....
r1266
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 ret = cls.query()
Fixed #161 form saves the create repository permission....
r1266
if cache:
Nicolas VINOT
Correct code style
r1593 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
Fixed #161 form saves the create repository permission....
r1266
if not ret:
Nicolas VINOT
Correct code style
r1593 raise Exception('Could not get application settings !')
Fixed #161 form saves the create repository permission....
r1266 settings = {}
for each in ret:
settings['rhodecode_' + each.app_settings_name] = \
each.app_settings_value
return settings
@classmethod
fixes #288...
r1594 def get_ldap_settings(cls, cache=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 ret = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.app_settings_name.startswith('ldap_')).all()
Fixed #161 form saves the create repository permission....
r1266 fd = {}
for row in ret:
Nicolas VINOT
Correct code style
r1593 fd.update({row.app_settings_name:row.app_settings_value})
fixes #204, ldap active checkbox, credits goes to Matt Little.
r1381
Fixed #161 form saves the create repository permission....
r1266 return fd
Nicolas VINOT
Correct code style
r1593 class RhodeCodeUi(Base, BaseModel):
renamed hg_app to rhodecode
r548 __tablename__ = 'rhodecode_ui'
code garden
r1886 __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing': True})
Added more advanced hook management into rhodecode admin settings
r1460
HOOK_UPDATE = 'changegroup.update'
HOOK_REPO_SIZE = 'changegroup.repo_size'
HOOK_PUSH = 'pretxnchangegroup.push_logger'
HOOK_PULL = 'preoutgoing.pull_logger'
fixes #288...
r1594 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
Hacking for git support,and new faster repo scan
r631
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_key(cls, key):
return cls.query().filter(cls.ui_key == key)
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345
Added more advanced hook management into rhodecode admin settings
r1460 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_builtin_hooks(cls):
Added more advanced hook management into rhodecode admin settings
r1460 q = cls.query()
Nicolas VINOT
Correct code style
r1593 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
Added more advanced hook management into rhodecode admin settings
r1460 cls.HOOK_REPO_SIZE,
Nicolas VINOT
Correct code style
r1593 cls.HOOK_PUSH, cls.HOOK_PULL]))
Added more advanced hook management into rhodecode admin settings
r1460 return q.all()
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_custom_hooks(cls):
Added more advanced hook management into rhodecode admin settings
r1460 q = cls.query()
Nicolas VINOT
Correct code style
r1593 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
Added more advanced hook management into rhodecode admin settings
r1460 cls.HOOK_REPO_SIZE,
Nicolas VINOT
Correct code style
r1593 cls.HOOK_PUSH, cls.HOOK_PULL]))
q = q.filter(cls.ui_section == 'hooks')
Added more advanced hook management into rhodecode admin settings
r1460 return q.all()
@classmethod
Nicolas VINOT
Correct code style
r1593 def create_or_update_hook(cls, key, val):
new_ui = cls.get_by_key(key).scalar() or cls()
Added more advanced hook management into rhodecode admin settings
r1460 new_ui.ui_section = 'hooks'
new_ui.ui_active = True
new_ui.ui_key = key
new_ui.ui_value = val
commit less models...
r1749 Session.add(new_ui)
Added more advanced hook management into rhodecode admin settings
r1460
Nicolas VINOT
Correct code style
r1593 class User(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'users'
code garden
r1886 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing': True})
fixes #288...
r1594 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
active = Column("active", Boolean(), nullable=True, unique=None, default=None)
admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
fixes #298, ldap email addresses created by rhodecode automatically during first login didn't get converted to lower case, which lead to lookup failures and than wrong checks for uniqueness. Fixed that by putting a setter on db model column that will enforce converting to lowercase.
r1757 _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
fixes #288...
r1594 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
fixes #288...
r1594 user_log = relationship('UserLog', cascade='all')
user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 repositories = relationship('Repository')
fixes #288...
r1594 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
refactoring of models names for repoGroup permissions
r1633 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
fixed #72 show warning on removal when user still is owner of existing repositories...
r713
fixes #288...
r1594 group_member = relationship('UsersGroupMember', cascade='all')
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
Notification fixes...
r1717 notifications = relationship('UserNotification',)
#302 - basic notification system, models+tests
r1702
fixes #298, ldap email addresses created by rhodecode automatically during first login didn't get converted to lower case, which lead to lookup failures and than wrong checks for uniqueness. Fixed that by putting a setter on db model column that will enforce converting to lowercase.
r1757 @hybrid_property
def email(self):
return self._email
@email.setter
def email(self, val):
self._email = val.lower() if val else None
Models code cleanups
r759 @property
implements #222 registration feedback...
r1731 def full_name(self):
return '%s %s' % (self.name, self.lastname)
@property
Nicolas VINOT
Correct code style
r1593 def full_contact(self):
return '%s %s <%s>' % (self.name, self.lastname, self.email)
Hacking for git support,and new faster repo scan
r631
Added some more details into user edit permissions view
r895 @property
Nicolas VINOT
Correct code style
r1593 def short_contact(self):
return '%s %s' % (self.name, self.lastname)
made simple global rss and atom feed
r1088
@property
Nicolas VINOT
Correct code style
r1593 def is_admin(self):
Added some more details into user edit permissions view
r895 return self.admin
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
Notification system improvements...
r1712 return "<%s('id:%s:%s')>" % (self.__class__.__name__,
self.user_id, self.username)
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065 @classmethod
Added cache options to some db getters
r1665 def get_by_username(cls, username, case_insensitive=False, cache=False):
Simplified last_login call on user, and changed login to use User model directly
r1400 if case_insensitive:
Added cache options to some db getters
r1665 q = cls.query().filter(cls.username.ilike(username))
Simplified last_login call on user, and changed login to use User model directly
r1400 else:
Added cache options to some db getters
r1665 q = cls.query().filter(cls.username == username)
if cache:
q = q.options(FromCache("sql_cache_short",
"get_user_%s" % username))
return q.scalar()
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
fixes #223 improve password reset form
r1417 @classmethod
Added cache options to some db getters
r1665 def get_by_api_key(cls, api_key, cache=False):
q = cls.query().filter(cls.api_key == api_key)
if cache:
q = q.options(FromCache("sql_cache_short",
"get_api_key_%s" % api_key))
fix for api key lookup, reuse same function in user model
r1693 return q.scalar()
fixes #223 improve password reset form
r1417
notification to commit author + gardening
r1716 @classmethod
fixes #298, ldap email addresses created by rhodecode automatically during first login didn't get converted to lower case, which lead to lookup failures and than wrong checks for uniqueness. Fixed that by putting a setter on db model column that will enforce converting to lowercase.
r1757 def get_by_email(cls, email, case_insensitive=False, cache=False):
if case_insensitive:
q = cls.query().filter(cls.email.ilike(email))
else:
q = cls.query().filter(cls.email == email)
notification to commit author + gardening
r1716
if cache:
q = q.options(FromCache("sql_cache_short",
"get_api_key_%s" % email))
return q.scalar()
Nicolas VINOT
Correct code style
r1593 def update_lastlogin(self):
renamed project to rhodecode
r547 """Update user lastlogin"""
Simplified last_login call on user, and changed login to use User model directly
r1400 self.last_login = datetime.datetime.now()
commit less models...
r1749 Session.add(self)
Nicolas VINOT
Correct code style
r1593 log.debug('updated user %s lastlogin', self.username)
Hacking for git support,and new faster repo scan
r631
fixed repo_create permission by adding missing commit statements...
r1758 def __json__(self):
return dict(email=self.email,
full_name=self.full_name)
Nicolas VINOT
Correct code style
r1593 class UserLog(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'user_logs'
code garden
r1886 __table_args__ = {'extend_existing': True}
fixes #288...
r1594 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
implements #193 journal stores information about deleting of repos...
r1747 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
fixes #288...
r1594 repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
Added grouping by days in journal
r994 @property
Nicolas VINOT
Correct code style
r1593 def action_as_day(self):
- refactoring to overcome poor usage of global pylons config...
r1723 return datetime.date(*self.action_date.timetuple()[:3])
Added grouping by days in journal
r994
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
implements #193 journal stores information about deleting of repos...
r1747 repository = relationship('Repository',cascade='')
Hacking for git support,and new faster repo scan
r631
started working on issue #56
r956
Nicolas VINOT
Correct code style
r1593 class UsersGroup(Base, BaseModel):
started working on issue #56
r956 __tablename__ = 'users_groups'
code garden
r1886 __table_args__ = {'extend_existing': True}
started working on issue #56
r956
fixes #288...
r1594 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
started working on issue #56
r956
fixes #288...
r1594 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
started working on issue #56
r956
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return '<userGroup(%s)>' % (self.users_group_name)
Fixed permissions for users groups, group can have create repo permission now....
r1271
@classmethod
- fixes celery sqlalchemy session issues for async forking...
r1728 def get_by_group_name(cls, group_name, cache=False,
case_insensitive=False):
Fixed permissions for users groups, group can have create repo permission now....
r1271 if case_insensitive:
- fixes celery sqlalchemy session issues for async forking...
r1728 q = cls.query().filter(cls.users_group_name.ilike(group_name))
Fixed permissions for users groups, group can have create repo permission now....
r1271 else:
- fixes celery sqlalchemy session issues for async forking...
r1728 q = cls.query().filter(cls.users_group_name == group_name)
Fixed permissions for users groups, group can have create repo permission now....
r1271 if cache:
- fixes celery sqlalchemy session issues for async forking...
r1728 q = q.options(FromCache("sql_cache_short",
"get_user_%s" % group_name))
return q.scalar()
Fixed permissions for users groups, group can have create repo permission now....
r1271
removed users_group controller in replace for model methods,...
r1436 @classmethod
fixes #288...
r1594 def get(cls, users_group_id, cache=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 users_group = cls.query()
removed users_group controller in replace for model methods,...
r1436 if cache:
Nicolas VINOT
Correct code style
r1593 users_group = users_group.options(FromCache("sql_cache_short",
"get_users_group_%s" % users_group_id))
return users_group.get(users_group_id)
removed users_group controller in replace for model methods,...
r1436
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class UsersGroupMember(Base, BaseModel):
started working on issue #56
r956 __tablename__ = 'users_groups_members'
code garden
r1886 __table_args__ = {'extend_existing': True}
started working on issue #56
r956
fixes #288...
r1594 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
started working on issue #56
r956
fixes #288...
r1594 user = relationship('User', lazy='joined')
Nicolas VINOT
Correct code style
r1593 users_group = relationship('UsersGroup')
#56 implemented users groups editing,...
r972
fixes #288...
r1594 def __init__(self, gr_id='', u_id=''):
#56 implemented users groups editing,...
r972 self.users_group_id = gr_id
self.user_id = u_id
started working on issue #56
r956
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 @staticmethod
Nicolas VINOT
Correct code style
r1593 def add_user_to_group(group, user):
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 ugm = UsersGroupMember()
ugm.users_group = group
ugm.user = user
commit less models...
r1749 Session.add(ugm)
Session.commit()
Nicolas VINOT
Implement all CRUD API operation for repo
r1587 return ugm
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class Repository(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'repositories'
code garden
r1886 __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing': True},)
fixed Session problems in model class functions...
r1081
fixes #288...
r1594 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
private = Column("private", Boolean(), nullable=True, unique=None, default=None)
enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
Added simple forks page, resolves issue #179
r1301
fixes #288...
r1594 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
fixes #288...
r1594 fork = relationship('Repository', remote_side=repo_id)
refactoring of models names for repoGroup permissions
r1633 group = relationship('RepoGroup')
repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
fixes #288...
r1594 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
stats = relationship('Statistics', cascade='all', uselist=False)
fixes #51 deleting a repo didn't delete it's dependent db entries....
r667
fixes #288...
r1594 followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
implemented user dashboards, and following system.
r734
implements #193 journal stores information about deleting of repos...
r1747 logs = relationship('UserLog')
fixees for #106 relation issues on databases different than sqlite
r970
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.repo_id, self.repo_name)
Extended repo2db mapper with group creation via directory structures...
r878
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065 @classmethod
Nicolas VINOT
Correct code style
r1593 def url_sep(cls):
fixes #245 Rescan of the repositories on Windows
r1554 return '/'
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
fixes #245 Rescan of the repositories on Windows
r1554 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_repo_name(cls, repo_name):
commit less models...
r1749 q = Session.query(cls).filter(cls.repo_name == repo_name)
Nicolas VINOT
Correct code style
r1593 q = q.options(joinedload(Repository.fork))\
.options(joinedload(Repository.user))\
.options(joinedload(Repository.group))
commit less models...
r1749 return q.scalar()
Added simple forks page, resolves issue #179
r1301
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_repo_forks(cls, repo_id):
return cls.query().filter(Repository.fork_id == repo_id)
Added simple forks page, resolves issue #179
r1301
API added checks for a valid repository on pull command...
r1508 @classmethod
Nicolas VINOT
Correct code style
r1593 def base_path(cls):
API added checks for a valid repository on pull command...
r1508 """
Returns base path when all repos are stored
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
API added checks for a valid repository on pull command...
r1508 :param cls:
"""
commit less models...
r1749 q = Session.query(RhodeCodeUi)\
- fixes celery sqlalchemy session issues for async forking...
r1728 .filter(RhodeCodeUi.ui_key == cls.url_sep())
q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
API added checks for a valid repository on pull command...
r1508 return q.one().ui_value
added clone_uri,api_key into models. Fixed models for mysql compatibilty
r1113 @property
Nicolas VINOT
Correct code style
r1593 def just_name(self):
return self.repo_name.split(Repository.url_sep())[-1]
Added handy methods to Repository model for fetching groups with parents
r1155
@property
Nicolas VINOT
Correct code style
r1593 def groups_with_parents(self):
Added handy methods to Repository model for fetching groups with parents
r1155 groups = []
if self.group is None:
return groups
cur_gr = self.group
Nicolas VINOT
Correct code style
r1593 groups.insert(0, cur_gr)
Added handy methods to Repository model for fetching groups with parents
r1155 while 1:
Nicolas VINOT
Correct code style
r1593 gr = getattr(cur_gr, 'parent_group', None)
Added handy methods to Repository model for fetching groups with parents
r1155 cur_gr = cur_gr.parent_group
if gr is None:
break
Nicolas VINOT
Correct code style
r1593 groups.insert(0, gr)
Added handy methods to Repository model for fetching groups with parents
r1155
return groups
@property
Nicolas VINOT
Correct code style
r1593 def groups_and_repo(self):
Added handy methods to Repository model for fetching groups with parents
r1155 return self.groups_with_parents, self.just_name
added clone_uri,api_key into models. Fixed models for mysql compatibilty
r1113
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 @LazyProperty
Nicolas VINOT
Correct code style
r1593 def repo_path(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 """
Returns base full path for that repository means where it actually
exists on a filesystem
"""
commit less models...
r1749 q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
Nicolas VINOT
Correct code style
r1593 Repository.url_sep())
fixed caching query on repos path...
r1727 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
adde short cache for repo_path
r1368 return q.one().ui_value
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
@property
Nicolas VINOT
Correct code style
r1593 def repo_full_path(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 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
Nicolas VINOT
Correct code style
r1593 p += self.repo_name.split(Repository.url_sep())
return os.path.join(*p)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Nicolas VINOT
Correct code style
r1593 def get_new_name(self, repo_name):
fixes #260 Put repo in group, then move group to another group -> repo becomes unavailable
r1539 """
returns new full repository name based on assigned group and new new
Nicolas VINOT
Merge with upstream
r1591
fixes #260 Put repo in group, then move group to another group -> repo becomes unavailable
r1539 :param group_name:
"""
path_prefix = self.group.full_path_splitted if self.group else []
Nicolas VINOT
Correct code style
r1593 return Repository.url_sep().join(path_prefix + [repo_name])
fixes #260 Put repo in group, then move group to another group -> repo becomes unavailable
r1539
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 @property
Nicolas VINOT
Correct code style
r1593 def _ui(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 """
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()
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 ret = RhodeCodeUi.query()\
Nicolas VINOT
Correct code style
r1593 .options(FromCache("sql_cache_short", "repository_repo_ui")).all()
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
hg_ui = ret
for ui_ in hg_ui:
if ui_.ui_active:
Nicolas VINOT
Correct code style
r1593 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)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
return baseui
API added checks for a valid repository on pull command...
r1508 @classmethod
Nicolas VINOT
Correct code style
r1593 def is_valid(cls, repo_name):
API added checks for a valid repository on pull command...
r1508 """
returns True if given repo name is a valid filesystem repository
Nicolas VINOT
Implement all CRUD API operation for repo
r1587
sphinx doc cleanup
r1819 :param cls:
:param repo_name:
API added checks for a valid repository on pull command...
r1508 """
from rhodecode.lib.utils import is_valid_repo
Nicolas VINOT
Correct code style
r1593 return is_valid_repo(repo_name, cls.base_path())
API added checks for a valid repository on pull command...
r1508
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 #==========================================================================
Code cleanup...
r1466 # SCM PROPERTIES
#==========================================================================
Nicolas VINOT
Correct code style
r1593 def get_changeset(self, rev):
return get_changeset_safe(self.scm_instance, rev)
Code cleanup...
r1466
@property
Nicolas VINOT
Correct code style
r1593 def tip(self):
return self.get_changeset('tip')
Code cleanup...
r1466
@property
Nicolas VINOT
Correct code style
r1593 def author(self):
Code cleanup...
r1466 return self.tip.author
@property
Nicolas VINOT
Correct code style
r1593 def last_change(self):
Code cleanup...
r1466 return self.scm_instance.last_change
Added number of comments in changelog for each changeset...
r1884 def comments(self, revisions=None):
"""
Returns comments for this repository grouped by revisions
:param revisions: filter query by revisions only
"""
cmts = ChangesetComment.query()\
.filter(ChangesetComment.repo == self)
if revisions:
cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
grouped = defaultdict(list)
for cmt in cmts.all():
grouped[cmt.revision].append(cmt)
return grouped
Code cleanup...
r1466 #==========================================================================
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 # SCM CACHE INSTANCE
#==========================================================================
@property
Nicolas VINOT
Correct code style
r1593 def invalidate(self):
Cached readme generation...
r1607 return CacheInvalidation.invalidate(self.repo_name)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Nicolas VINOT
Correct code style
r1593 def set_invalidate(self):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 """
set a cache for invalidation for this instance
"""
Cached readme generation...
r1607 CacheInvalidation.set_invalidate(self.repo_name)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Code cleanup...
r1466 @LazyProperty
Nicolas VINOT
Correct code style
r1593 def scm_instance(self):
Simplified last_login call on user, and changed login to use User model directly
r1400 return self.__get_instance()
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
@property
Nicolas VINOT
Correct code style
r1593 def scm_instance_cached(self):
@cache_region('long_term')
def _c(repo_name):
Simplified last_login call on user, and changed login to use User model directly
r1400 return self.__get_instance()
Cached readme generation...
r1607 rn = self.repo_name
remove cache from default perms. In some cases of concurrent repo removal it crashed....
r1744 log.debug('Getting cached instance of repo')
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 inv = self.invalidate
fixed a bug in cache invalidation
r1427 if inv is not None:
Nicolas VINOT
Correct code style
r1593 region_invalidate(_c, None, rn)
fixed some issues with cache invalidation, and simplified invalidation codes
r1428 # update our cache
Cached readme generation...
r1607 CacheInvalidation.set_valid(inv.cache_key)
Nicolas VINOT
Correct code style
r1593 return _c(rn)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Nicolas VINOT
Correct code style
r1593 def __get_instance(self):
adde short cache for repo_path
r1368 repo_full_path = self.repo_full_path
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 try:
Nicolas VINOT
Correct code style
r1593 alias = get_scm(repo_full_path)[0]
log.debug('Creating instance of %s repository', alias)
backend = get_backend(alias)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 except VCSError:
Nicolas VINOT
Correct code style
r1593 log.error(traceback.format_exc())
log.error('Perhaps this repository is in db and not in '
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 'filesystem run rescan repositories with '
Nicolas VINOT
Correct code style
r1593 '"destroy old data " option from admin panel')
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 return
if alias == 'hg':
fixes #288...
r1594 repo = backend(safe_str(repo_full_path), create=False,
baseui=self._ui)
Cached readme generation...
r1607 # skip hidden web repository
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 if repo._get_hidden():
return
else:
fixes #288...
r1594 repo = backend(repo_full_path, create=False)
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
return repo
Moved BaseModel into base class for declarative base. Added some handy methods into...
r1065
refactoring of models names for repoGroup permissions
r1633 class RepoGroup(Base, BaseModel):
Extended repo2db mapper with group creation via directory structures...
r878 __tablename__ = 'groups'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('group_name', 'group_parent_id'),
code garden
r1886 CheckConstraint('group_id != group_parent_id'), {'extend_existing': True},)
#47 implemented basic gui for browsing repo groups
r1343 __mapper_args__ = {'order_by':'group_name'}
Extended repo2db mapper with group creation via directory structures...
r878
fixes #288...
r1594 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
Extended repo2db mapper with group creation via directory structures...
r878
refactoring of models names for repoGroup permissions
r1633 parent_group = relationship('RepoGroup', remote_side=group_id)
Extended repo2db mapper with group creation via directory structures...
r878
fixes #288...
r1594 def __init__(self, group_name='', parent_group=None):
Extended repo2db mapper with group creation via directory structures...
r878 self.group_name = group_name
self.parent_group = parent_group
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
self.group_name)
Hacking for git support,and new faster repo scan
r631
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 @classmethod
Nicolas VINOT
Correct code style
r1593 def groups_choices(cls):
unified generation of repo groups choices...
r1547 from webhelpers.html import literal as _literal
Nicolas VINOT
Correct code style
r1593 repo_groups = [('', '')]
unified generation of repo groups choices...
r1547 sep = ' &raquo; '
Nicolas VINOT
Correct code style
r1593 _name = lambda k: _literal(sep.join(k))
unified generation of repo groups choices...
r1547
Nicolas VINOT
Correct code style
r1593 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
for x in cls.query().all()])
Nicolas VINOT
Merge with upstream
r1591
fixes #288...
r1594 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
unified generation of repo groups choices...
r1547 return repo_groups
Nicolas VINOT
Merge with upstream
r1591
unified generation of repo groups choices...
r1547 @classmethod
Nicolas VINOT
Correct code style
r1593 def url_sep(cls):
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 return '/'
implements #226 repo groups available by path...
r1538 @classmethod
fixes #288...
r1594 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 if case_insensitive:
gr = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.group_name.ilike(group_name))
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 else:
gr = cls.query()\
Nicolas VINOT
Correct code style
r1593 .filter(cls.group_name == group_name)
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 if cache:
Nicolas VINOT
Correct code style
r1593 gr = gr.options(FromCache("sql_cache_short",
"get_group_%s" % group_name))
Nicolas VINOT
Improve API with user/group/repo CRUD methods
r1584 return gr.scalar()
implements #226 repo groups available by path...
r1538
Changes for repo groups
r1159 @property
Nicolas VINOT
Correct code style
r1593 def parents(self):
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 parents_recursion_limit = 5
Changes for repo groups
r1159 groups = []
if self.parent_group is None:
return groups
cur_gr = self.parent_group
Nicolas VINOT
Correct code style
r1593 groups.insert(0, cur_gr)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 cnt = 0
Changes for repo groups
r1159 while 1:
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 cnt += 1
Nicolas VINOT
Correct code style
r1593 gr = getattr(cur_gr, 'parent_group', None)
Changes for repo groups
r1159 cur_gr = cur_gr.parent_group
if gr is None:
break
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 if cnt == parents_recursion_limit:
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 # this will prevent accidental infinit loops
Nicolas VINOT
Correct code style
r1593 log.error('group nested more than %s' %
parents_recursion_limit)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 break
Nicolas VINOT
Correct code style
r1593 groups.insert(0, gr)
Changes for repo groups
r1159 return groups
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 @property
Nicolas VINOT
Correct code style
r1593 def children(self):
refactoring of models names for repoGroup permissions
r1633 return RepoGroup.query().filter(RepoGroup.parent_group == self)
fixed saving settings on repositories inside groups, also fixes #187...
r1323
@property
Nicolas VINOT
Correct code style
r1593 def name(self):
refactoring of models names for repoGroup permissions
r1633 return self.group_name.split(RepoGroup.url_sep())[-1]
implements #226 repo groups available by path...
r1538
@property
Nicolas VINOT
Correct code style
r1593 def full_path(self):
fixes #288...
r1594 return self.group_name
implements #226 repo groups available by path...
r1538
@property
Nicolas VINOT
Correct code style
r1593 def full_path_splitted(self):
refactoring of models names for repoGroup permissions
r1633 return self.group_name.split(RepoGroup.url_sep())
fixed saving settings on repositories inside groups, also fixes #187...
r1323
Added repo group page showing what reposiories are inside a group
r1193 @property
Nicolas VINOT
Correct code style
r1593 def repositories(self):
return Repository.query().filter(Repository.group == self)
Added repo group page showing what reposiories are inside a group
r1193
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 @property
Nicolas VINOT
Correct code style
r1593 def repositories_recursive_count(self):
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 cnt = self.repositories.count()
Nicolas VINOT
Correct code style
r1593 def children_count(group):
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 cnt = 0
for child in group.children:
cnt += child.repositories.count()
Nicolas VINOT
Correct code style
r1593 cnt += children_count(child)
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385 return cnt
Nicolas VINOT
Correct code style
r1593 return cnt + children_count(self)
#209 Added recursive count on repositories to calculate all repos within all nested groups
r1385
implements #226 repo groups available by path...
r1538
Nicolas VINOT
Correct code style
r1593 def get_new_name(self, group_name):
implements #226 repo groups available by path...
r1538 """
returns new full group name based on parent and new name
Nicolas VINOT
Merge with upstream
r1591
implements #226 repo groups available by path...
r1538 :param group_name:
"""
Cached readme generation...
r1607 path_prefix = (self.parent_group.full_path_splitted if
fixes #288...
r1594 self.parent_group else [])
refactoring of models names for repoGroup permissions
r1633 return RepoGroup.url_sep().join(path_prefix + [group_name])
implements #226 repo groups available by path...
r1538
Nicolas VINOT
Correct code style
r1593 class Permission(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'permissions'
code garden
r1886 __table_args__ = {'extend_existing': True}
fixes #288...
r1594 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.permission_id, self.permission_name)
renamed project to rhodecode
r547
Fixed #161 form saves the create repository permission....
r1266 @classmethod
Nicolas VINOT
Correct code style
r1593 def get_by_key(cls, key):
return cls.query().filter(cls.permission_name == key).scalar()
Fixed #161 form saves the create repository permission....
r1266
- fixes celery sqlalchemy session issues for async forking...
r1728 @classmethod
remove cache from default perms. In some cases of concurrent repo removal it crashed....
r1744 def get_default_perms(cls, default_user_id):
commit less models...
r1749 q = Session.query(UserRepoToPerm, Repository, cls)\
- fixes celery sqlalchemy session issues for async forking...
r1728 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
.join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
.filter(UserRepoToPerm.user_id == default_user_id)
return q.all()
refactoring of models names for repoGroup permissions
r1633 class UserRepoToPerm(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'repo_to_perm'
code garden
r1886 __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing': True})
fixes #288...
r1594 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
permission = relationship('Permission')
repository = relationship('Repository')
renamed project to rhodecode
r547
implements #236 forking copy permission option
r1729 @classmethod
def create(cls, user, repository, permission):
n = cls()
n.user = user
n.repository = repository
n.permission = permission
commit less models...
r1749 Session.add(n)
implements #236 forking copy permission option
r1729 return n
def __repr__(self):
return '<user:%s => %s >' % (self.user, self.repository)
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class UserToPerm(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'user_to_perm'
code garden
r1886 __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing': True})
fixes #288...
r1594 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
Hacking for git support,and new faster repo scan
r631
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
- fixes celery sqlalchemy session issues for async forking...
r1728 permission = relationship('Permission', lazy='joined')
renamed project to rhodecode
r547
#56 added assignments of users groups into repository
r1014
Nicolas VINOT
Correct code style
r1593 class UsersGroupRepoToPerm(Base, BaseModel):
Fixed permissions for users groups, group can have create repo permission now....
r1271 __tablename__ = 'users_group_repo_to_perm'
code garden
r1886 __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing': True})
fixes #288...
r1594 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
added user group to perm table
r958
Nicolas VINOT
Correct code style
r1593 users_group = relationship('UsersGroup')
permission = relationship('Permission')
repository = relationship('Repository')
added user group to perm table
r958
implements #236 forking copy permission option
r1729 @classmethod
def create(cls, users_group, repository, permission):
n = cls()
n.users_group = users_group
n.repository = repository
n.permission = permission
commit less models...
r1749 Session.add(n)
implements #236 forking copy permission option
r1729 return n
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return '<userGroup:%s => %s >' % (self.users_group, self.repository)
Fixed permissions for users groups, group can have create repo permission now....
r1271
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class UsersGroupToPerm(Base, BaseModel):
Fixed permissions for users groups, group can have create repo permission now....
r1271 __tablename__ = 'users_group_to_perm'
fixes #288...
r1594 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
Fixed permissions for users groups, group can have create repo permission now....
r1271
Nicolas VINOT
Correct code style
r1593 users_group = relationship('UsersGroup')
permission = relationship('Permission')
Fixed permissions for users groups, group can have create repo permission now....
r1271
refactoring of models names for repoGroup permissions
r1633 class UserRepoGroupToPerm(Base, BaseModel):
added group to perm mapping table
r879 __tablename__ = 'group_to_perm'
code garden
r1886 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing': True})
added group to perm mapping table
r879
fixes #288...
r1594 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
added group to perm mapping table
r879
Nicolas VINOT
Correct code style
r1593 user = relationship('User')
permission = relationship('Permission')
refactoring of models names for repoGroup permissions
r1633 group = relationship('RepoGroup')
pep8ify
r1800
refactoring of models names for repoGroup permissions
r1633 class UsersGroupRepoGroupToPerm(Base, BaseModel):
__tablename__ = 'users_group_repo_group_to_perm'
code garden
r1886 __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing': True})
refactoring of models names for repoGroup permissions
r1633
users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
users_group = relationship('UsersGroup')
permission = relationship('Permission')
group = relationship('RepoGroup')
added group to perm mapping table
r879
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class Statistics(Base, BaseModel):
renamed project to rhodecode
r547 __tablename__ = 'statistics'
code garden
r1886 __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing': True})
fixes #288...
r1594 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
Hacking for git support,and new faster repo scan
r631
fixes #288...
r1594 repository = relationship('Repository', single_parent=True)
renamed project to rhodecode
r547
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class UserFollowing(Base, BaseModel):
implemented user dashboards, and following system.
r734 __tablename__ = 'user_followings'
Nicolas VINOT
Correct code style
r1593 __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
UniqueConstraint('user_id', 'follows_user_id')
code garden
r1886 , {'extend_existing': True})
implemented user dashboards, and following system.
r734
fixes #288...
r1594 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
implemented user dashboards, and following system.
r734
fixes #288...
r1594 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
implemented user dashboards, and following system.
r734
fixes #288...
r1594 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
follows_repository = relationship('Repository', order_by='Repository.repo_name')
implemented user dashboards, and following system.
r734
#179 Added followers page
r1279
@classmethod
Nicolas VINOT
Correct code style
r1593 def get_repo_followers(cls, repo_id):
return cls.query().filter(cls.follows_repo_id == repo_id)
#179 Added followers page
r1279
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class CacheInvalidation(Base, BaseModel):
Adde table for cache invalidation
r670 __tablename__ = 'cache_invalidation'
code garden
r1886 __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing': True})
fixes #288...
r1594 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
Adde table for cache invalidation
r670
fixes #288...
r1594 def __init__(self, cache_key, cache_args=''):
#50 on point cache invalidation changes....
r692 self.cache_key = cache_key
self.cache_args = cache_args
self.cache_active = False
Nicolas VINOT
Correct code style
r1593 def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.cache_id, self.cache_key)
added current db version into rhodecode,...
r834
Cached readme generation...
r1607 @classmethod
def invalidate(cls, key):
"""
Returns Invalidation object if this given key should be invalidated
None otherwise. `cache_active = False` means that this cache
state is not valid and needs to be invalidated
auto white-space removal
r1818
Cached readme generation...
r1607 :param key:
"""
return cls.query()\
.filter(CacheInvalidation.cache_key == key)\
.filter(CacheInvalidation.cache_active == False)\
.scalar()
@classmethod
def set_invalidate(cls, key):
"""
Mark this Cache key for invalidation
auto white-space removal
r1818
Cached readme generation...
r1607 :param key:
"""
log.debug('marking %s for invalidation' % key)
commit less models...
r1749 inv_obj = Session.query(cls)\
Cached readme generation...
r1607 .filter(cls.cache_key == key).scalar()
if inv_obj:
inv_obj.cache_active = False
else:
log.debug('cache key not found in invalidation db -> creating one')
inv_obj = CacheInvalidation(key)
try:
commit less models...
r1749 Session.add(inv_obj)
Session.commit()
Cached readme generation...
r1607 except Exception:
log.error(traceback.format_exc())
commit less models...
r1749 Session.rollback()
Cached readme generation...
r1607
@classmethod
def set_valid(cls, key):
"""
Mark this cache key as active and currently cached
auto white-space removal
r1818
Cached readme generation...
r1607 :param key:
"""
Tests updates, Session refactoring
r1713 inv_obj = CacheInvalidation.query()\
Cached readme generation...
r1607 .filter(CacheInvalidation.cache_key == key).scalar()
inv_obj.cache_active = True
commit less models...
r1749 Session.add(inv_obj)
Session.commit()
Cached readme generation...
r1607
Added cache options to some db getters
r1665
#77 code review...
r1670 class ChangesetComment(Base, BaseModel):
__tablename__ = 'changeset_comments'
code garden
r1886 __table_args__ = ({'extend_existing': True},)
#77 code review...
r1670 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
code refactoring
r1675 revision = Column('revision', String(40), nullable=False)
#71 code-review...
r1677 line_no = Column('line_no', Unicode(10), nullable=True)
f_path = Column('f_path', Unicode(1000), nullable=True)
#77 code review...
r1670 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
#71 code-review...
r1677 text = Column('text', Unicode(25000), nullable=False)
modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
#77 code review...
r1670
notification fixes and improvements
r1703 author = relationship('User', lazy='joined')
#77 code review...
r1670 repo = relationship('Repository')
notification fixes and improvements
r1703 @classmethod
def get_users(cls, revision):
"""
Returns user associated with this changesetComment. ie those
who actually commented
auto white-space removal
r1818
notification fixes and improvements
r1703 :param cls:
:param revision:
"""
commit less models...
r1749 return Session.query(User)\
notification fixes and improvements
r1703 .filter(cls.revision == revision)\
.join(ChangesetComment.author).all()
code garden
r1886
notification fixes and improvements
r1703
#302 - basic notification system, models+tests
r1702 class Notification(Base, BaseModel):
__tablename__ = 'notifications'
code garden
r1886 __table_args__ = ({'extend_existing': True},)
notification fixes and improvements
r1703
Notification system improvements...
r1712 TYPE_CHANGESET_COMMENT = u'cs_comment'
TYPE_MESSAGE = u'message'
TYPE_MENTION = u'mention'
implements #222 registration feedback...
r1731 TYPE_REGISTRATION = u'registration'
notification fixes and improvements
r1703
#302 - basic notification system, models+tests
r1702 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
subject = Column('subject', Unicode(512), nullable=True)
body = Column('body', Unicode(50000), nullable=True)
notification fixes and improvements
r1703 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
#302 - basic notification system, models+tests
r1702 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
notification fixes and improvements
r1703 type_ = Column('type', Unicode(256))
#302 - basic notification system, models+tests
r1702
Notification system improvements...
r1712 created_by_user = relationship('User')
Notification fixes...
r1717 notifications_to_users = relationship('UserNotification', lazy='joined',
cascade="all, delete, delete-orphan")
#302 - basic notification system, models+tests
r1702
@property
def recipients(self):
return [x.user for x in UserNotification.query()\
.filter(UserNotification.notification == self).all()]
@classmethod
notification fixes and improvements
r1703 def create(cls, created_by, subject, body, recipients, type_=None):
if type_ is None:
type_ = Notification.TYPE_MESSAGE
#302 - basic notification system, models+tests
r1702 notification = cls()
Notification system improvements...
r1712 notification.created_by_user = created_by
#302 - basic notification system, models+tests
r1702 notification.subject = subject
notification.body = body
notification fixes and improvements
r1703 notification.type_ = type_
Notification fixes...
r1717 notification.created_on = datetime.datetime.now()
Tests updates, Session refactoring
r1713
#302 - basic notification system, models+tests
r1702 for u in recipients:
Tests updates, Session refactoring
r1713 assoc = UserNotification()
assoc.notification = notification
u.notifications.append(assoc)
commit less models...
r1749 Session.add(notification)
#302 - basic notification system, models+tests
r1702 return notification
Notification system improvements...
r1712 @property
def description(self):
from rhodecode.model.notification import NotificationModel
return NotificationModel().make_description(self)
pep8ify
r1800
#302 - basic notification system, models+tests
r1702 class UserNotification(Base, BaseModel):
__tablename__ = 'user_to_notification'
notification fixes and improvements
r1703 __table_args__ = (UniqueConstraint('user_id', 'notification_id'),
code garden
r1886 {'extend_existing': True})
Tests updates, Session refactoring
r1713 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), primary_key=True)
notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
notification fixes and improvements
r1703 read = Column('read', Boolean, default=False)
#302 - basic notification system, models+tests
r1702 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
Tests updates, Session refactoring
r1713 user = relationship('User', lazy="joined")
Notification fixes...
r1717 notification = relationship('Notification', lazy="joined",
fixed bug with eager deletes in notifications...
r1733 order_by=lambda:Notification.created_on.desc(),)
#302 - basic notification system, models+tests
r1702
Notification system improvements...
r1712 def mark_as_read(self):
self.read = True
commit less models...
r1749 Session.add(self)
#302 - basic notification system, models+tests
r1702
pep8ify
r1800
Nicolas VINOT
Correct code style
r1593 class DbMigrateVersion(Base, BaseModel):
added current db version into rhodecode,...
r834 __tablename__ = 'db_migrate_version'
code garden
r1886 __table_args__ = {'extend_existing': True}
fixes #288...
r1594 repository_id = Column('repository_id', String(250), primary_key=True)
Nicolas VINOT
Correct code style
r1593 repository_path = Column('repository_path', Text)
version = Column('version', Integer)