#!/usr/bin/perl -w
#
# "Cmmi" is a "configure ; make ; make install" tool.
#               You can do it more easy.
#   Copyright (C) 1999,2000,2001 Kiyoka Nishyama
#     $Date: 2002/10/20 12:07:30 $
#
# This file is part of Cmmi
#
# Cmmi 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 2, or (at your option)
# any later version.
# 
# Cmmi 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 Cmmi; see the file COPYING.
#
#
require 5.003;
use English;

use strict 'vars';
use vars qw($VERSION  $debug $verbose
	    $SCRIPT_NAME
	    $ARCIVE_DIR
	    $PACKAGE_TYPE
	    $PACKAGE_DIR
	    $opt_v $opt_d $opt_n
	    );
use Getopt::Std;
use File::Basename;
# ---------- CONSTANT VALUE ----------
$VERSION = "0.2.1";
$debug = 0;
$verbose = 0;

$SCRIPT_NAME = "cmmi.script";

# ---------- PROGRAM CODE --------
main( );
exit( 0 );

sub main {
    my( $comm ) = "";
    my( $done ) = 0;
    my( $home ) = $ENV{'HOME'};
    load_rcfiles( "$home/.cmmirc" );
    getopts( 'vdn' );
    if( $opt_v ) { $verbose = 1; }         # verbose switch
    if( $opt_d ) { $debug   = 1; }         # verbose switch
    if( $opt_n ) { $PACKAGE_TYPE = 0; }    # set package type to NON
    if( scalar(@ARGV)) { $comm = $ARGV[0]; }
    if( "clean" eq $comm ) {
	my( $state ) = get_curdir_state( $home );
	if( 1 == $state ) {
	    my( $name ) = sprintf( "/bin/rm -rf */%s */build", $SCRIPT_NAME );
	    system( $name );
	    $done = 1;
	}
	if( 2 == $state ) {
 	    my( $name ) = sprintf( "/bin/rm -rf ./%s ./build", $SCRIPT_NAME );
	    system( $name );
	    $done = 1;
	}
    }
    if( "install" eq $comm ) {
	system( sprintf( "./%s install", $SCRIPT_NAME ));
	$done = 1;
    }
    if( $comm =~ m/.*[.]tar[.].*/ ) {
	my( @arc ) = @ARGV;

	# ɤɬפʤ wgetǤȤäƤ
	foreach (@arc) {
	    if( m/^http:/ || m/^ftp:/ ) {
		my( $st ) = system( "wget -nd $_" );           if( $st ) { die $ERRNO; }
		s/.*:\///;
		$_ = basename( $_ );
		if( $debug ) {
		    printf( "Info:Got file [%s]\n", $_ );
		}
	    }
	}

	# cmmi֤Ͽ
	my( $configure, $dir ) = get_dirname( @arc );
	printf( "%13s : %s\n", "arcives",      join( " ", @arc ));
	printf( "%13s : %s\n", "dir",          $dir );
	system( sprintf( "/bin/mkdir %s/%s/%s", $home, $ARCIVE_DIR, $dir ))
	    unless(-d sprintf( "%s/%s/%s", $home, $ARCIVE_DIR, $dir ));
	foreach ( @arc ) {
	    system( sprintf( "/bin/mv %s %s/%s/%s", $_, $home, $ARCIVE_DIR, $dir ));
	    printf( "%13s  : %s -> %s/%s/%s\n", "move", $_, $home, $ARCIVE_DIR, $dir );
	    printf( "# (for Emacs shell-mode, Please return)\n" );
	    printf( "cd %s/%s/%s\n", $home, $ARCIVE_DIR, $dir );
	}
	
	$done = 1;
    }
    if( !$done || ( "make" eq $comm )) {
	my( $go ) = 1;
	my( $configure, $dir ) = get_dirname( <*.tar.*> );
	my( $state, $pwd     ) = get_curdir_state( $home );
	if( 2 != $state      ) { $go = 0; }

	if( $go ) {
	    # make cmmi.script
	    make_cmmi_script( );
	    $done = 1;
	}
    }
    if( !$done ) { usage( $home ); exit( 1 ); }
}

#
# rcե¹Ԥ
# 
sub load_rcfiles () {
    my ($rcfile) = @_;

    if( $verbose ) {
	printf( "Info: rcfile = %s\n", $rcfile );
    }
    if (-f $rcfile) { do $rcfile; }

    if( !defined( $ARCIVE_DIR )) {
	$ARCIVE_DIR  = "cmmi";
    }
    if( !defined( $PACKAGE_TYPE )) {
	$PACKAGE_TYPE  = 0;
    }
    else {
	if( !defined( $PACKAGE_DIR )) {
	    printf( STDERR "Cmmi Error : You must define pair variable \$PACKAGE_TYPE,\$PACKAGE_DIR\n" );
	}
    }
}

# ߤξ֤֤
#    ( $state, $name )
#  $state ... 0: ~/$ARCIVE_DIRγ
#             1: ~/$ARCIVE_DIR ǥ쥯ȥǤ
#             2: ~/$ARCIVE_DIR/xxxx Ǥ롣 $name  ȥǥ쥯ȥΥեѥ֤̾
sub get_curdir_state ($) {
    my( $home ) = @_;
    my( $state ) = 0;
    my( $pwd  ) = $ENV{'PWD'};
    my( $name ) = "";
    if( $debug ) {
	printf( "Info:home = %s, cwd = %s\n", $home,  $pwd );
    }

    if( $debug ) {
	printf( "Info: ARCIVE_DIR = %s\n", $ARCIVE_DIR );
	printf( "Info: base1(%s)  base0(%s)\n", basename( dirname( $pwd )), basename( $pwd ));
    }

    if( $ARCIVE_DIR eq basename( $pwd )) { $state = 1; }   
    if( $ARCIVE_DIR eq basename( dirname( $pwd ))) {
	$state = 2;
	$name  = $pwd;
    }
    if( $debug ) {
	printf( "Info: $state = %d\n", $state );
    }
    return( $state, $name );
}

sub usage ($) {
    my( $home ) = @_;
    printf( "cmmi $VERSION\n" );
    printf( "usage : cmmi [switch]  [install|clean|make|ARCFILE] \n" );
    printf( "  cmmi ARCFILE .... checkin ARCFILE to %s/%s/xxxxx/\n", $home, $ARCIVE_DIR );
    printf( "  cmmi         .... configure and make\n" );
    printf( "  cmmi install .... install \n" );
    printf( "  cmmi clean   .... cleaning work \n" );
    printf( "switch : \n" );
    printf( "  -v   verbose mode\n" );
    printf( "  -d   debug   mode\n" );
    printf( "  -n   force unset '\$PACKAGE_TYPE'\n" );
}

# cmmi.script 롣
sub make_cmmi_script {
    my( $name );
    my( @arc, $arcstr );
    my( @out );
    my( $found ) = 0;

    # ֥եǧ롣
    @arc = <*.tar.*>;
    if( ! @arc ) { printf( STDERR "Error : No archives.\n" ); exit( 0 ); }
    $arcstr = join( " ", @arc );
    if( $verbose ) {
	printf( "%13s : %s\n", "archives", $arcstr );
    }
    
    # configure եõ
    my( $configure, $dir ) = get_dirname( @arc );
    if( !$configure  ) { printf( STDERR "%13s : error configure script was not found.\n", "Warning" ); }
    if( $verbose ) { printf( "%13s : %s\n", "dir", $dir ); }
    
    # .cmmi եõ̤֤
    my( $configure_sw, $init_config, $make_str, $inst_str ) = read_dot_cmmi( );

    # cmmi.script 롣
    @out = output_cmmi_script( $arcstr, $dir, $configure_sw, $init_config, $make_str, $inst_str );
    if( $verbose ) {
	printf( "%13s : %s ( %s, %s )\n", "generate", $SCRIPT_NAME, $arcstr, $dir );
	my( $t ) = "NON (\"make install\" immediately)";
	if( $PACKAGE_TYPE eq "D" ) { $t = "Debian    package"; }
	if( $PACKAGE_TYPE eq "R" ) { $t = "RPM       package"; }
	if( $PACKAGE_TYPE eq "S" ) { $t = "Slackware package"; }
	printf( "%13s : %s\n", "package type", $t );
    }
    open( FP, ">$SCRIPT_NAME" );
    foreach (@out) { print FP $_, "\n"; }
    close( FP );
    system( "/bin/chmod +x $SCRIPT_NAME" );

    # configure, make ¹Ԥ롣
    $name = sprintf( "./%s config ; ./%s make", $SCRIPT_NAME, $SCRIPT_NAME );
    system( $name );
}

# .cmmi եɤ߹
sub read_dot_cmmi {
    my( @conf, @init, @make, @inst );
    my( $state ) = "";
    unless( open( FP, ".cmmi" )) {
	if( $verbose ) {
	    printf( "%13s : .cmmi not found\n", "Warning" );
	}
	return( ("", "", "", "") );
    }
    foreach ( <FP> ) {
	chop;
	if( $debug ) { print( ".cmmi : $_ \n" ); }
	if( /^conf/ ) { $state = "conf"; next; }
	if( /^init/ ) { $state = "init"; next; }
	if( /^make/ ) { $state = "make"; next; }
	if( /^inst/ ) { $state = "inst"; next; }

	if( "conf" eq $state ) { push( @conf,   $_ ); }
	if( "init" eq $state ) { push( @init, $_ ); }
	if( "make" eq $state ) { push( @make,   $_ ); }
	if( "inst" eq $state ) { push( @inst,   $_ ); }
    }
    close( FP );
    my( $conf_str )   = join( "!!!", @conf );
    my( $init_str )   = join( "!!!", @init );
    my( $make_str   ) = join( "!!!", @make );
    my( $inst_str   ) = join( "!!!", @inst );
    return( ( $conf_str, $init_str, $make_str, $inst_str ) );
}

# ǥ쥯ȥ֤̾
sub get_dirname {
    my( @arc ) = @_;
    my( $found ) = 0;
    my( $dir, @list );
    foreach ( @arc ) {
	my( $name ) = sprintf( "tar ztf %s|", $_ );
	open( FP, $name );
	@list = <FP>;
	foreach ( @list ) {  
	    chop;
	    if( /\/configure/ ) { $found = 1; }
	}
	$list[0] =~ s/^[.]+\///;
	$list[0] =~ m/([^\/]+)/;
	$dir = $1;
	close( FP );
    }
    return( ($found, $dir) );
}

sub output_cmmi_script {
    my( $arcfiles, $srcdir, $configure_str, $init_config_str, $make_str, $inst_str ) = @_;
    my( @arc )              = split( / /, $arcfiles );
    my( @configure_sw  )    = split( /!!!/, $configure_str );
    my( @init_config )      = split( /!!!/, $init_config_str );
    my( @make )             = split( /!!!/, $make_str );
    my( @inst )             = split( /!!!/, $inst_str );
    my( @out );
    if( $debug ) {
	printf( "%13s : %s\n", "conf_str", $configure_str );
	printf( "%13s : %s\n", "init_str", $init_config_str );
	printf( "%13s : %s\n", "make_str", $make_str );
	printf( "%13s : %s\n", "inst_str", $inst_str );
    }

    push( @out, "#!/bin/sh" );
    push( @out, "" );
    push( @out, "case \$1 in" );
    push( @out, "  \"config\")" );
    push( @out, "    echo \"--------------------------------------------------------------------------------\";" );
    push( @out, "    /bin/rm    -rf build" );
    push( @out, "    /bin/mkdir     build" );
    push( @out, "    cd             build" );
    foreach ( @arc ) {
	push( @out, "    tar zxf ../$_" );
    }
    push( @out, "    cd $srcdir" );

    foreach ( @init_config  ) { push( @out, $_ ); }
    if( length( $configure_str )) {
	foreach ( @configure_sw ) {   push( @out, "    $_" ); }
    }
    else {
	push( @out, "    ./configure" );
    }
    push( @out, "" );
    push( @out, "    if [ $? -ne 0 ]; then exit 1; fi;" );
    push( @out, "    ;;" );
    push( @out, "  \"make\")" );
    push( @out, "    echo \"--------------------------------------------------------------------------------\";" );
    push( @out, "    cd build/$srcdir" );
    if( $make_str ) {	foreach ( @make ) { push( @out, $_ ); }}
    else {              push( @out, "make" );    }
    push( @out, "    cd .." );
    push( @out, "    if [ $? -ne 0 ]; then exit 1; fi;" );
    push( @out, "    ;;" );
    push( @out, "  \"install\")" );
    push( @out, "    echo \"--------------------------------------------------------------------------------\";" );
    push( @out, "    cd build/$srcdir" );
    if( $PACKAGE_TYPE ) {
	my( $package_name ) = $srcdir;
	$package_name =~ s/_/./g;
	push( @out, "mkdir -p $PACKAGE_DIR" );
	push( @out, "mkdir doc-pak" );
	push( @out, sprintf( "echo \'Cmmi:%s\' > description-pak", $package_name ));
	push( @out, sprintf( "checkinstall --pkgname='%s' -%s ../../%s install-core", $package_name, $PACKAGE_TYPE, $SCRIPT_NAME));
    }
    if( "D" eq $PACKAGE_TYPE ) {
	push( @out, " pushd .");
	push( @out, " /bin/cp -f *.deb $PACKAGE_DIR" );
	push( @out, " cd $PACKAGE_DIR" );
	push( @out, " dpkg-scanpackages . /dev/null | gzip -c9 > Packages.gz" );
	push( @out, " popd ");
    }
    if( !$PACKAGE_TYPE ) {
	push( @out, sprintf( "../../%s install-core", $SCRIPT_NAME))
    }
    push( @out, "    cd .." );
    push( @out, "    if [ $? -ne 0 ]; then exit 1; fi;" );
    push( @out, "    ;;" );
    push( @out, "  \"install-core\")" );
    if( $inst_str ) {	foreach ( @inst ) { push( @out, $_ ); }}
    else {
	push( @out, "    make install" );
    }
    push( @out, "    ;;" );
    push( @out, "  *)" );
    push( @out, "    echo \"usage : \`basename \$0\` (config|make|install)\";" );
    push( @out, "    exit 2;" );
    push( @out, "    ;;" );
    push( @out, "esac" );
    push( @out, "exit 0;" );
    return( @out );
}
