Subversion Repositories DevTools

Rev

Rev 361 | Rev 4086 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
341 dpurdie 1
########################################################################
2
# Copyright ( C ) 2010 ERG Limited, All rights reserved
3
#
4
# Module name   : jats_update_release.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 Deployment Manager
10
#                 SBom(s) and copies resultant packages to release specific
11
#                 directory.
12
#......................................................................#
13
 
14
require 5.008_002;
15
use File::Basename;
16
use File::Copy;
17
use File::Path;
18
use strict;
19
use warnings;
20
use JatsEnv;
21
use JatsError;
22
use JatsSystem;
23
use JatsRmApi;
3987 dpurdie 24
use ArrayHashUtils;
341 dpurdie 25
use DBI;
26
use Getopt::Long;
27
use Pod::Usage;                             # required for help support
28
use Storable qw (dclone);
29
 
30
#
31
#   Config Options
32
#
33
my $VERSION = "1.0.0";                      # Update this
34
my $opt_help = 0;
35
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
36
my @opt_sbom_ids;
37
my $opt_rootdir;
38
my @opt_filters;
39
my $opt_projectdir;
40
my $opt_releasedir;
41
my $opt_test;
3987 dpurdie 42
my @opt_addFilters;
43
my @opt_delFilters;
341 dpurdie 44
 
45
#
46
#   Constants
47
#
48
my $CONFFILE = ".updateRelease";
49
 
50
#
51
#   Data Base Interface
52
#
53
my $DM_DB;
54
 
55
 
56
#
57
#   The directory we copy to.
58
#
59
my $projectDestDir;
60
 
61
#
62
#   Configuration file vars
63
#
64
my @confFilters;
65
my $writeConf = 0;
3987 dpurdie 66
my %filtersUsed;
341 dpurdie 67
 
68
# -------------------------------------------------------------------------
69
sub GetYesNo
70
#
71
# -------------------------------------------------------------------------
72
{
73
    my ($question) = @_;
74
    my ($u_tmp) = "";
75
    Question ("$question, (default: y) [y,n]: ");
76
 
77
    while ( <STDIN> )
78
    {
79
        $u_tmp = $_;
80
        chomp($u_tmp);
81
 
82
        return 1
83
            if ( "$u_tmp" eq "" );
84
 
85
        if( $u_tmp =~ /[yn]{1}/i )
86
        {
87
            return ( "$u_tmp" eq "y" );
88
        }
89
        else
90
        {
91
            Question("Please re-enter response? (default: y) [y,n]: ");
92
        }
93
    }
94
}
95
 
96
 
97
#==============================================================================
98
#   getSbomProjectAndRelease
99
#   Returns the Project Name and Release for supplied SBoms
100
#   Calls Error and exists on error condition
101
#==============================================================================
102
sub getSbomProjectAndRelease
103
{
104
    my ( $DB, $sboms ) = @_;
105
    my ( $bom, $proj, $rel, $lastProj, $lastRel );
106
 
107
    Error("getSbomProjectAndRelease: SBom Parameter Error, must pass array") if ( ref($sboms) ne "ARRAY" );
108
 
109
    # create a hash of sbom values so we can test after if any sboms could not be found
110
    my %sbomIdx = map { $_ => 1 } @{$sboms};
111
 
112
    my $m_sqlstr = "SELECT   boms.bom_id, dm_projects.proj_name, branches.branch_name " .
113
                   "FROM     deployment_manager.boms, deployment_manager.branches, deployment_manager.dm_projects " .
114
                   "WHERE    branches.branch_id = boms.branch_id AND " .
115
                   "         dm_projects.proj_id = branches.proj_id AND " .
116
                   "         boms.bom_id " . ( $#{$sboms} == 0 ? "= " . $sboms->[0] : "IN ( " . join(",", @{$sboms}) . ")" );
117
 
118
    my $sth = $DB->prepare($m_sqlstr);
119
    if ( defined($sth) )
120
    {
121
        if ( $sth->execute( ) )
122
        {
123
            if ( $sth->rows )
124
            {
125
                while ( ( $bom, $proj, $rel ) = $sth->fetchrow_array )
126
                {
127
                    if ( ! defined($proj) )
128
                    {
129
                        Error("getSbomProjectAndRelease: NULL Project Name from Deployment Manager Sbom : $bom");
130
                    }
131
                    elsif ( ! defined($rel) )
132
                    {
133
                        Error("getSbomProjectAndRelease: NULL Release Tag Name from Deployment Manager Sbom : $bom");
134
                    }
135
                    elsif ( defined($lastProj) && $proj ne $lastProj )
136
                    {
137
                        Error("getSbomProjectAndRelease: SBom Id [$bom] is in a different project [$proj]", "All SBom Id's must all be part of the same Deployment Manager Project");
138
                    }
139
                    elsif ( defined($lastRel) && $rel ne $lastRel )
140
                    {
141
                        Error("getSbomProjectAndRelease: SBom Id [$bom] is in a different project release [$rel]", "All SBom Id's must all be part of the same Deployment Manager Project Release");
142
                    }
143
                    $lastProj = $proj;
144
                    $lastRel  = $rel;
145
 
146
                    # delete sbom from idx, any remaining after loop will indicate we have an sbom that could not found
147
                    delete($sbomIdx{$bom});
148
                }
149
 
150
                my @sbomsNotFound = keys %sbomIdx;
151
                if ( $#sbomsNotFound > -1 )
152
                {
153
                    Error("getSbomProjectAndRelease: Could not find details for the following SBomId(s) " . join(",", @sbomsNotFound) );
154
                }
155
            }
156
            else
157
            {
158
                Error("getSbomProjectAndRelease: No SBom(s) found for Deployment Manager SBomId(s) " . join(",", @{$sboms}) );
159
            }
160
            $sth->finish();
161
        }
162
        else
163
        {
164
            Error("getSbomProjectAndRelease: Execute failure", $m_sqlstr );
165
        }
166
    }
167
    else
168
    {
169
        Error("getSbomProjectAndRelease: Prepare failure", $m_sqlstr );
170
    }
171
 
172
    return ( $lastProj, $lastRel );
173
}   # getSbomProjectAndRelease
174
 
175
 
176
#-------------------------------------------------------------------------------
177
# Function        : Main
178
#
179
# Description     : Main entry point
180
#                   Parse user options
181
#
182
# Inputs          :
183
#
184
# Returns         :
185
#
186
 
187
my $result = GetOptions (
188
                "help:+"            => \$opt_help,              # flag, multiple use allowed
189
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
190
                "verbose:+"         => \$opt_verbose,           # flag
191
                "sbomid|sbom_id=s"  => \@opt_sbom_ids,          # multiple numbers
192
                "filter=s"          => \@opt_filters,           # multiple strings
3987 dpurdie 193
                "addfilter=s"       => \@opt_addFilters,        # multiple strings
194
                "delfilter=s"       => \@opt_delFilters,        # multiple strings
341 dpurdie 195
                "rootdir=s"         => \$opt_rootdir,           # string
196
                "projectdir=s"      => \$opt_projectdir,        # string
197
                "releasedir=s"      => \$opt_releasedir,        # string
198
                "test"              => \$opt_test,              # flag
199
                );
200
 
201
#
202
#   Process help and manual options
203
#
204
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
205
pod2usage(-verbose => 1)  if ($opt_help == 2 );
206
pod2usage(-verbose => 2)  if ($opt_help > 2);
207
 
208
 
209
ErrorConfig( 'name'    => 'updateRelease',
210
             'verbose' => $opt_verbose );
211
 
212
#
213
#   Sanity tests
214
#
215
 
216
# Must supply at least one SbomId and the rootdir
217
if ( $#opt_sbom_ids == -1 || ! defined($opt_rootdir) )
218
{
219
    Error("Need -sbomid and -rootdir", "Example: -sbomid=2362 -rootdir=/export/devl/releases" ) ;
220
}
221
# Supplied rootdir must exists as a directory
222
elsif ( ! -d $opt_rootdir )
223
{
224
    Error("Root dir $opt_rootdir not a valid directory");
225
}
226
# Environment var GBE_DPKG must exists as a directory
227
elsif ( ! -d $ENV{GBE_DPKG} )
228
{
229
    Error("GBE_DPKG Environment var is not a directory") ;
230
}
231
# projectdir and releasedir must be specified together or not at all
232
elsif ( (  defined($opt_projectdir) && !defined($opt_releasedir) ) ||
233
        ( !defined($opt_projectdir) &&  defined($opt_releasedir) ) )
234
{
235
    Error("Both -projectdir and -releasedir are required if either one is specified") ;
236
}
237
# if projectdir is specified it must be a valid dir in the rootdir
238
elsif ( defined($opt_projectdir) && ! -d "$opt_rootdir/$opt_projectdir" )
239
{
240
    Error("The specified project directory does not exist in the root directory");
241
}
242
# if releasedir is specified it must be a valid dir in the projectdir
243
elsif ( defined($opt_releasedir) && ! -d "$opt_rootdir/$opt_projectdir/$opt_releasedir" )
244
{
245
    Error("The specified project/release directory does not exist in the root directory");
246
}
247
 
248
 
249
# Now lets connect and do our thing
250
connectRM(\$DM_DB);
251
 
252
 
253
if ( defined($opt_projectdir) && defined($opt_releasedir) )
254
{
255
    # If project and release dirs are specified we DONT need to get projectDir & releaseDir from DM but 
256
    # we do need to make sure that all sbomids specified have the same project & release in DM
257
    # so we call the getSbomProjectAndRelease but ignore the return values for project and release names
258
    getSbomProjectAndRelease($DM_DB, \@opt_sbom_ids);
259
}
260
else
261
{
262
    # If project and release dirs not specified then get the projectDir & releaseDir from DM and in addition 
263
    # we need to check that all sbomids specified have the same project & release in DM
264
    ( $opt_projectdir, $opt_releasedir ) = getSbomProjectAndRelease($DM_DB, \@opt_sbom_ids);
265
}
266
 
267
 
268
Message("Using Project [$opt_projectdir] Release [$opt_releasedir]");
269
 
270
# now set the projectDestDir 
271
$projectDestDir = "$opt_rootdir/$opt_projectdir/$opt_releasedir";
272
 
273
# load the config file if one exists
274
if ( -f "$projectDestDir/$CONFFILE" )
275
{
276
    Message("Loading release specific Config File");
277
 
278
    open(CONF, "<$projectDestDir/$CONFFILE") || Error("Failed to open config file");
279
    while( <CONF> )
280
    {
281
        chomp;
282
        if ( /^\s*filter\s*=\s*(.*)\s*$/ )
283
        {
284
            push(@confFilters, $1);
285
        }
286
    }
287
    close(CONF);
288
}
289
 
290
# validate config and command line options
291
if ( $#opt_filters > -1 && $#confFilters > -1 )
292
{
293
    Message("Filters supplied on Command line", @opt_filters);
294
    Message("Filters in release configuration file", @confFilters);
3987 dpurdie 295
    if ( !GetYesNo("Replace Config Filters with command line Filters, be careful as this may change the copy rules") )
341 dpurdie 296
    {
297
        Error("Script terminated by user.");
298
    }
3987 dpurdie 299
    @confFilters = ();
300
    foreach my $element (@opt_filters) {
301
        UniquePush (\@confFilters, $_ ) foreach  ( split(/,/, $element));
302
    }
341 dpurdie 303
    $writeConf = 1;
304
}
305
elsif ( $#opt_filters > -1 && $#confFilters == -1 )
306
{
307
    Message("Filters supplied on Command line will be written to config file for release", @opt_filters);
3987 dpurdie 308
    @confFilters = ();
309
    foreach my $element (@opt_filters) {
310
        UniquePush (\@confFilters, $_ ) foreach  ( split(/,/, $element));
311
    }
341 dpurdie 312
    $writeConf = 1;
313
}
314
elsif ( $#opt_filters == -1 && $#confFilters > -1 )
315
{
316
    Message("Filters loaded from config file for release will be used", @confFilters) if ( IsVerbose(1) );
317
}
318
elsif ( $#opt_filters == -1 && $#confFilters == -1 )
319
{
320
    Error("No Filters supplied on command line or release config file");
321
}
322
 
3987 dpurdie 323
if ( @opt_addFilters )
324
{
325
    Message ("Adding command line filters to the release config file");
326
    foreach my $element (@opt_addFilters) {
327
        UniquePush (\@confFilters, $_ ) foreach  ( split(/,/, $element));
328
    }
329
    $writeConf = 1;
330
}
331
 
332
if ( @opt_delFilters )
333
{
334
    Message ("Deleting command line filters to the release config file");
335
    foreach my $element (@opt_delFilters) {
336
        ArrayDelete (\@confFilters, $_ ) foreach  ( split(/,/, $element));
337
    }
338
    $writeConf = 1;
339
}
340
 
341 dpurdie 341
Message("Copying packages from $ENV{GBE_DPKG} to $projectDestDir");
342
 
343
if ( ! -d $projectDestDir )
344
{
345
    if ( defined($opt_test) )
346
    {
347
        Message("mkdir $projectDestDir");
348
    }
349
    else
350
    {
351
        eval { mkpath($projectDestDir) };
352
        Error("Failed to make project directory tree $projectDestDir") if ( $@ || ! -d $projectDestDir );
353
    }
354
}
355
 
356
my $m_sqlstr = "SELECT   packages.pkg_name, package_versions.pkg_version " .
357
               "FROM     deployment_manager.bom_contents, " .
358
               "         deployment_manager.network_nodes, " .
359
               "         deployment_manager.os_contents, " .
360
               "         deployment_manager.operating_systems, " .
361
               "         release_manager.package_versions, " .
362
               "         release_manager.packages " .
363
               "WHERE    network_nodes.node_id = bom_contents.node_id AND " .
364
               "         network_nodes.node_id = operating_systems.node_id AND " .
365
               "         operating_systems.os_id = os_contents.os_id AND " .
366
               "         os_contents.prod_id = package_versions.pv_id AND " .
367
               "         package_versions.pkg_id = packages.pkg_id AND " .
368
               "         bom_contents.bom_id " . ( $#opt_sbom_ids == 0 ? "= " . $opt_sbom_ids[0] : "IN ( " . join(",", @opt_sbom_ids) . ")" ) . " " .
369
               "GROUP BY packages.pkg_name, package_versions.pkg_version " .
370
               "ORDER BY packages.pkg_name ASC, package_versions.pkg_version ASC";
371
 
372
my ( $PKG_NAME, $PKG_VERSION );
373
 
374
my $sth = $DM_DB->prepare($m_sqlstr);
375
if ( defined($sth) )
376
{
377
    if ( $sth->execute( ) )
378
    {
379
        if ( $sth->rows )
380
        {
381
            while ( ( $PKG_NAME, $PKG_VERSION ) = $sth->fetchrow_array )
382
            {
383
                my $pkgDir = "$ENV{GBE_DPKG}/$PKG_NAME";
384
                my $srcDir = "$ENV{GBE_DPKG}/$PKG_NAME/$PKG_VERSION";
385
                my $dstDir = "$projectDestDir/$PKG_NAME/$PKG_VERSION";
386
 
387
                if ( -d "$srcDir" )
388
                {
389
                    my @filelist;
390
                    my $foundFiltered = 0;
391
 
392
                    # for each of the filter rules we glob the rule in the src pkg/version dir
393
                    # and if any of the globbed files dont exist in the dst dir add it to the 
394
                    # the filelist array of files to copy
395
                    foreach my $filter ( @confFilters )
396
                    {
397
                        foreach my $srcPath ( glob("$srcDir/$filter") )
398
                        {
3987 dpurdie 399
                            next unless ( -f $srcPath );
341 dpurdie 400
                            $foundFiltered = 1;
3987 dpurdie 401
                            $filtersUsed{$filter} = 1;
402
                            my $dstFile = basename($srcPath);
403
                            my $srcFile = $srcPath;
404
                            $srcFile =~ s~^$srcDir/~~;
405
                            push(@filelist, $srcFile) if ( ! -f "$dstDir/$dstFile" );
341 dpurdie 406
                        }
407
                    }
408
 
409
                    # if no files found using filters then issue warning
410
                    if ( $foundFiltered == 0 )
411
                    {
412
                        Warning("No Files found for Package Version $PKG_NAME/$PKG_VERSION using supplied filters");
413
                    }
3987 dpurdie 414
                    # else we have found filtered files but they may already exist
415
                    # if so filelist may be empty, so check it b4 doing anything
341 dpurdie 416
                    elsif ( $#filelist > -1 )
417
                    {
418
                        Message("Copying files for package $PKG_NAME version $PKG_VERSION");
419
                        if ( defined($opt_test) )
420
                        {
421
                            Message( map("$_...", @filelist) );
422
                        }
423
                        else
424
                        {
425
                            eval { mkpath($dstDir) };
426
                            Error("Failed to make destination directory") if ( $@ || ! -d $dstDir );
427
                            foreach my $file ( @filelist )
428
                            {
429
                                Verbose("$file...");
430
                                if ( ! copy("$srcDir/$file", $dstDir) )
431
                                {
432
                                    Warning("Failed to copy $file ($!)");
433
                                }
434
                            }
435
                        }
436
                    }
437
                }
438
                elsif ( ! -d "$pkgDir" )
439
                {
440
                    # if srcDir and pkgDir dont exist then package is not in dpkg_archive so display message
441
                    Verbose("Skipping Package $PKG_NAME as it does not exist in dpkg_archive");
442
                }
443
                else
444
                {
445
                    # However if srcDir does not exist but pkgDir does exist then the package version is missing which maybe an issue
446
                    Warning("Missing Version $PKG_VERSION for Package $PKG_NAME in dpkg_archive");
447
                }
448
            }
3987 dpurdie 449
 
450
            #
451
            #   Report filter elements that where not used.
452
            #
453
            my @notUsed;
454
            foreach my $filter ( @confFilters )
455
            {
456
                next if ( exists $filtersUsed{$filter} );
457
                push @notUsed, $filter
458
            }
459
            Warning ("Unused filter rules:", @notUsed )
460
                if ( @notUsed );
461
 
341 dpurdie 462
        }
463
        else
464
        {
465
            Error("No Boms found for Deployment Manager SBomId(s) " . join(",", @opt_sbom_ids) );
466
        }
467
        $sth->finish();
468
    }
469
    else
470
    {
471
        Error("Execute failure", $m_sqlstr );
472
    }
473
}
474
else
475
{
476
    Error("Prepare failure", $m_sqlstr );
477
}
478
 
479
if ( ! defined($opt_test) && $writeConf )
480
{
481
    open(CONF, ">$projectDestDir/$CONFFILE") || Error("Failed to open config file");
482
    print CONF map( "filter=$_\n", @confFilters);
483
    close CONF;
484
}
485
 
486
#-------------------------------------------------------------------------------
487
#   Documentation
488
#
489
 
490
=pod
491
 
361 dpurdie 492
=for htmltoc    DEPLOY::Update Release
493
 
341 dpurdie 494
=head1 NAME
495
 
496
jats_update_release - Extracts current package version list from Deployment Manager SBom(s)
497
                and copy resultant packages to release specific directory.
498
 
499
=head1 SYNOPSIS
500
 
501
  jats update_release -sbomid=xxx -rootdir=xxx [options]
502
 
503
 Options:
504
    -help              - brief help message
505
    -help -help        - Detailed help message
506
    -man               - Full documentation
507
    -sbomid=xxx        - Specify the Deployment Manager SBom(s) to process (Mandatory)
508
                       - Can be specified multiple times to combine SBoms
509
    -rootdir=xxx       - Specifies the root of the releases directory (Mandatory)
510
    -projectdir=xxx    - Override the project directory name that normally comes 
511
                       - from the Deployment Manager Project Name
512
    -releasedir=xxx    - Override the project release directory name that normally 
513
                       - comes from the Deployment Manager Project Release Name
514
    -filter=xxx        - Specifies a shell wildcard used to filter package files to copy
515
                       - Can be specified multiple times to use multiple filters
3987 dpurdie 516
    -addfilter=xxx     - Add a new filter to the existing filter set
517
    -delfilter=xxx     - Delete a filter from the existing filter set
341 dpurdie 518
    -test              - Just log actions without copying files.
519
    -verbose           - Enable verbose output
520
 
521
=head1 OPTIONS
522
 
523
=over 8
524
 
525
=item B<-help>
526
 
527
Print a brief help message and exits.
528
 
529
=item B<-help -help>
530
 
531
Print a detailed help message with an explanation for each option.
532
 
533
=item B<-man>
534
 
535
Prints the manual page and exits.
536
 
537
=item B<-sbomid=xxx>
538
 
539
This option specifies one or more SBOM_ID's to use as the source of packages that will be copied.
540
The SBoms will be used to get a unique list of package/versions that can be copied from dpkg_archive.
541
 
542
This option is Mandatory and a minimum of one SBom must be supplied.  If more that one SBom is
543
supplied then all Sbom Ids must be of the same project and release with in that project.
544
 
545
=item B<-rootdir=xxx>
546
 
547
This option specifies the root directory where the packages will be copied to.
548
It is the top level directory in which the project/release directories will be created
549
and the packages copied to.
550
 
551
This option is mandatory and must specify a directory that exists.
552
 
553
=item B<-projectdir=xxx>
554
 
555
This option specifies the project directory that will be used in the rootdir for this release.
556
The project directory by default comes from the project name in Deployment Manager under which the 
557
SBom sbomid is under.
558
 
559
This option is provided to allow this script to be used against releases that are already 
560
populated and whose project directory does not match the Deployment Manager project name.
561
 
562
If the option is specified it must be used with the -releasedir option and must be a directory 
563
name that exists in the rootdir.
564
Additionally if used to populate a release then it must always be used to update the release.
565
 
566
=item B<-releasedir=xxx>
567
 
568
This option specifies the release directory that will be used in the projectdir for this release.
569
The release directory by default comes from the release name in Deployment Manager under 
570
which the SBom sbomid is under.
571
 
572
This option is provided to allow this script to be used against releases that are already 
573
populated and whose release directory does not match the Deployment Manager release name.
574
 
575
If the option is specified it must be used with the -projectdir option and must be a directory 
576
name that exists in the projectdir.
577
Additionally if used to populate a release then it must always be used to update the release.
578
 
3987 dpurdie 579
=item B<-filter=xxx[,yyy]>
341 dpurdie 580
 
3987 dpurdie 581
This option specifies a comma separated list of shell wildcard filter rule that
582
is used to determine which files are copied from package version directory in
583
GBE_DPKG to the release directory. This can be supplied multiple times to
584
specify rules for copying.
341 dpurdie 585
 
586
This must be specified on the command line the first time this command is run against a release 
587
and packages are copied to the project/release directory.  These values are then written to a 
588
config file in the project/release directory so the same values can be used on subsequent runs.  
589
In these subsequent runs this option need not be specified as the config items will be used, however
590
they can be changed by specifying them again on the command line and the config will be re-written.
591
 
592
The values of these will depend on what builds are required for each project.  Some examples are
593
--filter='*-SOLARIS10_SPARC64-[DP].pkg.gz'
594
--filter='*-SOLARIS10_SPARC86-[DP].pkg.gz'
595
--filter='*-SOLARIS10_X64-[DP].pkg.gz'
596
--filter='*-SOLARIS10_X86-[DP].pkg.gz'
3987 dpurdie 597
--filter='*-WIN32.exe,*.deb'
598
--filter='scripts/*.sh'
341 dpurdie 599
 
3987 dpurdie 600
=item B<-addFilter=xxx[,yyy]>
601
 
602
This option allows new filters to be added to an existing set of filters. This
603
option can be specified multiple times.
604
 
605
=item B<-delFilter=xxx[,yyy]>
606
 
607
This option deletes one or more filter rules from an existing set of filters. This
608
option can be specified multiple times.
609
 
341 dpurdie 610
=item B<-test>
611
 
612
This option will display what would be copied without actually copying anything
613
 
614
=item B<-verbose>
615
 
616
This option will display progress information as the program executes.
617
 
618
=back
619
 
620
=head1 DESCRIPTION
621
 
622
This program is used to update a projects release directory with the versions of
623
packages as indicated by the specified Deployment Manager SBoms.
624
 
625
Every invocation of this tool requires the -sbomid and -rootdir options specified.
626
 
627
The sbomid is used to get all the required information from Deployment Manager about
628
which package version are required, as well as the project name and release name under
629
which the Sboms are under.
630
 
631
The sbomid option can be specified multiple times to copy packages from multiple SBoms
632
to the Project Release directory.  All Sboms that are specified must be under the 
633
same Release under the same Project otherwise the script will abort.
634
 
635
The rootdir is used to specify the root location of the global releases directory.
636
This will be used as the root location from where the project and release specific
637
directories will be created to copy the files to.
638
 
639
By default the project and release names come from the project and release tree under
640
which the Sboms appear in Deployment Manager.  These values are used to populate the releasedir 
641
and projectdir respectively.
642
 
643
Alternatively you may override the projectdir and releasedir from Deployment Manager
644
by specifying the -projectdir=xxx and -releasedir=xxx options on the command line.
645
If they are used they must both be specified and must be valid directories of
646
rootdir/projectdir/releasedir.  These options are provided to allow existing release
647
directory structures to be used that don't match Deployment Managers project and release names.
648
 
649
The final release specific directory will be B<rootdir/projectdir/releasedir> and
650
all packages will be copied into this directory under a PkgName/PkgVersion directory tree.
651
 
652
For example running the command 
653
 
654
=over 8
655
 
656
=item jats updateRelease -sbomid=51904 -rootdir=/export/devl/releases
657
 
658
=back
659
 
660
will retrieve "BANGKOK (BKK)" as the project and "R1" as the release and will
661
copy packages into the "/export/devl/releases/BANGKOK (BKK)/R1" directory.
662
 
663
In addition to using Deployment Manager SBoms to determine which Package/Versions are
664
required to be copied this script also uses a set of shell wildcard filters that are
665
used to determine which files are actually copied when invoked.
666
 
667
The filter rules can be supplied on the command line if available read from a 
668
configuration file saved in the project/releasedir the last time the script was run
669
on this release directory.
670
 
671
One or more filter rules must be specified on the command line the first time this command 
672
is run against a project release directory.  These filter values are then written to a config
673
file in the project/release directory so the same values can be used on subsequent runs.  
674
In subsequent runs the filter rules will be loaded from the config file and need not be specified 
675
on the command line, however the filter rules in the config file can be changed by specifying 
676
them again on the command line and the config will be re-written.
677
 
678
=cut
679