Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

########################################################################
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
#
# Module name   : rmMerge_spitRelease.pl
# Module type   : JATS Utility
# Compiler(s)   : Perl
# Environment(s): jats
#
# Description   : Insert Extacted Release data into a different RM instance
#
# Usage         : See POD at the end of this file
#
#......................................................................#

require 5.008_002;
use strict;
use warnings;

use Pod::Usage;
use Getopt::Long;

use JatsError;
use JatsRmApi;
use JatsSystem;
use FileUtils;
use ConfigurationFile;
use File::Copy;
use DBI;
my $RM_DB;
my $VERSION = "1.0";
my $testRMCred = ['TST', 'jdbc:oracle:thin:@relmanu1.coidtfba5ouc.ap-southeast-2.rds.amazonaws.com:1521:relmanu1', 'RELEASE_MANAGER', 'MPM0$U74'];
my $oldRMCred =  ['OLD', 'jdbc:oracle:thin:@auawsards001:1521:RELEASEM', 'RELEASE_MANAGER', 'ske2k0se'];
my $useRmCred;

my $opt_reuse=1;
my $opt_help=0;
my $opt_verbose=0;
my $opt_debug=0;
my $opt_live = 0;
my $opt_rtagId;
my $opt_infile;
my $opt_name;
my $opt_sloppy;

our %rmData;
my %keyFieldsData;
my $rtagId;


#-------------------------------------------------------------------------------
# Function        : Mainline Entry Point
#
# Description     :
#
# Inputs          :
#
my $result = GetOptions (
                "help:+"        => \$opt_help,
                "manual:3"      => \$opt_help,
                "verbose:+"     => \$opt_verbose,
                "debug:+"       => \$opt_debug,
                "live!"         => \$opt_live,
                "sloppy!"       => \$opt_sloppy,
                "rtagid:i"      => \$opt_rtagId,            # Used to idenify the input file
                "infile:s"      => \$opt_infile,            # Name of the imput file
                "name:s"        => \$opt_name,
                );

                #
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
                #

#
#   Process help and manual options
#
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
pod2usage(-verbose => 1) if ( $opt_help == 2 );
pod2usage(-verbose => 2) if ( $opt_help > 2 );
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ( $#ARGV >= 0 );

#
#   Configure the error reporting rmMerge_process now that we have the user options
#
ErrorConfig( 'name'    =>'SPITRELEASE',
             'verbose' => $opt_verbose,
             'debug' => $opt_debug,
            );
Error("Must specify rtagID or Infile") unless (defined $opt_infile or defined $opt_rtagId);

#
# 
if ($opt_live) {
    Message("Using Live Database");
    $useRmCred = $oldRMCred;
} else  {
    $useRmCred = $testRMCred;
}
  
#   Generate the output filename
#   
$opt_infile = join('.', $opt_rtagId, 'releaseinfo', 'txt') unless $opt_infile;
Message("Using: $opt_infile") ;
my $localDataStore = $opt_infile;
  
$ENV{GBE_RM_LOCATION} = $useRmCred->[1];
$ENV{GBE_RM_USERNAME} = $useRmCred->[2];
$ENV{GBE_RM_PASSWORD} = $useRmCred->[3];
connectRM(\$RM_DB) unless ( $RM_DB );

#
#   Get the data saved by rmMerge_suck
#
restoreLocalData();

# Use existing rtag name, unless a new one has been provided
my $rtagName = GetRtagName(); 
unless ($opt_name) {
    $opt_name = $rtagName;
} else {
    $opt_name =~ s~\%~$rtagName~g;
}
Message ("Creating Release:$opt_name");

$rtagId = GetRtagByName($opt_name);
Error ("Named Release already exists") if defined $rtagId;

#
#   Potentially massage the data a bit
#
MassageRtagId();

#
#   Generate Cross reference information for the various tables
#   Need to have all the cross references in place first
#
GetXrefsUsers(qw(CREATOR_ID RELEASOR_ID OFFICIAL_ID INSERTOR_ID));
GetXrefsPvid(qw(PV_ID ROOT_PV_ID));
GetXrefsRtagId(qw( RTAG_ID PARENT_RTAG_ID ));
GetXrefsProjId(qw( PROJ_ID ));
GetXrefsGbeId(qw( GBE_ID ));
#GetXrefsPkgId(qw( PKG_ID ));
GetXrefsBaseViewId(qw( BASE_VIEW_ID ));

ErrorDoExit();

#GetXrefsIgnore(qw( TEST_ID TESTRUN_ID DOC_ID BUILD_ID));        # Primary keys - ignore
#GetXrefsIgnore(qw( BE_ID BM_ID BSA_ID BS_ID VCS_TYPE_ID));      # Assume these have not changed

#
#   Now insert data into tables in the target database
#   Need to MAP some fields
#
CreateNewRtagId();
CreateRelease('RELEASE_TAGS');
CreateReleaseData('RELEASE_CONTENT');
CreateReleaseData('PEGGED_VERSIONS');
CreateReleaseData('ADVISORY_RIPPLE');
CreateReleaseConfig();
RebuildReleaseIcons();

disconnectRM(\$RM_DB);
#DebugDumpData("keyFieldsData",\%keyFieldsData);
exit 0;

#-------------------------------------------------------------------------------
# Function        : GetRtagName 
#
# Description     : Get the Rtag Name of the release 
#
# Inputs          : 
#
# Returns         : 
#
sub GetRtagName
{
    my $index = getIndex('RELEASE_TAGS', 'RTAG_NAME');
    my $table = $rmData{'RELEASE_TAGS_DATA'};
    return $table->[0][$index] ;
}

#-------------------------------------------------------------------------------
# Function        : MassageRtagId 
#
# Description     : Need to massage the data for my own RTAG_ID as we are renaming
#                   the Release 
#
# Inputs          : 
#
# Returns         : 
#
sub MassageRtagId
{
}

#-------------------------------------------------------------------------------
# Function        : RebuildReleaseIcons 
#
# Description     : Mark the Release to that its icons are rebuild on the next access
#
# Inputs          : 
#
# Returns         : 
#
sub RebuildReleaseIcons 
{
    #   Force the Release Icons to be rebuilt
    my $m_sqlstr =  "BEGIN RELEASE_MANAGER.TOUCH_RELEASE ( $rtagId ); END;";
    getDataFromRm('addToRelease', $m_sqlstr, {});
}

#-------------------------------------------------------------------------------
# Function        : CreateReleaseConfig 
#
# Description     : Create must of the Release Config 
#
# Inputs          : 
#
# Returns         : 
#
sub CreateReleaseConfig
{
    my ($tableName) = 'RELEASE_CONFIG';
    my $tableData = $tableName. '_DATA';

    #
    #   Get one row of data and massage it into a form suitable for insertion
    #
    unless ( $rmData{$tableData}[0]) {
        Message ("No data found for $tableName");
        return;
    }

    foreach my $data (@{$rmData{$tableData}}) {
        my $rconId;
         
        InsertTableRow($tableName, $data, {
            'RCON_ID' => sub {
                my ($fname, $value) = @_;  
                $rconId  = GetNextSeqNum('SEQ_RCON_ID');
                return $rconId;
                },
            'BMCON_ID' => sub {my ($fname, $value) = @_;  return '';},
            });

        CreateRunLevel($rconId) if $rconId;
    }
}

#-------------------------------------------------------------------------------
# Function        : CreateRunLevel 
#
# Description     : Create a run_level entry and return its rcon_id
#
# Inputs          : None 
#
# Returns         : rcon_id - unique seqience number
#
sub CreateRunLevel
{
    my ($rconId) =  @_;
    getDataFromRm('CreateRunLevel', "INSERT INTO release_manager.RUN_LEVEL (RCON_ID, PAUSE) VALUES ($rconId, 1)", {});
    return $rconId;
}

#-------------------------------------------------------------------------------
# Function        : CreateRelease 
#
# Description     : Create a new Release 
#
# Inputs          : $tableName 
#
# Returns         : 
#
sub CreateRelease
{
    my ($tableName) = @_;
    my $tableData = $tableName. '_DATA';

    #
    #   Get one row of data and massage it into a form suitable for insertion
    #
    my $data = $rmData{$tableData}[0];
    Error ("Internal: No data found for $tableName") unless $data;
    
    InsertTableRow($tableName, $data, {
        'REBUILD_STAMP' => sub {my ($fname, $value) = @_;  return 0;},
        'RTAG_NAME' => sub {my ($fname, $value) = @_;  return $opt_name;},
        });
}

#-------------------------------------------------------------------------------
# Function        : CreateNewRtagId 
#
# Description     : Create a new RTAG_ID 
#
# Inputs          : 
#
# Returns         : 
#
sub CreateNewRtagId
{
    $rtagId = GetNextSeqNum('seq_rtag_id');
    Message("ReleaseTag: RTAG_ID: $rtagId");

    #
    #   PV_ID in the origin
    #   
    my $rtagIdOrigin = $rmData{METADATA}{RTAG_ID};
    $keyFieldsData{RTAG_ID}{$rtagIdOrigin} = $rtagId;
}


#-------------------------------------------------------------------------------
# Function        : getIndex 
#
# Description     : Get the index of a data item from specified meta data
#
# Inputs          : $table  - Name of table to access
#                   $field  - Name of field to locate
#
# Returns         : Will generate an error if not found 
#
sub getIndex
{
    my ($table,$field) = @_;
    my $rv;
    my $tableName = $table . "_NAMES";
    Error ("Internal: getIndex. Metadata not found for: $table") unless exists $rmData{$tableName};

    my $pvMetaData = $rmData{$tableName};

    foreach ( @{$pvMetaData} ) {
        next unless $_->[0] eq $field;
        $rv =  $_->[3] - 1;
        last;
    }

    Error("Internal: getIndex. Cannot find metadata for field($field) in table($table)") unless $rv;
    return $rv;
}

#-------------------------------------------------------------------------------
# Function        : GetNextSeqNum 
#
# Description     : Get the next sequence numbber froom a named sequence 
#
# Inputs          : $seqName 
#
# Returns         : A number
#
sub GetNextSeqNum
{
    my ($seqName) = @_;
    my $row = getDataFromRm('GetNextSeqNum',"SELECT $seqName.NEXTVAL from DUAL", {oneRow => 1});
    #Debug0("Generate $seqName: $row[0]");
    return $row->[0];
}

#-------------------------------------------------------------------------------
# Function        : GetRtagByName 
#
# Description     : Get an rtag_id based on a user name
#
# Inputs          : $name 
#
# Returns         : ratg_id 
#
sub GetRtagByName
{
    my ($name) = @_;
    my $data = getDataFromRm('GetRtagByName',"SELECT rtag_id from release_tags where upper(rtag_name) = upper('$name')", {oneRow => 1});
    return $data unless $data;
    return $data->[0];
}

#-------------------------------------------------------------------------------
# Function        : CreateReleaseData  
#
# Description     : Insert one or more rows into a table
#                   Assumes no data massaging needs to be done
#
# Inputs          : $tableName      - Not sure it will be used
#
# Returns         : 
#
sub CreateReleaseData
{
    my ($tableName) = @_;
    my $tableData = $tableName. '_DATA';

    my $pvidIndex = getIndex($tableName, 'PV_ID');

    #
    #   Get one row of data and massage it into a form suitable for insertion
    #
    foreach my $data (@{$rmData{$tableData}}) {

        if ($opt_sloppy)
        {
            #
            #   Only insert data for packagaes that exist in the target Release
            #
            my $pvid = $data->[$pvidIndex];
            next if ( $keyFieldsData{PV_ID}{$pvid} =~ m~^MISSING-~);

        }
        InsertTableRow($tableName, $data);
    }

}

#-------------------------------------------------------------------------------
# Function        : InsertTableRow 
#
# Description     : Insert a row into a table
#   
# Inputs          : $tableName
#                   $data   - Ref to data
#                   $metaData - REf to meta data    
#                   $callBacks - Hash of FieldNames, functions
#
# Returns         : 
#
sub InsertTableRow
{
    my ($tableName, $data, $callBacks) = @_;
    my $tableMetaData = $tableName. '_NAMES';
    my $metaData = $rmData{$tableMetaData};

    my @insertFields;
    my @insertValues;

    #
    #   Scan the metadata and fiddle the data
    #
    foreach my $entry ( @$metaData) {
        my $fname = $entry->[0];
        my $ftype = $entry->[1];
        my $isNullable = $entry->[2] eq 'Y';
        my $findex = $entry->[3]-1;
        my $value = $data->[$findex];
        $value = '' unless (defined($value));

        # Does this field need to be mapped
        if (exists $rmData{XREF_MAP}{$fname}) {
            my $mapTable = $rmData{XREF_MAP}{$fname}; 
            Error ("Mapping table not found: $mapTable") unless exists $keyFieldsData{$mapTable};

            unless ( $value eq '' && $isNullable) {

                unless (exists $keyFieldsData{$mapTable}{$value}) {
                    DebugDumpData("keyFieldsData",\%keyFieldsData);
                    DebugDumpData("Data",$data);
                    Error ("Mapping value not found: $mapTable, $value, while rmMerge_processing $tableName, $fname\[$findex\]") ;
                }
                my $newValue = $keyFieldsData{$mapTable}{$value};
                unless (defined $newValue) {
                    DebugDumpData("keyFieldsData",\%keyFieldsData);
                    DebugDumpData("Data",$data);
                    Error("Undefined map for: $tableName, $fname, $value");
                }
                if ($newValue ne $value) {
Verbose("Mapping $tableName:$mapTable:$fname:$value -> $newValue");
                    $value = $newValue;
                }
            }
        }

        #
        #   Does the field need to be massaged
        #
        if (defined $callBacks && $callBacks->{$fname}) {
            my $newValue = $callBacks->{$fname}->($fname, $value);
            if ($newValue ne $value) {
Verbose("Massage $tableName:$fname:$value -> $newValue");
                $value = $newValue;
            }
        }

        #
        #   Does the field need to be quoted
        #   Assume that the 'suck' rmMerge_process has quoted special characters
        #   %0D -> return
        #   %0A -> newLine
        #   %09 -> Tab
        #   %25 -> As a percent
        #   %27 -> Single Quote
        #   Also need to handle a single quote char
        #
        if ($ftype =~ m~CHAR|VARCHAR~) {
            $value =~ s~'~'||chr(39)||'~g;
            $value =~ s~%0D~'||chr(13)||'~g;
            $value =~ s~%0A~'||chr(10)||'~g;
            $value =~ s~%09~'||chr(9)||'~g;
            $value =~ s~%27~'||chr(39)||'~g;
            $value =~ s~%25~%~g;
            $value = "'" . $value . "'";
#print("String Length ($fname):", length($value),"\n");

        } elsif ($ftype =~ m~DATE|TIMESTAMP~) {
            $value = "TO_TIMESTAMP('$value','YYYY-MM-DD HH24:MI:SS.FF')"
        }

        # Null item if we are allowed to
        if ($isNullable && length($value) <= 0) {
            $value = 'null';
        }

        push @insertFields, $fname;
        push @insertValues, $value;
    }

    #
    #   Generate the SQL
    #
    my $m_sqlstr = "insert into $tableName (" . join(',', @insertFields) . ")" . " VALUES (". join(',', @insertValues) .")";
    Debug("$m_sqlstr");

    my $sth = $RM_DB->prepare($m_sqlstr);
    my @row;
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    print("@row\n");
                }
            }
            $sth->finish();
        }
        else
        {
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
        }
    }
    else
    {
        Error("Prepare failure" );
    }
}

#-------------------------------------------------------------------------------
# Function        : GetXrefCommon 
#
# Description     : Common code for fetch XREF data from the database 
#
# Inputs          : $name       - Tag name
#                   $sql        - sql fragment to do the work    
#                   $options    - Ref to a hack of options
#                                   'default' - Value to use when not found
#                                   'delete'  - Key to delete from rmMerge_process list
#                                   'call'   - sub so call when data is missing
#
# Returns         : 
#
sub GetXrefCommon
{
    my ($name,$sql, $options) = @_;

    my (@fields) = @_;
    my %idList;
    my %data;
    $options = {} unless $options;

    #
    #   Generate a hash of items that we need
    #
    foreach my $tableName ( keys %rmData ) {
        next unless $tableName =~ m~_XREF$~;
        next unless exists $rmData{$tableName}{$name};
        foreach my $id (keys %{ $rmData{$tableName}{$name} }) {
            if (exists $options->{delete}) {
                next if $options->{delete} eq $id;
            }
            $idList{ $rmData{$tableName}{$name}{$id} } = $id;
        }
    }

    #DebugDumpData("GetXrefCommon, $name", \%idList);
    return unless %idList;

    #
    #   Get all the table data
    #
    my $m_sqlstr =  $sql . " in (". quoteList(keys %idList) .")";
    my $rawData = getDataFromRm('GetXrefsCommon', $m_sqlstr, {} );

    #
    #   Post rmMerge_process the data
    #
    foreach my $row ( @{$rawData} ){
        $data{$row->[1]} = $row->[0];
    }

    #
    #   Check that all required values have been found
    #
    foreach my $id (keys %idList) {
        if (exists $data{$id}) {
            $keyFieldsData{$name}{$idList{$id}} = $data{$id};
        } elsif (defined $options->{default}) {
            $keyFieldsData{$name}{$idList{$id}} = $options->{default};
        } elsif (defined $options->{call}) {
            $keyFieldsData{$name}{$idList{$id}} = $options->{call}->($name, $id);
        } else {
            ReportError("No Crossref for $name matching: $id");
            #DebugDumpData("RmData", \%rmData);
        }
    }

    #
    #   Keep the raw data in the output hash - possibly for debugging purposes
    $keyFieldsData{$name . '_DEBUG'} = \%data;
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsBaseViewId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsBaseViewId
{
    my (@fields) = @_;
    GetXrefCommon('VIEW_ID',"select view_id, view_name from views where view_name");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsPkgId
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsPkgId
{
    my (@fields) = @_;
    GetXrefCommon('PKG_ID',"select pkg_id, pkg_name from packages where pkg_name");
    DebugDumpData("keyFieldsData", \%keyFieldsData);
    Error("Test");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsProjId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsProjId
{
    my (@fields) = @_;
    GetXrefCommon('PROJ_ID', "select proj_id, proj_name from projects where proj_name");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsGbeId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsGbeId
{
    my (@fields) = @_;
    GetXrefCommon('GBE_ID', "select gbe_id, gbe_value from release_manager.gbe_machtype where gbe_value");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsRtagId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsRtagId
{
    my (@fields) = @_;
    GetXrefCommon('RTAG_ID', 'select rtag_id, rtag_name from release_tags where rtag_name', {
        'delete' => $rmData{METADATA}{RTAG_ID},
        });
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsPvid 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsPvid
{
    my (@fields) = @_;
    my $options;

    #
    #   Callback functio to handle missing packages
    #   The PVID will be marked and rmMerge_processed later
    #
    if ($opt_sloppy) {
        $options->{call} = sub{
            my ($name, $id) = @_;
            Message("Package not found: " . join( ' ', split($;,$id)));
            return "MISSING-".$id;
        };
    }

    GetXrefCommon('PV_ID', "select pv.pv_id, p.pkg_name || '$;' ||pv.pkg_version from release_manager.packages p, release_manager.package_versions pv" . 
                   " where p.pkg_id = pv.pkg_id and p.pkg_name || '$;' || pv.pkg_version",
                   $options
                   );

}

#-------------------------------------------------------------------------------
# Function        : GetXrefsUsers 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsUsers
{
    my (@fields) = @_;
    GetXrefCommon('USER_ID', 'select user_id, user_name from access_manager.users where user_name');
}

#-------------------------------------------------------------------------------
# Function        : quoteList  
#
# Description     : Convert an array of strings into a quoted comma-sep string
#                   Used in sql of the form select ... in ( 'aaa','bbb',ccc') 
#
# Inputs          : An array of strings 
#
# Returns         : quoted comma-sep string
#

sub quoteList
{
    my $rv = '';
    my $join = '';
    foreach  (@_) {
        $rv .= $join . "'" . $_ . "'";
        $join = ',';
    }
    return $rv;
}

#-------------------------------------------------------------------------------
# Function        : getDataFromRm 
#
# Description     : Get an array of data from RM 
#
# Inputs          : $name           - Query Name
#                   $m_sqlstr       - Query
#                   $options        - Ref to a hash of options
#                                       sql     - show sql
#                                       data    - show data
#                                       dump    - show results
#                                       oneRow  - Only feth one row
#                                       error   - Must find data
#                                       
# Returns         : 
#
sub getDataFromRm
{
    my ($name,$m_sqlstr, $options ) = @_;
    my @row;
    my $data;

    if (ref $options ne 'HASH') {
        $options = {}; 
    }

    if ($options->{sql}) {
        Message("$name: $m_sqlstr")
    }
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) ) {
            if ( $sth->rows ) {
                while ( @row = $sth->fetchrow_array ) {
                    if ($options->{data}) {
                        Message ("$name: @row");
                    }
                    #Debug0("$name: @row");
                    push @{$data}, [@row];

                    last if $options->{oneRow};
                }
            }
            $sth->finish();
        } else {
            Error("Execute failure:$name: $m_sqlstr", $sth->errstr() );
        }
    } else {
        Error("Prepare failure:$name" );
    }

    if (!$data && $options->{error}) {
        Error( $options->{error} );
    }

    if ($data && $options->{oneRow}) {
        $data = $data->[0];
    }
 
    if ($options->{dump}) {
        DebugDumpData("$name", $data);
    }
    return $data;
}

#-------------------------------------------------------------------------------
# Function        : saveLocalData 
#
# Description     : Saves a hash of data to disk 
#
# Inputs          : 
#
# Returns         : 
#
sub saveLocalData
{
    #
    #   Dump out the configuration information
    #
    my $fh = ConfigurationFile::New( $localDataStore);

    $fh->DumpData( "\n# rmData\n#\n", "rmData", \%rmData );
    $fh->Close();

    DebugDumpData("rmData", \%rmData);
}

#-------------------------------------------------------------------------------
# Function        : restoreLocalData 
#
# Description     : Read in the locally preserved data 
#
# Inputs          : 
#
# Returns         : 
#
sub restoreLocalData
{
    if (-f $localDataStore) {
        require ( $localDataStore );
    } else {
        Error ("Extracted data not found: $localDataStore");
    }
}

#-------------------------------------------------------------------------------
#   Documentation
#

=pod

=for htmltoc    GENERAL::ClearCase::

=head1 NAME

rmMerge_suck - Inject Package-Version info into RM from a previous extraction

=head1 SYNOPSIS

jats rmMerge_spit [options] PackageName PackageVersion

 Options:
    -help              - brief help message
    -help -help        - Detailed help message
    -man               - Full documentation
    -live              - Operation on Live data
    -prev=txt          - Prevous package version
    -[no]placeKeeper   - Only partial package creation
    -[no]history       - Append a text summary of the package history
    -newPackage        - Special Handling for a new package
    -[no]Sloppy        - Ignore packages that can't be found in the Release

=head1 OPTIONS

=over 8

=item B<-help>

Print a brief help message and exits.

=item B<-help -help>

Print a detailed help message with an explanation for each option.

=back

=head2 OPTIONS

=over

=item -placeKeeper

This mode will only insert some of the package information. Suffiecient to preserve the
version number.

The dependencies are not imported. The package will not build.

Used to capture package-versions with some history.

=item -history

This option will cause a textual summary of the packages history to be added created.

The summary track non-ripple builds back to the Release Manager split.

=item -newPackage

Enable special handling of a new package. In particular the Previous version will be set to null.

=back

=head1 EXAMPLE

jats eprog rmMerge_spit PackageName PackageVersion

=cut