Changeset - 72c525a7e7ad
rhodecode/__init__.py
Show inline comments
 
@@ -7,49 +7,49 @@
 
    versioning implementation: http://semver.org/
 

	
 
    :created_on: Apr 9, 2010
 
    :author: marcink
 
    :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
import sys
 
import platform
 

	
 
VERSION = (1, 3, 0, 'beta')
 
__version__ = '.'.join((str(each) for each in VERSION[:4]))
 
__dbversion__ = 4  # defines current db version for migrations
 
__dbversion__ = 5  # defines current db version for migrations
 
__platform__ = platform.system()
 
__license__ = 'GPLv3'
 
__py_version__ = sys.version_info
 

	
 
PLATFORM_WIN = ('Windows')
 
PLATFORM_OTHERS = ('Linux', 'Darwin', 'FreeBSD', 'OpenBSD', 'SunOS')
 

	
 
requirements = [
 
    "Pylons==1.0.0",
 
    "Beaker==1.6.2",
 
    "WebHelpers>=1.2",
 
    "formencode==1.2.4",
 
    "SQLAlchemy==0.7.4",
 
    "Mako==0.5.0",
 
    "pygments>=1.4",
 
    "whoosh>=2.3.0,<2.4",
 
    "celery>=2.2.5,<2.3",
 
    "babel",
 
    "python-dateutil>=1.5.0,<2.0.0",
 
    "dulwich>=0.8.0,<0.9.0",
 
    "vcs>=0.2.3.dev",
 
    "webob==1.0.8",
 
    "markdown==2.0.3",
 
    "docutils==0.8.1",
rhodecode/lib/auth.py
Show inline comments
 
@@ -205,50 +205,50 @@ def authenticate(username, password):
 
                  'bind_dn': ldap_settings.get('ldap_dn_user'),
 
                  'bind_pass': ldap_settings.get('ldap_dn_pass'),
 
                  'tls_kind': ldap_settings.get('ldap_tls_kind'),
 
                  'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'),
 
                  'ldap_filter': ldap_settings.get('ldap_filter'),
 
                  'search_scope': ldap_settings.get('ldap_search_scope'),
 
                  'attr_login': ldap_settings.get('ldap_attr_login'),
 
                  'ldap_version': 3,
 
                  }
 
            log.debug('Checking for ldap authentication')
 
            try:
 
                aldap = AuthLdap(**kwargs)
 
                (user_dn, ldap_attrs) = aldap.authenticate_ldap(username,
 
                                                                password)
 
                log.debug('Got ldap DN response %s' % user_dn)
 

	
 
                get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\
 
                                                           .get(k), [''])[0]
 

	
 
                user_attrs = {
 
                 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')),
 
                 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')),
 
                 'email': get_ldap_attr('ldap_attr_email'),
 
                }
 
                
 
                # don't store LDAP password since we don't need it. Override 
 

	
 
                # don't store LDAP password since we don't need it. Override
 
                # with some random generated password
 
                _password = PasswordGenerator().gen_password(length=8)
 
                # create this user on the fly if it doesn't exist in rhodecode
 
                # database
 
                if user_model.create_ldap(username, _password, user_dn,
 
                                          user_attrs):
 
                    log.info('created new ldap user %s' % username)
 

	
 
                Session.commit()
 
                return True
 
            except (LdapUsernameError, LdapPasswordError,):
 
                pass
 
            except (Exception,):
 
                log.error(traceback.format_exc())
 
                pass
 
    return False
 

	
 

	
 
def login_container_auth(username):
 
    user = User.get_by_username(username)
 
    if user is None:
 
        user_attrs = {
 
            'name': username,
 
            'lastname': None,
rhodecode/lib/db_manage.py
Show inline comments
 
@@ -150,60 +150,63 @@ class DbManage(object):
 
                                % __dbversion__)
 
                api.upgrade(db_uri, repository_path, __dbversion__)
 
                print ('Schema upgrade completed')
 

	
 
            def step_1(self):
 
                pass
 

	
 
            def step_2(self):
 
                print ('Patching repo paths for newer version of RhodeCode')
 
                self.klass.fix_repo_paths()
 

	
 
                print ('Patching default user of RhodeCode')
 
                self.klass.fix_default_user()
 

	
 
                log.info('Changing ui settings')
 
                self.klass.create_ui_settings()
 

	
 
            def step_3(self):
 
                print ('Adding additional settings into RhodeCode db')
 
                self.klass.fix_settings()
 
                print ('Adding ldap defaults')
 
                self.klass.create_ldap_options(skip_existing=True)
 

	
 
            def step_4(self):
 
                print ('TODO:')
 
                print ('create permissions and fix groups')
 
                self.klass.create_permissions()
 
                self.klass.fixup_groups()
 

	
 
            def step_5(self):
 
                pass
 
            
 
        upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
 

	
 
        # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
 
        for step in upgrade_steps:
 
            print ('performing upgrade step %s' % step)
 
            getattr(UpgradeSteps(self), 'step_%s' % step)()
 
            self.sa.commit()
 
            
 

	
 
    def fix_repo_paths(self):
 
        """
 
        Fixes a old rhodecode version path into new one without a '*'
 
        """
 

	
 
        paths = self.sa.query(RhodeCodeUi)\
 
                .filter(RhodeCodeUi.ui_key == '/')\
 
                .scalar()
 

	
 
        paths.ui_value = paths.ui_value.replace('*', '')
 

	
 
        try:
 
            self.sa.add(paths)
 
            self.sa.commit()
 
        except:
 
            self.sa.rollback()
 
            raise
 

	
 
    def fix_default_user(self):
 
        """
 
        Fixes a old default user with some 'nicer' default values,
 
        used mostly for anonymous access
 
        """
 
        def_user = self.sa.query(User)\
rhodecode/lib/dbmigrate/migrate/changeset/ansisql.py
Show inline comments
 
"""
 
   Extensions to SQLAlchemy for altering existing tables.
 

	
 
   At the moment, this isn't so much based off of ANSI as much as
 
   things that just happen to work with multiple databases.
 
"""
 
import StringIO
 

	
 
import sqlalchemy as sa
 
from sqlalchemy.schema import SchemaVisitor
 
from sqlalchemy.engine.default import DefaultDialect
 
from sqlalchemy.sql import ClauseElement
 
from sqlalchemy.schema import (ForeignKeyConstraint,
 
                               PrimaryKeyConstraint,
 
                               CheckConstraint,
 
                               UniqueConstraint,
 
                               Index)
 

	
 
from rhodecode.lib.dbmigrate.migrate import exceptions
 
from rhodecode.lib.dbmigrate.migrate.changeset import constraint, SQLA_06
 
from rhodecode.lib.dbmigrate.migrate.changeset import constraint
 

	
 
if not SQLA_06:
 
    from sqlalchemy.sql.compiler import SchemaGenerator, SchemaDropper
 
else:
 
    from sqlalchemy.schema import AddConstraint, DropConstraint
 
    from sqlalchemy.sql.compiler import DDLCompiler
 
    SchemaGenerator = SchemaDropper = DDLCompiler
 
from sqlalchemy.schema import AddConstraint, DropConstraint
 
from sqlalchemy.sql.compiler import DDLCompiler
 
SchemaGenerator = SchemaDropper = DDLCompiler
 

	
 

	
 
class AlterTableVisitor(SchemaVisitor):
 
    """Common operations for ``ALTER TABLE`` statements."""
 

	
 
    if SQLA_06:
 
        # engine.Compiler looks for .statement
 
        # when it spawns off a new compiler
 
        statement = ClauseElement()
 
    # engine.Compiler looks for .statement
 
    # when it spawns off a new compiler
 
    statement = ClauseElement()
 

	
 
    def append(self, s):
 
        """Append content to the SchemaIterator's query buffer."""
 

	
 
        self.buffer.write(s)
 

	
 
    def execute(self):
 
        """Execute the contents of the SchemaIterator's buffer."""
 
        try:
 
            return self.connection.execute(self.buffer.getvalue())
 
        finally:
 
            self.buffer.truncate(0)
 

	
 
    def __init__(self, dialect, connection, **kw):
 
        self.connection = connection
 
        self.buffer = StringIO.StringIO()
 
        self.preparer = dialect.identifier_preparer
 
        self.dialect = dialect
 

	
 
    def traverse_single(self, elem):
 
        ret = super(AlterTableVisitor, self).traverse_single(elem)
 
        if ret:
 
            # adapt to 0.6 which uses a string-returning
 
            # object
 
@@ -102,51 +98,50 @@ class ANSIColumnGenerator(AlterTableVisi
 

	
 
        for cons in column.constraints:
 
            self.traverse_single(cons)
 
        self.execute()
 

	
 
        # ALTER TABLE STATEMENTS
 

	
 
        # add indexes and unique constraints
 
        if column.index_name:
 
            Index(column.index_name,column).create()
 
        elif column.unique_name:
 
            constraint.UniqueConstraint(column,
 
                                        name=column.unique_name).create()
 

	
 
        # SA bounds FK constraints to table, add manually
 
        for fk in column.foreign_keys:
 
            self.add_foreignkey(fk.constraint)
 

	
 
        # add primary key constraint if needed
 
        if column.primary_key_name:
 
            cons = constraint.PrimaryKeyConstraint(column,
 
                                                   name=column.primary_key_name)
 
            cons.create()
 

	
 
    if SQLA_06:
 
        def add_foreignkey(self, fk):
 
            self.connection.execute(AddConstraint(fk))
 
    def add_foreignkey(self, fk):
 
        self.connection.execute(AddConstraint(fk))
 

	
 
class ANSIColumnDropper(AlterTableVisitor, SchemaDropper):
 
    """Extends ANSI SQL dropper for column dropping (``ALTER TABLE
 
    DROP COLUMN``).
 
    """
 

	
 
    def visit_column(self, column):
 
        """Drop a column from its table.
 

	
 
        :param column: the column object
 
        :type column: :class:`sqlalchemy.Column`
 
        """
 
        table = self.start_alter_table(column)
 
        self.append('DROP COLUMN %s' % self.preparer.format_column(column))
 
        self.execute()
 

	
 

	
 
class ANSISchemaChanger(AlterTableVisitor, SchemaGenerator):
 
    """Manages changes to existing schema elements.
 

	
 
    Note that columns are schema elements; ``ALTER TABLE ADD COLUMN``
 
    is in SchemaGenerator.
 

	
 
    All items may be renamed. Columns can also have many of their properties -
 
@@ -211,148 +206,87 @@ class ANSISchemaChanger(AlterTableVisito
 
        ret = func(table, delta.result_column, delta)
 
        self.execute()
 

	
 
    def start_alter_column(self, table, col_name):
 
        """Starts ALTER COLUMN"""
 
        self.start_alter_table(table)
 
        self.append("ALTER COLUMN %s " % self.preparer.quote(col_name, table.quote))
 

	
 
    def _visit_column_nullable(self, table, column, delta):
 
        nullable = delta['nullable']
 
        if nullable:
 
            self.append("DROP NOT NULL")
 
        else:
 
            self.append("SET NOT NULL")
 

	
 
    def _visit_column_default(self, table, column, delta):
 
        default_text = self.get_column_default_string(column)
 
        if default_text is not None:
 
            self.append("SET DEFAULT %s" % default_text)
 
        else:
 
            self.append("DROP DEFAULT")
 

	
 
    def _visit_column_type(self, table, column, delta):
 
        type_ = delta['type']
 
        if SQLA_06:
 
            type_text = str(type_.compile(dialect=self.dialect))
 
        else:
 
            type_text = type_.dialect_impl(self.dialect).get_col_spec()
 
        type_text = str(type_.compile(dialect=self.dialect))
 
        self.append("TYPE %s" % type_text)
 

	
 
    def _visit_column_name(self, table, column, delta):
 
        self.start_alter_table(table)
 
        col_name = self.preparer.quote(delta.current_name, table.quote)
 
        new_name = self.preparer.format_column(delta.result_column)
 
        self.append('RENAME COLUMN %s TO %s' % (col_name, new_name))
 

	
 

	
 
class ANSIConstraintCommon(AlterTableVisitor):
 
    """
 
    Migrate's constraints require a separate creation function from
 
    SA's: Migrate's constraints are created independently of a table;
 
    SA's are created at the same time as the table.
 
    """
 

	
 
    def get_constraint_name(self, cons):
 
        """Gets a name for the given constraint.
 

	
 
        If the name is already set it will be used otherwise the
 
        constraint's :meth:`autoname <migrate.changeset.constraint.ConstraintChangeset.autoname>`
 
        method is used.
 

	
 
        :param cons: constraint object
 
        """
 
        if cons.name is not None:
 
            ret = cons.name
 
        else:
 
            ret = cons.name = cons.autoname()
 
        return self.preparer.quote(ret, cons.quote)
 

	
 
    def visit_migrate_primary_key_constraint(self, *p, **k):
 
        self._visit_constraint(*p, **k)
 

	
 
    def visit_migrate_foreign_key_constraint(self, *p, **k):
 
        self._visit_constraint(*p, **k)
 

	
 
    def visit_migrate_check_constraint(self, *p, **k):
 
        self._visit_constraint(*p, **k)
 

	
 
    def visit_migrate_unique_constraint(self, *p, **k):
 
        self._visit_constraint(*p, **k)
 

	
 
if SQLA_06:
 
    class ANSIConstraintGenerator(ANSIConstraintCommon, SchemaGenerator):
 
        def _visit_constraint(self, constraint):
 
            constraint.name = self.get_constraint_name(constraint)
 
            self.append(self.process(AddConstraint(constraint)))
 
            self.execute()
 

	
 
    class ANSIConstraintDropper(ANSIConstraintCommon, SchemaDropper):
 
        def _visit_constraint(self, constraint):
 
            constraint.name = self.get_constraint_name(constraint)
 
            self.append(self.process(DropConstraint(constraint, cascade=constraint.cascade)))
 
            self.execute()
 

	
 
else:
 
    class ANSIConstraintGenerator(ANSIConstraintCommon, SchemaGenerator):
 

	
 
        def get_constraint_specification(self, cons, **kwargs):
 
            """Constaint SQL generators.
 

	
 
            We cannot use SA visitors because they append comma.
 
            """
 
class ANSIConstraintGenerator(ANSIConstraintCommon, SchemaGenerator):
 
    def _visit_constraint(self, constraint):
 
        constraint.name = self.get_constraint_name(constraint)
 
        self.append(self.process(AddConstraint(constraint)))
 
        self.execute()
 

	
 
            if isinstance(cons, PrimaryKeyConstraint):
 
                if cons.name is not None:
 
                    self.append("CONSTRAINT %s " % self.preparer.format_constraint(cons))
 
                self.append("PRIMARY KEY ")
 
                self.append("(%s)" % ', '.join(self.preparer.quote(c.name, c.quote)
 
                                               for c in cons))
 
                self.define_constraint_deferrability(cons)
 
            elif isinstance(cons, ForeignKeyConstraint):
 
                self.define_foreign_key(cons)
 
            elif isinstance(cons, CheckConstraint):
 
                if cons.name is not None:
 
                    self.append("CONSTRAINT %s " %
 
                                self.preparer.format_constraint(cons))
 
                self.append("CHECK (%s)" % cons.sqltext)
 
                self.define_constraint_deferrability(cons)
 
            elif isinstance(cons, UniqueConstraint):
 
                if cons.name is not None:
 
                    self.append("CONSTRAINT %s " %
 
                                self.preparer.format_constraint(cons))
 
                self.append("UNIQUE (%s)" % \
 
                    (', '.join(self.preparer.quote(c.name, c.quote) for c in cons)))
 
                self.define_constraint_deferrability(cons)
 
            else:
 
                raise exceptions.InvalidConstraintError(cons)
 

	
 
        def _visit_constraint(self, constraint):
 

	
 
            table = self.start_alter_table(constraint)
 
            constraint.name = self.get_constraint_name(constraint)
 
            self.append("ADD ")
 
            self.get_constraint_specification(constraint)
 
            self.execute()
 

	
 

	
 
    class ANSIConstraintDropper(ANSIConstraintCommon, SchemaDropper):
 

	
 
        def _visit_constraint(self, constraint):
 
            self.start_alter_table(constraint)
 
            self.append("DROP CONSTRAINT ")
 
            constraint.name = self.get_constraint_name(constraint)
 
            self.append(self.preparer.format_constraint(constraint))
 
            if constraint.cascade:
 
                self.cascade_constraint(constraint)
 
            self.execute()
 

	
 
        def cascade_constraint(self, constraint):
 
            self.append(" CASCADE")
 
class ANSIConstraintDropper(ANSIConstraintCommon, SchemaDropper):
 
    def _visit_constraint(self, constraint):
 
        constraint.name = self.get_constraint_name(constraint)
 
        self.append(self.process(DropConstraint(constraint, cascade=constraint.cascade)))
 
        self.execute()
 

	
 

	
 
class ANSIDialect(DefaultDialect):
 
    columngenerator = ANSIColumnGenerator
 
    columndropper = ANSIColumnDropper
 
    schemachanger = ANSISchemaChanger
 
    constraintgenerator = ANSIConstraintGenerator
 
    constraintdropper = ANSIConstraintDropper
rhodecode/lib/dbmigrate/migrate/changeset/constraint.py
Show inline comments
 
"""
 
   This module defines standalone schema constraint classes.
 
"""
 
from sqlalchemy import schema
 

	
 
from rhodecode.lib.dbmigrate.migrate.exceptions import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import SQLA_06
 

	
 

	
 
class ConstraintChangeset(object):
 
    """Base class for Constraint classes."""
 

	
 
    def _normalize_columns(self, cols, table_name=False):
 
        """Given: column objects or names; return col names and
 
        (maybe) a table"""
 
        colnames = []
 
        table = None
 
        for col in cols:
 
            if isinstance(col, schema.Column):
 
                if col.table is not None and table is None:
 
                    table = col.table
 
                if table_name:
 
                    col = '.'.join((col.table.name, col.name))
 
                else:
 
                    col = col.name
 
            colnames.append(col)
 
        return colnames, table
 

	
 
    def __do_imports(self, visitor_name, *a, **kw):
 
        engine = kw.pop('engine', self.table.bind)
 
        from rhodecode.lib.dbmigrate.migrate.changeset.databases.visitor import (get_engine_visitor,
 
                                                                                 run_single_visitor)
 
@@ -64,76 +64,76 @@ class ConstraintChangeset(object):
 
        #self.columns.clear()
 
        return self
 

	
 

	
 
class PrimaryKeyConstraint(ConstraintChangeset, schema.PrimaryKeyConstraint):
 
    """Construct PrimaryKeyConstraint
 

	
 
    Migrate's additional parameters:
 

	
 
    :param cols: Columns in constraint.
 
    :param table: If columns are passed as strings, this kw is required
 
    :type table: Table instance
 
    :type cols: strings or Column instances
 
    """
 

	
 
    __migrate_visit_name__ = 'migrate_primary_key_constraint'
 

	
 
    def __init__(self, *cols, **kwargs):
 
        colnames, table = self._normalize_columns(cols)
 
        table = kwargs.pop('table', table)
 
        super(PrimaryKeyConstraint, self).__init__(*colnames, **kwargs)
 
        if table is not None:
 
            self._set_parent(table)
 

	
 

	
 
    def autoname(self):
 
        """Mimic the database's automatic constraint names"""
 
        return "%s_pkey" % self.table.name
 

	
 

	
 
class ForeignKeyConstraint(ConstraintChangeset, schema.ForeignKeyConstraint):
 
    """Construct ForeignKeyConstraint
 

	
 
    Migrate's additional parameters:
 

	
 
    :param columns: Columns in constraint
 
    :param refcolumns: Columns that this FK reffers to in another table.
 
    :param table: If columns are passed as strings, this kw is required
 
    :type table: Table instance
 
    :type columns: list of strings or Column instances
 
    :type refcolumns: list of strings or Column instances
 
    """
 

	
 
    __migrate_visit_name__ = 'migrate_foreign_key_constraint'
 

	
 
    def __init__(self, columns, refcolumns, *args, **kwargs):
 
        colnames, table = self._normalize_columns(columns)
 
        table = kwargs.pop('table', table)
 
        refcolnames, reftable = self._normalize_columns(refcolumns,
 
                                                        table_name=True)
 
        super(ForeignKeyConstraint, self).__init__(colnames, refcolnames, *args,
 
                                                   **kwargs)
 
        super(ForeignKeyConstraint, self).__init__(
 
            colnames, refcolnames, *args,**kwargs
 
        )
 
        if table is not None:
 
            self._set_parent(table)
 

	
 
    @property
 
    def referenced(self):
 
        return [e.column for e in self.elements]
 

	
 
    @property
 
    def reftable(self):
 
        return self.referenced[0].table
 

	
 
    def autoname(self):
 
        """Mimic the database's automatic constraint names"""
 
        if hasattr(self.columns, 'keys'):
 
            # SA <= 0.5
 
            firstcol = self.columns[self.columns.keys()[0]]
 
            ret = "%(table)s_%(firstcolumn)s_fkey" % dict(
 
                table=firstcol.table.name,
 
                firstcolumn=firstcol.name,)
 
        else:
 
            # SA >= 0.6
 
            ret = "%(table)s_%(firstcolumn)s_fkey" % dict(
 
                table=self.table.name,
 
                firstcolumn=self.columns[0],)
 
@@ -144,59 +144,57 @@ class CheckConstraint(ConstraintChangese
 
    """Construct CheckConstraint
 

	
 
    Migrate's additional parameters:
 

	
 
    :param sqltext: Plain SQL text to check condition
 
    :param columns: If not name is applied, you must supply this kw\
 
    to autoname constraint
 
    :param table: If columns are passed as strings, this kw is required
 
    :type table: Table instance
 
    :type columns: list of Columns instances
 
    :type sqltext: string
 
    """
 

	
 
    __migrate_visit_name__ = 'migrate_check_constraint'
 

	
 
    def __init__(self, sqltext, *args, **kwargs):
 
        cols = kwargs.pop('columns', [])
 
        if not cols and not kwargs.get('name', False):
 
            raise InvalidConstraintError('You must either set "name"'
 
                'parameter or "columns" to autogenarate it.')
 
        colnames, table = self._normalize_columns(cols)
 
        table = kwargs.pop('table', table)
 
        schema.CheckConstraint.__init__(self, sqltext, *args, **kwargs)
 
        if table is not None:
 
            if not SQLA_06:
 
                self.table = table
 
            self._set_parent(table)
 
        self.colnames = colnames
 

	
 
    def autoname(self):
 
        return "%(table)s_%(cols)s_check" % \
 
            dict(table=self.table.name, cols="_".join(self.colnames))
 

	
 

	
 
class UniqueConstraint(ConstraintChangeset, schema.UniqueConstraint):
 
    """Construct UniqueConstraint
 

	
 
    Migrate's additional parameters:
 

	
 
    :param cols: Columns in constraint.
 
    :param table: If columns are passed as strings, this kw is required
 
    :type table: Table instance
 
    :type cols: strings or Column instances
 

	
 
    .. versionadded:: 0.6.0
 
    """
 

	
 
    __migrate_visit_name__ = 'migrate_unique_constraint'
 

	
 
    def __init__(self, *cols, **kwargs):
 
        self.colnames, table = self._normalize_columns(cols)
 
        table = kwargs.pop('table', table)
 
        super(UniqueConstraint, self).__init__(*self.colnames, **kwargs)
 
        if table is not None:
 
            self._set_parent(table)
 

	
 
    def autoname(self):
 
        """Mimic the database's automatic constraint names"""
 
        return "%s_%s_key" % (self.table.name, self.colnames[0])
 
        return "%s_%s_key" % (self.table.name, '_'.join(self.colnames))
rhodecode/lib/dbmigrate/migrate/changeset/databases/firebird.py
Show inline comments
 
"""
 
   Firebird database specific implementations of changeset classes.
 
"""
 
from sqlalchemy.databases import firebird as sa_base
 
from sqlalchemy.schema import PrimaryKeyConstraint
 
from rhodecode.lib.dbmigrate.migrate import exceptions
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql
 

	
 

	
 
if SQLA_06:
 
    FBSchemaGenerator = sa_base.FBDDLCompiler
 
else:
 
    FBSchemaGenerator = sa_base.FBSchemaGenerator
 
FBSchemaGenerator = sa_base.FBDDLCompiler
 

	
 
class FBColumnGenerator(FBSchemaGenerator, ansisql.ANSIColumnGenerator):
 
    """Firebird column generator implementation."""
 

	
 

	
 
class FBColumnDropper(ansisql.ANSIColumnDropper):
 
    """Firebird column dropper implementation."""
 

	
 
    def visit_column(self, column):
 
        """Firebird supports 'DROP col' instead of 'DROP COLUMN col' syntax
 

	
 
        Drop primary key and unique constraints if dropped column is referencing it."""
 
        if column.primary_key:
 
            if column.table.primary_key.columns.contains_column(column):
 
                column.table.primary_key.drop()
 
                # TODO: recreate primary key if it references more than this column
 

	
 
        for index in column.table.indexes:
 
            # "column in index.columns" causes problems as all
 
            # column objects compare equal and return a SQL expression
 
            if column.name in [col.name for col in index.columns]:
 
                index.drop()
 
                # TODO: recreate index if it references more than this column
 

	
 
        for cons in column.table.constraints:
 
            if isinstance(cons,PrimaryKeyConstraint):
 
                # will be deleted only when the column its on
 
                # is deleted!
 
                continue
 

	
 
            if SQLA_06:
 
                should_drop = column.name in cons.columns
 
            else:
 
                should_drop = cons.contains_column(column) and cons.name
 
            should_drop = column.name in cons.columns
 
            if should_drop:
 
                self.start_alter_table(column)
 
                self.append("DROP CONSTRAINT ")
 
                self.append(self.preparer.format_constraint(cons))
 
                self.execute()
 
            # TODO: recreate unique constraint if it refenrences more than this column
 

	
 
        self.start_alter_table(column)
 
        self.append('DROP %s' % self.preparer.format_column(column))
 
        self.execute()
 

	
 

	
 
class FBSchemaChanger(ansisql.ANSISchemaChanger):
 
    """Firebird schema changer implementation."""
 

	
 
    def visit_table(self, table):
 
        """Rename table not supported"""
 
        raise exceptions.NotSupportedError(
 
            "Firebird does not support renaming tables.")
 

	
 
    def _visit_column_name(self, table, column, delta):
 
        self.start_alter_table(table)
 
        col_name = self.preparer.quote(delta.current_name, table.quote)
 
        new_name = self.preparer.format_column(delta.result_column)
rhodecode/lib/dbmigrate/migrate/changeset/databases/mysql.py
Show inline comments
 
"""
 
   MySQL database specific implementations of changeset classes.
 
"""
 

	
 
from sqlalchemy.databases import mysql as sa_base
 
from sqlalchemy import types as sqltypes
 

	
 
from rhodecode.lib.dbmigrate.migrate import exceptions
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql
 

	
 

	
 
if not SQLA_06:
 
    MySQLSchemaGenerator = sa_base.MySQLSchemaGenerator
 
else:
 
    MySQLSchemaGenerator = sa_base.MySQLDDLCompiler
 
MySQLSchemaGenerator = sa_base.MySQLDDLCompiler
 

	
 
class MySQLColumnGenerator(MySQLSchemaGenerator, ansisql.ANSIColumnGenerator):
 
    pass
 

	
 

	
 
class MySQLColumnDropper(ansisql.ANSIColumnDropper):
 
    pass
 

	
 

	
 
class MySQLSchemaChanger(MySQLSchemaGenerator, ansisql.ANSISchemaChanger):
 

	
 
    def visit_column(self, delta):
 
        table = delta.table
 
        colspec = self.get_column_specification(delta.result_column)
 
        if delta.result_column.autoincrement:
 
            primary_keys = [c for c in table.primary_key.columns
 
                       if (c.autoincrement and
 
                            isinstance(c.type, sqltypes.Integer) and
 
                            not c.foreign_keys)]
 

	
 
            if primary_keys:
 
                first = primary_keys.pop(0)
 
                if first.name == delta.current_name:
 
                    colspec += " AUTO_INCREMENT"
 
        old_col_name = self.preparer.quote(delta.current_name, table.quote)
 

	
 
        self.start_alter_table(table)
 

	
 
        self.append("CHANGE COLUMN %s " % old_col_name)
 
        self.append(colspec)
 
        self.execute()
 

	
 
    def visit_index(self, param):
 
        # If MySQL can do this, I can't find how
 
        raise exceptions.NotSupportedError("MySQL cannot rename indexes")
 

	
 

	
 
class MySQLConstraintGenerator(ansisql.ANSIConstraintGenerator):
 
    pass
 

	
 
if SQLA_06:
 
    class MySQLConstraintDropper(MySQLSchemaGenerator, ansisql.ANSIConstraintDropper):
 
        def visit_migrate_check_constraint(self, *p, **k):
 
            raise exceptions.NotSupportedError("MySQL does not support CHECK"
 
                " constraints, use triggers instead.")
 

	
 
else:
 
    class MySQLConstraintDropper(ansisql.ANSIConstraintDropper):
 

	
 
        def visit_migrate_primary_key_constraint(self, constraint):
 
            self.start_alter_table(constraint)
 
            self.append("DROP PRIMARY KEY")
 
            self.execute()
 

	
 
        def visit_migrate_foreign_key_constraint(self, constraint):
 
            self.start_alter_table(constraint)
 
            self.append("DROP FOREIGN KEY ")
 
            constraint.name = self.get_constraint_name(constraint)
 
            self.append(self.preparer.format_constraint(constraint))
 
            self.execute()
 

	
 
        def visit_migrate_check_constraint(self, *p, **k):
 
            raise exceptions.NotSupportedError("MySQL does not support CHECK"
 
                " constraints, use triggers instead.")
 

	
 
        def visit_migrate_unique_constraint(self, constraint, *p, **k):
 
            self.start_alter_table(constraint)
 
            self.append('DROP INDEX ')
 
            constraint.name = self.get_constraint_name(constraint)
 
            self.append(self.preparer.format_constraint(constraint))
 
            self.execute()
 
class MySQLConstraintDropper(MySQLSchemaGenerator, ansisql.ANSIConstraintDropper):
 
    def visit_migrate_check_constraint(self, *p, **k):
 
        raise exceptions.NotSupportedError("MySQL does not support CHECK"
 
            " constraints, use triggers instead.")
 

	
 

	
 
class MySQLDialect(ansisql.ANSIDialect):
 
    columngenerator = MySQLColumnGenerator
 
    columndropper = MySQLColumnDropper
 
    schemachanger = MySQLSchemaChanger
 
    constraintgenerator = MySQLConstraintGenerator
 
    constraintdropper = MySQLConstraintDropper
rhodecode/lib/dbmigrate/migrate/changeset/databases/postgres.py
Show inline comments
 
"""
 
   `PostgreSQL`_ database specific implementations of changeset classes.
 

	
 
   .. _`PostgreSQL`: http://www.postgresql.org/
 
"""
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql
 

	
 

	
 
if not SQLA_06:
 
    from sqlalchemy.databases import postgres as sa_base
 
    PGSchemaGenerator = sa_base.PGSchemaGenerator
 
else:
 
    from sqlalchemy.databases import postgresql as sa_base
 
    PGSchemaGenerator = sa_base.PGDDLCompiler
 
from sqlalchemy.databases import postgresql as sa_base
 
PGSchemaGenerator = sa_base.PGDDLCompiler
 

	
 

	
 
class PGColumnGenerator(PGSchemaGenerator, ansisql.ANSIColumnGenerator):
 
    """PostgreSQL column generator implementation."""
 
    pass
 

	
 

	
 
class PGColumnDropper(ansisql.ANSIColumnDropper):
 
    """PostgreSQL column dropper implementation."""
 
    pass
 

	
 

	
 
class PGSchemaChanger(ansisql.ANSISchemaChanger):
 
    """PostgreSQL schema changer implementation."""
 
    pass
 

	
 

	
 
class PGConstraintGenerator(ansisql.ANSIConstraintGenerator):
 
    """PostgreSQL constraint generator implementation."""
 
    pass
 

	
 

	
 
class PGConstraintDropper(ansisql.ANSIConstraintDropper):
 
    """PostgreSQL constaint dropper implementation."""
rhodecode/lib/dbmigrate/migrate/changeset/databases/sqlite.py
Show inline comments
 
"""
 
   `SQLite`_ database specific implementations of changeset classes.
 

	
 
   .. _`SQLite`: http://www.sqlite.org/
 
"""
 
from UserDict import DictMixin
 
from copy import copy
 

	
 
from sqlalchemy.databases import sqlite as sa_base
 

	
 
from rhodecode.lib.dbmigrate.migrate import exceptions
 
from rhodecode.lib.dbmigrate.migrate.changeset import ansisql, SQLA_06
 

	
 
SQLiteSchemaGenerator = sa_base.SQLiteDDLCompiler
 

	
 
if not SQLA_06:
 
    SQLiteSchemaGenerator = sa_base.SQLiteSchemaGenerator
 
else:
 
    SQLiteSchemaGenerator = sa_base.SQLiteDDLCompiler
 

	
 
class SQLiteCommon(object):
 

	
 
    def _not_supported(self, op):
 
        raise exceptions.NotSupportedError("SQLite does not support "
 
            "%s; see http://www.sqlite.org/lang_altertable.html" % op)
 

	
 

	
 
class SQLiteHelper(SQLiteCommon):
 

	
 
    def recreate_table(self,table,column=None,delta=None):
 
        table_name = self.preparer.format_table(table)
 

	
 
        # we remove all indexes so as not to have
 
        # problems during copy and re-create
 
        for index in table.indexes:
 
            index.drop()
 

	
 
        self.append('ALTER TABLE %s RENAME TO migration_tmp' % table_name)
 
        self.execute()
 

	
 
        insertion_string = self._modify_table(table, column, delta)
 

	
 
        table.create(bind=self.connection)
rhodecode/lib/dbmigrate/migrate/changeset/schema.py
Show inline comments
 
@@ -328,70 +328,64 @@ class ColumnDelta(DictMixin, sqlalchemy.
 
        return ret
 

	
 
    def _extract_parameters(self, p, k, column):
 
        """Extracts data from p and modifies diffs"""
 
        p = list(p)
 
        while len(p):
 
            if isinstance(p[0], basestring):
 
                k.setdefault('name', p.pop(0))
 
            elif isinstance(p[0], sqlalchemy.types.AbstractType):
 
                k.setdefault('type', p.pop(0))
 
            elif callable(p[0]):
 
                p[0] = p[0]()
 
            else:
 
                break
 

	
 
        if len(p):
 
            new_col = column.copy_fixed()
 
            new_col._init_items(*p)
 
            k = self.compare_2_columns(column, new_col, **k)
 
        return k
 

	
 
    def process_column(self, column):
 
        """Processes default values for column"""
 
        # XXX: this is a snippet from SA processing of positional parameters
 
        if not SQLA_06 and column.args:
 
            toinit = list(column.args)
 
        else:
 
            toinit = list()
 
        toinit = list()
 

	
 
        if column.server_default is not None:
 
            if isinstance(column.server_default, sqlalchemy.FetchedValue):
 
                toinit.append(column.server_default)
 
            else:
 
                toinit.append(sqlalchemy.DefaultClause(column.server_default))
 
        if column.server_onupdate is not None:
 
            if isinstance(column.server_onupdate, FetchedValue):
 
                toinit.append(column.server_default)
 
            else:
 
                toinit.append(sqlalchemy.DefaultClause(column.server_onupdate,
 
                                            for_update=True))
 
        if toinit:
 
            column._init_items(*toinit)
 

	
 
        if not SQLA_06:
 
            column.args = []
 

	
 
    def _get_table(self):
 
        return getattr(self, '_table', None)
 

	
 
    def _set_table(self, table):
 
        if isinstance(table, basestring):
 
            if self.alter_metadata:
 
                if not self.meta:
 
                    raise ValueError("metadata must be specified for table"
 
                        " reflection when using alter_metadata")
 
                meta = self.meta
 
                if self.engine:
 
                    meta.bind = self.engine
 
            else:
 
                if not self.engine and not self.meta:
 
                    raise ValueError("engine or metadata must be specified"
 
                        " to reflect tables")
 
                if not self.engine:
 
                    self.engine = self.meta.bind
 
                meta = sqlalchemy.MetaData(bind=self.engine)
 
            self._table = sqlalchemy.Table(table, meta, autoload=True)
 
        elif isinstance(table, sqlalchemy.Table):
 
            self._table = table
 
            if not self.alter_metadata:
 
                self._table.meta = sqlalchemy.MetaData(bind=self._table.bind)
 
@@ -448,56 +442,60 @@ class ChangesetTable(object):
 
                # its entire definition to drop the column, just its
 
                # name, so create a dummy column with the same name.
 
                column = sqlalchemy.Column(str(column), sqlalchemy.Integer())
 
        column.drop(table=self, *p, **kw)
 

	
 
    def rename(self, name, connection=None, **kwargs):
 
        """Rename this table.
 

	
 
        :param name: New name of the table.
 
        :type name: string
 
        :param connection: reuse connection istead of creating new one.
 
        :type connection: :class:`sqlalchemy.engine.base.Connection` instance
 
        """
 
        engine = self.bind
 
        self.new_name = name
 
        visitorcallable = get_engine_visitor(engine, 'schemachanger')
 
        run_single_visitor(engine, visitorcallable, self, connection, **kwargs)
 

	
 
        # Fix metadata registration
 
        self.name = name
 
        self.deregister()
 
        self._set_parent(self.metadata)
 

	
 
    def _meta_key(self):
 
        """Get the meta key for this table."""
 
        return sqlalchemy.schema._get_table_key(self.name, self.schema)
 

	
 
    def deregister(self):
 
        """Remove this table from its metadata"""
 
        key = self._meta_key()
 
        meta = self.metadata
 
        if key in meta.tables:
 
            del meta.tables[key]
 
        if SQLA_07:
 
            self.metadata._remove_table(self.name, self.schema)
 
        else:
 
            key = self._meta_key()
 
            meta = self.metadata
 
            if key in meta.tables:
 
                del meta.tables[key]
 

	
 

	
 
class ChangesetColumn(object):
 
    """Changeset extensions to SQLAlchemy columns."""
 

	
 
    def alter(self, *p, **k):
 
        """Makes a call to :func:`alter_column` for the column this
 
        method is called on.
 
        """
 
        if 'table' not in k:
 
            k['table'] = self.table
 
        if 'engine' not in k:
 
            k['engine'] = k['table'].bind
 
        return alter_column(self, *p, **k)
 

	
 
    def create(self, table=None, index_name=None, unique_name=None,
 
               primary_key_name=None, populate_default=True, connection=None, **kwargs):
 
        """Create this column in the database.
 

	
 
        Assumes the given table exists. ``ALTER TABLE ADD COLUMN``,
 
        for most databases.
 

	
 
        :param table: Table instance to create on.
 
        :param index_name: Creates :class:`ChangesetIndex` on this column.
rhodecode/lib/dbmigrate/migrate/versioning/schemadiff.py
Show inline comments
 
@@ -18,49 +18,49 @@ def getDiffOfModelAgainstDatabase(metada
 
      are differences else :keyword:`False`.
 
    """
 
    db_metadata = sqlalchemy.MetaData(engine, reflect=True)
 

	
 
    # sqlite will include a dynamically generated 'sqlite_sequence' table if
 
    # there are autoincrement sequences in the database; this should not be
 
    # compared.
 
    if engine.dialect.name == 'sqlite':
 
        if 'sqlite_sequence' in db_metadata.tables:
 
            db_metadata.remove(db_metadata.tables['sqlite_sequence'])
 

	
 
    return SchemaDiff(metadata, db_metadata,
 
                      labelA='model',
 
                      labelB='database',
 
                      excludeTables=excludeTables)
 

	
 

	
 
def getDiffOfModelAgainstModel(metadataA, metadataB, excludeTables=None):
 
    """
 
    Return differences of model against another model.
 

	
 
    :return: object which will evaluate to :keyword:`True` if there \
 
      are differences else :keyword:`False`.
 
    """
 
    return SchemaDiff(metadataA, metadataB, excludeTables)
 
    return SchemaDiff(metadataA, metadataB, excludeTables=excludeTables)
 

	
 

	
 
class ColDiff(object):
 
    """
 
    Container for differences in one :class:`~sqlalchemy.schema.Column`
 
    between two :class:`~sqlalchemy.schema.Table` instances, ``A``
 
    and ``B``.
 

	
 
    .. attribute:: col_A
 

	
 
      The :class:`~sqlalchemy.schema.Column` object for A.
 

	
 
    .. attribute:: col_B
 

	
 
      The :class:`~sqlalchemy.schema.Column` object for B.
 

	
 
    .. attribute:: type_A
 

	
 
      The most generic type of the :class:`~sqlalchemy.schema.Column`
 
      object in A.
 

	
 
    .. attribute:: type_B
 

	
 
      The most generic type of the :class:`~sqlalchemy.schema.Column`
rhodecode/lib/dbmigrate/migrate/versioning/util/__init__.py
Show inline comments
 
@@ -137,43 +137,43 @@ def construct_engine(engine, **opts):
 
    log.debug('Constructing engine')
 
    # TODO: return create_engine(engine, poolclass=StaticPool, **kwargs)
 
    # seems like 0.5.x branch does not work with engine.dispose and staticpool
 
    return create_engine(engine, **kwargs)
 

	
 
@decorator
 
def with_engine(f, *a, **kw):
 
    """Decorator for :mod:`migrate.versioning.api` functions
 
    to safely close resources after function usage.
 

	
 
    Passes engine parameters to :func:`construct_engine` and
 
    resulting parameter is available as kw['engine'].
 

	
 
    Engine is disposed after wrapped function is executed.
 

	
 
    .. versionadded: 0.6.0
 
    """
 
    url = a[0]
 
    engine = construct_engine(url, **kw)
 

	
 
    try:
 
        kw['engine'] = engine
 
        return f(*a, **kw)
 
    finally:
 
        if isinstance(engine, Engine):
 
            log.debug('Disposing SQLAlchemy engine %s' % engine)
 
        if isinstance(engine, Engine) and engine is not url:
 
            log.debug('Disposing SQLAlchemy engine %s', engine)
 
            engine.dispose()
 

	
 

	
 
class Memoize:
 
    """Memoize(fn) - an instance which acts like fn but memoizes its arguments
 
       Will only work on functions with non-mutable arguments
 

	
 
       ActiveState Code 52201
 
    """
 
    def __init__(self, fn):
 
        self.fn = fn
 
        self.memo = {}
 

	
 
    def __call__(self, *args):
 
        if not self.memo.has_key(args):
 
            self.memo[args] = self.fn(*args)
 
        return self.memo[args]
rhodecode/lib/dbmigrate/schema/db_1_2_0.py
Show inline comments
 
@@ -906,48 +906,49 @@ class UserToPerm(Base, BaseModel):
 
        try:
 
            cls.query().filter(cls.user_id == user_id)\
 
                .filter(cls.permission == perm).delete()
 
            Session.commit()
 
        except:
 
            Session.rollback()
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
 
    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)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    def __repr__(self):
 
        return '<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = {'extend_existing':True}
 
    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)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
    @classmethod
 
    def has_perm(cls, users_group_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        return cls.query().filter(cls.users_group_id ==
 
                                         users_group_id)\
 
                                         .filter(cls.permission == perm)\
 
                                         .scalar() is not None
 

	
 
    @classmethod
 
    def grant_perm(cls, users_group_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        new = cls()
rhodecode/lib/dbmigrate/schema/db_1_3_0.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.db
 
    ~~~~~~~~~~~~~~~~~~
 

	
 
    Database Models for RhodeCode
 

	
 
    :created_on: Apr 08, 2010
 
    :author: marcink
 
    :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
 
    :license: GPLv3, see COPYING for more details.
 
"""
 
# 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.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

	
 
#TODO: when branch 1.3 is finished replacem with db.py content
 

	
 
from rhodecode.model.db import *
rhodecode/lib/dbmigrate/versions/002_version_1_1_0.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 
from rhodecode.model.meta import Base
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 

	
 
    #==========================================================================
 
    # Upgrade of `users` table
 
    #==========================================================================
 
    tblname = 'users'
 
    tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 

	
 
    #ADD is_ldap column
 
    is_ldap = Column("is_ldap", Boolean(), nullable=True,
 
                     unique=None, default=False)
 
    is_ldap.create(tbl, populate_default=True)
 
    is_ldap.alter(nullable=False)
 

	
 
    #==========================================================================
 
    # Upgrade of `user_logs` table
 
    #==========================================================================
 

	
 
    tblname = 'users'
 
    tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 

	
 
    #ADD revision column
 
    revision = Column('revision', TEXT(length=None, convert_unicode=False,
 
                                       assert_unicode=None),
 
                      nullable=True, unique=None, default=None)
 
    revision.create(tbl)
 

	
 

	
 

	
 
    #==========================================================================
 
    # Upgrade of `repositories` table
 
    #==========================================================================
 
    tblname = 'repositories'
 
    tbl = Table(tblname, MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 

	
 
    #ADD repo_type column#
 
    repo_type = Column("repo_type", String(length=None, convert_unicode=False,
 
                                           assert_unicode=None),
 
                       nullable=True, unique=False, default='hg')
 

	
 
    repo_type.create(tbl, populate_default=True)
 
    #repo_type.alter(nullable=False)
 

	
 
    #ADD statistics column#
 
    enable_statistics = Column("statistics", Boolean(), nullable=True,
 
                               unique=None, default=True)
 
    enable_statistics.create(tbl)
 

	
 
    #==========================================================================
 
    # Add table `user_followings`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_1_0 import UserFollowing
 
    UserFollowing().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `cache_invalidation`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_1_0 import CacheInvalidation
 
    CacheInvalidation().__table__.create()
 

	
 
    return
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 

	
 
    #==========================================================================
 
    # Add table `groups``
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import RepoGroup as Group
 
    Group().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserRepoGroupToPerm
 
    UserRepoGroupToPerm().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `users_groups`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroup
 
    UsersGroup().__table__.create()
 

	
 
    #==========================================================================
rhodecode/lib/dbmigrate/versions/004_version_1_3_0.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 
    #==========================================================================
 
    # Add table `users_group_repo_group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroupRepoGroupToPerm
 
    UsersGroupRepoGroupToPerm().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `changeset_comments`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import  ChangesetComment
 
    ChangesetComment().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `notifications`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import  Notification
 
    Notification().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `user_to_notification`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import  UserNotification
 
    UserNotification().__table__.create()
 

	
 
    #==========================================================================
 
    # Add unique to table `users_group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroupToPerm
 
    tbl = UsersGroupToPerm().__table__
 
    cons = UniqueConstraint('users_group_id', 'permission_id', table=tbl)
 
    cons.create()
 

	
 
    #==========================================================================
 
    # Fix unique constrain on table `user_logs`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserLog
 
    tbl = UserLog().__table__
 
    col = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'),
 
                 nullable=False, unique=None, default=None)
 
    col.alter(nullable=True, table=tbl)
 

	
 
    #==========================================================================
 
    # Rename table `group_to_perm` to `user_repo_group_to_perm`
 
    #==========================================================================
 
    tbl = Table('group_to_perm', MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 
    tbl.rename('user_repo_group_to_perm')
 

	
 
    return
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
rhodecode/lib/dbmigrate/versions/005_version_1_3_0.py
Show inline comments
 
new file 100644
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 

	
 
    #==========================================================================
 
    # Change unique constraints of table `repo_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserRepoToPerm
 
    tbl = UserRepoToPerm().__table__
 
    new_cons = UniqueConstraint('user_id', 'repository_id', 'permission_id', table=tbl)
 
    new_cons.create()
 

	
 
    if migrate_engine.name in ['mysql']:
 
        old_cons = UniqueConstraint('user_id', 'repository_id', table=tbl, name="user_id")
 
        old_cons.drop()
 
    elif migrate_engine.name in ['postgresql']:
 
        old_cons = UniqueConstraint('user_id', 'repository_id', table=tbl)
 
        old_cons.drop()
 
    else:
 
        # sqlite doesn't support dropping constraints...
 
        print """Please manually drop UniqueConstraint('user_id', 'repository_id')"""
 

	
 
    #==========================================================================
 
    # fix uniques of table `user_repo_group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserRepoGroupToPerm
 
    tbl = UserRepoGroupToPerm().__table__
 
    new_cons = UniqueConstraint('group_id', 'permission_id', 'user_id', table=tbl)
 
    new_cons.create()
 

	
 
    # fix uniqueConstraints
 
    if migrate_engine.name in ['mysql']:
 
        #mysql is givinig troubles here...
 
        old_cons = UniqueConstraint('group_id', 'permission_id', table=tbl, name="group_id")
 
        old_cons.drop()
 
    elif migrate_engine.name in ['postgresql']:
 
        old_cons = UniqueConstraint('group_id', 'permission_id', table=tbl, name='group_to_perm_group_id_permission_id_key')
 
        old_cons.drop()
 
    else:
 
        # sqlite doesn't support dropping constraints...
 
        print """Please manually drop UniqueConstraint('group_id', 'permission_id')"""
 

	
 
    return
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
rhodecode/model/db.py
Show inline comments
 
@@ -19,54 +19,54 @@
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU General Public License for more details.
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 

	
 
import os
 
import logging
 
import datetime
 
import traceback
 
from collections import defaultdict
 

	
 
from sqlalchemy import *
 
from sqlalchemy.ext.hybrid import hybrid_property
 
from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
 
from beaker.cache import cache_region, region_invalidate
 

	
 
from vcs import get_backend
 
from vcs.utils.helpers import get_scm
 
from vcs.exceptions import VCSError
 
from vcs.utils.lazy import LazyProperty
 

	
 
from rhodecode.lib import str2bool, safe_str, get_changeset_safe, safe_unicode
 
from rhodecode.lib.exceptions import UsersGroupsAssignedException
 
from rhodecode.lib.compat import json
 
from rhodecode.lib.caching_query import FromCache
 

	
 
from rhodecode.model.meta import Base, Session
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
#==============================================================================
 
# BASE CLASSES
 
#==============================================================================
 

	
 

	
 
class ModelSerializer(json.JSONEncoder):
 
    """
 
    Simple Serializer for JSON,
 

	
 
    usage::
 

	
 
        to make object customized for serialization implement a __json__
 
        method that will return a dict for serialization into json
 

	
 
    example::
 

	
 
        class Task(object):
 

	
 
            def __init__(self, name, value):
 
                self.name = name
 
                self.value = value
 

	
 
@@ -661,48 +661,49 @@ class Repository(Base, BaseModel):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 
        inv = self.invalidate
 
        if inv is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(inv.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(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(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True},
 
    )
 
    __mapper_args__ = {'order_by': 'group_name'}
 

	
 
    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)
 
@@ -835,144 +836,144 @@ class Permission(Base, BaseModel):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session.query(UserRepoToPerm, Repository, cls)\
 
         .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()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id'),
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True}
 
    )
 
    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)
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session.add(n)
 
        return n
 

	
 
    def __repr__(self):
 
        return '<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True}
 
    )
 
    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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id',),
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True}
 
    )
 
    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)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session.add(n)
 
        return n
 

	
 
    def __repr__(self):
 
        return '<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True}
 
    )
 
    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)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id'),
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True}
 
    )
 

	
 
    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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True}
 
    )
 

	
 
    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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing': True})
 
    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)
0 comments (0 inline, 0 general)