Rev 2026 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
######################################################################### Copyright (c) VIX TECHNOLOGY (AUST) LTD## Module name : cc2svn_gendata_sbom.pl# Module type : Makefile system# Compiler(s) : Perl# Environment(s): jats## Description : Get all packages that are used in all releases# Create a data file that can be used offline## The process will exclude some old releases## Generate data on Essential Package Versions to be# transferred from CC to Subversion##......................................................................#require 5.006_001;use strict;use warnings;use JatsError;use JatsSystem;use Getopt::Long;use Pod::Usage; # required for help supportuse JatsRmApi;use ConfigurationFile;use DBI;use HTTP::Date;my $VERSION = "1.2.3"; # Update thismy $opt_verbose = 0;my $opt_help = 0;my $opt_manual;my $opt_test;my $opt_limit;my $opt_quick;my $opt_mode = '';my $opt_sbom = 0;my $RM_DB;my $DM_DB;my $now = time();## Package information#my %Releases;my %Packages;my %Suffixes;my @StrayPackages;my %AllPackages;my %sboms;my %os_id_list;my %os_env_list;my %sbom_pvid;my @sbomNeeded;my $doAllReleases = 0;my $doIncludeOnly = 1;my @includedProjects = (# 481, # UK BUS HOPS);my @includedReleases = (6222, # HOME > UK STAGE COACH (SSW) > Mainline14503, # HOME > UK STAGE COACH (SSW) > ITSO_HOPS_321303, # HOME > UK STAGE COACH (SSW) > SUPPORT_HOPS_REPORTS21343, # HOME > UK STAGE COACH (SSW) > SUPPORT_CIPP17223, # HOME > UK STAGE COACH (SSW) > ITSO HOPS 4);my @excludeProjects = ( 162, # WASHINGTON (WDC)341, # TUTORIAL (TUT)142, # SYDNEY (SYD)182 , # ROME (ROM)6 , # GMPTE/PCL (GMP)521, # NSW CLUB CARD221, # NZ STAGE COACH (NZS)82, # LVS42, # SFO641, # BCC Releaeses62, # OSLO4, # Singapore441, # Tas102, # Ventura);my @excludeReleases = ( 20424, # MASS_REF (MAS) > test# RJACK 9043, # TECHNOLOGY GROUP > Development Environment - For Test Setup# RJACK 14383, # TECHNOLOGY GROUP > eBrio TDS# RJACK 20463, # TECHNOLOGY GROUP > TPIT - BackOffice Linux build# RJACK 14603, # TECHNOLOGY GROUP > TPIT - BackOffice 64 bit [CCB Mode!]#9263, # TECHNOLOGY GROUP > Buildtool DEVI&TEST22163, # GLOBAL PRODUCT MGMT > Rio Tinto - Remote Draught Survey19483, # SEATTLE (SEA) > Phase 2 - I18 [backup] [Restrictive Mode]20403, # SEATTLE (SEA) > Phase 2 - I19 [backup]20983, # ??? May have been deleted13083, # TECHNOLOGY GROUP > TRACS15224, # 64Bit Solaris Test);my @excludeBomProjects = (4, # SINGAPORE (SG)6, # GMPTE/PCL (GMP)42, # SAN FRANCISCO (SFO)62, # OSLO (OSO)82, # LAS VEGAS (LVS)102, # VENTURA (VC)# 122, # VASTTRAFIK (VTK)142, # SYDNEY (SYD)162, # WASHINGTON (WDC)# 164, # SEATTLE (SEA)182, # ROME (ROM)# 202, # STOCKHOLM (SLS)# 221 # NZ STAGE COACH (NZS)# 261 # VÄSTTRAFIK PRODUCTION (VTProd)# 301 # BEIJING (BEI)321, # SAN FRANCISCO PRODUCTION (SFOProd)# 361 # UK STAGE COACH (SSW) Historical# 401 # SEATTLE INTEGRATION (SEA Int)# 421 # UK STAGE COACH PRODUCTION (SSWProd)441, # COTRAL461, # TASMANIA DEMO (MFCS)# 481 # TECHNOLOGY GROUP# 501 # UK Certification (UKCert)# 503 # UK SOUTHWEST TRAINS (SWT)# 521 # UKSP# 541 # UK BUS HOPS (SBH)# 561 # NSW Club Card (NCC)# 581 # UK Projects# 601 # GLOBAL PRODUCT MGMT(GPM)621, # NEW DEHLI (NDL)# 641 # TRACS Projects# 701 # BANGKOK (BKK)# 721, # CAPE TOWN);my @includeBomProjects = (361, # UK STAGE COACH (SSW) Historical421, # UK STAGE COACH PRODUCTION (SSWProd)501, # UK Certification (UKCert)503, # UK SOUTHWEST TRAINS (SWT)521, # UKSP541, # UK BUS HOPS (SBH)581, # UK Projects641, # TRACS Projects);my %sillyVersions =('2b6' => '2.6.0.cots','1.0b2' => '1.0.2.cots','1.6.x' => '1.6.0.cots','3.5beta12.5' => '3.5.12.5.cots','1.0b1.1.mas' => '1.1.1.mas',);my %suffixFixup = ('.sf' => '.sfo','.vt' => '.vtk','.lv' => '.lvs','.was' => '.wdc','.uk.1' => '.uk','.ssts.demo' => '.ssts','.u244.syd' => '.syd','.pxxx.sea' => '.sea','.pxxx.syd' => '.syd','.pxxx.sydddd' => '.syd','.oslo' => '.oso',);#-------------------------------------------------------------------------------# Function : Main Entry## Description :## Inputs :## Returns :#my $result = GetOptions ("help+" => \$opt_help, # flag, multiple use allowed"manual" => \$opt_manual, # flag"verbose+" => \$opt_verbose, # flag"test:s" => \$opt_test, # Test a version string"limit:n" => \$opt_limit, #"quick" => \$opt_quick, # Don't look for indirects'mode:s' => \$opt_mode, # Mode of operation'sbom!' => \$opt_sbom, # Include Sboms);## 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_manual || ($opt_help > 2));ErrorConfig( 'name' =>'CC2SVN_GENDATA' );if ( $opt_test ){my @results = massageVersion( $opt_test, 'DummyName' );Message ("Version", $opt_test, @results);exit 1;}## Set up the mode# Must be specified#if ( $opt_mode eq 'all' ) {$doAllReleases = 1;$doIncludeOnly = 0;} elsif ( $opt_mode eq 'hops' ) {$doAllReleases = 0;$doIncludeOnly = 1;} elsif ( $opt_mode eq 'standard' ) {$doAllReleases = 0;$doIncludeOnly = 0;} else {Error ("Mode not specified: all, hops, standard");}## Extract information from Deployment Manager#if ( $opt_sbom ){Message ("Get BOMs");getBoms();Message ("Get SBOM Info");getOSIDforBOMID($_) foreach keys %sboms;Message ("SBOMs : " . scalar @sbomNeeded);Message ("get SBOM Details");getSBOMDetails($_) foreach ( @sbomNeeded );## Locate packages associated with the base install for each os#Message ("get Base Install Packages");foreach my $base_env_id ( sort keys %os_env_list ){getPackagesforBaseInstall( $base_env_id );}## Determine all the top level packages in the BOM#Message ("get Top Level BOM Packages");foreach my $os_id ( sort keys %os_id_list ){getPackages_by_osid( $os_id );}Message ("SBOM PackageVersions : " . scalar keys %sbom_pvid);#DebugDumpData("PVID", \%sbom_pvid );}else{Message ("SBOM Information not included");}GetAllPackageNames();getReleaseDetails();getPkgDetailsByRTAG_ID();my ($pcount, $vcount) = countPackages();print "Directly referenced Packages: $pcount Versions: $vcount\n";LocateStrays() unless ($opt_quick);($pcount, $vcount) = countPackages();print "Indirectly referenced Packages: $pcount Versions: $vcount\n";processData();outputData();if ( $opt_verbose > 1 ){print "=========================================================================\n";DebugDumpData("Releases", \%Releases);print "=========================================================================\n";DebugDumpData("Packages", \%Packages );print "=========================================================================\n";DebugDumpData("Suffixes", \%Suffixes );}($pcount, $vcount) = countPackages();print "Total References Packages: $pcount Versions: $vcount\n";exit;#-------------------------------------------------------------------------------# Function : getBoms## Description : Get all the BOM Id's and parent project IDs# Also get base_env_id's where they exist## Inputs :## Returns :#sub getBoms{my $foundDetails = 0;my (@row);Verbose ("getBoms");connectDM(\$DM_DB) unless ($DM_DB);my $m_sqlstr = "SELECT "."p.PROJ_ID,"."p.PROJ_NAME,"."br.BRANCH_ID,"."bm.BOM_ID"." FROM DEPLOYMENT_MANAGER.DM_PROJECTS p, " ."DEPLOYMENT_MANAGER.BRANCHES br, "."DEPLOYMENT_MANAGER.BOMS bm "." WHERE p.PROJ_ID = br.PROJ_ID "."AND br.BRANCH_ID = bm.BRANCH_ID";my $sth = $DM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){while ( @row = $sth->fetchrow_array ){#print "----@row\n";my $project_id = $row[0];my $name = $row[1];my $bom_id = $row[3];if ( exists $sboms{$bom_id} ){print "---- BAD: Multiple BOM IDS\n";}$sboms{$bom_id}{project_id} = $project_id;$sboms{$bom_id}{project_name} = $name;$foundDetails = 1;}}$sth->finish();}else{Error("getBoms:Execute failure: $m_sqlstr" );}}else{Error("getBoms:Prepare failure" );}Warnng("getBoms:No BOM Information Found" ) unless $foundDetails;# DebugDumpData("sboms", \%sboms );}#-------------------------------------------------------------------------------# Function : getOSIDforBOMID## Description : Get all the os_id's associated with a BOMID# Also get base_env_id's where they exist## Inputs : $bom_id - BOM to process## Returns :#sub getOSIDforBOMID{my ($bom_id) = @_;my $foundDetails = 0;my (@row);print("getOSIDforBOMID: $bom_id\n");Verbose ("getOSIDforBOMID: $bom_id");connectDM(\$DM_DB) unless ($DM_DB);my $project_id = $sboms{$bom_id}{project_id};#print "getOSIDforBOMID: $bom_id, $project_id\n";if ( $doIncludeOnly ){unless ( grep {$_ eq $project_id} @includeBomProjects){#print "Ignoring $bom_id, $project_id\n";return;}}else{if ( grep {$_ eq $project_id} @excludeBomProjects){#print "Ignoring $bom_id\n";return;}}## Save for later#push @sbomNeeded, $bom_id;#print "Processing getOSIDforBOMID: $bom_id, $project_id\n";my $m_sqlstr = "SELECT distinct bc.BOM_ID, os.OS_ID, os.OS_NAME, nn.NODE_NAME, obe.BASE_ENV_ID " ." FROM DEPLOYMENT_MANAGER.OPERATING_SYSTEMS os, " ."DEPLOYMENT_MANAGER.BOM_CONTENTS bc, "."DEPLOYMENT_MANAGER.NETWORK_NODES nn, "."DEPLOYMENT_MANAGER.OS_BASE_ENV obe" ." WHERE bc.BOM_ID = $bom_id "."AND bc.NODE_ID = os.NODE_ID "."AND nn.NODE_ID = os.NODE_ID "."AND obe.OS_ID (+) = os.OS_ID ";my $sth = $DM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){while ( @row = $sth->fetchrow_array ){#print "----@row\n";Verbose ("OS_ID: ".join (',',@row) );$sboms{$row[0]}{needed} = 1;$os_id_list{$row[1]}{bom_id} = $row[0];$os_id_list{$row[1]}{os_name} = $row[2];$os_id_list{$row[1]}{node_name} = $row[3];if ( defined $row[4] ){$os_env_list{$row[4]}{needed} = 1;$os_env_list{$row[4]}{os_id}{$row[1]} = 1;}$foundDetails = 1;}}$sth->finish();}else{Error("getOSIDforBOMID:Execute failure" );}}else{Error("getOSIDforBOMID:Prepare failure" );}Warning("getOSIDforBOMID:No OS Information Found: Project:$project_id BOM:$bom_id" ) unless $foundDetails;}#-------------------------------------------------------------------------------# Function : getSBOMDetails## Description : Get some details about the SBOM# Used for descriptive text## Inputs : $bom_id - BOM to process## Returns :#sub getSBOMDetails{my ($bom_id) = @_;my $foundDetails = 0;my (@row);Verbose ("getSBOMDetails: $bom_id");connectDM(\$DM_DB) unless ($DM_DB);my $m_sqlstr = "SELECT distinct "." dp.PROJ_NAME ,"." bn.BOM_NAME, "." br.BRANCH_NAME, "." bm.BOM_VERSION, "." bm.BOM_LIFECYCLE" ." FROM "." DEPLOYMENT_MANAGER.BOMS bm, "." DEPLOYMENT_MANAGER.BOM_NAMES bn, "." DEPLOYMENT_MANAGER.BRANCHES br, "." DEPLOYMENT_MANAGER.DM_PROJECTS dp" ." WHERE bm.BOM_ID = $bom_id "." AND bm.BOM_NAME_ID = bn.BOM_NAME_ID "." AND bm.BRANCH_ID = br.BRANCH_ID "." AND br.PROJ_ID = dp.PROJ_ID";my $sth = $DM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){while ( @row = $sth->fetchrow_array ){# $sboms{$bom_id}{sbom_project} = $row[0];$sboms{$bom_id}{sbom_name} = $row[1];$sboms{$bom_id}{sbom_branch} = $row[2];$sboms{$bom_id}{sbom_version} = $row[3] . '.' . $row[4];$foundDetails = 1;}}$sth->finish();}else{Error("getSBOMDetails:Execute failure", $m_sqlstr );}}else{Error("getSBOMDetails:Prepare failure" );}Error("getSBOMDetails:No OS Information Found" ) unless $foundDetails;}#-------------------------------------------------------------------------------# Function : getPackagesforBaseInstall## Description : Get all the packages for a given base install## Inputs :## Returns :#sub getPackagesforBaseInstall{my ($base_env_id) = @_;my $foundDetails = 0;my (@row);connectDM(\$DM_DB) unless ($DM_DB);# First get details from pv_idmy $m_sqlstr = "SELECT DISTINCT "." bec.PROD_ID, "." pkg.pkg_name, "." pv.pkg_version, "." pkg.pkg_id, "." pv.pv_id" ." FROM "." RELEASE_MANAGER.PACKAGES pkg, "." RELEASE_MANAGER.PACKAGE_VERSIONS pv, ".# " DEPLOYMENT_MANAGER.PRODUCT_DETAILS pd, "." DEPLOYMENT_MANAGER.BASE_ENV_CONTENTS bec"." WHERE bec.BASE_ENV_ID = $base_env_id "." AND bec.PROD_ID (+)= pv.PV_ID "." AND pv.pkg_id = pkg.pkg_id";my $sth = $DM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){while ( @row = $sth->fetchrow_array ){Verbose ("OS ENV Package($base_env_id}:" . join (',',@row) );my $pv_id = $row[0];my $name = $row[1] || 'BadName';my $ver = $row[2] || 'BadVer';$sbom_pvid{$pv_id}{pkg_name} =$name;$sbom_pvid{$pv_id}{pkg_ver} = $ver;push @{$Packages{$pv_id}{sbomBase}}, $base_env_id;push @StrayPackages, $pv_id;foreach my $os_id ( keys %{$os_env_list{$base_env_id}{os_id}} ){$sbom_pvid{$pv_id}{os_id}{$os_id} = 2;}}}$sth->finish();}else{Error ("getPackagesforBaseInstall: Execute error");}}else{Error("getPackagesforBaseInstall:Prepare failure" );}}#-------------------------------------------------------------------------------# Function : getPackages_by_osid## Description : Get all the packages used by a given os_id## Inputs :## Returns :#sub getPackages_by_osid{my ($os_id) =@_;my $foundDetails = 0;my (@row);connectDM(\$DM_DB) unless ($DM_DB);# First get details from pv_idmy $m_sqlstr = "SELECT osc.*, "." pkg.pkg_name, "." pv.pkg_version, "." pd.IS_REJECTED, "." pv.IS_PATCH,"." pv.IS_OBSOLETE, "." pkg.pkg_id,"." pv.pv_id" ." FROM RELEASE_MANAGER.PACKAGES pkg, "." RELEASE_MANAGER.PACKAGE_VERSIONS pv, "." DEPLOYMENT_MANAGER.PRODUCT_DETAILS pd,"."(" ." SELECT "." osc.seq_num, "." osc.prod_id"." FROM "." DEPLOYMENT_MANAGER.os_contents osc"." WHERE osc.os_id = $os_id" ." ) osc" ." WHERE pd.PROD_ID (+)= pv.PV_ID" ." AND pv.pkg_id = pkg.pkg_id" ." AND osc.PROD_ID = pv.pv_id" ." ORDER BY osc.SEQ_NUM desc" ;my $sth = $DM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){$foundDetails = 1;while ( @row = $sth->fetchrow_array ){print ("SBOM Package:".join (',',@row). "\n" );Verbose ("SBOM Package:".join (',',@row) );my $pv_id = $row[8];unless ( exists $sbom_pvid{$pv_id} ){my $name = $row[2] || 'BadName';my $ver = $row[3] || 'BadVer';$sbom_pvid{$pv_id}{pkg_name} =$name;$sbom_pvid{$pv_id}{pkg_ver} = $ver;push @{$Packages{$pv_id}{sbomOsidUsed}}, $os_id;$Packages{$pv_id}{sbomOsid} = 1;push @StrayPackages, $pv_id;}$sbom_pvid{$pv_id}{os_id}{$os_id} = 1;}}$sth->finish();}}else{Error("getPackages_by_osid:Prepare failure" );}Error ("getPackages_by_osid: Nothing found for os_id: $os_id ")unless ( $foundDetails );}#-------------------------------------------------------------------------------# Function : getReleaseDetails## Description : Determine all candiate releases## Inputs :## Returns :#sub getReleaseDetails{my (@row);# if we are not or cannot connect then return 0 as we have not found anythingconnectRM(\$RM_DB) unless $RM_DB;# First get all packages that are referenced in a Release# This will only get the top level packages# From non-archived releasesmy $m_sqlstr = "SELECT prj.PROJ_NAME, rt.RTAG_NAME, rt.PROJ_ID, rt.RTAG_ID, rt.official" ." FROM release_manager.release_tags rt, release_manager.projects prj" ." WHERE prj.PROJ_ID = rt.PROJ_ID " .# " AND rt.official != 'A' ".# " AND rt.official != 'Y'" ." order by prj.PROJ_NAME";my $sth = $RM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){# print "--- Execute\n";if ( $sth->rows ){# print "--- Execute ROWS\n";while ( @row = $sth->fetchrow_array ){my $rtag_id =$row[3];my $proj_id = $row[2];$Releases{$rtag_id}{pName} = $row[0];$Releases{$rtag_id}{name} = $row[1];$Releases{$rtag_id}{proj_id} = $proj_id;$Releases{$rtag_id}{rtag_id} = $rtag_id;$Releases{$rtag_id}{official} = $row[4];unless ( $doAllReleases ){if (grep {$_ eq $proj_id} @excludeProjects) {$Releases{$rtag_id}{excluded} = 'E';}if (grep {$_ eq $rtag_id} @excludeReleases) {$Releases{$rtag_id}{excluded} = 'E';}}if ( $doIncludeOnly ){if (grep {$_ eq $proj_id} @includedProjects){delete $Releases{$rtag_id}{excluded};}else{$Releases{$rtag_id}{excluded} = 'E';}if (grep {$_ eq $rtag_id} @includedReleases){delete $Releases{$rtag_id}{excluded};}}unshift @row, $Releases{$rtag_id}{excluded} || ' ';print join (',',@row), "\n" if ($opt_verbose);}}# print "--- Finish\n";$sth->finish();}else{Error("Execute failure: $m_sqlstr", $sth->errstr() );}}else{Error("Prepare failure" );}}sub getPkgDetailsByPVID{my ($pv_id) = @_;my (@row);## Only do once#return if ( exists $Packages{$pv_id}{name} );# if we are not or cannot connect then return 0 as we have not found anythingconnectRM(\$RM_DB) unless $RM_DB;my $m_sqlstr = "SELECT" ." pv.PV_ID, ". #[0]" pkg.PKG_NAME, ". #[1]" pv.PKG_VERSION, ". #[2]" pv.DLOCKED," . #[3]" release_manager.PK_RMAPI.return_vcs_tag(pv.PV_ID), ". #[4]" pv.PKG_ID," . #[5]" pv.MODIFIED_STAMP ". #[6]" FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv,"." RELEASE_MANAGER.PACKAGES pkg "." WHERE pv.PV_ID = \'$pv_id\' "." AND pv.PKG_ID = pkg.PKG_ID" ;my $sth = $RM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){# print "--- Execute\n";if ( $sth->rows ){# print "--- Execute ROWS\n";while ( @row = $sth->fetchrow_array ){print join (',',@row), "\n" if ($opt_verbose);my $pvid = $row[0];$Packages{$pvid}{name} = $row[1];$Packages{$pvid}{version} = $row[2];$Packages{$pvid}{locked} = $row[3];$row[4] =~ tr~\\/~/~;$Packages{$pvid}{vcstag} = $row[4];$Packages{$pvid}{pkgid} = $row[5];# $Packages{$pvid}{tlp} = 1;($Packages{$pvid}{suffix}, $Packages{$pvid}{fullVersion},$Packages{$pvid}{isaRipple} ) = massageVersion( $Packages{$pvid}{version}, $Packages{$pvid}{name} );$Suffixes{$Packages{$pvid}{suffix}}++;$Packages{$pvid}{Age} = ($now - str2time( $row[6] )) / (60 * 60 * 24);}}# print "--- Finish\n";$sth->finish();}else{Error("getPkgDetailsByPVID:Execute failure: $m_sqlstr", $sth->errstr() );}}else{Error("getPkgDetailsByPVID:Prepare failure" );}}sub getPkgDetailsByRTAG_ID{my (@row);my $excludes = '';my $count = 0;# if we are not or cannot connect then return 0 as we have not found anythingconnectRM(\$RM_DB) unless $RM_DB;Message ("Extract toplevel dependencies");# First get all packages that are referenced in a Release# This will only get the top level packages# From non-archived releasesunless ($doAllReleases){foreach ( @excludeProjects ){$excludes .= " AND prj.PROJ_ID != $_ ";}foreach ( @excludeReleases ){$excludes .= " AND rt.RTAG_ID != $_ ";}}my $m_sqlstr = "SELECT DISTINCT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION, pv.DLOCKED" ." , release_manager.PK_RMAPI.return_vcs_tag(pv.PV_ID), pv.PKG_ID" ." , rt.RTAG_ID, rmv.VIEW_NAME, pv.MODIFIED_STAMP, prj.PROJ_ID" ." FROM RELEASE_MANAGER.RELEASE_CONTENT rc, RELEASE_MANAGER.PACKAGE_VERSIONS pv,"." RELEASE_MANAGER.PACKAGES pkg, release_manager.release_tags rt, release_manager.projects prj" ." , release_manager.views rmv" ." WHERE rc.PV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID" ." AND rmv.VIEW_ID = rc.BASE_VIEW_ID" ." AND prj.PROJ_ID = rt.PROJ_ID and rt.RTAG_ID = rc.RTAG_ID" .# " AND rt.official != 'A'" .# " AND rt.official != 'Y' " .$excludes ." order by pkg.PKG_NAME";my $sth = $RM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){# print "--- Execute\n";if ( $sth->rows ){# print "--- Execute ROWS\n";while ( @row = $sth->fetchrow_array ){print join (',',@row), "\n" if ($opt_verbose);my $pvid = $row[0];unless ( exists $Packages{$pvid}{name} ){$Packages{$pvid}{name} = $row[1];$Packages{$pvid}{version} = $row[2];$Packages{$pvid}{locked} = $row[3];$row[4] =~ tr~\\/~/~;$Packages{$pvid}{vcstag} = $row[4];$Packages{$pvid}{pkgid} = $row[5];$Packages{$pvid}{tlp} = 1;($Packages{$pvid}{suffix}, $Packages{$pvid}{fullVersion},$Packages{$pvid}{isaRipple} ) = massageVersion( $Packages{$pvid}{version}, $Packages{$pvid}{name} );$Suffixes{$Packages{$pvid}{suffix}}++;push @StrayPackages, $pvid;}my $rtag_id = $row[6];push @{$Packages{$pvid}{release}}, $rtag_id;$Packages{$pvid}{view}{$row[7]}++ if ( $row[7] );$Packages{$pvid}{Age} = ($now - str2time( $row[8] )) / (60 * 60 * 24);my $proj_id = $row[9];push @{$Packages{$pvid}{projects}}, $proj_idunless (grep {$_ eq $proj_id} @{$Packages{$pvid}{projects}});if ( $doIncludeOnly ){if (grep {$_ eq $proj_id} @includedProjects){$Packages{$pvid}{NamedProject} = 1;}if (grep {$_ eq $rtag_id} @includedReleases){$Packages{$pvid}{NamedProject} = 2;}}else{$Packages{$pvid}{NamedProject} = 3;}if ( $opt_limit ){last if ( $count++ > $opt_limit );}}}# print "--- Finish\n";$sth->finish();}else{Error("Execute failure: $m_sqlstr", $sth->errstr() );}}else{Error("Prepare failure" );}}#-------------------------------------------------------------------------------# Function : GetDepends## Description :## Inputs : $pvid## Returns :#sub GetDepends{my ($pv_id ) = @_;## Ensure we have package information#getPkgDetailsByPVID( $pv_id );return if ( $Packages{$pv_id}{depend} );$Packages{$pv_id}{depend} = 1;## Now extract the package dependacies# There may not be any#my $m_sqlstr = "SELECT "." pd.PV_ID, "." pd.DPV_ID " ." FROM RELEASE_MANAGER.PACKAGE_DEPENDENCIES pd "." WHERE pd.PV_ID = \'$pv_id\'";my $sth = $RM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){while ( my @row = $sth->fetchrow_array ){my $pvid = $row[0];my $dpvid = $row[1];push @StrayPackages, $dpvid;push @{$Packages{$dpvid}{usedBy}}, $pvid;}}$sth->finish();}else{Error("GetDepends:Execute failure: $m_sqlstr", $sth->errstr() );}}else{Error("GetDepends:Prepare failure" );}}#-------------------------------------------------------------------------------# Function : GetAllPackageNames## Description :## Inputs : None## Returns :#sub GetAllPackageNames{# if we are not or cannot connect then return 0 as we have not found anythingconnectRM(\$RM_DB) unless $RM_DB;## Now extract all the package names#my $m_sqlstr = "SELECT pkg.PKG_ID, pkg.PKG_NAME" ." FROM RELEASE_MANAGER.PACKAGES pkg";my $sth = $RM_DB->prepare($m_sqlstr);if ( defined($sth) ){if ( $sth->execute( ) ){if ( $sth->rows ){while ( my @row = $sth->fetchrow_array ){my $id = $row[0];my $name = $row[1];next unless ( $id );$AllPackages{$id} = $name;}}$sth->finish();}else{Error("GetAllPackageNames:Execute failure" );}}else{Error("GetAllPackageNames:Prepare failure" );}}#-------------------------------------------------------------------------------# Function : massageVersion## Description : Process a version number and return usful bits## Inputs : Version Number# Package Name - debug only## Returns : An array# suffix# multipart version string useful for text comparisons#sub massageVersion{my ($version, $name) = @_;my ($major, $minor, $patch, $build, $suffix);my $result;my $buildVersion;my $isaRipple;my $isaWIP;$build = 0;#print "--- $name, $version\n";$version =~ s~^_~~;$version =~ s~^\Q${name}\E_~~;## Pre-massage some silly ones#if ( exists $sillyVersions{$version} ) {$version = $sillyVersions{$version};}if ( $name eq 'ReleaseName' ) {$version =~ s~[a-z]~.~g;$version =~ s~\.+~.~g;$version =~ s~\.$~~g}## xxxxxxxxx.nnnn.cots#if ( $version =~ m~(.*)\.cots$~ ) {my $cots_base = $1;$suffix = '.cots';if ( $version =~ m~(.*?)\.([0-9]{4})\.cots$~ ){$result = $1 . sprintf (".%4.4d", $2) . $suffix;}else{$result = $cots_base . '.0000.cots';}}## Convert version into full form for comparisions# nnn.nnn.nnn.[p]nnn.xxx# nnn.nnn.nnn.[p]nnn-xxx# nnn.nnn.nnn-[p]nnn.xxx# nnn.nnn.nnn-[p]nnn-xxx# nnn.nnn.nnn[p]nnn-xxx# Don't flag as ripples - they are patches#elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)[-.p][p]?(\d+)([-.](.*))?$~ ) {$major = $1;$minor = $2;$patch = $3;$build = $4;$suffix = defined $6 ? ".$6" : '';$isaRipple = 0;}## nn.nnn.nnnnn.xxx# nn.nnn.nnnnn-xxx# nnn.nnn.nnnx.xxx# Don't flag as ripples - they are patches#elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)\w?([-.](.*))?$~ ) {$major = $1;$minor = $2;$patch = $3;if ( length( $patch) >= 4 ){$build = substr( $patch, -3 ,3);$patch = substr( $patch, 0 ,length($patch)-3);}$suffix = defined $5 ? ".$5" : '';}## nnn.nnn.nnn# nnn.nnn-nnn# nnn.nnn_nnn#elsif ( $version =~ m~^(\d+)\.(\d+)[-._](\d+)$~ ) {$major = $1;$minor = $2;$patch = $3;$suffix = '';}## nnn.nnn.nnn.nnn# nnn.nnn.nnn-nnn# nnn.nnn.nnn_nnn#elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)[-._](\d+)$~ ) {$major = $1;$minor = $2;$patch = $3;$build = $4;$suffix = '';$isaRipple = 0;}## nnn.nnn#elsif ( $version =~ m~^(\d+)\.(\d+)$~ ) {$major = $1;$minor = $2;$patch = 0;$suffix = '';}## nnn.nnn.xxx#elsif ( $version =~ m~^(\d+)\.(\d+)(\.\w+)$~ ) {$major = $1;$minor = $2;$patch = 0;$suffix = $3;}## nnn.nnn.nnnz#elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)([a-z])$~ ) {$major = $1;$minor = $2;$patch = $3;$build = ord($4) - ord('a');$suffix = '.cots';$isaRipple = 0;}## ???REV=???#elsif ( $version =~ m~REV=~ ) {$suffix = '.cots';$result = $version . '.0000.cots';}## Wip Packages# (nnnnnn).xxx# Should be essential, but want to sort very low#elsif ($version =~ m~\((.*)\)(\..*)?~) {$suffix = $2 || '';$result = "000.000.000.000$suffix";$isaWIP = 1;}## !current#elsif ($version eq '!current' || $version eq 'current_$USER' || $version eq 'current' || $version eq 'beta' || $version eq 'latest' || $version eq 'beta.cr' || $version eq 'CREATE') {$suffix = '';$result = "000.000.000.000$suffix";$isaWIP = 1;}## Also WIP: FINRUN.103649.BEI.WIPelsif ($version =~ m~(\.[a-zA-Z]+)\.WIP$~) {$suffix = lc($1);$result = "000.000.000.000$suffix";$isaWIP = 1;}## Also ERGOFSSLS190100_015# Don't flag as a rippleelsif ($version =~ m~^ERG[A-Z]+(\d\d)(\d\d)(\d\d)[-_](\d+)(\.\w+)?$~) {$major = $1;$minor = $2;$patch = $3;$build = $4;$suffix = $5 || '.sls';$isaRipple = 0;}## Stuff we don't yet handle#else {Warning ("Unknown version number: $name,$version");$version =~ m~(\.\w+)$~;$suffix = $1 || '';$result = $version;}$isaRipple = ($build > 0) unless defined $isaRipple;unless ( $result ){# Major and minor of 99.99 are normally funny versions# Don't make important decisions on them#if (defined $major && defined $minor && $major == 99 && $minor == 99 ){$major = 0;$minor = 0;$patch = 0;}$result = sprintf("%3.3d.%3.3d.%3.3d.%3.3d%s", $major,$minor,$patch,$build,$suffix || '.0000');$buildVersion = [ $major, $minor, $patch, $build ];}$suffix = lc( $suffix );if ( exists $suffixFixup{$suffix} ){$suffix = $suffixFixup{$suffix} ;}return ($suffix, $result, $isaRipple, $isaWIP, $buildVersion );}#-------------------------------------------------------------------------------# Function : LocateStrays## Description :## Inputs :## Returns :#sub LocateStrays{Message ("Locate indirectly referenced packages");while ( $#StrayPackages >= 0 ){my $pv_id = pop @StrayPackages;next if ( exists $Packages{$pv_id}{done} );#print "... ",$#StrayPackages,"\n";GetDepends( $pv_id);$Packages{$pv_id}{done} = 1;}}#-------------------------------------------------------------------------------# Function : countPackages## Description :## Inputs :## Returns : Number of packages and number oof versions#sub countPackages{my $v = 0;my $p = 0;my %names;foreach ( keys %Packages ){my $name = $Packages{$_}{name};next unless ( $name );$names{$name} = 1;$v++;}$p = keys %names;return $p,$v;}#-------------------------------------------------------------------------------# Function : processData## Description : Process data before its written out# Remove a few packages that we do not want to now about# Determine Reason that a version is in the list# Finish taging packages in NamedProject## Inputs :## Returns :#sub processData{foreach ( keys %Packages ){delete $Packages{$_}{done};next if ( $Packages{$_}{name} =~ ~m~CSWcfengine~ );if ($Packages{$_}{name} eq 'Activestate Perl - Solaris'){delete $Packages{$_};next;}if ( $Packages{$_}{name} =~ m/^CSW/ || $Packages{$_}{name} =~ m/^Solaris$/){delete $Packages{$_};next;}if ( $Packages{$_}{name} =~ m/^jats_/){delete $Packages{$_};next;}## Determine why version is here# tpl - Top Level Package from a Release# sbom - Included because of an sbom## tplDepend - Used by a TLP# sbomDepend - Used by an SBOM## Where there are multiple reasons for inclusion a tlp is more# significant than a sbom##if ( exists $Packages{$_}{'tlp'}) {$Packages{$_}{Reason} = 'tlp';} elsif ( exists $Packages{$_}{'sbomBase'}) {$Packages{$_}{Reason} = 'sbom';} elsif ( exists $Packages{$_}{'sbomOsid'}) {$Packages{$_}{Reason} = 'sbom';} else {my $reason;my %usedBy;my @examineThese = @{$Packages{$_}{'usedBy'}};while ( @examineThese ){my $pvid = pop @examineThese;next if ( $usedBy{$pvid} );if ( exists $Packages{$pvid}{Reason} ){$reason = $Packages{$pvid}{Reason};} elsif ( exists $Packages{$pvid}{'tlp'}) {$reason = 'tlpDepend';last;} elsif ( exists $Packages{$pvid}{'sbomBase'}) {$reason = 'sbomDepend';} elsif ( exists $Packages{$pvid}{'sbomOsid'}) {$reason = 'sbomDepend';}push @examineThese, @{$Packages{$pvid}{'usedBy'}}if (exists $Packages{$pvid}{'usedBy'});}if ( $reason ){$Packages{$_}{Reason} = $reason;}else{Message ("Don't know why I'm here: $_, $Packages{$_}{name} $Packages{$_}{'version'}");}}## Catch packages that are dependents of NamedProject's#if ( $doIncludeOnly ){if ( exists $Packages{$_}{'sbomBase'} || exists $Packages{$_}{'sbomOsid'} ){$Packages{$_}{NamedProject} = 4;}unless ( $Packages{$_}{NamedProject} ){my $named;my %usedBy;if ( exists $Packages{$_}{'usedBy'}){my @examineThese = @{$Packages{$_}{'usedBy'}};while ( @examineThese ){my $pvid = pop @examineThese;next if ( $usedBy{$pvid} );if ( $Packages{$pvid}{NamedProject} ){$named = 1;last;}push @examineThese, @{$Packages{$pvid}{'usedBy'}}if (exists $Packages{$pvid}{'usedBy'});}$Packages{$_}{NamedProject} = 5if ( $named );}# else# {# Warning("Not Named and not usedBy: $Packages{$_}{name} $Packages{$_}{'version'}");# }}}else{$Packages{$_}{NamedProject} = 6;}}}#-------------------------------------------------------------------------------# Function : outputData## Description : Write out data in a form to allow post processing## Inputs :## Returns :#sub outputData{my $file = "cc2svn.raw.txt";Message ("Create: $file");my $fh = ConfigurationFile::New( $file );$fh->DumpData("\n# Releases.\n#\n","ScmReleases", \%Releases );$fh->DumpData("\n# Packages.\n#\n","ScmPackages", \%Packages );$fh->DumpData("\n# Suffixes.\n#\n","ScmSuffixes", \%Suffixes );$fh->DumpData("\n# All Package Names.\n#\n","ScmAllPackages", \%AllPackages );## Just for debug### Remove unused SBOMs#my %AllBomProjects;foreach ( keys %sboms ){if ( $sboms{$_}{needed} ){my $project_id = $sboms{$_}{project_id};$AllBomProjects{$project_id}{project_name} = $sboms{$_}{project_name};next;}delete $sboms{$_};}$fh->DumpData("\n# All Bom Projects.\n#\n", "ScmAllBomProjects", \%AllBomProjects );$fh->DumpData("\n# All SBOMS.\n#\n", "ScmSboms", \%sboms );$fh->DumpData("\n# All os_id_list.\n#\n", "ScmOsIdList", \%os_id_list );$fh->DumpData("\n# All os_env_list.\n#\n", "ScmOsEnvList", \%os_env_list );$fh->DumpData("\n# All sbom_pvid.\n#\n", "ScmSbomPVID", \%sbom_pvid );## Close out the file#$fh->Close();# ## # Split up package data into small files for easy consumption# ### foreach ( keys %Packages )# {# my $file = "cc2svn.raw.${_}.txt";# Message ("Create: $file");# my $fh = ConfigurationFile::New( $file );## $fh->DumpData(# "\n# Releases.\n#\n",# "ScmReleases", \$Packages{$_} );# $fh->Close();# }}#-------------------------------------------------------------------------------# Documentation#=pod=for htmltoc SYSUTIL::cc2svn::=head1 NAMEcc2svn_gendata - Extract CC2SVN Essential Package Data from Release Manager=head1 SYNOPSISjats cc2svn_gendata [options]Options:-help - brief help message-help -help - Detailed help message-man - Full documentation-test=version - Test a version string, then exit-limit=n - Limit packages processed. Test only-mode=xxx - Set Mode: all, hops, standard-[no]sbom - Include SBOM versions. Default: Yes=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.=item B<-man>Prints the manual page and exits.=item B<-test=version>Examine a package version string and report how the tool will parse it.=item B<-limit=n>Limit the number of packages processed by the tool. This is only used tosimplify testing of the program=back=head1 DESCRIPTIONThis program is a tool used in the conversion of ClearCase VOBS to subversion.It will:=over 8=item *Determine all Releases in Release manager and mark those thatare to be excluded.=item *Determine all the package-versions used by the releases that arenot excluded. These are called 'direct' dependencies.=item *Recursively find all the dependent packages of all packages. New packageversions are called 'indirect' dependencies. They are buried. This process cantake several minutes.=backThe data collected is dumped into a text file for later processing.=cut