"""all files also on disk.

Revision ID: 913efdf409e5
Revises: <PASSWORD>
Create Date: 2017-07-12 15:44:20.568447

"""

import shutil

from alembic import context
from alembic import op
from depot.fields.sqlalchemy import UploadedFileField
from depot.fields.upload import UploadedFile
from depot.io.utils import FileIntent
from depot.manager import DepotManager
import sqlalchemy as sa
from sqlalchemy.sql.expression import func

# revision identifiers, used by Alembic.
revision = '913<PASSWORD>5'
down_revision = '<PASSWORD>'


revision_helper = sa.Table(
    'content_revisions',
    sa.MetaData(),
    sa.Column('revision_id', sa.Integer, primary_key=True),
    sa.Column('label', sa.String(1024), nullable=False),
    sa.Column('file_extension', sa.String(255), nullable=False),
    sa.Column('file_mimetype', sa.String(255), nullable=False),
    sa.Column('file_content', sa.LargeBinary),
    sa.Column('depot_file', UploadedFileField, nullable=True),
    sa.Column('type', sa.String(32), nullable=False),
)


def configure_depot():
    """Configure Depot."""
    depot_storage_name = context.config.get_main_option('depot_storage_name')
    depot_storage_path = context.config.get_main_option('depot_storage_dir')
    depot_storage_settings = {'depot.storage_path': depot_storage_path}
    DepotManager.configure(
        depot_storage_name,
        depot_storage_settings,
    )


def delete_files_on_disk(connection: sa.engine.Connection):
    """Deletes files from disk and their references in database."""
    delete_query = revision_helper.update() \
        .where(revision_helper.c.type == 'file') \
        .where(revision_helper.c.depot_file.isnot(None)) \
        .values(depot_file=None)
    connection.execute(delete_query)
    depot_storage_path = context.config.get_main_option('depot_storage_dir')
    shutil.rmtree(depot_storage_path, ignore_errors=True)


def upgrade():
    """
    Sets all depot files for file typed revisions.

    Until now, files are both in database and, for the newly created
    ones, on disk. In order to simplify the migration, this procedure
    will:
    - delete the few files on disk,
    - create all files on disk from database.
    """
    # Creates files depot used in this migration
    configure_depot()
    connection = op.get_bind()
    delete_files_on_disk(connection=connection)
    select_query = revision_helper.select() \
        .where(revision_helper.c.type == 'file') \
        .where(revision_helper.c.depot_file.is_(None)) \
        .where(func.length(revision_helper.c.file_content) > 0)
    files = connection.execute(select_query).fetchall()
    for file in files:
        file_filename = '{0}{1}'.format(
            file.label,
            file.file_extension,
        )
        depot_file_intent = FileIntent(
            file.file_content,
            file_filename,
            file.file_mimetype,
        )
        depot_file_field = UploadedFile(depot_file_intent, 'tracim')
        update_query = revision_helper.update() \
            .where(revision_helper.c.revision_id == file.revision_id) \
            .values(depot_file=depot_file_field)
        connection.execute(update_query)


def downgrade():
    """Resets depot file for file typed revisions."""
    connection = op.get_bind()
    delete_files_on_disk(connection=connection)

"""all files also on disk.

Revision ID: 913efdf409e5
Revises: <PASSWORD>
Create Date: 2017-07-12 15:44:20.568447

"""

import shutil

from alembic import context
from alembic import op
from depot.fields.sqlalchemy import UploadedFileField
from depot.fields.upload import UploadedFile
from depot.io.utils import FileIntent
from depot.manager import DepotManager
import sqlalchemy as sa
from sqlalchemy.sql.expression import func

# revision identifiers, used by Alembic.
revision = '913<PASSWORD>5'
down_revision = '<PASSWORD>'


revision_helper = sa.Table(
    'content_revisions',
    sa.MetaData(),
    sa.Column('revision_id', sa.Integer, primary_key=True),
    sa.Column('label', sa.String(1024), nullable=False),
    sa.Column('file_extension', sa.String(255), nullable=False),
    sa.Column('file_mimetype', sa.String(255), nullable=False),
    sa.Column('file_content', sa.LargeBinary),
    sa.Column('depot_file', UploadedFileField, nullable=True),
    sa.Column('type', sa.String(32), nullable=False),
)


def configure_depot():
    """Configure Depot."""
    depot_storage_name = context.config.get_main_option('depot_storage_name')
    depot_storage_path = context.config.get_main_option('depot_storage_dir')
    depot_storage_settings = {'depot.storage_path': depot_storage_path}
    DepotManager.configure(
        depot_storage_name,
        depot_storage_settings,
    )


def delete_files_on_disk(connection: sa.engine.Connection):
    """Deletes files from disk and their references in database."""
    delete_query = revision_helper.update() \
        .where(revision_helper.c.type == 'file') \
        .where(revision_helper.c.depot_file.isnot(None)) \
        .values(depot_file=None)
    connection.execute(delete_query)
    depot_storage_path = context.config.get_main_option('depot_storage_dir')
    shutil.rmtree(depot_storage_path, ignore_errors=True)


def upgrade():
    """
    Sets all depot files for file typed revisions.

    Until now, files are both in database and, for the newly created
    ones, on disk. In order to simplify the migration, this procedure
    will:
    - delete the few files on disk,
    - create all files on disk from database.
    """
    # Creates files depot used in this migration
    configure_depot()
    connection = op.get_bind()
    delete_files_on_disk(connection=connection)
    select_query = revision_helper.select() \
        .where(revision_helper.c.type == 'file') \
        .where(revision_helper.c.depot_file.is_(None)) \
        .where(func.length(revision_helper.c.file_content) > 0)
    files = connection.execute(select_query).fetchall()
    for file in files:
        file_filename = '{0}{1}'.format(
            file.label,
            file.file_extension,
        )
        depot_file_intent = FileIntent(
            file.file_content,
            file_filename,
            file.file_mimetype,
        )
        depot_file_field = UploadedFile(depot_file_intent, 'tracim')
        update_query = revision_helper.update() \
            .where(revision_helper.c.revision_id == file.revision_id) \
            .values(depot_file=depot_file_field)
        connection.execute(update_query)


def downgrade():
    """Resets depot file for file typed revisions."""
    connection = op.get_bind()
    delete_files_on_disk(connection=connection)

all files also on disk.  Revision ID: 913efdf409e5 Revises: <PASSWORD> Create Date: 2017-07-12 15:44:20.568447 # revision identifiers, used by Alembic. Configure Depot. Deletes files from disk and their references in database. Sets all depot files for file typed revisions.      Until now, files are both in database and, for the newly created     ones, on disk. In order to simplify the migration, this procedure     will:     - delete the few files on disk,     - create all files on disk from database. # Creates files depot used in this migration Resets depot file for file typed revisions.