Subversion Repositories DevTools

Rev

Rev 2026 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
392 dpurdie 1
########################################################################
2
# Copyright ( C ) 2009 ERG Limited, All rights reserved
3
#
4
# Module name   : escrow.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats build system
8
#
9
# Description   : Determine packages from an SBOM for escrow purposes
10
#                 For a given bom_id determine all used packages
11
#                 Create various bits of useful information
12
#                   Extract commands
13
#                   Build Order
14
#                   Depenendency Info
15
#                   Bad Packages
16
#
17
#......................................................................#
18
 
19
require 5.006_001;
20
use strict;
21
use warnings;
22
use JatsEnv;
23
use JatsError;
24
use JatsSystem;
25
use JatsRmApi;
26
use DBI;
27
use Getopt::Long;
28
use Pod::Usage;                             # required for help support
29
use Storable qw (dclone);
30
 
31
#
32
#   Config Options
33
#
34
my $VERSION = "1.0.0";              # Update this
35
my $opt_help = 0;
36
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
37
my $opt_sbom_id;
38
my $opt_rtag_id;
39
my $opt_test = 0;
40
my $opt_patch = 1;
41
my $opt_extract;
42
my $opt_rootpkg;
43
my $opt_rootpkg_version;
44
 
45
#
46
#   Data Base Interface
47
#
48
my $RM_DB;
49
my $DM_DB;
50
 
51
#
52
#   Global variables
53
#
54
my %os_id_list;                 # os_id in the SBOM
55
my %os_env_list;                # OS Environments
56
my %pv_id;                      # Packages in the SBOM
57
my %Package;                    # Per Package information
58
my %Release;                    # Release information
59
my %Release_pvid;               # Release info
60
my @StrayPackages;              # Non-top level packages
61
my @create_list;                # List of files created
62
my $fpref = "sbom";             # Sbom Prefix
63
our $GBE_RM_URL;
64
our $GBE_DM_URL;
65
my $sbom_name;
66
my $sbom_branch;
67
my $sbom_project;
68
my $sbom_version;
69
my $rtag_release;
70
my $rtag_project;
71
 
72
#
73
#   Constants, that should be variable
74
#
75
my $rm_base = "/dependencies.asp?pv_id=";
76
my $dm_base = "/OsDefault.asp?bom_id=BOMID&os_id=";
77
 
78
#
79
#   Build types. Should be populated from a table
80
#
81
my %BM_ID = (
82
    1 => "Solaris",
83
    2 => "Win32",
84
    3 => "Linux",
85
    4 => "Generic",
86
);
87
 
88
my %BSA_ID = (
89
    1 => "Jats Debug",
90
    2 => "Jats Prod",
91
    3 => "Jats Debug+Prod",
92
    4 => "Ant Java 1.4",
93
    5 => "Ant Java 1.5",
94
    6 => "Ant Java 1.6",
95
);
96
 
97
#
98
#   Packages to be ignored
99
#
100
my %ignore;
101
my %patch;
102
 
103
 
104
#-------------------------------------------------------------------------------
105
# Function        : Main
106
#
107
# Description     : Main entry point
108
#                   Parse user options
109
#
110
# Inputs          :
111
#
112
# Returns         :
113
#
114
 
115
my $result = GetOptions (
116
                "help:+"            => \$opt_help,              # flag, multiple use allowed
117
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
118
                "verbose:+"         => \$opt_verbose,           # flag
119
                "sbomid|sbom_id=s"  => \$opt_sbom_id,           # string
120
                "rtagid|rtag_id=s"  => \$opt_rtag_id,           # string
121
                "rootpackage=s"     => \$opt_rootpkg,           # String
122
                "ignore=s",         => sub{my ($a,$i) = @_; $ignore{$i} = 0 },
123
                "test!"             => \$opt_test,              #[no]flag
124
                "patch!"            => \$opt_patch,             #[no]flag
125
                "extract=s"         => \$opt_extract,           # Name of file
126
                );
127
 
128
#
129
#   Process help and manual options
130
#
131
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
132
pod2usage(-verbose => 1)  if ($opt_help == 2 );
133
pod2usage(-verbose => 2)  if ($opt_help > 2);
134
 
135
ErrorConfig( 'name'    => 'ESCROW',
136
             'verbose' => $opt_verbose );
137
 
138
#
139
#   Sanity test
140
#
141
unless ( $opt_rtag_id || $opt_sbom_id || $opt_extract || $#ARGV >= 1)
142
{
143
    Error ("Need sbomid and/or rtagid, or -extract",
144
           "Example: -sbomid=13543, for NZS Phase-1",
145
           "Example: -sbomid=13543 -rtagid=xxxx, for NZS Phase-1, comapred against given release",
146
           "Example: -rtagid=2362, for Sydney R1/R2",
147
           "Example: -rtagid=8843 -root=StockholmSBOM",
148
           "Example: PackageName PackageVersion, for extracting a single package",
149
    )
150
}
151
 
152
#
153
#   The extract option is special
154
#   It places the progam in a different mode
155
#
156
if ( $opt_extract )
157
{
158
    Error ("Cannot mix -extract with sbomid or rtagid" )
159
        if ( $opt_rtag_id || $opt_sbom_id || $#ARGV >= 0 );
160
 
161
    Error ("Cannot use -nopatch or -ignore with -extract")
162
        if ( ! $opt_patch || keys %ignore );
163
 
164
    extract_files();
165
    exit (0);
166
}
167
 
168
Warning ("No sbomid provided. Output based an a Release") unless ( $opt_sbom_id );
169
$dm_base =~ s~BOMID~$opt_sbom_id~ if ($opt_sbom_id);
170
$fpref = "release" unless ( $opt_sbom_id );
171
 
172
#
173
#   Import essential EnvVars
174
#
175
EnvImport('GBE_RM_URL');
176
EnvImport('GBE_DM_URL');
177
 
178
$rm_base = $GBE_RM_URL . $rm_base;
179
$dm_base = $::GBE_DM_URL . $dm_base;
180
 
181
if ( $opt_sbom_id )
182
{
183
    #
184
    #   Determines the OS_ID's for the bom
185
    #
186
    getOSIDforBOMID($opt_sbom_id);
187
    getSBOMDetails($opt_sbom_id);
188
 
189
    #
190
    #   Locate packages associated with the base install for each os
191
    #
192
    foreach my $base_env_id ( sort keys %os_env_list )
193
    {
194
        getPackagesforBaseInstall( $base_env_id );
195
    }
196
 
197
    #
198
    #   Determine all the top level packages in the BOM
199
    #
200
    foreach my $os_id ( sort keys %os_id_list )
201
    {
202
        getPackages_by_osid( $os_id );
203
    }
204
 
205
    #
206
    #   For each Top Level Package determine the dependent packages
207
    #
208
    getPkgDetailsForPVIDs (keys %pv_id);
209
    LocateStrays(0);
210
 
211
    #
212
    #   Determine packages in a given Release
213
    #
214
    if ( $opt_rtag_id )
215
    {
216
        getPkgDetailsByRTAG_ID( $opt_rtag_id );
217
    }
218
}
219
elsif ( $opt_rtag_id )
220
{
221
    getPkgDetailsByRTAG_ID( $opt_rtag_id );
222
    if ( $opt_rootpkg )
223
    {
224
        #
225
        #   Base the report on a single package in a release
226
        #   Determine the package
227
        #
228
        Error ("Root Package not found: $opt_rootpkg") unless ( exists $Release{$opt_rootpkg} );
229
        my @root_vers = keys %{$Release{$opt_rootpkg}};
230
        Error ("Multiple versions of Root Package: $opt_rootpkg", @root_vers ) if ( $#root_vers > 0 );
231
        $opt_rootpkg_version = $root_vers[0];
232
        Message("Root Package: $opt_rootpkg, " . $opt_rootpkg_version);
233
 
234
        getPkgDetailsByPV_ID( $Release{$opt_rootpkg}{$opt_rootpkg_version}{pv_id} );
235
    }
236
    else
237
    {
238
        getPkgDetailsForPVIDs (keys %Release_pvid);
239
    }
240
    LocateStrays(1);
241
}
242
elsif ( $#ARGV >= 1 )
243
{
244
    #
245
    #   Locate package and dependents
246
    #   Convert package name into a PVID
247
    #
248
    my $pv_id = getPkgDetailsByName( @ARGV );
249
    Error ("Cannot locate package by name and version: @ARGV")
250
        unless ( $pv_id );
251
 
252
    #
253
    #   Set package as the root package
254
    $opt_rootpkg = $ARGV[0];
255
    $opt_rootpkg_version = $ARGV[1];
256
    getPkgDetailsByPV_ID( $pv_id  );
257
    LocateStrays(2);
258
}
259
else
260
{
261
    Error ("Don't know what to do with common line arguments provided");
262
}
263
 
264
 
265
#
266
#   Remove packages to be ignored
267
#
268
foreach my $pkg ( keys %ignore )
269
{
270
    delete $Package{$pkg};
271
}
272
 
273
##
274
##   Display a list of all packages found so far
275
##
276
#foreach my $name ( sort keys %Package )
277
#{
278
#    foreach my $ver ( sort keys %{$Package{$name}} )
279
#    {
280
#
281
#        my $tag = $Package{$name}{$ver}{vcstag} || '';
282
#
283
#        printf ("%30s %15s %s\n", $name, $ver, $tag );
284
#    }
285
#}
286
 
287
#
288
#   Generate output files
289
#       1) Jats extract commands
290
#       2) Error list
291
my $file;
292
$file = "${fpref}_extract.txt";
293
push @create_list, $file;
294
open (JE, ">$file" ) || Error ("Cannot create $file");
295
 
296
$file = "${fpref}_status.txt";
297
push @create_list, $file;
298
 
299
open (ST, ">$file" ) || Error("Cannot create $file");
300
print ST "Cannot build:\n";
301
 
302
foreach my $name ( sort keys %Package )
303
{
304
    foreach my $ver ( sort keys %{$Package{$name}} )
305
    {
306
 
307
        my $vcstag = $Package{$name}{$ver}{vcstag};
308
        my $mtest = exists ($Package{$name}{$ver}{build} ) || '0';
309
        my @reason1;            # can't extract files
310
        my @reason2;            # Others
311
        push @reason1, 'No VCS Info' unless ( $vcstag );
312
        if ( $vcstag =~ m~^CC::(.*?)(::(.+))?$~ )
313
        {
314
            my $path = $1;
315
            my $label = $2 || '';
316
            push @reason1, 'No Label' unless ( $label );
317
            push @reason1, 'Bad Label, N/A' if ( $label =~ s~^N/A$~~i || $label  =~ s~^na$~~i );
318
 
319
            push @reason1, 'No Source Path' unless ( $path );
320
            push @reason1, 'Bad Path, N/A' if ( $path =~ m~^N/A$~i || $path  =~ m~^na$~i );
321
            push @reason1, 'Bad Path, dpkg' if ( $path =~ m~^/dpkg_archive~ || $path  =~ m~^dpkg_archive~ );
322
            push @reason1, 'Bad Path, http' if ( $path =~ m~^http:~i );
323
            push @reason1, 'Bad Path, Drive' if ( $path =~ m~^[A-Za-z]\:~ );
324
            push @reason1, 'Bad Path, UNC' if ( $path =~ m~^//~ );
325
            push @reason1, 'Bad Path, Relative' unless ( $path =~ m~^/~ );
326
        }
327
 
328
 
329
        push @reason2, 'No Build System' unless ( exists ($Package{$name}{$ver}{build} ) );
330
 
331
        unless ( @reason1 )
332
        {
333
            my $vname = "$name $ver";
334
            $vname =~ s~ ~_~g;
335
            $vname =~ s~__~~g;
336
 
337
            print JE "jats jats_vcsrelease -extractfiles \"-view=$vname\" \"-label=$vcstag\" -root=. -noprefix\n";
338
        }
339
 
340
        if ( @reason1 || @reason2 )
341
        {
342
            $Package{$name}{$ver}{bad_extract} = [@reason1, @reason2];
343
            printf ST "%40s %20s (%s) %s\n", $name, $ver, $mtest, $vcstag ;
344
        }
345
    }
346
}
347
 
348
close (JE);
349
close (ST);
350
 
351
#
352
#   Generate build order info
353
#
354
BuildOrder();
355
CompleteDepList();
356
#DebugDumpData ("Package", \%Package);
357
 
358
 
359
#
360
#   Generate HTML depenedancy information and other useful stuff
361
#
362
GenerateHTML();
363
GenerateHTMLLodgement();
364
 
365
 
366
#
367
#   Display names of files created
368
#
369
foreach my $file ( sort @create_list )
370
{
371
    Message ("Created: $file");
372
}
373
exit;
374
 
375
 
376
#-------------------------------------------------------------------------------
377
# Function        : getSBOMDetails
378
#
379
# Description     : Get some details about the SBOM
380
#                   Used fro descriptive text
381
#
382
# Inputs          : $bom_id             - BOM to process
383
#
384
# Returns         : 
385
#
386
sub getSBOMDetails
387
{
388
    my ($bom_id) = @_;
389
    my $foundDetails = 0;
390
    my (@row);
391
Verbose ("getSBOMDetails");
392
    connectDM(\$DM_DB) unless ($DM_DB);
393
 
394
    my $m_sqlstr = "SELECT distinct dp.PROJ_NAME ,bn.BOM_NAME, br.BRANCH_NAME, bm.BOM_VERSION, bm.BOM_LIFECYCLE" .
395
                   " FROM DEPLOYMENT_MANAGER.BOMS bm, DEPLOYMENT_MANAGER.BOM_NAMES bn, DEPLOYMENT_MANAGER.BRANCHES br, DEPLOYMENT_MANAGER.DM_PROJECTS dp" .
396
                   " 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";
397
 
398
    my $sth = $DM_DB->prepare($m_sqlstr);
399
    if ( defined($sth) )
400
    {
401
        if ( $sth->execute( ) )
402
        {
403
            if ( $sth->rows )
404
            {
405
                while ( @row = $sth->fetchrow_array )
406
                {
407
                    $sbom_project   = $row[0];
408
                    $sbom_name      = $row[1];
409
                    $sbom_branch    = $row[2];
410
                    $sbom_version   = $row[3] . '.' . $row[4];
411
                    $foundDetails = 1;
412
                }
413
            }
414
            $sth->finish();
415
        }
416
        else
417
        {
418
            Error("getSBOMDetails:Execute failure", $m_sqlstr );
419
        }
420
    }
421
    else
422
    {
423
        Error("getSBOMDetails:Prepare failure" );
424
    }
425
 
426
    Error("getSBOMDetails:No OS Information Found" ) unless $foundDetails;
427
 
428
}
429
 
430
#-------------------------------------------------------------------------------
431
# Function        : getReleaseDetails
432
#
433
# Description     : Get some details about the Release
434
#                   Used fro descriptive text
435
#
436
# Inputs          : $rtag_id             - RTAG_ID to process
437
#
438
# Returns         : 
439
#
440
sub getReleaseDetails
441
{
442
    my ($rtag_id) = @_;
443
    my $foundDetails = 0;
444
    my (@row);
445
Verbose ("getReleaseDetails");
446
    connectDM(\$DM_DB) unless ($DM_DB);
447
 
448
    my $m_sqlstr = "SELECT distinct rt.RTAG_NAME, pr.PROJ_NAME" .
449
                   " FROM RELEASE_MANAGER.RELEASE_TAGS rt, RELEASE_MANAGER.PROJECTS pr" .
450
                   " WHERE rt.RTAG_ID = $rtag_id AND rt.PROJ_ID = pr.PROJ_ID";
451
 
452
    my $sth = $DM_DB->prepare($m_sqlstr);
453
    if ( defined($sth) )
454
    {
455
        if ( $sth->execute( ) )
456
        {
457
            if ( $sth->rows )
458
            {
459
                while ( @row = $sth->fetchrow_array )
460
                {
461
                    $rtag_release = $row[0];
462
                    $rtag_project = $row[1];
463
                    $foundDetails = 1;
464
                }
465
            }
466
            $sth->finish();
467
        }
468
        else
469
        {
470
            Error("getReleaseDetails:Execute failure", $m_sqlstr );
471
        }
472
    }
473
    else
474
    {
475
        Error("getReleaseDetails:Prepare failure" );
476
    }
477
 
478
    Error("getReleaseDetails:No OS Information Found" ) unless $foundDetails;
479
 
480
}
481
 
482
 
483
 
484
#-------------------------------------------------------------------------------
485
# Function        : getOSIDforBOMID
486
#
487
# Description     : Get all the os_id's associated with a BOMID
488
#                   Also get base_env_id's where they exist
489
#
490
# Inputs          : $bom_id             - BOM to process
491
#
492
# Returns         :
493
#
494
 
495
sub getOSIDforBOMID
496
{
497
    my ($bom_id) = @_;
498
    my $foundDetails = 0;
499
    my (@row);
500
    Verbose ("getOSIDforBOMID");
501
    connectDM(\$DM_DB) unless ($DM_DB);
502
 
503
    my $m_sqlstr = "SELECT distinct os.OS_ID, os.OS_NAME, nn.NODE_NAME, obe.BASE_ENV_ID " .
504
                   " FROM DEPLOYMENT_MANAGER.OPERATING_SYSTEMS os, " .
505
                         "DEPLOYMENT_MANAGER.BOM_CONTENTS bc, ".
506
                         "DEPLOYMENT_MANAGER.NETWORK_NODES nn, ".
507
                         "DEPLOYMENT_MANAGER.OS_BASE_ENV obe" .
508
                   " WHERE bc.BOM_ID = $bom_id ".
509
                      "AND bc.NODE_ID = os.NODE_ID ".
510
                      "AND nn.NODE_ID = os.NODE_ID ".
511
                      "AND obe.OS_ID (+) = os.OS_ID ";
512
 
513
    my $sth = $DM_DB->prepare($m_sqlstr);
514
    if ( defined($sth) )
515
    {
516
        if ( $sth->execute( ) )
517
        {
518
            if ( $sth->rows )
519
            {
520
                while ( @row = $sth->fetchrow_array )
521
                {
522
                    Verbose ("OS_ID: ".join (',',@row) );
523
                    $os_id_list{$row[0]}{os_name} = $row[1];
524
                    $os_id_list{$row[0]}{node_name} = $row[2];
525
 
526
                    if ( defined $row[3] )
527
                    {
528
                        $os_env_list{$row[3]}{needed} = 1;
529
                        $os_env_list{$row[3]}{os_id}{$row[0]} = 1;
530
                    }
531
 
532
                    $foundDetails = 1;
533
                }
534
            }
535
            $sth->finish();
536
        }
537
        else
538
        {
539
            Error("getOSIDforBOMID:Execute failure" );
540
        }
541
    }
542
    else
543
    {
544
        Error("getOSIDforBOMID:Prepare failure" );
545
    }
546
 
547
    Error("getOSIDforBOMID:No OS Information Found" ) unless $foundDetails;
548
 
549
}
550
 
551
#-------------------------------------------------------------------------------
552
# Function        : getPackagesforBaseInstall
553
#
554
# Description     : Get all the packages for a given base install
555
#
556
# Inputs          :
557
#
558
# Returns         :
559
#
560
 
561
sub getPackagesforBaseInstall
562
{
563
    my ($base_env_id) =@_;
564
    my $foundDetails = 0;
565
    my (@row);
566
 
567
    connectDM(\$DM_DB) unless ($DM_DB);
568
 
569
    # First get details from pv_id
570
 
571
    my $m_sqlstr = "SELECT DISTINCT bec.PROD_ID, pkg.pkg_name, pv.pkg_version, pkg.pkg_id, pv.pv_id" .
572
                " FROM RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_VERSIONS pv, DEPLOYMENT_MANAGER.PRODUCT_DETAILS pd, DEPLOYMENT_MANAGER.BASE_ENV_CONTENTS bec".
573
                " WHERE bec.BASE_ENV_ID = $base_env_id AND bec.PROD_ID (+)= pv.PV_ID AND pv.pkg_id = pkg.pkg_id";
574
 
575
    my $sth = $DM_DB->prepare($m_sqlstr);
576
    if ( defined($sth) )
577
    {
578
        if ( $sth->execute( ) )
579
        {
580
            if ( $sth->rows )
581
            {
582
                while ( @row = $sth->fetchrow_array )
583
                {
584
                    Verbose ("OS ENV Package($base_env_id}:" . join (',',@row) );
585
 
586
                    my $pv_id =     $row[0];
587
                    my $name =      $row[1]  || 'BadName';
588
                    my $ver =       $row[2]  || 'BadVer';
589
 
590
                    $pv_id{$pv_id}{pkg_name} =$name;
591
                    $pv_id{$pv_id}{pkg_ver} = $ver;
592
                    foreach my $os_id ( keys %{$os_env_list{$base_env_id}{os_id}} )
593
                    {
594
                        $pv_id{$pv_id}{os_id}{$os_id} = 2;
595
                    }
596
                }
597
            }
598
            $sth->finish();
599
        }
600
        else
601
        {
602
            Error ("getPackagesforBaseInstall: Execute error");
603
        }
604
    }
605
    else
606
    {
607
        Error("getPackagesforBaseInstall:Prepare failure" );
608
    }
609
 
610
}
611
 
612
 
613
#-------------------------------------------------------------------------------
614
# Function        : getPackages_by_osid
615
#
616
# Description     : Get all the packages used by a given os_id
617
#
618
# Inputs          :
619
#
620
# Returns         :
621
#
622
 
623
my $count = 0;
624
sub getPackages_by_osid
625
{
626
    my ($os_id) =@_;
627
    my $foundDetails = 0;
628
    my (@row);
629
 
630
    connectDM(\$DM_DB) unless ($DM_DB);
631
 
632
    # First get details from pv_id
633
 
634
    my $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" .
635
                " FROM RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_VERSIONS pv, DEPLOYMENT_MANAGER.PRODUCT_DETAILS pd,".
636
	            "(" .
637
		        " SELECT osc.seq_num, osc.prod_id".
638
		        " FROM DEPLOYMENT_MANAGER.os_contents osc".
639
		        " WHERE osc.os_id = $os_id" .
640
	            " ) osc" .
641
                " WHERE pd.PROD_ID (+)= pv.PV_ID" .
642
                "   AND pv.pkg_id = pkg.pkg_id" .
643
                "   AND osc.PROD_ID = pv.pv_id" .
644
                " ORDER BY osc.SEQ_NUM desc" ;
645
 
646
    my $sth = $DM_DB->prepare($m_sqlstr);
647
    if ( defined($sth) )
648
    {
649
        if ( $sth->execute( ) )
650
        {
651
            if ( $sth->rows )
652
            {
653
                while ( @row = $sth->fetchrow_array )
654
                {
655
next if ( $opt_test && ++$count > 30 );
656
                    Verbose ("SBOM Package:".join (',',@row) );
657
                    my $pv_id =     $row[8];
658
                    my $name =      $row[2]  || 'BadName';
659
                    my $ver =       $row[3]  || 'BadVer';
660
 
661
                    $pv_id{$pv_id}{pkg_name} =$name;
662
                    $pv_id{$pv_id}{pkg_ver} = $ver;
663
                    $pv_id{$pv_id}{os_id}{$os_id} = 1;
664
                }
665
            }
666
            $sth->finish();
667
        }
668
    }
669
    else
670
    {
671
        Error("getPackages_by_osid:Prepare failure" );
672
    }
673
}
674
 
675
#-------------------------------------------------------------------------------
676
# Function        : getPkgDetailsByPV_ID
677
#
678
# Description     : Populate the Packages structure given a PV_ID
679
#                   Called for each package in the SBOM
680
#
681
# Inputs          : PV_ID           - Package Unique Identifier
682
#
683
# Returns         : Populates Package
684
#
685
sub getPkgDetailsByPV_ID
686
{
687
    my ($PV_ID) = @_;
688
    my $foundDetails = 0;
689
    my (@row);
690
 
691
    connectRM(\$RM_DB) unless ($RM_DB);
692
 
693
    # First get details from pv_id
694
 
695
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION, pv.IS_DEPLOYABLE, pbi.BSA_ID, pbi.BM_ID, PV_DESCRIPTION, release_manager.PK_RMAPI.return_vcs_tag($PV_ID)" .
696
                    " FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_BUILD_INFO pbi" .
697
                    " WHERE pv.PV_ID = \'$PV_ID\' AND pv.PKG_ID = pkg.PKG_ID AND pv.PV_ID = pbi.PV_ID (+) ";
698
 
699
    my $sth = $RM_DB->prepare($m_sqlstr);
700
    if ( defined($sth) )
701
    {
702
        if ( $sth->execute( ) )
703
        {
704
            if ( $sth->rows )
705
            {
706
                while ( @row = $sth->fetchrow_array )
707
                {
708
                    my $pv_id       = $row[0];
709
                    my $name        = $row[1];
710
                    my $ver         = $row[2];
711
                    my $deployable  = $row[3];
712
                    my $build_info  = $row[4] || '';
713
                    my $build_mach  = $row[5] || '';
714
                    my $description = $row[6] || '';
715
                    my $vcstag      = $row[7] || '';
716
 
717
                    #
718
                    #   BSA_ID: 1:debug, 2:prod, 3:debug+prod, 4:Java1.4 5: Java 1.5
719
                    #   BM_ID : 1:solaris, 2:win32, 3: linux, 4:generic
720
                    #
721
 
722
 
723
                    #
724
                    #   Does it look like a patch
725
                    #   We may want to ignore it.
726
                    #
727
                    my $patch = "";
728
                    unless ( $opt_patch )
729
                    {
730
                        if ( $ver =~ m~\.p\d+.\w+$~ )
731
                        {
732
                            $patch = "Patch";
733
                            $patch{$name} = 0
734
                                unless (  exists $patch{$name} );
735
                            $patch{$name}++;
736
                        }
737
                    }
738
                    Verbose ("getPkgDetailsByPV_ID: $PV_ID, $name, $ver, $build_mach ,$build_info, $patch");
739
                    next if ( $patch );
740
 
741
 
742
                    if ( exists $ignore{$name} )
743
                    {
744
                        Verbose2( "    Ignoring: $PV_ID, $name, $ver, $build_mach ,$build_info, $patch\n");
745
                        $ignore{$name}++;
746
                        last;
747
                    }
748
 
749
                    $vcstag =~ tr~\\/~/~;
750
 
751
                    $Package{$name}{$ver}{pvid} = $PV_ID;
752
                    $Package{$name}{$ver}{done} = 1;
753
                    $Package{$name}{$ver}{base} = 1;
754
                    $Package{$name}{$ver}{deployable} = 1 if ($deployable);
755
                    $Package{$name}{$ver}{build}{$build_mach} = $build_info if $build_mach;
756
                    $Package{$name}{$ver}{description} = $description;
757
                    $Package{$name}{$ver}{vcstag} = $vcstag;
758
 
759
                    GetDepends( $pv_id, $name, $ver );
760
 
761
                }
762
            }
763
            else
764
            {
765
                Warning ("No Package details for: PVID: $PV_ID");
766
            }
767
            $sth->finish();
768
        }
769
        else
770
        {
771
            Error("getPkgDetailsByPV_ID: Execute failure", $m_sqlstr );
772
        }
773
    }
774
    else
775
    {
776
        Error("Prepare failure" );
777
    }
778
}
779
 
780
#-------------------------------------------------------------------------------
781
# Function        : getPkgDetailsByName
782
#
783
# Description     : Determine the PVID for a given package name and version
784
#
785
# Inputs          : $pname          - Package name
786
#                   $pver           - Package Version
787
#
788
# Returns         : 
789
#
790
 
791
sub getPkgDetailsByName
792
{
793
    my ($pname, $pver) = @_;
794
    my $pv_id;
795
    my (@row);
796
 
797
    connectRM(\$RM_DB) unless ($RM_DB);
798
 
799
    # First get details for a given package version
800
 
801
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION" .
802
                    " FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
803
                    " WHERE pkg.PKG_NAME = \'$pname\' AND pv.PKG_VERSION = \'$pver\' AND pv.PKG_ID = pkg.PKG_ID";
804
    my $sth = $RM_DB->prepare($m_sqlstr);
805
    if ( defined($sth) )
806
    {
807
        if ( $sth->execute( ) )
808
        {
809
            if ( $sth->rows )
810
            {
811
                while ( @row = $sth->fetchrow_array )
812
                {
813
                    $pv_id = $row[0];
814
                    my $name = $row[1];
815
                    my $ver = $row[2];
816
                    Verbose( "getPkgDetailsByName :PV_ID= $pv_id");
817
                }
818
            }
819
            $sth->finish();
820
        }
821
    }
822
    else
823
    {
824
        Error("Prepare failure" );
825
    }
826
    return $pv_id;
827
}
828
 
829
#-------------------------------------------------------------------------------
830
# Function        : getPkgDetailsForPVIDs
831
#
832
# Description     : Get all package details by PVID, from a list of PVIDs
833
#
834
# Inputs          : List of PVID's to process
835
#
836
# Returns         : Nothing
837
#
838
sub getPkgDetailsForPVIDs
839
{
840
 
841
    my $count = 0;
842
    foreach my $pv_id ( @_ )
843
    {
844
        next if ( $opt_test && ++$count > 3 );
845
        getPkgDetailsByPV_ID( $pv_id);
846
    }
847
}
848
 
849
#-------------------------------------------------------------------------------
850
# Function        : GetDepends
851
#
852
# Description     : Extract the dependancies for a given package version
853
#
854
# Inputs          : $pvid
855
#
856
# Returns         :
857
#
858
sub GetDepends
859
{
860
    my ($pv_id, $pname, $pver ) = @_;
861
 
862
    connectRM(\$RM_DB) unless ($RM_DB);
863
 
864
    #
865
    #   Now extract the package dependacies
866
    #
867
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pv.PKG_VERSION, pd.DPV_ID" .
868
                   " FROM RELEASE_MANAGER.PACKAGE_DEPENDENCIES pd, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
869
                   " WHERE pd.PV_ID = \'$pv_id\' AND pd.DPV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
870
    my $sth = $RM_DB->prepare($m_sqlstr);
871
    if ( defined($sth) )
872
    {
873
        if ( $sth->execute( ) )
874
        {
875
            if ( $sth->rows )
876
            {
877
                my %depends;
878
                while ( my @row = $sth->fetchrow_array )
879
                {
880
#print "$pname $pver ===== @row\n";
881
                    my $name = $row[0];
882
                    my $ver = $row[1];
883
 
884
                    Verbose2( "       Depends: $name, $ver");
885
 
886
                    $depends{$name,$ver} = 1;
887
                    $Package{$name}{$ver}{usedby}{$pname,$pver} = 1;
888
 
889
                    unless ( exists $Package{$name}{$ver}{done} )
890
                    {
891
                        my @DATA = ($name, $ver, $row[2]);
892
                        push @StrayPackages, \@DATA;
893
                    }
894
                }
895
                $Package{$pname}{$pver}{depends} = \%depends;
896
            }
897
            $sth->finish();
898
        }
899
    }
900
    else
901
    {
902
        Error("GetDepends:Prepare failure" );
903
    }
904
}
905
 
906
#-------------------------------------------------------------------------------
907
# Function        : getPkgDetailsByRTAG_ID
908
#
909
# Description     : Extract all the packages for a given rtag_id
910
#
911
# Inputs          : RTAG_ID
912
#
913
# Returns         : 
914
#
915
 
916
sub getPkgDetailsByRTAG_ID
917
{
918
    my ($RTAG_ID) = @_;
919
    my $foundDetails = 0;
920
    my (@row);
921
 
922
    connectRM(\$RM_DB);
923
 
924
    # First get details from pv_id
925
 
926
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION".
927
                   " FROM RELEASE_MANAGER.RELEASE_CONTENT rc, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
928
                   " WHERE rc.RTAG_ID = $RTAG_ID AND rc.PV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
929
    my $sth = $RM_DB->prepare($m_sqlstr);
930
    if ( defined($sth) )
931
    {
932
        if ( $sth->execute( ) )
933
        {
934
            if ( $sth->rows )
935
            {
936
                while ( @row = $sth->fetchrow_array )
937
                {
938
                    my $pv_id   = $row[0];
939
                    my $name    = $row[1];
940
                    my $ver     = $row[2];
941
                    Verbose ("getPkgDetailsByRTAG_ID: $RTAG_ID, $name, $ver, $pv_id");
942
 
943
                    $Release{$name}{$ver}{pv_id} = $pv_id;
944
                    $Release_pvid{$pv_id} = 1;
945
                }
946
            }
947
            $sth->finish();
948
        }
949
    }
950
    else
951
    {
952
        Error("getPkgDetailsByRTAG_ID:Prepare failure" );
953
    }
954
}
955
 
956
 
957
#-------------------------------------------------------------------------------
958
# Function        : LocateStrays
959
#
960
# Description     : Locate stray packages
961
#                   These are packages that have not been defined by the
962
#                   top level SBOM. These are not really stray
963
#
964
# Inputs          : $mode           2: No stray tagging
965
#                                   0: Mark all as stray
966
#                                   1: Don't mark packages as stray
967
#                                      if they are in releases hash
968
# Returns         : Nothing
969
#
970
sub LocateStrays
971
{
972
    my ($mode) = @_;
973
    while ( $#StrayPackages >= 0 )
974
    {
975
        my $DATA = pop @StrayPackages;
976
        my $name = $DATA->[0];
977
        my $ver = $DATA->[1];
978
        my $pv_id = $DATA->[2];
979
 
980
        next if ( exists $Package{$name}{$ver}{done} );
981
        getPkgDetailsByPV_ID ( $pv_id );
982
 
983
        next if ( $mode > 1 );
984
        if ( $mode )
985
        {
986
            next if ( exists $Release{$name}{$ver} );
987
        }
988
        $Package{$name}{$ver}{stray} = 1;
989
#print "Stray: $pv_id, $name, $ver\n";
990
    }
991
}
992
 
993
#-------------------------------------------------------------------------------
994
# Function        : BuildOrder
995
#
996
# Description     : Determine the order to build packages
997
#
998
# Inputs          :
999
#
1000
# Returns         :
1001
#
1002
sub BuildOrder
1003
{
1004
    foreach my $name ( keys %Package )
1005
    {
1006
        foreach my $ver ( keys %{$Package{$name}} )
1007
        {
1008
            AddToBuildList( $name, $ver, $Package{$name}{$ver}{depends} );
1009
        }
1010
    }
1011
 
1012
    DetermineBuildOrder();
1013
}
1014
 
1015
#-------------------------------------------------------------------------------
1016
# Function        : AddToBuildList
1017
#
1018
# Description     : Add packages to a build list
1019
#
1020
# Inputs          : PackageName
1021
#                   PackageVersion
1022
#                   Hash of dependancies
1023
#
1024
# Returns         :
1025
#
1026
my %BuildList;
1027
sub AddToBuildList
1028
{
1029
    my ($name, $ver, $pdepends ) = @_;
1030
 
1031
    Warning ("Duplicate Package to build: $name, $ver") if exists $BuildList{$name,$ver};
1032
 
1033
    #
1034
    #   Clone dependancies as we will destroy the list as we process data
1035
    #
1036
    my $ref;
1037
    $ref = dclone ($pdepends ) if $pdepends;
1038
    $BuildList{$name,$ver}{depends} = $ref;
1039
}
1040
 
1041
#-------------------------------------------------------------------------------
1042
# Function        : DetermineBuildOrder
1043
#
1044
# Description     : Determine the build order
1045
#
1046
# Inputs          :
1047
#
1048
# Returns         :
1049
#
1050
sub DetermineBuildOrder
1051
{
1052
 
1053
    my $file = "${fpref}_buildinfo.txt";
1054
    push @create_list, $file;
1055
 
1056
    open (BI, ">$file" )  || Error ("Cannot create $file");
1057
 
1058
#    DebugDumpData ("BuildList", \%BuildList); exit 1;
1059
 
1060
    my $more = 1;
1061
    my $level = 0;
1062
    while ( $more )
1063
    {
1064
        my @build;
1065
        $level ++;
1066
        $more = 0;
1067
        foreach my $key ( keys %BuildList )
1068
        {
1069
            #
1070
            #   Locate packges with no dependencies left
1071
            #
1072
            next if ( keys %{$BuildList{$key}{depends}} );
1073
            push @build, $key;
1074
        }
1075
 
1076
        foreach my $build ( @build )
1077
        {
1078
            $more = 1;
1079
            delete $BuildList{$build};
1080
            my ($name, $ver) = split $;, $build;
1081
            my $vcstag = $Package{$name}{$ver}{vcstag} || '';
1082
            $Package{$name}{$ver}{buildorder}  = $level;
1083
 
1084
            my @machs;
1085
            if ( exists($Package{$name}{$ver}{build}) )
1086
            {
1087
                @machs = sort keys %{$Package{$name}{$ver}{build}};
1088
            }
1089
 
1090
            my $btext = "Build";
1091
            foreach my $mach ( @machs )
1092
            {
1093
                my $type = $Package{$name}{$ver}{build}{$mach};
1094
                $btext .= ':' .
1095
                    ($BM_ID{$mach} || "Unknown, $mach") . ' ' .
1096
                    ($BSA_ID{$type} || 'Unknown');
1097
            }
1098
 
1099
 
1100
            printf BI "Build(%2d): %40s %15s %s %s\n", $level, $name, $ver, $vcstag, $btext;
1101
        }
1102
 
1103
        #
1104
        #   Delete dependencies
1105
        #
1106
        foreach my $key ( keys %BuildList )
1107
        {
1108
            foreach my $build ( @build )
1109
            {
1110
                delete $BuildList{$key}{depends}->{$build};
1111
            }
1112
        }
1113
    }
1114
    close BI;
1115
}
1116
 
1117
#-------------------------------------------------------------------------------
1118
# Function        : CompleteDepList
1119
#
1120
# Description     : 
1121
#
1122
# Inputs          : Generate complete dep list
1123
#
1124
# Returns         : 
1125
#
1126
sub CompleteDepList
1127
{
1128
    foreach my $name ( sort keys %Package )
1129
    {
1130
        foreach my $ver ( sort keys %{$Package{$name}} )
1131
        {
1132
            my %dependAll;
1133
            #
1134
            #   Depends On info
1135
            #
1136
            foreach my $depend ( sort keys %{$Package{$name}{$ver}{depends}} )
1137
            {
1138
                AddDepends (\%dependAll, $depend);
1139
            }
1140
            $Package{$name}{$ver}{AllDepends} = \%dependAll;
1141
            my $file = "data_${name}_${ver}.txt";
1142
            $file =~ s~/~_~g;
1143
            open (FI, ">$file" )  || Error ("Cannot create $file");
1144
            print FI "Package: $name $ver\n";
1145
            print FI  GetBuildString($name, $ver) . "\n";
1146
            foreach my $depend ( sort keys %{$Package{$name}{$ver}{AllDepends}} )
1147
            {
1148
                my ($name, $ver) = split $;, $depend;
1149
                my $btext = GetBuildString( $name, $ver);
1150
                print FI "$name $ver $btext\n";
1151
            }
1152
            close FI;
1153
 
1154
        }
1155
    }
1156
}
1157
 
1158
sub AddDepends
1159
{
1160
    my ($pref, $depend) = @_;
1161
    my ($dname, $dver) = split $;, $depend;
1162
    $pref->{$dname, $dver} = 1;
1163
    foreach my $depend1 ( sort keys %{$Package{$dname}{$dver}{depends}} )
1164
    {
1165
        AddDepends ($pref, $depend1);
1166
    }
1167
}
1168
 
1169
sub GetBuildString
1170
{
1171
    my ($name,$ver) = @_;
1172
    my @machs;
1173
    if ( exists($Package{$name}{$ver}{build}) )
1174
    {
1175
        @machs = sort keys %{$Package{$name}{$ver}{build}};
1176
    }
1177
 
1178
    my $btext = "Build";
1179
    foreach my $mach ( @machs )
1180
    {
1181
        my $type = $Package{$name}{$ver}{build}{$mach};
1182
        $btext .= ':' .
1183
            ($BM_ID{$mach} || "Unknown, $mach")
1184
#            . ' ' . ($BSA_ID{$type} || 'Unknown')
1185
            ;
1186
    }
1187
    return $btext;
1188
}
1189
 
1190
#-------------------------------------------------------------------------------
1191
# Function        : GenerateHTML
1192
#
1193
# Description     : Generate Dependency information
1194
#                   Generate a nive HTML dependancy table
1195
#                   Shows DependOn and UsedBy
1196
# Inputs          :
1197
#
1198
# Returns         :
1199
#
1200
 
1201
sub th
1202
{
1203
    my ($text, $span) = @_;
1204
 
1205
    my $string = '<th style="vertical-align: top;"';
1206
    $string .= " colspan=\"$span\"" if ( $span );
1207
    $string .= '>' . $text . '</th>' . "\n";
1208
    return $string;
1209
}
1210
 
1211
sub thl
1212
{
1213
    my ($text, $span) = @_;
1214
 
1215
    my $string = '<th style="text-align: left;"';
1216
    $string .= " colspan=\"$span\"" if ( $span );
1217
    $string .= '>' . $text . '</th>' . "\n";
1218
    return $string;
1219
}
1220
 
1221
 
1222
sub GenerateHTML
1223
{
1224
    my $td = '<td style="vertical-align: top;">' . "\n";
1225
    my $tdr = '<td style="text-align: right;">';
1226
 
1227
    my $file = "${fpref}_depends.html";
1228
    push @create_list, $file;
1229
    open (DP, ">$file" )  || Error ("Cannot create $file");
1230
 
1231
    #
1232
    #   Generate a header
1233
    #
1234
    print DP "<dl><dt><h1>Extraction Details</h1></dt>\n";
1235
    if ( $opt_sbom_id )
1236
    {
1237
        print DP "<dd>SBOM Base</dd>\n";
1238
        print DP "<dd>Project: $sbom_project</dd>\n";
1239
        print DP "<dd>BOM    : $sbom_name</dd>\n";
1240
        print DP "<dd>Branch : $sbom_branch</dd>\n";
1241
        print DP "<dd>Version: $sbom_version</dd>\n";
1242
        print DP "<dd>SBOM ID: $opt_sbom_id</dd>\n";
1243
    }
1244
 
1245
    if ( $opt_rtag_id )
1246
    {
1247
        getReleaseDetails($opt_rtag_id);
1248
        print DP "<dd>Release Base</dd>\n";
1249
        print DP "<dd>Project: $rtag_project</dd>\n";
1250
        print DP "<dd>Release: $rtag_release</dd>\n";
1251
        print DP "<dd>RTAG ID: $opt_rtag_id</dd>\n";
1252
    }
1253
 
1254
    print DP "<dd>Root Package: $opt_rootpkg , $opt_rootpkg_version</dd>\n" if ($opt_rootpkg);
1255
    print DP "</dl>\n";
1256
 
1257
    #
1258
    #   Generate an index
1259
    #
1260
    print DP "<dl><dt><h1>Index</h1></dt>\n";
1261
    print DP "<dd><a href=\"#Ignore\">Ignored Packages</a></dd>\n";
1262
    print DP "<dd><a href=\"#Depend\">Dependency Info</a></dd>\n";
1263
    print DP "<dd><a href=\"#Multi\">Multiple Package Version</a></dd>\n";
1264
    print DP "<dd><a href=\"#Leaf\">Packages that have no parents</a></dd>\n";
1265
    print DP "<dd><a href=\"#NoBuild\">Packages that cannot be built</a></dd>\n";
1266
    print DP "<dd><a href=\"#Excess\">Excess Packages from Release: $opt_rtag_id</a></dd>\n" if ( $opt_rtag_id && ($opt_sbom_id || $opt_rootpkg ));
1267
    print DP "<dd><a href=\"#Stray\">Required Packages, not part of the release</a></dd>\n" if ( $opt_rtag_id && ! ($opt_sbom_id || $opt_rootpkg) );
1268
    print DP "<dd><a href=\"#Inconsistent\">Packages in the Release, with inconsistent dependencies</a></dd>\n" if ( $opt_rtag_id && !$opt_sbom_id );
1269
 
1270
    print DP "</dl>\n";
1271
 
1272
    #
1273
    #   Ignored Packages
1274
    #
1275
    print DP "<h1><a name=\"Ignore\">Ignored Packages</a></h1>\n";
1276
 
1277
    print DP "The following package, and all dependents, have been ignored.<br><br>\n";
1278
 
1279
    foreach my $name ( sort keys %ignore )
1280
    {
1281
        print DP "$name: $ignore{$name} versions<br>\n";
1282
    }
1283
 
1284
    unless ( $opt_patch )
1285
    {
1286
        print DP "The following package have patches that have been ignored.<br><br>\n";
1287
        foreach my $name ( sort keys %patch )
1288
        {
1289
            print DP "$name: $patch{$name} patches<br>\n";
1290
        }
1291
    }
1292
 
1293
    #
1294
    #   Dependency Information
1295
    #
1296
    print DP "<h1><a name=\"Depend\">Dependency Info</a></h1>\n";
1297
 
1298
    print DP "<table border=\"1\"><tbody>\n";
1299
    print DP "<tr>\n";
1300
    print DP th("Package Dependency");
1301
    print DP th("Package Used by");
1302
    print DP th("Build Info");
1303
    print DP "</tr>\n";
1304
    my $package_count = 0;
1305
    foreach my $name ( sort keys %Package )
1306
    {
1307
        foreach my $ver ( sort keys %{$Package{$name}} )
1308
        {
1309
            print DP "<tr>\n";
1310
            $package_count++;
1311
            #
1312
            #   Depends On info
1313
            #
1314
 
1315
            print DP $td;
1316
            my $anchor= "${name}_${ver}";
1317
            my $tag = "usedby_${name}_${ver}";
1318
            printf  DP "<dl><dt><a name=\"$anchor\"></a><a href=\"#$tag\">%s&nbsp;%s</a> Depends on:</dt>\n", $name, $ver;
1319
            foreach my $depend ( sort keys %{$Package{$name}{$ver}{depends}} )
1320
            {
1321
                my ($dname, $dver) = split $;, $depend;
1322
                my $tag = "${dname}_${dver}";
1323
                printf  DP "    <dd><a href=\"#$tag\">%s&nbsp;%s</a></dd>\n", $dname, $dver;
1324
            }
1325
            print DP "</dl>\n";
1326
            print DP "</td>\n";
1327
 
1328
 
1329
            #
1330
            #   Used By information
1331
            #
1332
            print DP $td;
1333
            $anchor= "usedby_${name}_${ver}";
1334
            $tag = "${name}_${ver}";
1335
            printf  DP "<dl><dt><a name=\"$anchor\"></a><a href=\"#$tag\">%s&nbsp;%s</a> Used by:</dt>\n", $name, $ver;
1336
            foreach my $depend ( sort keys %{$Package{$name}{$ver}{usedby}} )
1337
            {
1338
                my ($dname, $dver) = split $;, $depend;
1339
                my $tag = "usedby_${dname}_${dver}";
1340
                printf  DP "    <dd><a href=\"#$tag\">%s&nbsp;%s</a></dd>\n", $dname, $dver;
1341
            }
1342
            print DP "</dl>\n";
1343
            print DP "</td>\n";
1344
 
1345
            #
1346
            #   Build Info
1347
            #
1348
            print DP $td;
1349
            print DP "<table>";
1350
            my $stray = ( exists ($Package{$name}{$ver}{stray}) && $Package{$name}{$ver}{stray} );
1351
 
1352
            my $pv_id = $Package{$name}{$ver}{pvid} || 'No PVID';
1353
            my $pv_id_ref = $rm_base . $pv_id;
1354
               $pv_id_ref .= "&rtag_id=" . $opt_rtag_id if ($opt_rtag_id && !$stray);
1355
            my $pv_id_str = "<a href=\"$pv_id_ref\" TARGET=\"_blank\">$pv_id</a>";
1356
 
1357
            printf DP "<tr>${tdr}Pvid:</td><td>%s</td></tr>\n", $pv_id_str;
1358
            printf DP "<tr>${tdr}VcsTag:</td><td>%s</td></tr>\n", $Package{$name}{$ver}{vcstag} || 'NoneProvided';
1359
 
1360
            my $order = 'Not Built';
1361
            my @machs;
1362
 
1363
            if ( exists($Package{$name}{$ver}{build}) )
1364
            {
1365
                $order = $Package{$name}{$ver}{buildorder};
1366
                @machs = sort keys %{$Package{$name}{$ver}{build}};
1367
            }
1368
            else
1369
            {
1370
                my $tag = "notbuilt_${name}_${ver}";
1371
                $order = "<a href=\"#$tag\">Not Built</a>"
1372
            }
1373
 
1374
            printf DP "<tr>${tdr}Build Order:</td><td>%s</td></tr>\n", $order;
1375
 
1376
            my $text = "Build:";
1377
            foreach my $mach ( @machs )
1378
            {
1379
                my $type = $Package{$name}{$ver}{build}{$mach};
1380
                printf DP "<tr>${tdr}$text</td><td>%s&nbsp;%s</td></tr>\n", $BM_ID{$mach} || "Unknown, $mach", $BSA_ID{$type} || 'Unknown';
1381
                $text = '';
1382
            }
1383
 
1384
            my $pvid = $Package{$name}{$ver}{pvid};
1385
            $text = "Deployed:";
1386
            foreach my $osid ( sort keys %{ $pv_id{$pvid}{os_id}  } )
1387
            {
1388
                my $os_name = $os_id_list{$osid}{os_name};
1389
                my $node =    $os_id_list{$osid}{node_name};
1390
 
1391
                my $ref = $dm_base . $osid;
1392
                my $str = "<a href=\"$ref\">$node,($os_name)</a>";
1393
 
1394
 
1395
                printf DP "<tr>${tdr}$text</td><td>$str</td></tr>\n";
1396
                $text = '';
1397
            }
1398
 
1399
            if ( $stray )
1400
            {
1401
                printf DP "<tr>${tdr}Stray:</td><td>Package included indirectly</td></tr>\n";
1402
            }
1403
 
1404
 
1405
 
1406
            print DP "</table>";
1407
            print DP "</td>\n";
1408
 
1409
            #
1410
            #   End of Row
1411
            #
1412
            print DP "</tr>\n";
1413
        }
1414
    }
1415
    print DP "<tr>\n";
1416
    print DP thl("Total Count: $package_count", 3);
1417
    print DP "</tr>\n";
1418
 
1419
    print DP "</tbody></table>\n";
1420
 
1421
 
1422
    #
1423
    #   Multiple versions of a package
1424
    #
1425
    print DP "<h1><a name=\"Multi\">Multiple Package Versions</a></h1>\n";
1426
    print DP "<table border=\"1\"><tbody>\n";
1427
    print DP "<tr>\n";
1428
    print DP th("Multiple Versions");
1429
    print DP "</tr>\n";
1430
    my $multiple_count = 0;
1431
    foreach my $name ( sort keys %Package )
1432
    {
1433
        my @versions = keys %{$Package{$name}};
1434
        next unless ( $#versions > 0 );
1435
        $multiple_count++;
1436
        print DP "<tr>\n";
1437
        print DP $td;
1438
        printf  DP "<dl><dt>$name</a> Versions:<dt>\n";
1439
 
1440
        foreach my $ver ( sort @versions )
1441
        {
1442
            my $tag = "${name}_${ver}";
1443
            printf  DP "    <dd>";
1444
            printf  DP "<a href=\"#$tag\">%s&nbsp;%s</a>\n", $name, $ver;
1445
            print   DP " - Not in Release" if ($opt_rtag_id && $Package{$name}{$ver}{stray});
1446
            printf  DP "</dd>\n", $name, $ver;
1447
        }
1448
        print DP "</dl>\n";
1449
        print DP "</td>\n";
1450
        print DP "</tr>\n";
1451
    }
1452
    print DP "<tr>\n";
1453
    print DP thl("Total Count: $multiple_count");
1454
    print DP "</tr>\n";
1455
 
1456
    print DP "</tbody></table>\n";
1457
 
1458
 
1459
    #
1460
    #   Leaf Packages
1461
    #
1462
    print DP "<h1><a name=\"Leaf\">Packages that have no parents</a></h1>\n";
1463
    print DP "<table border=\"1\"><tbody>\n";
1464
    print DP "<tr>\n";
1465
    print DP th("Leaf Packages");
1466
    print DP "</tr>\n";
1467
    my $leaf_count = 0;
1468
    foreach my $name ( sort keys %Package )
1469
    {
1470
        foreach my $ver ( sort keys %{$Package{$name}} )
1471
        {
1472
            my @usedby = keys %{$Package{$name}{$ver}{usedby}};
1473
            next if ( @usedby );
1474
            $leaf_count++;
1475
 
1476
            print DP "<tr>\n";
1477
            print DP $td;
1478
 
1479
            my $tag = "${name}_${ver}";
1480
 
1481
            printf  DP "<dt><a href=\"#$tag\">%s&nbsp;%s</a>\n", $name, $ver;
1482
 
1483
            print DP "</td>\n";
1484
            print DP "</tr>\n";
1485
        }
1486
    }
1487
    print DP "<tr>\n";
1488
    print DP thl("Total Count: $leaf_count");
1489
    print DP "</tr>\n";
1490
    print DP "</tbody></table>\n";
1491
 
1492
 
1493
 
1494
    #
1495
    #   Packages that cannot be built
1496
    #
1497
    print DP "<h1><a name=\"NoBuild\">Packages that cannot be built</a></h1>\n";
1498
    print DP "<table border=\"1\"><tbody>\n";
1499
    print DP "<tr>\n";
1500
    print DP th("Not Built");
1501
    print DP "</tr>\n";
1502
    my $no_build_count = 0;
1503
 
1504
    foreach my $name ( sort keys %Package )
1505
    {
1506
        my @versions = keys %{$Package{$name}};
1507
        foreach my $ver ( sort @versions )
1508
        {
1509
            next unless exists($Package{$name}{$ver}{bad_extract});
1510
            $no_build_count++;
1511
            my @reasons = @{$Package{$name}{$ver}{bad_extract}};
1512
 
1513
            print DP "<tr><dl>\n";
1514
            print DP $td;
1515
 
1516
            my $tag = "${name}_${ver}";
1517
            my $anchor = "notbuilt_${name}_${ver}";
1518
 
1519
            printf  DP "<dt><a name=\"$anchor\"></a><a href=\"#$tag\">%s&nbsp;%s</a></dt>\n", $name, $ver;
1520
            foreach my $reason ( @reasons )
1521
            {
1522
                print  DP "<dd>$reason</dd>\n";
1523
            }
1524
 
1525
 
1526
            print DP "</dl>\n";
1527
            print DP "</td>\n";
1528
            print DP "</tr>\n";
1529
 
1530
        }
1531
    }
1532
    print DP "<tr>\n";
1533
    print DP thl("Total Count: $no_build_count");
1534
    print DP "</tr>\n";
1535
 
1536
    print DP "</tbody></table>\n";
1537
 
1538
    #
1539
    #   Packages that are in a specified release, but not described by the SBOM
1540
    #
1541
    if ( $opt_rtag_id && ($opt_sbom_id || $opt_rootpkg) )
1542
    {
1543
        print DP "<h1><a name=\"Excess\">Excess Packages from Release: $opt_rtag_id</a></h1>\n";
1544
        print DP "<table border=\"1\"><tbody>\n";
1545
        print DP "<tr>\n";
1546
        print DP th("Excess Packages",3);
1547
        print DP "</tr>\n";
1548
 
1549
        print DP "<tr>\n";
1550
        print DP th("Package");
1551
        print DP th("PVID");
1552
        print DP th("Used Package");
1553
        print DP "</tr>\n";
1554
 
1555
        my $were_found = 0;
1556
        my $not_found = 0;
1557
        foreach my $name ( sort keys %Release )
1558
        {
1559
            my @versions = keys %{$Release{$name}};
1560
            foreach my $ver ( sort @versions )
1561
            {
1562
                if (exists($Package{$name}{$ver}))
1563
                {
1564
                    $were_found++;
1565
                    next;
1566
                }
1567
                $not_found++;
1568
 
1569
                print DP "<tr>\n";
1570
                print DP $td;
1571
 
1572
                my $pv_id = $Release{$name}{$ver}{pv_id} || 'No PVID';
1573
                my $pv_id_ref = $rm_base . $pv_id . "&rtag_id=" . $opt_rtag_id;
1574
                my $pv_id_str = "<a href=\"$pv_id_ref\" TARGET=\"_blank\">$pv_id</a>";
1575
 
1576
                printf  DP "$name $ver ", $name, $ver;
1577
                print DP "</td>\n";
1578
 
1579
                print DP $td;
1580
                printf DP "Pvid: %s\n", $pv_id_str;
1581
                print DP "</td>\n";
1582
 
1583
                print DP $td;
1584
                my @pver = keys %{$Package{$name}};
1585
                if (@pver)
1586
                {
1587
                    printf  DP "<dl><dt> Uses Versions:<dt>\n";
1588
                    foreach my $ver ( sort @pver  )
1589
                    {
1590
                        my $tag = "${name}_${ver}";
1591
                        printf  DP "    <dd><a href=\"#$tag\">%s&nbsp;%s</a></dd>\n", $name, $ver;
1592
                    }
1593
                    print DP "</dl>\n";
1594
                }
1595
                else
1596
                {
1597
                    printf DP "No Versions of this package used\n"
1598
                }
1599
                print DP "</td>\n";
1600
 
1601
 
1602
                print DP "</tr>\n";
1603
            }
1604
        }
1605
 
1606
        print DP "<tr>\n";
1607
        print DP thl("Packages found in SBOM: $were_found",3);
1608
        print DP "</td>\n";
1609
        print DP "</tr>\n";
1610
 
1611
        print DP "<tr>\n";
1612
        print DP thl("Packages NOT found in SBOM: $not_found", 3);
1613
        print DP "</td>\n";
1614
        print DP "</tr>\n";
1615
 
1616
        print DP "</tbody></table>\n";
1617
    }
1618
 
1619
    #
1620
    #   Packages that are strays
1621
    #   They are not top level packages in the release
1622
    #
1623
    if ( $opt_rtag_id && ! ($opt_sbom_id || $opt_rootpkg) )
1624
    {
1625
        print DP "<h1><a name=\"Stray\">Required Packages, not part of the release</a></h1>\n";
1626
        print DP "<table border=\"1\"><tbody>\n";
1627
        print DP "<tr>\n";
1628
        print DP th("Stray Packages",3);
1629
        print DP "</tr>\n";
1630
 
1631
        print DP "<tr>\n";
1632
        print DP th("Inconsisient Package");
1633
        print DP th("PVID");
1634
        print DP th("Preferred Package");
1635
        print DP "</tr>\n";
1636
        my $stray_count = 0;
1637
 
1638
        foreach my $name ( sort keys %Package )
1639
        {
1640
 
1641
            my @versions = keys %{$Package{$name}};
1642
            foreach my $ver ( sort @versions )
1643
            {
1644
                unless (exists($Package{$name}{$ver}{stray}) && $Package{$name}{$ver}{stray} )
1645
                {
1646
                    next;
1647
                }
1648
 
1649
                #
1650
                #   Determine preferred package version(s)
1651
                #   These will be those without a 'stray' tag
1652
                #
1653
                my @preferred = ();
1654
                foreach my $pver ( keys %{$Package{$name}} )
1655
                {
1656
                    next if (exists($Package{$name}{$pver}{stray} ) && $Package{$name}{$pver}{stray} );
1657
                    push @preferred, $pver;
1658
                }
1659
 
1660
                print DP "<tr>\n";
1661
                $stray_count++;
1662
 
1663
                #
1664
                #  Package name and Used By information
1665
                #
1666
                print DP $td;
1667
                my $anchor= "usedby_${name}_${ver}";
1668
                my $tag = "${name}_${ver}";
1669
                printf  DP "<dl><dt><a name=\"$anchor\"></a><a href=\"#$tag\">%s&nbsp;%s</a> Used by:</dt>\n", $name, $ver;
1670
                foreach my $depend ( sort keys %{$Package{$name}{$ver}{usedby}} )
1671
                {
1672
                    my ($dname, $dver) = split $;, $depend;
1673
                    my $tag = "usedby_${dname}_${dver}";
1674
                    printf  DP "    <dd><a href=\"#$tag\">%s&nbsp;%s</a></dd>\n", $dname, $dver;
1675
                }
1676
                print DP "</dl>\n";
1677
                print DP "</td>\n";
1678
 
1679
 
1680
                my $pv_id = $Package{$name}{$ver}{pvid} || 'No PVID';
1681
 
1682
                my $pv_id_ref = $rm_base . $pv_id;
1683
                my $pv_id_str = "<a href=\"$pv_id_ref\" TARGET=\"_blank\">$pv_id</a>";
1684
 
1685
                print DP $td;
1686
                printf DP "Pvid: %s\n", $pv_id_str;
1687
                print DP "</td>\n";
1688
 
1689
                #
1690
                #   Insert Preferred package(s)
1691
                #
1692
                print DP $td;
1693
                print DP "<table>\n";
1694
                foreach my $pver ( sort @preferred )
1695
                {
1696
                    my $tag = "${name}_${pver}";
1697
                    printf  DP "<tr><td><a href=\"#$tag\">%s&nbsp;%s</a></td></tr>\n", $name, $pver;
1698
                }
1699
 
1700
                print DP "</table>\n";
1701
                print DP "</tr>\n";
1702
 
1703
            }
1704
        }
1705
 
1706
        print DP "<tr>\n";
1707
        print DP thl("Total Count: $stray_count", 3);
1708
        print DP "</tr>\n";
1709
        print DP "</tbody></table>\n";
1710
    }
1711
 
1712
    #
1713
    #   Packages that have components not in the release
1714
    #   They are not top level packages in the release
1715
    #
1716
    if ( $opt_rtag_id && !$opt_sbom_id )
1717
    {
1718
        print DP "<h1><a name=\"Inconsistent\">Packages in the Release, with inconsistent dependencies</a></h1>\n";
1719
        print DP "<table border=\"1\"><tbody>\n";
1720
 
1721
        print DP "<tr>\n";
1722
        print DP th("Inconsisient Package");
1723
        print DP "</tr>\n";
1724
        my $inconsistent_count = 0;
1725
 
1726
        foreach my $name ( sort keys %Package )
1727
        {
1728
 
1729
            my @versions = keys %{$Package{$name}};
1730
            foreach my $ver ( sort @versions )
1731
            {
1732
                #
1733
                #   Ignore 'stray' packages
1734
                #
1735
                next if (exists($Package{$name}{$ver}{stray}) && $Package{$name}{$ver}{stray} );
1736
 
1737
                #
1738
                #   Is it inconsitient
1739
                #
1740
                my $ok = 1;
1741
                foreach my $depend ( sort keys %{$Package{$name}{$ver}{depends}} )
1742
                {
1743
                    my ($dname, $dver) = split $;, $depend;
1744
                    if (exists($Package{$dname}{$dver}{stray}) && $Package{$dname}{$dver}{stray} )
1745
                    {
1746
                        $ok = 0;
1747
                        last;
1748
                    }
1749
                }
1750
 
1751
                next if ( $ok );
1752
                $inconsistent_count++;
1753
 
1754
                #
1755
                #   Depends On info
1756
                #
1757
 
1758
                print DP "<tr>\n";
1759
                print DP $td;
1760
                my $anchor= "${name}_${ver}";
1761
                my $tag = "usedby_${name}_${ver}";
1762
                printf  DP "<dl><dt><a name=\"$anchor\"></a><a href=\"#$tag\">%s&nbsp;%s</a> Inconsistent::</dt>\n", $name, $ver;
1763
                foreach my $depend ( sort keys %{$Package{$name}{$ver}{depends}} )
1764
                {
1765
                    my ($dname, $dver) = split $;, $depend;
1766
                    next unless (exists($Package{$dname}{$dver}{stray}) && $Package{$dname}{$dver}{stray} );
1767
 
1768
                    my $tag = "${dname}_${dver}";
1769
                    printf  DP "    <dd><a href=\"#$tag\">%s&nbsp;%s</a></dd>\n", $dname, $dver;
1770
                }
1771
                print DP "</dl>\n";
1772
                print DP "</td>\n";
1773
                print DP "<tr>\n";
1774
 
1775
            }
1776
        }
1777
 
1778
        print DP "<tr>\n";
1779
        print DP thl("Total Count: $inconsistent_count");
1780
        print DP "</tr>\n";
1781
        print DP "</tbody></table>\n";
1782
    }
1783
 
1784
    close DP;
1785
}
1786
 
1787
#-------------------------------------------------------------------------------
1788
# Function        : GenerateHTMLLodgement
1789
#
1790
# Description     : Simple document to describe packages
1791
#
1792
# Inputs          : 
1793
#
1794
# Returns         : 
1795
#
1796
sub GenerateHTMLLodgement
1797
{
1798
    my $td  = '<td style="vertical-align: top;">' . "\n";
1799
 
1800
    my $file = "${fpref}_lodgement.html";
1801
    push @create_list, $file;
1802
    open (DP, ">$file" )  || Error ("Cannot create $file");
1803
 
1804
    #
1805
    #   Package Information
1806
    #
1807
    print DP "<h1>Package Information</h1>\n";
1808
 
1809
    print DP "<table border=\"1\"><tbody>\n";
1810
    print DP "<tr>\n";
1811
    print DP th("Name, Version");
1812
    print DP th("Dependencies");
1813
    print DP "</tr>\n";
1814
    my $package_count = 0;
1815
    foreach my $name ( sort keys %Package )
1816
    {
1817
        foreach my $ver ( sort keys %{$Package{$name}} )
1818
        {
1819
            print DP "<tr>\n";
1820
            $package_count++;
1821
 
1822
            my $anchor= "${name}_${ver}";
1823
 
1824
            #
1825
            #   Package Name and description
1826
            #   Cleanup and html-ize the description string
1827
            #
1828
            my $description = $Package{$name}{$ver}{description};
1829
            $description =~ s{\n\r}{\n}g;
1830
            $description =~ s{\r}{}g;
1831
            $description =~ s{^\n+}{};
1832
            $description =~ s{&}{&amp;}g;
1833
            $description =~ s{<}{&lt;}g;
1834
            $description =~ s{>}{&gt;}g;
1835
            $description =~ s{"}{&quot;}g;
1836
            $description =~ s{\n}{<br>\n}g;
1837
 
1838
            print DP $td;
1839
            printf  DP "<a name=\"$anchor\"></a>%s,&nbsp;%s<br>\n", $name, $ver;
1840
            print DP "<dl><dd>\n";
1841
            print  DP $description;
1842
            print DP "</dd></dl>\n";
1843
            print DP "\n</td>\n";
1844
 
1845
            #
1846
            #   Depends On info
1847
            #
1848
            my $icount = 0;
1849
            print DP $td;
1850
#            printf  DP "<dl><dt><a name=\"$anchor\"></a><a href=\"#$tag\">%s&nbsp;%s</a> Depends on:</dt>\n", $name, $ver;
1851
            foreach my $depend ( sort keys %{$Package{$name}{$ver}{depends}} )
1852
            {
1853
                my ($dname, $dver) = split $;, $depend;
1854
                my $tag = "${dname}_${dver}";
1855
                printf  DP "<a href=\"#$tag\">%s&nbsp;%s</a><br>\n", $dname, $dver;
1856
                $icount++;
1857
            }
1858
            print DP "<br>\n" unless $icount;
1859
            print DP "</td>\n";
1860
 
1861
            #
1862
            #   End of Row
1863
            #
1864
            print DP "</tr>\n";
1865
        }
1866
    }
1867
    print DP "<tr>\n";
1868
    print DP thl("Total Count: $package_count", 2);
1869
    print DP "</tr>\n";
1870
 
1871
    print DP "</tbody>\n";
1872
    print DP "</table>\n";
1873
    close DP;
1874
}
1875
 
1876
#-------------------------------------------------------------------------------
1877
# Function        : extract_files
1878
#
1879
# Description     : Alternate mode of operation
1880
#                   Extract files from the generated list. This is intended to
1881
#                   be run as a seperate phase taking the 'extract' file
1882
#
1883
# Inputs          :
1884
#
1885
# Returns         : 
1886
#
1887
sub extract_files
1888
{
1889
    my @extract_order;
1890
    my %extract;
1891
    ErrorConfig( 'name'    => 'ESCROW-EXTRACT' );
1892
 
1893
    #
1894
    #   Open the file and read in data in one hit
1895
    #   This will detect file errors early
1896
    #   The lines may have arguments that are quoted.
1897
    #   Supported forms are:
1898
    #           "-tag=data"         - data may contain spaces
1899
    #           -tag=data           - data must not contain spaces
1900
    #
1901
    #
1902
    Error ("Cannot find specified file: $opt_extract")
1903
        unless ( -f $opt_extract );
1904
 
1905
    open (FH, "<$opt_extract" ) || Error ("Cannot open file");
1906
    while ( <FH> )
1907
    {
1908
        s~[\r\n]+$~~;
1909
        Verbose2 ($_);
1910
        next unless ( $_ );
1911
 
1912
        my ($view, $vcstag);
1913
        if ( m{(\s"-view=([^"]+)")|(\s-view=(\S+))} )
1914
        {
1915
            $view = $2 || $4;
1916
        }
1917
 
1918
        if ( m{(\s"-label=([^"]+)")|(\s-label=(\S+))} )
1919
        {
1920
            $vcstag = $2 || $4;
1921
        }
1922
 
1923
 
1924
        Error "Bad file format in line: $_" unless ( $view && $vcstag );
1925
        Error "Duplicate view name: $view" if ( exists $extract{$view} );
1926
        push @extract_order, $view;
1927
        $extract{$view}{vcstag} = $vcstag;
1928
    }
1929
    close FH;
1930
 
1931
    #
1932
    #   Log the file processing
1933
    #
1934
    my $lfile = "${opt_extract}.log";
1935
    Message ("Creating logfile: ${opt_extract}.log");
1936
    open (FH, ">$lfile" ) || Error ("Cannot open log file: $lfile");
1937
 
1938
    #
1939
    #   Process each entry
1940
    #
1941
    foreach my $view ( @extract_order )
1942
    {
1943
        my $vcstag = $extract{$view}{vcstag};
1944
        if ( $opt_test )
1945
        {
1946
            Verbose ("view($view) vcstag($vcstag)");
1947
            print FH "view($view) vcstag($vcstag) : TEST\n";
1948
        }
1949
        else
1950
        {
1951
            my $rv = JatsCmd ('jats_vcsrelease', '-extractfiles', "-view=$view", "-label=$vcstag", "-root=.", "-noprefix");
1952
            print FH "$view : SUCCESS\n" unless $rv;
1953
            print FH "$view : ERROR\n" if $rv;
1954
        }
1955
    }
1956
    close FH;
1957
    Message ("Results in logfile: ${opt_extract}.log");
1958
 
1959
}
1960
 
1961
 
1962
#-------------------------------------------------------------------------------
1963
#   Documentation
1964
#
1965
 
1966
=pod
1967
 
1968
=head1 NAME
1969
 
1970
escrow - Extract Escrow Build Information
1971
 
1972
=head1 SYNOPSIS
1973
 
1974
  jats escrow [options] [name version]
1975
 
1976
 Options:
1977
    -help              - brief help message
1978
    -help -help        - Detailed help message
1979
    -man               - Full documentation
1980
    -sbomid=xxx        - Specify the SBOM to process
1981
    -rtagid=xxx        - Specify the Release to process (Optional)
1982
    -rootpackage=xxx   - Specifies a root package. In conjunction with -rtagid.
1983
    -ignore=name       - Ignore packages with the specified name
1984
    -extract=fname     - Extract files from a previous run
1985
    -verbose           - Enable verbose output
1986
    -[no]patch         - Ignore/Include patches. Default:Include
1987
    -[no]test          - Reduced package scanning for test
1988
 
1989
=head1 OPTIONS
1990
 
1991
=over 8
1992
 
1993
=item B<-help>
1994
 
1995
Print a brief help message and exits.
1996
 
1997
=item B<-help -help>
1998
 
1999
Print a detailed help message with an explanation for each option.
2000
 
2001
=item B<-man>
2002
 
2003
Prints the manual page and exits.
2004
 
2005
=item B<-sbomid=xxx>
2006
 
2007
This option specifies the SBOM to process. The sbomid must be determined from
2008
Deployment Manager.
2009
 
2010
=item B<-rtagid=xxx>
2011
 
2012
This option specified an RTAG_ID that must be determined from Release Manager.
2013
 
2014
This option may be used with or without the B<-sbomid=xxx> option.
2015
 
2016
With an SBOM_ID this option specifies an RTAG_ID to process in conjunction with the SBOM.
2017
The program will determine packages that are in the Release, but not in the
2018
SBOM.
2019
 
2020
Without an SBOM_ID, this option will limit the processing to the specified
2021
release. Less information is generated. This form of the generation may be
2022
combined with B<-rootpackage=xxx> to further limit the set of packages
2023
processed.
2024
 
2025
=item B<-rootpackage=xxx>
2026
 
2027
This option can be used in conjunction with B<-rtagid=xxx> to limit the
2028
extraction to named package and all of its dependent packages. The tool will
2029
determine the required version of the package via the specified release.
2030
 
2031
=item B<-ignore=name>
2032
 
2033
All versions of the named package will be ignored. This parameter is options.
2034
It may be used multiple times.
2035
 
2036
=item B<-extract=name>
2037
 
2038
This option will process the 'extract' file created in a previous run of this
2039
program and extract source files for the package-versions found in the file.
2040
 
2041
The command will then create a log file recording packages that could ne be
2042
extracted.
2043
 
2044
This option does not not interwork with many of the other command line options.
2045
This option cannot be used in conjunction with the -rtagid, -sbomid, rootpackage
2046
and -nopatch.
2047
 
2048
=item B<-[no]patch>
2049
 
2050
This option is used ignore patches. If -nopatch is selected, then packages
2051
versions that look like a patch will be added to the ignore list.
2052
 
2053
=item B<-[no]test>
2054
 
2055
This option is used for testing. It will only process the first two OS entries
2056
in the SBOM. This speeds up processing. It does not generate a complete list of
2057
packages.
2058
 
2059
=item B<-verbose>
2060
 
2061
This option will display progress information as the program executes.
2062
 
2063
=back
2064
 
2065
=head1 DESCRIPTION
2066
 
2067
This program is a tool for extracting Escrow build information.
2068
The program has two modes of operation:
2069
 
2070
=over 8
2071
 
2072
=item 1. Generation. Generate files describing packages within an SBOM/Release/
2073
Package.
2074
 
2075
=item 2. Extraction  Supervise extraction of source trees.
2076
 
2077
=back
2078
 
2079
=head2 Generation Operations
2080
 
2081
This program has several modes of operation. The mode is determined from the
2082
command line arguments provided.
2083
 
2084
=over 8
2085
 
2086
=item   Full Escrow
2087
 
2088
This mode requires an SBOM_ID. If an RTAG_ID is also provided, then additional
2089
information will be generated.
2090
 
2091
=item   Release Escrow
2092
 
2093
If only an RTAG_ID is provided then the processing wil be limited to the
2094
packages involved in creating the specified release.
2095
 
2096
If a 'rootpackage' name is provided, then the processing is limited to
2097
packages that depend on the named package.
2098
 
2099
=item   Single Package
2100
 
2101
If a package name and a package version are specified on the command line,
2102
then the processing will be limited to the specified package and ist dependents.
2103
No release related information will be provided.
2104
 
2105
=back
2106
 
2107
The 'Full Escrow' extract is the complete operation. All others are sub-sets of
2108
this processing. The complete processing is:
2109
 
2110
=over 8
2111
 
2112
=item * Determine all the NODES in the SBOM
2113
 
2114
=item * Determine all the Base Packages for each NODE
2115
 
2116
=item * Determine all the Packages for each NODE
2117
 
2118
=item * Determine all the dependent packages for all packages encountered
2119
 
2120
=item * Generate a list of jats commands to extract the package source
2121
 
2122
=item * Generate a file describing the build order
2123
 
2124
=item * Generate a file describing the packages that cannot be built
2125
 
2126
=item * Generate an HTML file with extensive cross reference information
2127
 
2128
=over 8
2129
 
2130
=item * List of all packages with references into Release Manager
2131
 
2132
=item * List of all packages showing dependent packages
2133
 
2134
=item * List of all packages showing consumer packages
2135
 
2136
=item * List of all packages for which multiple versions are required
2137
 
2138
=item * Details of packages that are not built.
2139
 
2140
=item * Build order
2141
 
2142
=item * Build machines and built types
2143
 
2144
=item * Deployed target nodes, with references into Deployment Manager
2145
 
2146
=back
2147
 
2148
=back
2149
 
2150
This may take some time, as a typical escrow build may contain many hundreds of packages.
2151
 
2152
The program will display a list of files that have been created.
2153
 
2154
=head2 Extraction Operations
2155
 
2156
Given an 'extract' file from a previous run of this program the program will:
2157
 
2158
=over 8
2159
 
2160
=item * Parse the 'extract' file
2161
 
2162
=item * Create subdirectories for each package version within the file. This is done
2163
in such a way that no views are left in place.
2164
 
2165
=item * Create a log file showing packages that could not be extracted.
2166
 
2167
=back
2168
 
2169
=cut
2170