#!/usr/bin/perl -w

# $Id: dasscm 190 2004-11-11 09:55:09Z joergs $

use strict;

use Env qw($DASSCM_PROD $DASSCM_REPO $USER $DASSCM_USER $DASSCM_PW);
use Cwd;
use File::Basename;
use File::stat;
use File::Path;
use File::Copy;
#use POSIX qw/getpgrp tcgetpgrp/;

#####################################################################
#
# global
#
my $SVN = "svn ";
my $subversion_options = "";

#####################################################################
#
# util functions
#
sub usage()
{
	print "usage: dasscm <subcommand> [options] [args]\n";
	print "\n";
	print "dasscm is intended to help versioning configuration files\n";
	print "\n";	
	print "Available subcommands:\n";
	print "   add <filename>\n";
	print "   commit <filename>\n";
	print "   diff <filename>\n";
	print "   help <subcommand>\n";
	print "\n";	
	print "preperation:\n";
	print "check out the configuration repository, e.g.\n";
	print "svn checkout --no-auth-cache --username $USER https://dass-it.de/svn/lvermgeo/technical/config/\n";
	print "environment variables DASSCM_REPO, DASSCM_PROD and DASSCM_USER are evaluated.\n";
	print "\n";
}

sub check_env()
{
	# DASSCM_PROD
	if ( ! $DASSCM_PROD ) {
		$DASSCM_PROD = "/";
	}
	print "DASSCM_PROD: ".$DASSCM_PROD."\n";
	if ( ! -d $DASSCM_PROD ) {
		die "DASSCM_PROD is not set to a  directory.\n";
	}
		
	# DASSCM_REPO
	if ( ! $DASSCM_REPO ) {
		die "Envirnonment variable DASSCM_REPO not set.\nSet DASSCM_REPO to the directory of the versioning system checkout for this machine.\n";
	}
	print "DASSCM_REPO: ".$DASSCM_REPO."\n";
	if ( ! -d $DASSCM_REPO ) {
		die "DASSCM_REPO must be is not set to the directory of the versioning system checkout for this machine.\n";
	}
	
	# User settings
	# user root is not allowed for checkins.
	# if user is root, DASSCM_USER has to be set, 
	# otherwise USER can be used
	if ( "$USER" eq "root" ) {
		if ( ! $DASSCM_USER ) {
			die "Envirnonment variable DASSCM_USER not set.\nSet DASSCM_USER to your subversion user account.\n";
		} 
		$subversion_options .= " --no-auth-cache "
	} elsif ( ! $DASSCM_USER ) {
		$DASSCM_USER=$USER;
	}	
}

sub check_parameter(@)
{
}

sub get_filenames(@)
{
	my $filename_prod = $_[0];
	if ( !($filename_prod =~ m/^\//) ) {
		$filename_prod = cwd()."/".$filename_prod;
	}

	-r $filename_prod or die "$filename_prod is not accessable";
	
	# TODO: dirname buggy: eg. "/etc/" is reduced to "/",
	#	"/etc" is used as filename
	my $dirname_prod = dirname($filename_prod);
	chdir $dirname_prod or die $!;
	$dirname_prod = cwd();
	my $basename = basename($filename_prod);
	
	print "dir: ".$dirname_prod."\n";
	print "fn: ".$basename."\n";
		
	my $dirname_repo = $DASSCM_REPO."/".$dirname_prod;
	my $filename_repo = "$dirname_repo/$basename";
	
	return ($basename,$dirname_prod,$dirname_repo,$filename_prod,$filename_repo);
}

sub run_command
{
  my $command = shift;

  #print "executing command: " . $command . "\n";

  open(RESULT, $command . ' 2>&1 |' );
  my @result = <RESULT>;
  close(RESULT);
  my $retcode = $?>>8;

  #print @result;
  #if( $retcode ) { print "return code: " . $retcode . "\n"; }

  return($retcode, @result);
}


#####################################################################
#
# functions

sub help(;@)
{
	if( @_ == 0 ) {
		usage();
	} else {
		print "help for @_: ...\n";
	}
}

sub add(@)
{
	check_parameter(@_,1);
	check_env();
	
	(my $basename, my $dirname_prod, my $dirname_repo, my $filename_prod, my $filename_repo) = get_filenames($_[0]);
		
	mkpath($dirname_repo);
	
	# update complete repository
	(my $retcode, my @result)=run_command( "$SVN update $DASSCM_REPO" );
	if( $retcode != 0 ) {
		print @result;
		die;
	}

	copy( $filename_prod, $filename_repo ) or die $!;
	
	# already checked in?
	chdir($DASSCM_REPO);
	# also add the path to filename.
	for my $dir (split('/', $dirname_prod) ) {
		if( $dir ) {
			run_command( "$SVN add --non-recursive $dir" );
			chdir $dir;
		}
	}
	run_command( "$SVN add $basename" );

	# commit calls $EDITOR. uses "system" here, to display output
	system( "$SVN commit --username $DASSCM_USER $subversion_options $DASSCM_REPO" );
	# TODO: commit (-m)

	print $filename_prod."\n";
	print $dirname_repo."\n";
}

sub commit(@)
{
	check_parameter(@_,1);
	check_env();
	
	(my $basename, my $dirname_prod, my $dirname_repo, my $filename_prod, my $filename_repo) = get_filenames($_[0]);

	(my $rc_update, my @result)=run_command( "$SVN update $filename_repo" );
	if( $rc_update != 0 ) {
		print @result;
		die;
	}
	
	copy( $filename_prod, $filename_repo ) or die $!;

	# commit calls $EDITOR. uses "system" here, to display output
	system( "$SVN commit --username $DASSCM_USER $subversion_options $DASSCM_REPO" );
	# TODO: commit (-m)
}

sub diff(@)
{
	check_parameter(@_,1);
	check_env();
	
	(my $basename, my $dirname_prod, my $dirname_repo, my $filename_prod, my $filename_repo) = get_filenames($_[0]);
		
	#print "$basename,$dirname_prod,$dirname_repo\n";

	(my $rc_update, my @result)=run_command( "$SVN update $filename_repo" );
	if( $rc_update != 0 ) {
		print @result;
		die;
	}
	
	(my $rc_diff, my @diff)=run_command( "diff $filename_repo $filename_prod" );
	print @diff;	
}

#####################################################################
#
# main
#

my $number_arguments = @ARGV;
#print "$number_arguments\n";

if ($number_arguments > 0) {
	my $command = $ARGV[0];
	shift @ARGV;
	#$command =~ s/[A-Z]/[a-z]/m;
	#print "$command\n";

	$_=$command;
	if (m/help/i) {
		help(@ARGV);
	} elsif (m/add/i) {
		add(@ARGV);
	} elsif (m/commit/i) {
		commit(@ARGV);
	} elsif (m/diff/i) {
		diff(@ARGV);
	} elsif (m/activate/i) {
		activate(@ARGV);
	} else {
		usage();
		check_env();
	}
}
