Subversion Repositories DevTools

Rev

Rev 321 | Blame | Compare with Previous | Last modification | View Log | RSS feed

########################################################################
# Copyright (C) 2007 ERG Limited, All rights reserved
#
# Module name   : jats.sh
# Module type   : Makefile system
# Compiler(s)   : n/a
# Environment(s): jats
#
# Description   : JATS Make Time Support
#                 This package contains a collection of very useful functions
#                 that are invoked by the JATS generated makefiles to perform
#                 complicated operations at Make Time
#
#                 The functions are designed to be invoked as:
#                   $(GBE_PERL) -Mjats_runtime -e <function> -- <args>+
#
#                 The functions in this packages are designed to take parameters
#                 from @ARVG as this makes the interface easier to read.
#
#                 This package is used to speedup and simplify the JATS builds
#                 Speedup (under windows)
#                       Its quicker to start up one perl instance than
#                       to invoke a shell script that performs multiple commands
#                       Windows is very slow in forking another task.
#
#                 Simplify
#                       Removes some of the complications incurred due to different
#                       behaviour of utilities on different platforms. In particular
#                       the 'rm' command
#
#                       Perl is a better cross platform language than shell script
#                       as we have greater control over the release of perl.
#
#......................................................................#

require 5.006_001;
use strict;
use warnings;

package jats_runtime;

our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION);
use Exporter;
use JatsError qw(:name=jats_runtime);

$VERSION = 1.00;
@ISA = qw(Exporter);

# Symbols to autoexport (:DEFAULT tag)
@EXPORT = qw( rmlitter
              rm_opr
              rm_rf
              rm_f
              mkpath
              printenv
              printargs
              echo
            );

use File::Path qw(rmtree);
our %opts;

#BEGIN
#{
#    print "-------jats_runtime initiated\n";
#}

#-------------------------------------------------------------------------------
# Function        : process_options
#
# Description     : Extract options from the front of the command stream
#                   Stops at the first argument that doesn't start with a
#                   '--'
#
#                   Options of the form --Opt=Val are split out
#                   Options of the form --Opt will set (or increment a value)
#
# Inputs          : None: Uses global ARGV
#
# Returns         : None: Resets global argv
#                         Populates the %opts hash
#
sub process_options
{
    while ( my $entry = shift @ARGV )
    {
        last if ( $entry eq '--' );
        if ( $entry =~  m/^--(.*)/  )
        {
            if ( $1 =~ m/(.*)=(.*)/ )
            {
                $opts{$1} = $2;
            }
            else
            {
                $opts{$1}++;
            }
        }
        else
        {
            unshift @ARGV, $entry;
            last;
        }
    }
    #
    #   Process some known options
    #
    $opts{'Progress'} = $opts{'Verbose'}    if ( $opts{'Verbose'} );
    ErrorConfig( 'name', $opts{Name})       if ( $opts{'Name'} );
    ErrorConfig( 'verbose', $opts{Verbose}) if ( $opts{'Verbose'} );
    DebugDumpData("RunTime Opts", \%opts )  if ( $opts{'ShowOpts'} );;
    Message ("RunTime args: @ARGV")         if ( $opts{'ShowArgs'} );
    printenv()                              if ( $opts{'ShowEnv'} );
    Message ($opts{'Message'})              if ( $opts{'Message'} );
}

#-------------------------------------------------------------------------------
# Function        : rmlitter
#
# Description     : Remove litter from a build directory
#
# Inputs          : ARGV    A list of files (with wildcards) to delete in the
#                           current, and named, directories.
#
#                           Options:    -f File list follows (default)
#                                       -d Dir  list follows
#
#                           Example:    *.err -d OBJ BIN
#                                       Will delete *.err OBJ/*.err BIN/*.err
#
# Returns         : 0
#
sub rmlitter
{
    process_options();

    my @flist;
    my @dlist = '.';

    #
    #   Parse arguments
    #   Collect filenames and dirnames. Switch between the two collection lists
    #
    #
    my $listp = \@flist;
    foreach my $ii ( @ARGV )
    {
        if ( $ii eq '-f' ) {
            $listp = \@flist;

        } elsif ( $ii eq '-d' ) {
            $listp = \@dlist;

        } else {
            push @$listp, $ii;
        }
    }

    #
    #   Process all directories looking for matching files
    #   Delete files
    #
    foreach my $dir ( @dlist )
    {
        foreach my $file ( @flist )
        {
            my $path = "$dir/$file";
            $path =~ s~ ~\\ ~g;
            my @del = glob ( $path );
            if ( @del )
            {
                Message ("rmlitter. @del") if ($opts{'Progress'} );
                chmod '777', @del;
                unlink @del;
            }
        }
    }
}

#-------------------------------------------------------------------------------
# Function        : expand_wildcards
#
# Description     : Expand argument wildcards
#                   Replace @ARGV with an expanded list of files to process
#                   This is a helper function
#
#
# Inputs          : @ARGV
#
# Returns         : @ARGV
#
sub expand_wildcards
{
    #
    #   Replace spaces with escaped spaces to assist the 'glob'
    #
    sub escape_space
    {
        my ($item) = @_;
        $item =~ s~ ~\\ ~g;
        return $item;
    }
    @ARGV = map(/[*?]/o ? glob (escape_space($_)) : $_ , @ARGV);
}

#-------------------------------------------------------------------------------
# Function        : rm_rf
#
# Description     : Remove all files and directories specified
#
# Inputs          : @ARGV       - A list of files and directories
#
# Returns         : Nothing
#
sub rm_rf
{
    process_options();
    expand_wildcards();
    my @dirs =  grep -e $_,@ARGV;
    if ( @dirs )
    {
        rmtree(\@dirs,0,0);
    }
}

#-------------------------------------------------------------------------------
# Function        : rm_f
#
# Description     : Remove all named files
#                   Will not remove directores - even if named
#
#                   Unix Note:
#                   Need to handle broken soft links
#
#
# Inputs          : @ARGV       - A list of files to delete
#
# Returns         :
#
sub rm_f {
    process_options();
    expand_wildcards();

    foreach my $file (@ARGV) {
        Message ("Delete: $file") if ($opts{'Progress'} );
        next if -d $file;
        next unless ( -e $file || -l $file );
        next if _unlink($file);
        Warning "Cannot delete $file: $!";
    }
}

#-------------------------------------------------------------------------------
# Function        : rm_opr
#
# Description     : Combo deletion operation
#                   Parameter driven to delete many things in one command
#
# Inputs          : Options and paths
#                   Options. Set mode for following paths
#                       -f   remove named file
#                       -d   remove named directory if empty
#                       -rf  remove directory or file
#                       -fd  remove file and directory if empty
#
# Returns         : 
#
sub rm_opr
{
    my $mode = '-f';
    process_options();
    foreach my $file (@ARGV) {
        if ( $file eq '-f' ) {
            $mode = $file;
        } elsif ( $file eq '-d' ) {
            $mode =$file;
        } elsif ( $file eq '-rf' ) {
            $mode =$file;
        } elsif ( $file eq '-fd' ) {
            $mode =$file;
        } elsif ( $file =~ m/^-/ ) {
            Error ("rm_opr - unknown option: $file");
        } else {
            #
            #   Not an option must be a file/dir to delete
            #
            if ( $mode eq '-f' ) {
                Message ("Delete File: $file") if ($opts{'Progress'} );
                _unlink($file);

            } elsif ( $mode eq '-d' ) {
                Message ("Delete Empty Dir: $file") if ($opts{'Progress'} );
                rmdir $file;

            } elsif ( $mode eq '-rf' ) {
                Message ("Delete Dir: $file") if ($opts{'Progress'} );
                rmtree($file,0,0);

            } elsif ( $mode eq '-fd' ) {
                Message ("Delete File: $file") if ($opts{'Progress'} );
                _unlink($file);
                my $dir = $file;
                $dir =~ tr~\\/~/~s;
                Message ("Remove Empty Dir: $dir") if ($opts{'Progress'} );
                if ( $dir =~ s~/[^/]+$~~ )
                {
                    rmdir $dir;
                }
            }
        }
    }
}


#-------------------------------------------------------------------------------
# Function        : mkpath
#
# Description     : Create a directory tree
#                   This will create all the parent directories in the path
#
# Inputs          : @ARGV   - An array of paths to create
#
# Returns         :
#
sub mkpath
{
    process_options();
    expand_wildcards();
    File::Path::mkpath([@ARGV],0,0777);
}

#-------------------------------------------------------------------------------
# Function        : _unlink
#
# Description     : Helper function
#                   Unlink a list of files
#
# Inputs          : A file to delete
#
# Returns         : False: File still exists
#
sub _unlink {
    my ($file) = @_;
    if ( ! unlink $file  )
    {
        chmod(0777, $file);
        return unlink $file;
    }
    return 1;
}

#-------------------------------------------------------------------------------
# Function        : printenv
#
# Description     : 
#
# Inputs          : 
#
# Returns         : 
#
sub printenv
{
    foreach my $entry ( sort keys %ENV )
    {
        print "    $entry=$ENV{$entry}\n";
    }
}

#-------------------------------------------------------------------------------
# Function        : printargs
#
# Description     : Print my argumements
#
# Inputs          : User arguments
#
# Returns         : Nothing
#
sub printargs
{
    Message "Arguments", @ARGV;
}

#-------------------------------------------------------------------------------
# Function        : echo
#
# Description     : echo my argumements
#
# Inputs          : User arguments
#
# Returns         : Nothing
#
sub echo
{
    process_options();
    Message @ARGV;
}

#-------------------------------------------------------------------------------
# Function        : printArgsEnv
#
# Description     : Print my argumements nd environmen
#
# Inputs          : User arguments
#
# Returns         : Nothing
#
my $PSPLIT=':';
sub printArgsEnv
{
    Message "printargs....";
    Message "Program arguments", @ARGV;

    $PSPLIT = ';' if ( $ENV{GBE_MACHTYPE} eq 'win32' );

    sub penv
    {
        my ($var) = @_;
        pvar ($var, $ENV{$var} || '');
    }
    # Simple print of name and variable
    sub pvar
    {
        my ($text, $data) = @_;
        printf "%-17s= %s\n", $text, $data;
    }
    
    sub alist
    {
        my ($text, @var) = @_;
        my $sep = "=";
        for ( @var )
        {
            my $valid = ( -d $_ || -f $_ ) ? " " : "*";
            printf "%-17s%s%s%s\n", $text, $sep, $valid, $_;
            $text = "";
            $sep = " ";
        }
    }
    
    #   Display a ';' or ':' separated list, one entry per line
    sub dlist
    {
        my ($text, $var) = @_;
        alist( $text, split $PSPLIT, $var || " " );
    }

    Message ("Complete environment dump");
    foreach my $var ( sort keys(%ENV) )
    {
       penv  ($var);
    }

    dlist   "PATH"            , $ENV{PATH};
    exit (999);
}

1;