# -*- coding: iso-8859-1 -*-
#
# Copyright (C) 2005 Edgewall Software
# Copyright (C) 2005,2006 Lele Gaifax <lele@metapensiero.it>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://projects.edgewall.com/trac/.
#
# Author: Lele Gaifax <lele@metapensiero.it>

from trac.config import BoolOption, Option
from trac.core import Component, implements
from trac.db import Table, Column, DatabaseManager
from trac.env import IEnvironmentSetupParticipant
from trac.versioncontrol import IRepositoryConnector

from tracdarcs.repository import DarcsRepository

class DarcsConnector(Component):

    implements(IRepositoryConnector)

    dont_escape_8bit = BoolOption('darcs', 'dont_escape_8bit', 'false',
                                  "Avoid darcs automatic escape of non-7bit chars.")

    darcs_command = Option('darcs', 'command', 'darcs',
                           "Name of the external darcs binary.")

    # IRepositoryConnector methods

    def get_supported_types(self):
        """Support the `darcs:` scheme"""
        yield ("darcs", 8)

    def get_repository(self, type, dir, authname):
        """Return a `DarcsRepository`"""
        db = self.env.get_db_cnx()
        darcs = self.darcs_command
        if self.dont_escape_8bit:
            darcs = "DARCS_DONT_ESCAPE_8BIT=1 " + darcs
        return DarcsRepository( db, dir, self.env.log, darcs )

class DarcsSetup(Component):
    """Darcs customizer.

    The db tables required for the darcs backend are created here.
    """

    implements(IEnvironmentSetupParticipant)

    def environment_created(self):
        """After standard environment has been created, add the needed
        tables."""

        db = self.env.get_db_cnx()
        self.upgrade_environment(db)
        db.commit()

    def environment_needs_upgrade(self, db):
        """Check to see if the darcs tables are already there."""

        c = db.cursor()
        try:
            c.execute( 'SELECT rev,author,time,hash,name,comment '
                    'FROM darcs_revisions LIMIT 1' )
            c.execute( 'SELECT node_id,node_type,add_rev,remove_rev '
                    'FROM darcs_nodes LIMIT 1' )
            c.execute( 'SELECT node_id,rev,path,parent_id,the_change '
                    'FROM darcs_node_changes LIMIT 1' )
            c.execute( 'SELECT node_id,rev,content '
                    'FROM darcs_cache LIMIT 1' )
            return False
        except:
            db.rollback()
            return True

    def upgrade_environment(self, db):
        """Actually add the new db tables."""

        def drop_table( table_name ) :
            c = db.cursor()
            try :
                c.execute( 'drop table %s' % table_name )
            except :
                db.rollback()
                pass

        drop_table( 'darcs_revisions' )
        drop_table( 'darcs_nodes' )
        drop_table( 'darcs_node_changes' )
        drop_table( 'darcs_cache' )

        connector = DatabaseManager(self.env)._get_connector()[0]
        if 'postgres' in [supp[0] for supp in connector.get_supported_schemes()]:
            blobtype = 'bytea'
        else:
            blobtype = 'blob'
        rev_table = Table( 'darcs_revisions', key='rev' )[
                Column('rev',type='int'),
                Column('author'),
                Column('time',type='datetime'),
                Column('hash'),
                Column('name'),
                Column('comment') ]
        node_table = Table( 'darcs_nodes', key='node_id' )[
                Column('node_id',type='int'),
                Column('node_type'),
                Column('add_rev',type='int'),
                Column('remove_rev',type='int') ]
        change_table = Table( 'darcs_node_changes', key=('node_id','rev') )[
                Column('node_id',type='int'),
                Column('rev',type='int'),
                Column('path'),
                Column('parent_id',type='int'),
                Column('the_change') ]
        cache_table = Table( 'darcs_cache', key=('node_id','rev') )[
                Column('node_id',type='int'),
                Column('rev',type='int'),
                Column('content',type=blobtype) ]
        c = db.cursor()
        for t in [rev_table,node_table,change_table,cache_table] :
            for stmt in connector.to_sql(t) :
                c.execute( stmt )
