Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6133 dpurdie 1
########################################################################
7300 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
6133 dpurdie 3
#
4
# Module name   : jats_generate_deployable.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats build system
8
#
9
# Description   : Extracts current package version list from release manager
10
#                 based on the 'IS_DEPOLYABLE' flag in a given Release
11
#                 and copies resultant packages to release specific
12
#                 directory.
13
#                 
14
#                 Based on jats_update_release.pl and jats_gen_bom.pl but it is 
15
#                 intended to be used by the PULSE digital distribution process
16
#......................................................................#
17
 
18
require 5.008_002;
19
use File::Basename;
20
use File::Copy;
21
use File::Path;
22
use strict;
23
use warnings;
24
use JatsEnv;
25
use JatsError;
26
use JatsRmApi;
27
use ArrayHashUtils;
28
use FileUtils;
29
use DBI;
30
use Getopt::Long;
31
use Pod::Usage;                             # required for help support
32
use JSON;
33
 
34
#
35
#   Config Options
36
#
37
my $VERSION = "1.0.0";                      # Update this
38
my $opt_help = 0;
39
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
40
my $opt_rtagid;
41
my $opt_rootdir = '.';
42
my $opt_test;
43
my $opt_showFilters;
44
my @opt_addFilters;
45
my @opt_delFilters;
46
my $opt_showFiles;
47
my @opt_addFiles;
48
my @opt_delFiles;
49
 
50
 
51
#
52
#   Constants
53
#
54
my $CONFFILE = '.bomGen';
55
my $MANIFEST = 'MANIFEST.json';
56
my $TFVARS   = 'MANIFEST.tf';
57
 
58
#
59
#   Globals
60
#
61
my $DM_DB;              # Data Base Interface
62
my %bomList;            # All files in the BOM
63
my $bomInfo;            # Sbom meta data
7300 dpurdie 64
my %baseList;           # List of files in bin
6133 dpurdie 65
 
66
#
67
#   Configuration file vars
68
#
69
my @confFilters;
70
my @confFiles;
71
my %filtersUsed;
72
 
73
#-------------------------------------------------------------------------------
74
# Function        : Main
75
#
76
# Description     : Main entry point
77
#                   Parse user options
78
#
79
# Inputs          :
80
#
81
# Returns         :
82
#
83
 
84
my $result = GetOptions (
85
                "help:+"            => \$opt_help,              # flag, multiple use allowed
86
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
87
                "verbose:+"         => \$opt_verbose,           # flag
88
                "rtagid|rtag_id=s"  => \$opt_rtagid,            # Number
89
                "rootdir=s"         => \$opt_rootdir,           # string
90
 
91
                "addfilter=s"       => \@opt_addFilters,        # multiple strings
92
                "delfilter=s"       => \@opt_delFilters,        # multiple strings
93
                "showfilters"       => \$opt_showFilters,       # flag
94
 
95
                "addfiles=s"       => \@opt_addFiles,           # multiple strings
96
                "delfiles=s"       => \@opt_delFiles,           # multiple strings
97
                "showfiles"        => \$opt_showFiles,          # flag
98
 
99
                "test"              => \$opt_test,              # flag
100
                );
101
 
102
#
103
#   Process help and manual options
104
#
105
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
106
pod2usage(-verbose => 1)  if ($opt_help == 2 );
107
pod2usage(-verbose => 2)  if ($opt_help > 2);
108
 
109
ErrorConfig( 'name'    => 'GenDeploy',
110
             'verbose' => $opt_verbose );
111
 
112
#
113
#   Sanity tests
114
#
115
 
116
# Supplied rootdir must exists as a directory
117
Error("Root dir not specified") 
118
    unless defined $opt_rootdir;
119
Error("Root dir not a valid directory: ", $opt_rootdir )
120
    unless( -d $opt_rootdir );
121
 
122
    # Environment var GBE_DPKG must exists as a directory
123
Error("GBE_DPKG Environment var is not a directory")
124
    unless ( -d $ENV{GBE_DPKG} );
125
 
126
LoadFilterConfig();
127
ProcessFilterArgs();
128
 
129
#   Non Filter operations
130
#   Must supply an rtagid
131
Error("Need --rtagid", "Example: -rtagid=2362" )
132
    unless ($opt_rtagid);
133
 
134
#
135
#   This command is destined to be used in a directory where group permissions
136
#   are important. Ensure that the user is not killing group access
137
#
138
umask 0002;
139
 
140
#
141
#   Body of the processing
142
#       Save generation time into the meta data
143
my $now = time;
144
$bomInfo->{version} = "2.0.0";
145
$bomInfo->{timestamp}{epoch} = $now;
146
$bomInfo->{timestamp}{utc} = gmtime($now);
147
 
148
Message("Copying packages from $ENV{GBE_DPKG} to $opt_rootdir");
149
 
150
#
151
#   Processing
152
#
153
connectRM(\$DM_DB);
154
GetReleaseInfo();               # Get Release Metadata
155
GetPackageData();               # Get RM Data
156
RemoveDuplicates();             # Need P or D, but not both
157
CopyInNew();                    # Copy new files
158
RemoveExcess();                 # Remove files no longer required
159
GenFileData();                  # Generate file metadata
160
WriteManifest();                # Save out meta data
161
exit 0;
162
 
163
#-------------------------------------------------------------------------------
164
# Function        : GenFileData 
165
#
166
# Description     : Generate meta data on each file
167
#                   Much of this is a guess.
168
#                   Assume files look like:
169
#                   
170
#                       VIXcryptoKeyManager-1.0.2061.cr-WIN32.exe
171
#                       erg-pkgmnt_1.0.3010.cr_UBUNTU16_P.deb
172
#                       erg-pkgmnt_1.0.3010.cr_RHEL7_P.rpm
173
#                       xxxxxx.sh - bit trickier
174
#
175
# Inputs          : None
176
#
177
# Returns         : Populates $bomInfo
178
#
179
sub GenFileData
180
{
181
    my @elist;
182
    my @edup;
183
    foreach my $file (sort keys %bomList)
184
    {
185
        my $data;
186
        my $alias;
187
 
188
        $bomList{$file}{version} =~ m~(.*)\.([a-z]+)$~;
189
        my $pvfull = $1;
190
        my $proj = $2;
191
        my $pv = $pvfull;
192
        $pv =~ s~\.\d+$~~;
193
 
194
        if ($file =~ m~^(.*)-(.*)\.(.*)-(WIN.*)\.(exe)$~i)
195
        {
196
            $data->{name} = $1;
197
            $data->{version} = $2;
198
            $data->{prj} = $3;
199
            $data->{arch} = $4;
200
            $data->{type} = $5;
201
        }
202
        elsif ( $file =~ m~^(.*)_(.*)\.([^_]+)_(.*)\.(deb|tgz|rpm)$~i)
203
        {
204
            $data->{name} = $1;
205
            $data->{version} = $2;
206
            $data->{prj} = $3;
207
            $data->{arch} = $4;
208
            $data->{type} = $5;
209
            $data->{arch} =~ s~_[PD]~~;
210
        }
211
        elsif ( $file =~ m~^(.*)-($pv)\.(.*)\.(rpm)$~i)
212
        {
213
            # COTS package
214
            $data->{name} = $1;
215
            $data->{version} = $2;
216
            $data->{arch} = $3;
217
            $data->{type} = $4;
218
            $data->{prj} = $proj;
219
        }
220
        elsif ( $file =~ m~^(.*)_($pv)\.(tgz)$~i)
221
        {
222
            # COTS package
223
            $data->{name} = $1;
224
            $data->{version} = $2;
225
            $data->{arch} = 'UNKNOWN';
226
            $data->{type} = $3;
227
            $data->{prj} = $proj;
228
        }
229
        elsif ( $file =~ m~^(.*)-($pv)\.(.*)\.(deb)$~i)
230
        {
231
            # COTS package
232
            $data->{name} = $1;
233
            $data->{version} = $2;
234
            $data->{arch} = $3;
235
            $data->{type} = $4;
236
            $data->{prj} = $proj;
237
        }
238
        elsif ( $file =~ m~^(.*)\.(sh|zip|msi|tar\.gz)$~i)
239
        {
240
            $data->{name} = $1;
241
            $data->{arch} = 'NOARCH';
242
            $data->{type} = $2;
243
 
244
            $data->{version} = $pvfull;
245
            $data->{prj} = $proj;
246
        }
247
 
248
        unless ($data && $data->{name} && $data->{prj} && $data->{type}) {
249
            push @elist, $file;
250
            next;
251
        }
252
        $data->{fullname} = $file;
253
 
254
        #
255
        #   Create a nice alias
256
        #       ERG -> VIX  (not done)
257
        #       All lowercase
258
        #
259
        $alias = join ('.', $data->{name}, $data->{prj}, $data->{type});
260
        $alias = lc ($alias);
261
        #$alias =~ s~^erg~vix~;
262
        #$alias =~ s~^vix~vix-~;
263
        #$alias =~ s~^vix--~vix-~;
264
        push (@edup, join( ' : ', $alias, $file ,$bomInfo->{files}{$alias}{fullname})  ) if exists $bomInfo->{files}{$alias};
265
 
266
        delete $data->{type};
267
        $bomInfo->{files}{$alias} = $data;
268
    }
269
 
270
    ReportError ("Cannot extract file metadata from:", @elist)  if (@elist);
271
    ReportError ("Duplicate aliases for:", @edup)  if (@edup);
272
    ErrorDoExit();
273
}
274
 
275
#-------------------------------------------------------------------------------
276
# Function        : CopyInNew 
277
#
278
# Description     : Copy in new files
279
#                   Don't copy in files that already exist - assume that the
280
#                   files don't chnage without a chnage to the file name
281
#
282
# Inputs          : 
283
#
284
# Returns         : 
285
#
286
sub CopyInNew
287
{
288
    #
289
    #   Ensure the output directory exists
290
    #
291
    if ( ! -d $opt_rootdir )
292
    {
293
        if ( defined($opt_test) )
294
        {
295
            Message("mkdir $opt_rootdir");
296
        }
297
        else
298
        {
299
            eval { mkpath($opt_rootdir) };
300
            Error("Failed to make project directory tree $opt_rootdir") if ( $@ || ! -d $opt_rootdir );
301
        }
302
    }
303
 
304
    #
7300 dpurdie 305
    #   Generate a list of all files in the directory
306
    #
307
    foreach my $file ( glob("$opt_rootdir/*") ) {
308
        $baseList{$file}{data} = 1;
309
    }
310
 
311
    #
6133 dpurdie 312
    #   Determine the files to be transferred
313
    #
314
    my @filelist;
315
    foreach my $file ( keys %bomList)
316
    {
317
        push (@filelist, $file) unless ( -f "$opt_rootdir/$file" );
318
    }
319
 
320
    #
321
    #   Perform the actual copy
322
    #
323
    if ( @filelist )
324
    {
325
        #Message("Copying files for package $PKG_NAME version $PKG_VERSION");
326
        if ( defined($opt_test) )
327
        {
328
            Message( map("$_...", @filelist) );
329
        }
330
        else
331
        {
332
            eval { mkpath($opt_rootdir) };
333
            Error("Failed to make destination directory") if ( $@ || ! -d $opt_rootdir );
334
            foreach my $file ( @filelist )
335
            {
336
                Verbose("Copy: $file...");
337
 
338
                my $srcFile = $bomList{$file}{path};
339
                if ( ! copy($srcFile, $opt_rootdir) )
340
                {
341
                    Warning("Failed to copy $file ($!)");
342
                }
343
            }
344
        }
345
    }
346
}
347
 
348
#-------------------------------------------------------------------------------
349
# Function        : RemoveExcess 
350
#
351
# Description     : Remove excess files from the output directory 
352
#
353
# Inputs          : 
354
#
355
# Returns         : 
356
#
357
sub RemoveExcess
358
{
359
    my @filelist;
360
    my %keepList = map { $_ => 1 } @confFiles;
361
 
362
    #
363
    #   Find all files in the output directory
364
    #   Use the 'keepList' so that we don't pickup files that should
365
    #   be in the directory. README.md, MANIFEST ...
366
    #
367
    foreach my $srcPath ( glob("$opt_rootdir/*") )
368
    {
369
        my $dstFile = basename($srcPath);
370
        next if exists $keepList{$dstFile};
371
        next unless ( -f $srcPath );
372
 
373
        push (@filelist, $dstFile) unless (exists $bomList{$dstFile} );
374
    }
375
 
376
    if ( @filelist)
377
    {
378
        Message ("Delete execess files", @filelist );
379
        unless ( defined($opt_test) )
380
        {
381
            foreach my $file ( @filelist )
382
            {
383
                Verbose("Delete: $file...");
384
                if ( unlink("$opt_rootdir/$file") ne 1 )
385
                {
386
                    Warning("Failed to delete: $file. ($!)");
387
                }
388
            }
389
        }
390
    }
7300 dpurdie 391
 
392
    #
393
    #   Report changed files
394
    #   Generate a list of all files in the directory
395
    #
396
    foreach my $file ( glob("$opt_rootdir/*") ) {
397
        $baseList{$file}{data} |= 2;
398
    }
399
 
400
    #
401
    #   Determined added, removed and replaced
402
    #       
403
    #
404
    my (@replaced, @added, @removed, @unchanged, %newList);
405
    foreach my $entry ( keys %baseList )
406
    {
407
        (my $key = $entry) =~ s~\d+~z~g;
408
        $baseList{$entry}{key} = $key;
409
 
410
        (my $name = $entry) =~ s~^\./~~;
411
        $newList{$key}{$baseList{$entry}{data}} = $entry;
412
    }
413
 
414
    foreach my $key ( sort keys %newList )
415
    {
416
        if (exists $newList{$key}{1} && exists $newList{$key}{2}  ) {
417
            push @replaced, "$newList{$key}{1}   =>   $newList{$key}{2}";
418
        } elsif (exists $newList{$key}{1}) {
419
            push @removed, $newList{$key}{1};
420
        } elsif (exists $newList{$key}{2}) {
421
            push @added, $newList{$key}{2};
422
        } elsif (exists $newList{$key}{3}) {
423
            push @unchanged, $newList{$key}{3};
424
        }
425
    }
426
 
427
    Message ("Unchanged: " .(@unchanged ? scalar(@unchanged ) : 'None') );
428
    Message ("Replaced: " . (@replaced ?  scalar(@replaced )  : 'None'), @replaced);
429
    Message ("Added: " .    (@added    ?  scalar(@added )     : 'None'), @added);
430
    Message ("Removed: " .  (@removed  ?  scalar(@removed )   : 'None'), @removed);
6133 dpurdie 431
}
432
 
433
#-------------------------------------------------------------------------------
434
# Function        : RemoveDuplicates 
435
#
436
# Description     : Scan the BOM file list and remove duplicate installers
437
#                   Duplicate installers are that that have both a P and a D
438
#                   flavor of the installer
439
#                   
440
#                   This test has some nasty built-in knowledge (assumtions)
441
#                   It assumes that:
442
#                       Windows installers are only created for one flavor
443
#                           Don't need to worry about windoes installers
444
#                       Non windows installers are of the form:
445
#                           Name_Architecture_Type.deb    
446
#
447
# Inputs          : 
448
#
449
# Returns         : 
450
#
451
sub RemoveDuplicates
452
{
453
    my %baseNames;
454
    foreach my $file ( keys %bomList)
455
    {
456
        #
457
        #   Only process files that are of the expected form
458
        #       ie: erg-udcrypt_1.0.3043.vss_UBUNTU16_P.deb
459
        #
460
        if( $file =~ m~(.*)_([PD])(\.(deb|rpm|tgz))$~ )
461
        {
462
            my $base=$1;
463
            my $type=$2;
464
            my $suf=$3;
465
 
466
            if (exists $baseNames{$base} )
467
            {
468
                my $debugName = $base . '_D' . $suf;  
469
                Verbose("Remove debug installer: $file. Kill: $debugName");
470
                delete $bomList{$debugName};
471
            }
472
 
473
            $baseNames{$base} = $type;
474
        }
475
    }
476
}
477
 
478
#-------------------------------------------------------------------------------
479
# Function        : LoadFilterConfig  
480
#
481
# Description     : Load Filter Config
482
#                   Retain filter config for future reference 
483
#
484
# Inputs          : 
485
#
486
# Returns         : 
487
#
488
sub LoadFilterConfig
489
{
490
    if ( -f "$opt_rootdir/$CONFFILE" )
491
    {
492
        Message("Loading Config File");
493
 
494
        local $/;
495
        open(my $fh, "<$opt_rootdir/$CONFFILE") || Error("Failed to open config file");
496
        my $json_text = <$fh>;
497
        my $perl_scalar = decode_json( $json_text );
498
        Error ("Invalid format in Config file")
499
            unless (ref($perl_scalar->{filters}) eq 'ARRAY');
500
 
501
        push (@confFilters, @{$perl_scalar->{filters}});
502
        push (@confFiles, @{$perl_scalar->{keptfiles}}) if exists ($perl_scalar->{keptfiles});
503
        close($fh);
504
    }
505
}
506
 
507
#-------------------------------------------------------------------------------
508
# Function        : ProcessFilterArgs
509
#
510
# Description     : Process the filter based arguments 
511
#
512
# Inputs          : 
513
#
514
# Returns         : 
515
#
516
sub ProcessFilterArgs
517
{
518
    my $filterArgSeen;
519
    my $writeConf;
520
 
521
 
522
    unless ( @confFilters )
523
    {
524
        Error("No Filters defined.", "Add filters before creating BOM");
525
    }
526
 
527
    if ( @opt_addFilters )
528
    {
529
        Message ("Adding command line filters to the release config file");
530
        foreach my $element (@opt_addFilters) {
531
            UniquePush (\@confFilters, $_ ) foreach  ( split(/,/, $element));
532
        }
533
        $writeConf = 1;
534
    }
535
 
536
    if ( @opt_delFilters )
537
    {
538
        Message ("Deleting command line filters to the release config file");
539
        foreach my $element (@opt_delFilters) {
540
            ArrayDelete (\@confFilters, $_ ) foreach  ( split(/,/, $element));
541
        }
542
        $writeConf = 1;
543
    }
544
 
545
    if ( @opt_addFiles )
546
    {
547
        Message ("Adding command line files to the release config file");
548
        foreach my $element (@opt_addFiles) {
549
            UniquePush (\@confFiles, $_ ) foreach  ( split(/,/, $element));
550
        }
551
        $writeConf = 1;
552
    }
553
 
554
    if ( @opt_delFiles )
555
    {
556
        Message ("Deleting command line files to the release config file");
557
        foreach my $element (@opt_delFiles) {
558
            ArrayDelete (\@confFiles, $_ ) foreach  ( split(/,/, $element));
559
        }
560
        $writeConf = 1;
561
    }
562
 
563
    #
564
    #   Save filter information
565
    #
566
    if ( $writeConf && ! defined($opt_test) )
567
    {
568
        Verbose ("Write config file");
569
 
570
        #
571
        #   Add known files
572
        #
573
        UniquePush (\@confFiles, $CONFFILE, $MANIFEST, $TFVARS);
574
 
575
        my $config;
576
        push @{$config->{filters}},@confFilters;
577
        push @{$config->{keptfiles}},@confFiles;
578
        FileCreate ("$opt_rootdir/$CONFFILE", to_json( $config, { ascii => 1, pretty => 1 }));
579
    }
580
 
581
    #
582
    #   Display information to the user
583
    #
584
    if ($opt_showFilters)
585
    {
586
        Message ("Configured Filters",@confFilters );
587
        $filterArgSeen = 1;
588
    }
589
 
590
    if ($opt_showFiles)
591
    {
592
        Message ("Configured Files. Keep:",@confFiles );
593
        $filterArgSeen = 1;
594
    }
595
 
596
 
597
    #
598
    #   Terminate program on any filter operations
599
    #
600
    exit 0 if ( $writeConf || $filterArgSeen);
601
}
602
 
603
#-------------------------------------------------------------------------------
604
# Function        : WriteManifest 
605
#
606
# Description     : Save the filter config file if required
607
#
608
# Inputs          : 
609
#
610
# Returns         : 
611
#
612
sub WriteManifest
613
{
614
    return if defined($opt_test);
615
 
616
    #
617
    #   Create JSON metadata
618
    #
619
    Verbose ("Write JSON Manifest");
620
    my $jsonString = to_json( $bomInfo, { ascii => 1, pretty => 1, canonical => 1 } ); 
621
    FileCreate ($opt_rootdir . '/' . $MANIFEST, $jsonString);
622
 
623
    #
624
    #   Create Terraform data
625
    #       Note: Terraform variable cannot have a '.' in them
626
    #   
627
    my @tfData2;
628
 
629
    push @tfData2, "// Terraform variable definitions to map clean package name to full file name";
630
    push @tfData2, "variable vixFileName {";
631
    push @tfData2, "    type = \"map\"";
632
    push @tfData2, "    default = {" ;
633
 
7300 dpurdie 634
    foreach my $item ( sort keys %{$bomInfo->{files}} )
6133 dpurdie 635
    {
636
        push @tfData2, "        \"". $item  ."\" = \"" .$bomInfo->{files}{$item}{fullname} ."\"";
637
    }
638
 
639
    push @tfData2, "    }" ;
640
    push @tfData2, "}" ;
641
 
642
    FileCreate ($opt_rootdir . '/' . $TFVARS, @tfData2);
643
 
644
 
645
}
646
 
647
#-------------------------------------------------------------------------------
648
# Function        : GetReleaseInfo 
649
#
650
# Description     : Get Release Meta Data
651
#
652
# Inputs          : 
653
#
654
# Returns         : Will exit on error 
655
#
656
sub GetReleaseInfo
657
{
658
    my $m_sqlstr = "SELECT p.PROJ_ID, rt.rtag_id, p.PROJ_NAME, rt.RTAG_NAME" .
659
                    " FROM release_tags rt, PROJECTS p" .
660
                    " WHERE p.PROJ_ID = rt.PROJ_ID" .
661
                    " and rt.RTAG_ID = " . $opt_rtagid;
662
 
663
    my $sth = $DM_DB->prepare($m_sqlstr);
664
    if ( defined($sth) )
665
    {
666
        if ( $sth->execute( ) )
667
        {
668
            if ( $sth->rows )
669
            {
670
                while ( my ( $proj_id, $xx, $pname, $rname ) = $sth->fetchrow_array )
671
                {
672
                    my $data;
673
                    $data->{product_id} = $proj_id;
674
                    $data->{product_name} = $pname;
675
                    $data->{release_rtagid} = $opt_rtagid;
676
                    $data->{release_name} = $rname;
677
                    push @{$bomInfo->{release}}, $data;
678
                }
679
            }
680
            else
681
            {
682
                Error("GetReleaseInfo: No rtagid found for " . $opt_rtagid);
683
            }
684
            $sth->finish();
685
        }
686
        else
687
        {
688
            Error("GetReleaseInfo: Execute failure", $sth->errstr(), $m_sqlstr );
689
        }
690
    }
691
    else
692
    {
693
        Error("GetReleaseInfo: Prepare failure", $sth->errstr(), $m_sqlstr );
694
    }
695
}
696
 
697
#-------------------------------------------------------------------------------
698
# Function        : GetPackageData 
699
#
700
# Description     : Extract data from RM based on the provided rtag_id
701
#
702
# Inputs          : 
703
#
704
# Returns         : 
705
#
706
sub GetPackageData
707
{
708
    my $m_sqlstr =  "SELECT p.PKG_NAME, pv.PKG_VERSION" .
709
                    " FROM package_versions pv, RELEASE_CONTENT rc, PACKAGES p" .
710
                    " WHERE rc.rtag_id = " . $opt_rtagid .
711
                    " AND rc.pv_id = pv.pv_id" .
712
                    " and p.PKG_ID = pv.pkg_id" .
713
                    " and pv.IS_DEPLOYABLE = 'Y'";
714
#                    " and ( pv.IS_DEPLOYABLE = 'Y' or upper( p.PKG_NAME) like 'ERG%' or upper( p.PKG_NAME) like 'VIX%' )";
715
 
716
    my ( $PKG_NAME, $PKG_VERSION );
717
    my $sth = $DM_DB->prepare($m_sqlstr);
718
    if ( defined($sth) )
719
    {
720
        if ( $sth->execute( ) )
721
        {
722
            if ( $sth->rows )
723
            {
724
                while ( ( $PKG_NAME, $PKG_VERSION ) = $sth->fetchrow_array )
725
                {
726
                    Verbose ("Deployable: $PKG_NAME, $PKG_VERSION");
727
                    my $pkgDir = "$ENV{GBE_DPKG}/$PKG_NAME";
728
                    my $srcDir = "$ENV{GBE_DPKG}/$PKG_NAME/$PKG_VERSION";
729
                    my $dstDir = $opt_rootdir;
730
 
731
                    if ( -d "$srcDir" )
732
                    {
733
                        my $foundFiltered = 0;
734
 
735
                        # for each of the filter rules we glob the rule in the src pkg/version dir
736
                        # and if any of the globbed files dont exist in the dst dir add it to the 
737
                        # the filelist array of files to copy
738
                        foreach my $filter ( @confFilters )
739
                        {
740
                            foreach my $srcPath ( glob("$srcDir/$filter") )
741
                            {
742
                                next unless ( -f $srcPath );
743
                                $foundFiltered = 1;
744
                                $filtersUsed{$filter} = 1;
745
                                my $dstFile = basename($srcPath);
746
                                my $srcFile = $srcPath;
747
                                $srcFile =~ s~^$srcDir/~~;
748
                                $bomList{$srcFile}{path} = $srcPath;
749
                                $bomList{$srcFile}{package} = $PKG_NAME;
750
                                $bomList{$srcFile}{version} = $PKG_VERSION;
751
                            }
752
                        }
753
 
754
                        # if no files found using filters then issue warning
755
                        Warning("No Files found for Package Version $PKG_NAME/$PKG_VERSION using supplied filters") 
756
                            unless ( $foundFiltered );
757
 
758
                        if ($foundFiltered)
759
                        {
760
                            $bomInfo->{packages}{$PKG_NAME} = $PKG_VERSION;
761
                        }
762
                    }
763
                    elsif ( ! -d "$pkgDir" )
764
                    {
765
                        # if srcDir and pkgDir dont exist then package is not in dpkg_archive so display message
766
                        Warning("Skipping Package $PKG_NAME/$PKG_VERSION as it does not exist in dpkg_archive");
767
                    }
768
                    else
769
                    {
770
                        # However if srcDir does not exist but pkgDir does exist then the package version is missing which maybe an issue
771
                        Warning("Missing Version $PKG_VERSION for Package $PKG_NAME in dpkg_archive");
772
                    }
773
                }
774
 
775
                #
776
                #   Report filter elements that where not used.
777
                #
778
                my @notUsed;
779
                foreach my $filter ( @confFilters )
780
                {
781
                    next if ( exists $filtersUsed{$filter} );
782
                    push @notUsed, $filter
783
                }
784
                Warning ("Unused filter rules:", @notUsed )
785
                    if ( @notUsed );
786
 
787
            }
788
            else
789
            {
790
                Error("No Packages for rtagid: $opt_rtagid");
791
            }
792
            $sth->finish();
793
        }
794
        else
795
        {
796
            Error("Execute failure", $sth->errstr(), $m_sqlstr );
797
        }
798
    }
799
    else
800
    {
801
        Error("Prepare failure", $sth->errstr(), $m_sqlstr );
802
    }
803
}
804
 
805
#-------------------------------------------------------------------------------
806
#   Documentation
807
#
808
 
809
=pod
810
 
811
=for htmltoc    DEPLOY::generate_deployable
812
 
813
=head1 NAME
814
 
815
jats_generate_deployable - Extracts current package version list from Release Manager RtagId
816
                and copy resultant packages to a specific directory.
817
 
818
=head1 SYNOPSIS
819
 
820
  jats generate_deployable [options]
821
 
822
 Options:
823
    -help                   - Brief help message
824
    -help -help             - Detailed help message
825
    -man                    - Full documentation
826
    -rtagid=xxx             - Specify the Release Manager RtagId to process
827
    -rootdir=xxx            - Specifies the root of the releases directory
828
 
829
    -showfilters            - Display current filter set and exit
830
    -addfilter=xxx[,yyy]    - Add a new filter to the existing filter set
831
    -delfilter=xxx[,yyy]    - Delete a filter from the existing filter set
832
 
833
    -showfiles              - Display current kept file set and exit
834
    -addfiles=xxx[,yyy]     - Add a new file to the kept file set
835
    -delfiles=xxx[,yyy]     - Delete a file from the kept file set
836
 
837
    -test                   - Just log actions without copying files.
838
    -verbose                - Enable verbose output
839
 
840
=head1 OPTIONS
841
 
842
=over 8
843
 
844
=item B<-help>
845
 
846
Print a brief help message and exits.
847
 
848
=item B<-help -help>
849
 
850
Print a detailed help message with an explanation for each option.
851
 
852
=item B<-man>
853
 
854
Prints the manual page and exits.
855
 
856
=item B<-rtagid=xxx>
857
 
858
This option specifies one or more RTAG_ID's to use as the source of packages that will be copied.
859
The ID will be used to get a unique list of package/versions that can be copied from dpkg_archive.
860
 
861
This option is Mandatory, for non-filter command.
862
 
863
=item B<-rootdir=xxx>
864
 
865
This option specifies the root directory where the packages will be copied to.
866
 
867
The specified directory must exist.
868
 
869
The default value is the current directory.
870
 
871
=item B<-showfilters>
872
 
873
This option will display the current filter set. If it is combined with another filter operation 
874
then the other operations will be performed before the display.
875
 
876
=item B<-addFilter=xxx[,yyy]>
877
 
878
This option allows new filters to be added to the set of filters. This
879
option can be specified multiple times.
880
 
881
This option specifies a comma separated list of shell wildcard filter rule that
882
will be used to determine which files are copied from package version directory in
883
GBE_DPKG to the release directory. This can be supplied multiple times to
884
specify rules for copying.
885
 
886
Filters must be added the first time this command is run against a release 
887
and packages are copied to the project/release directory.  These values are then written to a 
888
config file in the release directory so the same values can be used on subsequent runs.  
889
In these subsequent runs this option need not be specified as the config items will be used, however
890
they can be changed by specifying them again on the command line and the config will be re-written.
891
 
892
The values of these will depend on what builds are required for each project.  Some examples are
893
    --filter='*-WIN32.exe,*.deb'
894
 
895
=item B<-delFilter=xxx[,yyy]>
896
 
897
This option deletes one or more filter rules from an existing set of filters. This
898
option can be specified multiple times.
899
 
900
=item B<-showfiles>
901
 
902
This option will display the current file set. If it is combined with another file operations
903
then the other operations will be performed before the display.
904
 
905
=item B<-addFile=xxx[,yyy]>
906
 
907
This option allows new files to be added to the set of kept files. This
908
option can be specified multiple times.
909
 
910
This option specifies a comma separated list of file names (No wild cards) that
911
will be used to specify a list of files that shold be kept in the directory. These
912
files do not form a part of the manifest, but are not deleted by the tool.
913
 
914
=item B<-delFile=xxx[,yyy]>
915
 
916
This option deletes one or more files from the set of kept files. This
917
option can be specified multiple times.
918
 
919
=item B<-test>
920
 
921
This option will display what would be copied without actually copying anything
922
 
923
=item B<-verbose>
924
 
925
This option will display progress information as the program executes.
926
 
927
=back
928
 
929
=head1 DESCRIPTION
930
 
931
This program is used to update a Distribution 'bin' directory with the versions of
932
packages as indicated by the specified Deployment Manager SBoms.
933
 
934
There are two modes of operation: Filter modification operations and BOM creation.
935
 
936
In 'Filter modification' mode the current filter set will be updated and the program will
937
exit.
938
 
939
In BOM creation mode an sbomid must be provided.
940
 
941
The rtagid is used to get all the required information from Release Manager about
942
which package version are required, as well as the project name and release name.
943
 
944
 
945
In addition to using Release Manager information to determine which Package/Versions are
946
required to be copied this script also uses a set of shell wildcard filters that are
947
used to determine which files are actually copied when invoked.
948
 
949
The filter rules can be supplied on the command line if available read from a 
950
configuration file saved in the output diretory the last time the script was run
951
on this release directory.
952
 
953
One or more filter rules must be specified on the command line the first time this command 
954
is run against a project release directory.  These filter values are then written to a config
955
file in the output directory so the same values can be used on subsequent runs.  
956
In subsequent runs the filter rules will be loaded from the config file and need not be specified 
957
on the command line, however the filter rules in the config file can be changed by specifying 
958
them again on the command line and the config will be re-written.
959
 
960
=cut
961