#!/usr/bin/perl
#
#

use lib ('.', "$ENV{'HOME'}/bin");

use Carp;
use Cwd;
use File::Basename;
use File::Copy 'cp';
use Getopt::Long;
use GetPackage;
use Pod::Usage;
use Time::localtime;

my %optctl = (
		"arch:s" => \$arch,
		"check" => \$checkOnly,
		"fromtags" => \$fromTags,
        "help" => \$help,
		"listPkg" => \$listPkg,
		"noGetUmbrellaPackage" => \$noGetUmbrellaPackage,
		"noPrcsDepUmbrella" => \$noPrcsDepUmbrella,
		"verbose+" => \$verbose,
		"wabase:s" => \$waBase
		);

GetOptions( %optctl ) or pod2usage(2);

pod2usage(1) if ( $help );

if ( (scalar( @ARGV ) < 1) || (scalar( @ARGV ) > 3) )
	{
    pod2usage(2);
	}

my $getUmbrellaPackage = (! $noGetUmbrellaPackage);
my $prcsDepUmbrella = (! $noPrcsDepUmbrella);
my $umbrella = shift;
my $release = shift;
if ( ! $release )
	{
	$release = 'trunk';
	}

my $wa = shift;
if ( ! $wa )
	{
	$wa = $release;
	}

if ( ! $waBase )
	{
	$waBase = "$ENV{'HOME'}/svn";
	}

if ( $verbose > 1 )
   {
   print( "getU Args\n" );
   print( "\tumbrella: ${umbrella}\n" );
   print( "\trelease: ${release}\n" );
   print( "\tarch: ${arch}\n" );
   print( "\tverbose: ${verbose}\n" );
   print( "\twa: ${wa}\n" );
   print( "\twaBase: ${waBase}\n" );
   }

my %pkgList = ();
my %beenDone = ();
my $workarea = "${waBase}/${wa}";
my @orderPkgList = ();

print( "Get Packages to WA: ${workarea}\n\n" );

$exitCode = getPackageList( $umbrella, $release, ${workarea}, ${fromTags},
		${arch}, ${verbose}, \%pkgList, \%beenDone, $getUmbrellaPackage,
		$prcsDepUmbrella, \@orderPkgList );

if ( $verbose > 1 )
	{
	print( "Ordered Package List Content:\n" );
    foreach $pkg ( @orderPkgList )
    	{
        print( "${pkg}\n" );
        }
	}

if ( $checkOnly )
   	{
	print( "__START__\n" );
    foreach $pkg ( @orderPkgList )
    	{
        print( "${pkg}\n" );
        }

	print( "__END__\n" );
   	exit $exitCode;
   	}

if ( $exitCode == 0 )
   {
   my $ky;

   foreach $ky ( sort( keys( %pkgList )) )
      {
      $exitCode = getPackage( ${ky}, $pkgList{${ky}}, ${workarea}, ${fromTags},
            ${verbose}, \%beenDone );
      #
      # Making sure that perl error codes are correctly
      # taken into account as such from caller shell script.
      # Typical example is perl returning error 256 on svn checkout issues
      #    svn: REPORT of '/svn/hpoc-serv-prof/!svn/vcc/default':
      #    Could not read chunk delimiter: Secure connection truncated
      #    (https://hpoc-serv-prof.csd200a.com)
      #    program finished with exit code 0
      # which is unfortunately considered as ... 0 by shell (256 mod 256)
      # since shell error codes are coded as 8-bit unsigned.
      #
      if ( $exitCode && ( ( $exitCode % 256 ) == 0 ) )
         {
         exit 255;
         }
      }
   }

# $exitCode = getPackage( $umbrella, $release, "${waBase}/${wa}", $fromTags, $verbose );

exit $exitCode;

__END__
=head1 NAME

getUmbrella - This command will attempt to retrieve from subversion the
version of all the source that is part of the umbrella.

=head1 SYNOPSIS

getUmbrella
	|--arch=(Architecture Name)
    [--check
    |--fromtags
	|--help
    |--listPkg
	|--noGetUmbrellaPackage
	|--noPrcsDepUmbrella
    |--verbose
	|--wabase=(WorkArea Base Directory)
    ] <Umbrella Name> [release] [work area]

=head1 OPTIONS

=over 8

=item arch=(Architecture Name)

If specified this limits the retrieval to be for the architecture(s)
specified. If not specified all the ARCH specific PackageList and
UmbrellaList files are used in creating the list of packages to
retrieve.

=item check

This causes the set of packages associated with the get to be created and
then checks that all the references for a package are for the same
release.

=item fromtags

If set this will cause the retrieval to be from the tags area instead
of branches if a release is specified that is not trunk.

=item help

Provides an overview on the usage of this script.

=item listPkg

This causes the list of packages associated with the umbrella to be
generated without attempting to get/refresh the content.
(An attempt is made to retrieve the Umbrella package.)

=item noGetUmbrellaPackage

This will keep the tool from checking out the Umbrella Package
before it starts to use it.

=item noPrcsDepUmbrella

This controls the use of the content of the umbrellalist associated
with an umbrella.  This limits the getUmbrella to only getting the
packages in the packagelist associated with the umbrella.

=item verbose

This will cause the script to be pretty chatty about what is going on.
It can be useful it trying to understand what has changed since  previous
getUmbrella was done for a workarea.

=item wabase=(Work Area Base Directory)

This allows the base of the work area to be specified to a location
other then $ENV{'HOME'}/svn.

=back

=head1 DESCRIPTION

The B<getUmbrella> script will attempt to retrieve the umbrella package
specified on the command line for the release specified. The retrieved
content will be placed into a workarea that will be common for all the
packages that are retrieved.

If the umbrella package already exists in the workarea it will
be refreshed with the repository content.

The script starts by retrieving/updating the umbrella project that
is specified on the command line.  If the retrieve step should be
skipped the --noGetUmbrellaPackage flag can be used on the command
line to avoid the retrieval.

The script will then use the content of the PackageList and UmbrellaList
files to determine which packages need to be retrieved.

The PackageList and UmbrellaList files are name PackageList.(ARCH) where
the ARCH can be specified(--arch) on the command line.  If not specified
all instances of the UmbrellaList and PackageList are used.

The first lists checked is the UmbrellaList(s).  If they are not
to be checked the --noPrcsDepUmbrella flag can be used to keep the
script from processing any of the files.  If the UmbrellaList for
a specific set of architecture(s) is to be perform the --arch command
line option can be specified.  If not specified all UmbrellaList.*
file will be processed by the script.  For each entry in an
UmbrellaList the package list for that umbrella will be added
to the set of packages that are to be retrieved.  The exact
algorithm described here is repeated for each entry.

After the UmbrellaList processing the PackageList file(s) are processed.
In similar fashion to the UmbrellaList the --arch option can
be used to limit the PackageList that are processed.  If not
specified all PackageList.* files are processed.  For each
package read from the PackageList a check is made to see if it
is already in the Package List.  If it is not in the list it
is added.  If it is in the list the release specified for the
package is checked against the release specified or assumed
for the entry that was just read to make sure it is the same.
This check guarantees that the release of a package has a
single value for a workarea.  It is not possible to bring 2
releases of the same package into a workarea.

Once the total list of packages is created and check the script is
ready to retrieve the set of packages that are defined by the umbrella
and it's dependencies.  Before this occures the script can be stopped
if the --check option is specified on the command line.

For each of the packages in the consolidated list the associated revision
will be retrieved into the workarea for the release that is specified.

The PackageList file format will be:

(Package Name) (Release)
	or
#include (Package List File)

The (Package List File) is located relative to the file that is being
processed.  The name is created by putting together the directory name
of the file that is currently being processed and the value specified
on the #include line.  The #include can be used to create package lists
that are common for a set of architectures or for the entire umbrella
if appropriate.

If the Release is not specified it is assumed to be the same as the
umbrella that is being worked on.

The UmbrellaList is in the same format it also support the #include
line.

=cut

