#!%PERL%
# Copyright (c) vhffs project and its contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions 
# are met:
#
# 1. Redistributions of source code must retain the above copyright 
#   notice, this list of conditions and the following disclaimer.
#2. Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in 
#   the documentation and/or other materials provided with the 
#   distribution.
#3. Neither the name of vhffs nor the names of its contributors 
#   may be used to endorse or promote products derived from this 
#   software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
#FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
#COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
#INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
#BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.

=pod

=head1 NAME

Vhffs::Services::Cvs - Handle CVS service in VHFFS

=head1 SYNOPSIS

TODO

=head1 METHODS

=cut

use strict;
use utf8;

package Vhffs::Services::Cvs;

use base qw(Vhffs::Object);
use Vhffs::Group;
use DBI;

=pod

=head2 check_name

    die("Invalid CVS root\n") unless(Vhffs::Services::Cvs::check_name($cvsroot));

Checks whether a cvsroot is valid or not.

=cut

sub check_name($) {
    my $name = shift;
    return ($name =~ /^[a-z0-9]+\/[a-z0-9]{3,64}$/);
}

sub delete
{
	my $self = shift;

    my $query = "DELETE FROM vhffs_cvs WHERE object_id='".$self->{'object_id'}."'";
    my $request = $self->{'db'}->prepare($query);
    $request->execute or return -1;

	return -1 if( $self->SUPER::delete < 0 );
	return 1;
}

=pod

=head2 create

    my $cvs = Vhffs::Services::Cvs::create($main, $cvsroot, $description, $user, $group);
    die("Unable to create cvs\n") unless($cvs);

Creates a new CVS service in database and returns the corresponding fully functional object.

=cut

sub create
{
    my ($main, $cvsroot, $description, $user, $group) = @_;
    return undef unless(defined($user) && defined($group));
    return undef unless(check_name($cvsroot));

    my $cvs;
    my $dbh = $main->get_db_object();
    local $dbh->{RaiseError} = 1;
    local $dbh->{PrintError} = 0;
    $dbh->begin_work;
    eval {

        my $parent = Vhffs::Object::create($main, $user->get_uid, $group->get_gid, $description, undef, Vhffs::Constants::TYPE_CVS);

        die('Unable to create parent object') unless(defined($parent));

        my $sql = 'INSERT INTO vhffs_cvs(cvsroot, public, object_id) VALUES (?, TRUE, ?)';
        my $sth = $dbh->prepare($sql);
        $sth->execute($cvsroot, $parent->get_oid);

        $dbh->commit;
        $cvs = get_by_cvsroot($main, $cvsroot);
    };

    if($@) {
        warn "Error creating cvs service: $@\n";
        $dbh->rollback;
    }
    return $cvs;

}

sub commit
{
	my $self = shift;	

    my $sql = 'UPDATE vhffs_cvs SET cvsroot = ?, public = ? WHERE cvs_id = ?';
    $self->get_db_object()->do($sql, undef, $self->{'cvsroot'},
                                        $self->{'public'}, $self->{'cvs_id'})
                                            or return -1;

	return -2 if( $self->SUPER::commit < 0 );
	return 1;
}


=head2 set_public

    $cvs->set_public(0);

Defines if a CVS repository is public (param == 1) or not (0).

=cut

sub set_public
{
	my ($self, $public) = @_;
	$self->{'public'} = $public;
}

sub is_public
{
	my $self = shift;
	
	return -1 if( ! defined $self->{'public'} );

	if( $self->{'public'} == 1 )
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

sub get_label {
    return $_[0]->{cvsroot};
}

sub get_cvsroot
{
	my $self = shift;
	return $self->{'cvsroot'};
}


sub set_cvsroot
{
	my ($self , $value) = @_;	
	$self->{'cvsroot'} = $value;
}



sub get_dir
{
    my $self = shift;
    return undef if( ! defined $self );
    
    return( $self->{'main'}->get_config->get_datadir . "/cvs/cvsroot/" . $self->get_cvsroot );
}

sub get_by_cvsroot {
    my($main, $cvsroot) = @_;
    my $sql = 'SELECT c.cvs_id, c.cvsroot, o.owner_uid, o.owner_gid, c.public, c.object_id, o.date_creation, o.description, o.state FROM vhffs_cvs c INNER JOIN vhffs_object o ON c.object_id = o.object_id WHERE c.cvsroot = ?';
    my $dbh = $main->get_db_object();
    my @params;
    return undef unless(@params = $dbh->selectrow_array($sql, undef, $cvsroot));

    return _new Vhffs::Services::Cvs($main, @params);
}

sub _new {
    my ($class, $main, $cvs_id, $cvsroot, $owner_uid, $owner_gid, $public, $oid, $date_creation, $description, $state) = @_;
    
    my $self = $class->SUPER::_new($main, $oid, $owner_uid, $owner_gid, $date_creation, $description, '', $state, Vhffs::Constants::TYPE_CVS);
    return undef unless(defined $self);
    
    $self->{cvsroot} = $cvsroot;
    $self->{cvs_id} = $cvs_id;
    $self->{public} = $public;
    return $self;
}


=head2 fill_object

See C<Vhffs::Object::fill_object>.

=cut
sub fill_object {
    my ($class, $obj) = @_;
    my $sql = q{SELECT cvsroot, cvs_id, public FROM vhffs_cvs
        WHERE object_id = ?};
    return $class->SUPER::_fill_object($obj, $sql);
}

sub getall
{
    my ($vhffs, $state, $name, $group) = @_;

    my $query;
    my $request;
    my @params;

    my $objs = [];
    my $result;
    my $tmp;

    $query = 'SELECT c.cvs_id, c.cvsroot, o.owner_uid, o.owner_gid, c.public, o.object_id, o.date_creation, o.description, o.state FROM vhffs_cvs c INNER JOIN vhffs_object o ON c.object_id = o.object_id';
    if(defined $state) {
        $query .= ' AND o.state=?';
        push(@params, $state);
    }
    if(defined $name) {
        $query .= ' AND c.cvsroot LIKE ?';
        push(@params, '%'.$name.'%');
    }

    if(defined $group) {
        $query .= ' AND o.owner_gid=?';
        push(@params, $group->get_gid);
    }
    $query .= " ORDER BY c.cvsroot";
    $request = $vhffs->{'db'}->prepare( $query );
    my $rows = $request->execute(@params);

    return undef if( ! $rows );

    while( $result = $request->fetchrow_arrayref )
    {
        $tmp = _new Vhffs::Services::Cvs( $vhffs, @{$result} ) ;
        push @{$objs} , $tmp;
    }
    return $objs;
}

sub getall_per_group
{
    my ($main, $group) = @_;
    my @result;
    my $cvsroot;
    return undef if ( ! defined $group );
    
    my $query = 'SELECT c.cvs_id, c.cvsroot, o.owner_uid, o.owner_gid, c.public, o.object_id, o.date_creation, o.description, o.state FROM vhffs_cvs c INNER JOIN vhffs_object o ON c.object_id = o.object_id WHERE o.owner_gid=? ORDER BY c.cvsroot';

    my $request = $main->{'db'}->prepare( $query ) or return -1;

    
    return undef if ( ! $request->execute($group->get_gid) );
    
    while( my $repos = $request->fetchrow_arrayref()  )
    {
        push(@result, _new Vhffs::Services::Cvs($main, @{$repos}))
    }
    

    return \@result;

}

1;
__END__
=head1 AUTHORS

soda < dieu at gunnm dot org>

Sebastien Le Ray < beuss at tuxfamily dot org >
