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 providedmy $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 rebuiltmy $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 mappedif (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 toif ($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 NAMErmMerge_suck - Inject Package-Version info into RM from a previous extraction=head1 SYNOPSISjats rmMerge_spit [options] PackageName PackageVersionOptions:-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 -placeKeeperThis mode will only insert some of the package information. Suffiecient to preserve theversion number.The dependencies are not imported. The package will not build.Used to capture package-versions with some history.=item -historyThis 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 -newPackageEnable special handling of a new package. In particular the Previous version will be set to null.=back=head1 EXAMPLEjats eprog rmMerge_spit PackageName PackageVersion=cut