Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
########################################################################
7300 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
227 dpurdie 3
#
263 dpurdie 4
# Module name   : jats_sandbox.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
7
# Environment(s): JATS
227 dpurdie 8
#
9
# Description   : A script to build a collection of packages in the
10
#                 same sandbox. This script will:
11
#
12
#                   Determine the packages in the sandbox
13
#                   Determine the build order of the packages
14
#                   Build the packages in the correct order
15
#                   Make the packages in the correct order
16
#
17
#                 The script will allow for:
18
#                   The creation of a sandbox
19
#                   The addition of packages to the sandbox
20
#                   Removal of packages from the sandbox
21
#
22
#
23
#                 Command syntax (basic)
24
#                   jats sandbox <command> (options | actions)@
25
#
26
#                 Commands include:
27
#                   create              - Create a sandbox
28
#                   delete              - Delete a sandbox
337 dpurdie 29
#                   info                - Show sandbox info
227 dpurdie 30
#
31
#                   build               - Build all packages in the sandbox
32
#                   make                - make all packages in the sandbox
33
#
34
#......................................................................#
35
 
263 dpurdie 36
require 5.008_002;
227 dpurdie 37
use strict;
38
use warnings;
39
use JatsError;
40
use JatsSystem;
41
use FileUtils;
245 dpurdie 42
use JatsBuildFiles;
227 dpurdie 43
use JatsVersionUtils;
4197 dpurdie 44
use ArrayHashUtils;
6133 dpurdie 45
use ToolsetFiles;
227 dpurdie 46
 
47
use Pod::Usage;                             # required for help support
48
use Getopt::Long qw(:config require_order); # Stop on non-option
6133 dpurdie 49
use Digest;
50
 
227 dpurdie 51
my $VERSION = "1.0.0";                      # Update this
7306 dpurdie 52
my $SCANDEPTH = 3;                          # Almost a constant
227 dpurdie 53
 
54
#
55
#   Options
56
#
57
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
58
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
359 dpurdie 59
my $opt_help = 0;                           # Help level
1329 dpurdie 60
my $opt_toPackage;                          # Control recursion
61
my $opt_fromPackage;                        # Control recursion
62
my @opt_justPackage;                        # Control recursion
63
my @opt_ignorePackage;                      # Control recursion
6133 dpurdie 64
my $opt_allSandbox;                         # Extend scope to entire sandbox
65
my $opt_processUsedBy;                      # Process dependants(consumers) not dependents(children)
66
my $opt_keepgoing;                          # Ignore errors
67
my $opt_reScan;                             # Rescan for buildfiles
7307 dpurdie 68
my $opt_multiBuilders = 0;                  # How handle packages with multiple bulders: 0:Error, 1:Report, 2:Ignore
227 dpurdie 69
 
70
#
71
#   Globals - Provided by the JATS environment
72
#
4688 dpurdie 73
my $USER            = $ENV{'USER'};
74
my $UNIX            = $ENV{'GBE_UNIX'};
75
my $HOME            = $ENV{'HOME'};
76
my $GBE_SANDBOX     = $ENV{'GBE_SANDBOX'};
77
my $GBE_DPKG_SBOX   = $ENV{'GBE_DPKG_SBOX'};
78
my $GBE_MACHTYPE    = $ENV{'GBE_MACHTYPE'};
3559 dpurdie 79
my $GBE_BUILDFILTER = $ENV{'GBE_BUILDFILTER'};
335 dpurdie 80
 
4688 dpurdie 81
my $GBE_DPKG_LOCAL      = $ENV{'GBE_DPKG_LOCAL'};
82
my $GBE_DPKG_CACHE      = $ENV{'GBE_DPKG_CACHE'};
83
my $GBE_DPKG            = $ENV{'GBE_DPKG'};
84
my $GBE_DPLY            = $ENV{'GBE_DPLY'};
85
my $GBE_DPKG_STORE      = $ENV{'GBE_DPKG_STORE'};
86
my $GBE_DPKG_REPLICA    = $ENV{'GBE_DPKG_REPLICA'};
87
 
227 dpurdie 88
#
89
#   Globals
90
#
7306 dpurdie 91
my @stopped = ();                               # Stopped entries
92
my @build_order = ();                           # Build Ordered list of entries
93
my %extern_deps;                                # Hash of external dependencies
94
my %packages;                                   # Hash of packages
95
my $currentPkgTag;                              # Tag of the current package - if any                                          
96
my $scanDepth;                                  # Depth for build file scan
7307 dpurdie 97
my $maxDname = 0;                               # Pretty display
227 dpurdie 98
 
7306 dpurdie 99
#
100
#   Known files
101
#
102
my $cacheFile  = $GBE_DPKG_SBOX . '/location_cache';
103
my $depthFile  = $GBE_DPKG_SBOX . '/scanDepth';
7307 dpurdie 104
my $filterFile = $GBE_DPKG_SBOX . '/buildfilter';
7306 dpurdie 105
 
227 dpurdie 106
#-------------------------------------------------------------------------------
107
# Function        : Mainline Entry Point
108
#
109
# Description     :
110
#
111
# Inputs          :
112
#
113
 
114
#
115
#   Process help and manual options
116
#
1329 dpurdie 117
my $result = getOptionsFromArray ( \@ARGV );
227 dpurdie 118
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
119
pod2usage(-verbose => 1)  if ($opt_help == 2 );
299 dpurdie 120
pod2usage(-verbose => 2)  if ($opt_help > 2 );
227 dpurdie 121
 
122
#
123
#   Configure the error reporting process now that we have the user options
124
#
125
ErrorConfig( 'name'    => 'SANDBOX',
126
             'verbose' => $opt_verbose );
127
 
128
#
359 dpurdie 129
#   Reconfigure the options parser to allow subcommands to parse options
227 dpurdie 130
#
359 dpurdie 131
Getopt::Long::Configure('permute');
227 dpurdie 132
 
133
#
134
#   Parse the user command and decide what to do
135
#
359 dpurdie 136
#   Remove user command from the command line. This will leave command options
137
#   in @ARGV so that they can be parsed by the subcommand.
227 dpurdie 138
#
139
my $cmd = shift @ARGV || "";
140
help(1)                                 if ( $cmd =~ m/^help$/ || $cmd eq "" );
359 dpurdie 141
buildcmd($cmd, @ARGV )                  if ( $cmd =~ m/(^all$)|(^build$)/  );
142
cache(@ARGV)                            if ( $cmd =~ m/^cache$/  );
143
clean($cmd, @ARGV)                      if ( $cmd =~ m/(^clobber$)|(^clean$)/  );
144
cmd('make', $cmd, @ARGV )               if ( $cmd =~ m/(^make$)/  );
145
cmd('cmd', @ARGV)                       if ( $cmd =~ m/^cmd$/ );
146
create_sandbox()                        if ( $cmd =~ m/^create$/ );
299 dpurdie 147
delete_sandbox()                        if ( $cmd =~ m/^delete$/ );
227 dpurdie 148
info(@ARGV)                             if ( $cmd =~ m/^info$/ );
359 dpurdie 149
populate(@ARGV)                         if ( $cmd =~ m/^populate$/  );
4197 dpurdie 150
buildfilter(@ARGV)                      if ( $cmd =~ m/^buildfilter$/  );
6133 dpurdie 151
skipBuild(0, @ARGV)                     if ( $cmd =~ m/^skip$/  );
152
skipBuild(1, @ARGV)                     if ( $cmd =~ m/^unskip$/  );
153
fingerPrintPkg(@ARGV)                   if ( $cmd =~ m/^finger/i );
7304 dpurdie 154
testLinks(@ARGV)                        if ( $cmd =~ m/^testlinks/i );
7306 dpurdie 155
setScanDepth(@ARGV)                     if ( $cmd =~ m/^scandepth/i );
227 dpurdie 156
 
157
Error ("Unknown sandbox command: $cmd");
158
exit 1;
159
 
160
 
161
#-------------------------------------------------------------------------------
162
#
163
#   Give the user a clue
164
#
165
sub help
166
{
167
    my ($level) = @_;
168
    $level = $opt_help unless ( $level );
169
 
170
    pod2usage(-verbose => 0, -message => "Version: ". $VERSION)  if ($level == 1 );
171
    pod2usage(-verbose => $level -1 );
172
}
173
 
174
#-------------------------------------------------------------------------------
175
# Function        : create_sandbox
176
#
177
# Description     : create a sandbox in the current current directory
178
#
179
# Inputs          : None
180
#
181
#
182
sub create_sandbox
183
{
359 dpurdie 184
    GetOptions (
185
                "help:+"        => \$opt_help,
186
                "manual:3"      => \$opt_help,
187
                ) || Error ("Invalid command line" );
188
 
189
    SubCommandHelp( $opt_help, "Create Sandbox") if ($opt_help || $#ARGV >= 0 );
190
 
227 dpurdie 191
    Error ("Cannot create a sandbox within a sandbox",
192
           "Sandbox base is: $GBE_SANDBOX" ) if ( $GBE_SANDBOX );
359 dpurdie 193
 
227 dpurdie 194
    mkdir ('sandbox_dpkg_archive') || Error ("Cannot create the directory: sandbox_dpkg_archive") ;
359 dpurdie 195
 
7301 dpurdie 196
    Message ('Sandbox created');
227 dpurdie 197
    exit  0;
198
}
199
 
200
#-------------------------------------------------------------------------------
299 dpurdie 201
# Function        : delete_sandbox
202
#
203
# Description     : Delete a sandbox
204
#                   Its up to the user the delete the components in the sandbox
205
#
206
# Inputs          : None
207
#
361 dpurdie 208
# Returns         :
299 dpurdie 209
#
210
sub delete_sandbox
211
{
359 dpurdie 212
    GetOptions (
213
                "help:+"        => \$opt_help,
214
                "manual:3"      => \$opt_help,
215
                ) || Error ("Invalid command line" );
216
 
217
    SubCommandHelp( $opt_help, "Delete Sandbox") if ($opt_help || $#ARGV >= 0 );
218
 
299 dpurdie 219
    unless ( $GBE_SANDBOX )
220
    {
221
        Warning("No sandbox found to delete");
222
    }
223
    else
224
    {
365 dpurdie 225
        Error ("Sandbox directory not completely removed")
361 dpurdie 226
            if RmDirTree( "$GBE_SANDBOX/sandbox_dpkg_archive" );
299 dpurdie 227
 
228
        Message("Sandbox information deleted",
229
                "Sandbox components must be manually deleted");
230
    }
231
    exit 0;
232
}
233
 
234
#-------------------------------------------------------------------------------
6133 dpurdie 235
# Function        : skipBuild 
236
#
237
# Description     : Mark the building of a package for skipping
238
#
239
# Inputs          : Mode -: Skip, 1:Unskip
240
#                   User commaand line 
241
#
242
# Returns         : Nothing
243
#
244
sub skipBuild
245
{
246
    my ($mode, @cmd_opts ) = @_;
247
    my $machine;
248
 
249
    Getopt::Long::Configure('pass_through');
250
    getOptionsFromArray ( \@cmd_opts,
251
                        'machine!' => \$machine,
252
                        ) || Error ("Invalid command line" );
253
 
254
    SubCommandHelp( $opt_help, "Skip Build") if ($opt_help );
255
    Error ("Command must be executed from within a Sandbox") unless ( $GBE_SANDBOX );
256
 
257
    #
258
    #   Determine Sandbox information
259
    #   Populate global variables
260
    #
261
    calc_sandbox_info(1);
262
 
263
    #
264
    #   Display only
265
    #   
266
    unless( @cmd_opts)
267
    {
268
        foreach my $pkg (keys %packages)
269
        {
270
            my $fe = $packages{$pkg};
271
            next unless $fe->{buildSkip};
272
 
273
            my $skipMsg = ($fe->{buildSkip}) ? ' (Build Skipped)' : ' (Build Suppressed)';
274
            if ($fe->{buildCurrent}) {
275
                $skipMsg .= ' (Current Package)';
276
            }
277
 
278
            Message( ' Name: ' . $fe->{dname} . $skipMsg );
279
 
280
        }
281
        exit 0;
282
    }
283
 
284
    foreach ( @cmd_opts )
285
    {
286
        #
287
        #   Locate the package
288
        #
289
        my $pe;
290
        if ($currentPkgTag && ($_ eq '.'))
291
        {
292
            if (exists $packages{$currentPkgTag})
293
            {
294
                $pe = $packages{$currentPkgTag}; 
295
            }
296
        }
297
        unless ($pe) {
298
            foreach my $pkg (keys %packages)
299
            {
300
                my $entry = $packages{$pkg};
301
                if ($entry->{dname} eq $_ || $entry->{fname} eq $_ )
302
                {
303
                    $pe = $entry;
304
                    last;
305
                }
306
            }
307
        }
308
 
309
        unless ($pe) {
310
            Warning("No package found matching: $_");
311
            next;
312
        }
313
 
314
        my $skipFile;
315
        if ($machine) {
316
            $skipFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', '_skip.' . $GBE_MACHTYPE . '.' . $pe->{dname});
317
        } else {
318
            $skipFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', '_skip.'. $pe->{dname});
319
        }
320
        Verbose("SkipFile: $skipFile");
321
        if ($mode)
322
        {
323
            unlink $skipFile;
324
        }
325
        else
326
        {
327
            TouchFile($skipFile);
328
        }
329
    }
330
    exit 0;
331
}
332
 
333
#-------------------------------------------------------------------------------
227 dpurdie 334
# Function        : info
335
#
336
# Description     : Display Sandbox information
337
#
338
# Inputs          : Command line args
339
#                   -v  - Be more verbose
340
#
341
# Returns         : Will exit
342
#
343
sub info
344
{
1329 dpurdie 345
    my (@cmd_opts ) = @_;
346
    my $show = 0;
6133 dpurdie 347
    my $showUsage = 0;
348
    my $showFingerPrint = 0;
7306 dpurdie 349
    my $showDependencies = 1;
350
    my $showOrder = 1;
7307 dpurdie 351
    my $showPath = 0;
227 dpurdie 352
 
1329 dpurdie 353
    Getopt::Long::Configure('pass_through');
354
    getOptionsFromArray ( \@cmd_opts,
7306 dpurdie 355
                          'verbose:+'       => \$show,
356
                          'usedby'          => \$showUsage,
357
                          'fingerprint!'    => \$showFingerPrint,
358
                          'dependencies!'   => \$showDependencies,
359
                          'buildorder!'     => \$showOrder,
7307 dpurdie 360
                          'path!'           => \$showPath,
1329 dpurdie 361
                        ) || Error ("Invalid command line" );
362
    SubCommandHelp( $opt_help, "Sandbox Information") if ($opt_help || $#cmd_opts >=0 );
6133 dpurdie 363
    $showUsage = 1 if ($show >= 2);
361 dpurdie 364
 
227 dpurdie 365
    #
366
    #   Determine Sandbox information
367
    #   Populate global variables
368
    #
6133 dpurdie 369
    calc_sandbox_info();
227 dpurdie 370
 
371
    #
372
    #   Display information
373
    #
6133 dpurdie 374
    Message ("Scope      : " . ($opt_allSandbox ? 'Entire Sandbox' : $packages{$currentPkgTag}{dname} ));
3559 dpurdie 375
    Message ("Base       : $GBE_SANDBOX");
376
    Message ("Archive    : $GBE_DPKG_SBOX");
7306 dpurdie 377
    Message ("BuildFilter: $GBE_BUILDFILTER" . ( (-f $filterFile)  ? ' - Local to sandbox' : ''));
227 dpurdie 378
 
7306 dpurdie 379
    if ($showOrder)
1329 dpurdie 380
    {
7306 dpurdie 381
        Message ("Build Order");
7307 dpurdie 382
        foreach my $pname ( @stopped ) {
7306 dpurdie 383
            Message( "    Level:" . "--"  . " [---] Name: " . $pname . ' (Stopped)');
384
        }
7307 dpurdie 385
 
7306 dpurdie 386
        foreach my $fe ( @build_order )
387
        {
7307 dpurdie 388
            displayHeader($fe, { indent => '    ', testFingerPrint =>  $showFingerPrint, showSimplePath => $showPath });
227 dpurdie 389
 
7306 dpurdie 390
            if ( $show )
227 dpurdie 391
            {
7306 dpurdie 392
                Message( DisplayPath ("        Path: $fe->{dir}" ));
393
                foreach my $idep ( sort values %{$fe->{'ideps'}} )
394
                {
395
                    Message ("        I:$idep");
396
                }
227 dpurdie 397
 
7306 dpurdie 398
                foreach my $edep ( sort keys %{$fe->{'edeps'}} )
399
                {
400
                    my ($ppn,$ppv) = split( $; , $edep);
401
                    Message ("        E:$ppn $ppv");
402
                }
227 dpurdie 403
            }
361 dpurdie 404
 
7306 dpurdie 405
            if ($showUsage && exists($fe->{'usedBy'}))
6133 dpurdie 406
            {
7306 dpurdie 407
                foreach my $edep ( sort {uc($a) cmp uc($b)} @{$fe->{'usedBy'}} )
408
                {
409
                    Message ("        U:$packages{$edep}{dname}");
410
                }
6133 dpurdie 411
            }
227 dpurdie 412
        }
413
    }
414
 
359 dpurdie 415
    #
416
    #   External dependencies flags
417
    #       * - Package does not exist in dpkg_archive
418
    #       + - Multiple versions of this package are used
419
 
7306 dpurdie 420
    if ($showDependencies)
227 dpurdie 421
    {
7306 dpurdie 422
        Message("External Dependencies");
423
        foreach my $de ( sort {uc($a) cmp uc($b)} keys %extern_deps )
227 dpurdie 424
        {
7306 dpurdie 425
            my @vlist = keys %{$extern_deps{$de}};
426
            my $flag = $#vlist ? '+' : '';
427
            foreach my $pve ( sort {uc($a) cmp uc($b)} @vlist )
227 dpurdie 428
            {
7306 dpurdie 429
                my ($pn,$pv) = split( $; , $pve );
430
                my $exists = check_package_existance($pn,$pv  ) ? '' : '*';
431
                my $flags = sprintf ("%4.4s", $flag . $exists);
432
                Message ("${flags}${pn} ${pv}");
433
                if ( $show || $showUsage )
227 dpurdie 434
                {
7306 dpurdie 435
                    foreach my $pkg ( sort {uc($a) cmp uc($b)} @{$extern_deps{$de}{$pve}} )
436
                    {
437
                        my $ppn = join ('.', split( $; , $pkg));
438
                        Message ("        U:$ppn");
439
                    }
227 dpurdie 440
                }
7306 dpurdie 441
 
227 dpurdie 442
            }
443
        }
444
    }
445
 
1329 dpurdie 446
    if ( $show > 2 || $opt_verbose > 2 )
227 dpurdie 447
    {
448
        DebugDumpData( "extern_deps", \%extern_deps);
449
        DebugDumpData( "build_order", \@build_order);
450
        DebugDumpData( "packages", \%packages);
451
    }
452
    exit (0);
453
}
454
 
455
#-------------------------------------------------------------------------------
6133 dpurdie 456
# Function        : fingerPrintPkg 
457
#
458
# Description     : Various finger print operations on the current package
459
#
460
# Inputs          : @ARGV   - Arguments
461
#
462
# Returns         : WIll not return
463
#
464
sub fingerPrintPkg
465
{
466
    my ( @cmd_opts ) = @_;
467
    my $opt_generate;
468
    my $opt_delete;
469
 
470
    Getopt::Long::Configure('pass_through');
471
    getOptionsFromArray ( \@cmd_opts,
472
                          'generate!' => \$opt_generate,
473
                          'delete!'   => \$opt_delete,
474
                        ) || Error ("Invalid command line" );
475
 
476
    SubCommandHelp( $opt_help, "Sandbox Finger Print") if ($opt_help );
477
    Error ("Command must be executed from within a Sandbox") unless ( $GBE_SANDBOX );
478
 
479
    #
480
    #   Determine Sandbox information
481
    #   Populate global variables
482
    #
483
    calc_sandbox_info(1);
484
 
485
    #
486
    #   Determine the named packages, or use the current package
487
    #
488
    my @pkgList;
489
    if (@cmd_opts)
490
    {
491
        @pkgList = @cmd_opts;
492
    }
493
    else
494
    {
495
        if ( $currentPkgTag )
496
        {
497
            if (exists $packages{$currentPkgTag})
498
            {
499
                push @pkgList, $packages{$currentPkgTag}{fname};
500
            }
501
        }
502
    }
503
    Error ("Command must be used within a package, or with named packages.") 
504
        unless @pkgList;
505
 
506
 
507
    #
508
    #   Process all required packages
509
    #
510
    foreach my $pkgName ( @pkgList)
511
    {
512
        #
513
        #   Locate the package
514
        #
515
        my $pe;
516
        foreach my $pkg (keys %packages)
517
        {
518
            my $entry = $packages{$pkg};
519
            if ($entry->{dname} eq $pkgName || $entry->{fname} eq $pkgName )
520
            {
521
                $pe = $entry;
522
                last;
523
            }
524
        }
525
 
526
        unless ( $pe ) {
527
            Warning ("Cannot locate package: $pkgName");
528
            next;
529
        }
530
 
531
        #
532
        #   Recalculate finger print
533
        #
534
        my $tagFile = getPkgFingerPrintFile($pe);
535
        if ($opt_generate)
536
        {
537
            my $ifaceDir = getpkgInterface($pe);
538
            if ($ifaceDir)
539
            {
540
                Message ("Generate Fingerprint");
7307 dpurdie 541
                Verbose ("Fingerprint file: $tagFile");
6133 dpurdie 542
                FileCreate( $tagFile, genPkgFingerPrint($pe,'Generation') );
543
            }
544
            else
545
            {
546
                Warning("Package has not been built. Cannot generate fingerprint: $pkgName");
547
            }
548
        }
549
        elsif ($opt_delete)
550
        {
551
            unlink $tagFile;
552
            Message ("Fingerprint file removed");
553
        }
554
        else
555
        {
556
            #
557
            #   Test the finger print on the current package
558
            #
559
            if ( -e $tagFile )
560
            {
561
                if ( TagFileMatch($tagFile, genPkgFingerPrint($pe, 'Test')) )
562
                {
563
                    Message ("Fingerprint match");
564
                }
565
                else
566
                {
567
                    Message("Fingerprint missmatch");
568
                }
569
            }
570
            else
571
            {
572
                Message ("Package does not have a fingerprint file");
573
            }
574
        }
575
    }
576
 
577
    exit (0);
578
}
579
 
7304 dpurdie 580
#-------------------------------------------------------------------------------
581
# Function        : testLinks 
582
#
583
# Description     : Test the lnk files in the sandbox directory
584
#                   These may be stake after packages are deleted
585
#
586
# Inputs          : 
587
#
7306 dpurdie 588
# Returns         : This function will not return
7304 dpurdie 589
#
590
sub testLinks
591
{
592
    my ( @cmd_opts ) = @_;
593
    my $opt_delete;
6133 dpurdie 594
 
7304 dpurdie 595
    GetOptions (
596
                "help:+"        => \$opt_help,
597
                "manual:3"      => \$opt_help,
598
                'delete!'       => \$opt_delete,
599
                ) || Error ("Invalid command line" );
600
 
7306 dpurdie 601
    SubCommandHelp( $opt_help, "Sandbox Test Links") if ($opt_help || ($#ARGV >= 0) );
7304 dpurdie 602
    Error ("Command must be executed from within a Sandbox") unless ( $GBE_SANDBOX );
603
 
604
    #
605
    #   Process all packages in the sandbox
606
    #
607
    foreach my $linkFile ( glob "$GBE_DPKG_SBOX/*/*.lnk")
608
    {
609
        my $pkg = TagFileRead($linkFile);
610
 
611
        $pkg =~ s~\\~/~g;
612
        if ($pkg =~ s~^GBE_SANDBOX/~$GBE_SANDBOX/~)
613
        {
614
                # If the target sandbox is in the 'deploymode' then the package
615
                # will not be in the expected location. It will be in a 'build/deploy'
616
                # subdir. Remove the pkg/name dir to get to the root of the package
617
                my @dirs = File::Spec->splitdir( $pkg );
618
                splice(@dirs, -2);
619
                my $deployBox = catdir(@dirs, 'build', 'deploy');
620
                $pkg = $deployBox if ( -d $deployBox);
621
        }
622
 
623
        unless ( -d $pkg )
624
        {
625
            if ($opt_delete)
626
            {
627
                Message ("Delete: $linkFile");
628
                unlink $linkFile;
629
            } 
630
            else
631
            {
632
                Message ("Broken link: $pkg", "Source link: $linkFile" );
633
            }
634
        }
635
 
636
    }
637
 
638
    exit (0);
639
}
640
 
7306 dpurdie 641
#-------------------------------------------------------------------------------
642
# Function        : setScanDepth 
643
#
644
# Description     : Set the depth of the build file scan usd in this sandbox 
645
#
646
# Inputs          : Command line arguments
647
#
648
# Returns         : This function will not return
649
#
650
sub setScanDepth
651
{
652
    my ( @cmd_opts ) = @_;
653
    GetOptions (
654
                "help:+"        => \$opt_help,
655
                "manual:3"      => \$opt_help,
656
                ) || Error ("Invalid command line" );
7304 dpurdie 657
 
7306 dpurdie 658
    SubCommandHelp( $opt_help, "Sandbox Scan Depth") if ($opt_help || ($#ARGV > 0 ));
659
    Error ("Command must be executed from within a Sandbox") unless ( $GBE_SANDBOX );
660
 
661
    if (defined $ARGV[0])
662
    {
663
        FileCreate($depthFile, $ARGV[0]);
664
 
665
        #
666
        #   Force a rescan of the cached information
667
        #
668
        unlink $cacheFile;
669
        exit 0;
670
    }
671
 
672
    #
673
    #   Report the current scan depth
674
    #
675
    getScanDepth();
676
    Information ("Build File scan depth: ". $scanDepth);
677
    exit (0);
678
 
679
}
680
 
6133 dpurdie 681
#-------------------------------------------------------------------------------
7306 dpurdie 682
# Function        : getScanDepth  
683
#
684
# Description     : Determine the build file scan depth for the current sandbox
685
#                   Non-default data is maintained in a data file    
686
#
687
# Inputs          : None
688
#
689
# Returns         : Nothing
690
#
691
 
692
sub getScanDepth
693
{
694
    my $depth = $SCANDEPTH;
695
    if ( -f $depthFile)
696
    {
697
        $depth = TagFileRead($depthFile);
698
        my $invalid = 0;
699
        if ($depth !~ m~^\d+$~) {
700
            $invalid = 1;
701
        } elsif ( $depth lt 0) {
702
            $invalid = 1;
703
        }
704
 
705
        if ($invalid)
706
        {
707
            unlink $depthFile;
708
            Warning ("Invalid scandepth file. File deleted.");
709
            $depth = $SCANDEPTH;
710
        }
711
    }
712
    $scanDepth = $depth;
713
}
714
 
715
 
716
#-------------------------------------------------------------------------------
335 dpurdie 717
# Function        : check_package_existance
718
#
719
# Description     : Determine if a given package-version exists
720
#
721
# Inputs          : $name           - Package Name
722
#                   $ver            - Package Version
723
#
724
# Returns         : true            - Package exists
725
#
726
sub check_package_existance
727
{
728
    my ($name, $ver) = @_;
729
    #
730
    #   Look in each package archive directory
731
    #
732
    foreach my $dpkg ( $GBE_DPKG_SBOX,
733
                       $GBE_DPKG_LOCAL,
734
                       $GBE_DPKG_CACHE,
4688 dpurdie 735
                       $GBE_DPKG_REPLICA,
335 dpurdie 736
                       $GBE_DPKG,
737
                       $GBE_DPLY,
738
                       $GBE_DPKG_STORE )
739
    {
740
        next unless ( $dpkg );
741
        if ( -d "$dpkg/$name/$ver" )
742
        {
743
            return 1;
744
        }
745
    }
746
   return 0;
747
}
748
 
6133 dpurdie 749
#-------------------------------------------------------------------------------
7301 dpurdie 750
# Function        : locatePreBuiltPackage 
751
#
752
# Description     : Locate a prebuilt package
753
#                   Skip the make process if a package with a matching signature 
754
#                   can be found. ie: We have a pre-built version
755
#                   
756
# Inputs          : $fe     - Package Entry
757
#
758
# Returns         : True - Prebuilt package found
759
#                   False - Prebuild package not found
760
#
761
sub locatePreBuiltPackage
762
{
763
    my ($fe) = @_;
764
 
765
    #
766
    #   Get the package signature
767
    #   This is held in the packages interface directory
768
    #
769
    my $ifaceDir = getpkgInterface($fe);
770
    return 0 unless $ifaceDir;
771
 
772
    my $sigFile = catdir($ifaceDir, 'Package.sig');
773
    return 0 unless -f $sigFile;
774
 
775
    my $pkgSig = TagFileRead($sigFile);
776
 
777
    #
778
    #   Look in each package archive directory
779
    #   
780
    foreach my $dpkg ( $GBE_DPKG_SBOX,
781
                       $GBE_DPKG_LOCAL,
782
                       $GBE_DPKG_CACHE,
783
                       $GBE_DPKG_REPLICA,
784
                       $GBE_DPKG,
785
                       $GBE_DPLY,
786
                       $GBE_DPKG_STORE )
787
    {
788
        my $pkgDir = catdir( $dpkg, $fe->{mname}, $pkgSig);
789
        if (-d $pkgDir )
790
        {
791
            Debug("Prebuilt Package found: $pkgSig");
792
            return 1;
793
        }
794
    }
795
    return 0;
796
}
797
 
798
#-------------------------------------------------------------------------------
6133 dpurdie 799
# Function        : getpkgInterface 
800
#
801
# Description     : Locate the packages interface directory 
802
#
803
# Inputs          : $fe     - Package Entry 
804
#
805
# Returns         : Undef if not found
806
#                   Path to the packages interface directory
807
#
808
sub getpkgInterface
809
{
810
    my ($fe) = @_;
335 dpurdie 811
 
6133 dpurdie 812
    #
813
    #   Determine the packages 'interface' directory
814
    #
815
    my $pSuffix = ($fe->{prj}) ? ( '.' . $fe->{prj}) : '';
816
    my $ifaceDir = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', $fe->{name}, 'sandbox' . $pSuffix . '.int');
817
    return unless -f $ifaceDir; 
818
    $ifaceDir = TagFileRead($ifaceDir);
819
    $ifaceDir =~ s~\\~/~g;
820
    $ifaceDir =~ s~GBE_SANDBOX/~$GBE_SANDBOX/~;
821
    return $ifaceDir; 
822
}
823
 
824
 
335 dpurdie 825
#-------------------------------------------------------------------------------
227 dpurdie 826
# Function        : calc_sandbox_info
827
#
828
# Description     : Examine the sandbox and determine all the important
829
#                   information
830
#
1329 dpurdie 831
#                   Operation will be modified by
832
#                       $opt_toPackage
833
#                       $opt_fromPackage
834
#                       @opt_justPackage
835
#                       @opt_ignorePackage
227 dpurdie 836
#
6133 dpurdie 837
# Inputs          : quiet       undef - noisy
838
#                               1 - quiet           
1329 dpurdie 839
#
227 dpurdie 840
# Returns         : Will exit if not in a sandbox
841
#                   Populates global variables
842
#                       @build_order - build ordered array of build entries
843
#
844
sub calc_sandbox_info
845
{
6133 dpurdie 846
    my ($quiet) = @_;
7306 dpurdie 847
    my $buildFileDepth = 0;
848
    getScanDepth();
849
 
227 dpurdie 850
    #
851
    #   Start from the root of the sandbox
852
    #
853
    Error ("Command must be executed from within a Sandbox") unless ( $GBE_SANDBOX );
6133 dpurdie 854
    my $startDir = Getcwd();
227 dpurdie 855
    chdir ($GBE_SANDBOX) || Error ("Cannot chdir to $GBE_SANDBOX");
856
 
857
    #
6133 dpurdie 858
    #   Retain subdir so we can figure out a starting package
859
    # 
860
    $startDir = '' unless ($startDir =~ s~^$GBE_SANDBOX/~~);
861
 
862
    #
227 dpurdie 863
    #   Locate all packages within the sandbox
864
    #   These will be top-level directories - one per package
865
    #
866
    my @build_list;
6133 dpurdie 867
    my $currentRootFingerPrint = calc_rootFingerPrint();
868
 
869
    if (-f $cacheFile && !$opt_reScan) 
227 dpurdie 870
    {
6133 dpurdie 871
        #
872
        #   Read in the location cache
873
        #   Greatly speeds up the location process
874
        #
875
        open( my $lf, '<', $cacheFile) || Error ("Read error: $cacheFile. $!");
275 dpurdie 876
 
6133 dpurdie 877
        #
878
        #   Check root directory signature
879
        #       Has the user added or removed packages from the sandbox
880
        #
881
        my $rootFingerPrint = <$lf>;
882
        $rootFingerPrint =~ s~\s*$~~;
883
 
884
        if ($rootFingerPrint eq $currentRootFingerPrint )
275 dpurdie 885
        {
6133 dpurdie 886
            while (<$lf>)
887
            {
7306 dpurdie 888
                s~\s+$~~;
6133 dpurdie 889
                my @locationEntry = split($;, $_);
890
                my $pname = $locationEntry[0];
7306 dpurdie 891
                if ($locationEntry[1] eq ':STOP:') {
892
                    push @stopped, $pname;
893
                    Verbose("Package contains stop file: $pname");
894
                    next;
895
                }
6133 dpurdie 896
 
897
                #
898
                #   Locate the build files in each package
899
                #   Scan the build files and extract dependancy information
900
                #
901
                my $bscanner = BuildFileScanner( $pname, 'build.pl',
902
                                                         '--LocateAll',
7306 dpurdie 903
                                                         '--LimitDepth=' . $scanDepth,
6133 dpurdie 904
                                                         '--ScanDependencies' );
905
                unless ($bscanner->setLocation($_)) {
906
                    Verbose("Build file missing: Force full scan");
907
                    @build_list = ();
908
                    last;
909
                }
910
                $bscanner->scan();
911
                my @blist = $bscanner->getInfo();
912
                unless ($quiet) {
913
                    Warning ("Package does not have build files: $pname") unless ( @blist );
914
                    Warning ("Package has multiple build files: $pname") if ( $#blist > 0 );
915
                }
916
                push @build_list, @blist;
917
            }
275 dpurdie 918
        }
6133 dpurdie 919
        close $lf;
920
    }
275 dpurdie 921
 
6133 dpurdie 922
    unless (@build_list)
923
    {
924
        Message ("Scanning sandbox for build files");
925
        FileCreate($cacheFile, $currentRootFingerPrint );
227 dpurdie 926
 
6133 dpurdie 927
        my @locationData;
928
        foreach my $pname ( glob("*") )
929
        {
930
            next if ( $pname =~ m~^\.~ );
931
            next if ( $pname =~ m~dpkg_archive$~ );
7300 dpurdie 932
            next if ( $pname eq 'CSV' );
933
            next if ( $pname eq 'lost+found' );
6133 dpurdie 934
            next unless ( -d $pname );
935
            Verbose ("Package discovered: $pname");
936
 
937
            if ( -f "$pname/stop" || -f "$pname/stop.$GBE_MACHTYPE" )
938
            {
939
                push @stopped, $pname;
940
                Warning("Package contains stop file: $pname");
7306 dpurdie 941
                push @locationData, join($;, $pname, ':STOP:');
6133 dpurdie 942
                next;
943
            }
944
 
945
            #
946
            #   Locate the build files in each package
947
            #   Scan the build files and extract dependancy information
948
            #
949
            my $bscanner = BuildFileScanner( $pname, 'build.pl',
950
                                                     '--LocateAll',
7306 dpurdie 951
                                                     '--LimitDepth=' . $scanDepth,
6133 dpurdie 952
                                                     '--ScanDependencies' );
953
            $bscanner->scan();
954
            my @blist = $bscanner->getInfo();
955
            unless ($quiet) {
956
                Warning ("Package does not have build files: $pname") unless ( @blist );
957
                Warning ("Package has multiple build files: $pname") if ( $#blist > 0 );
958
            }
959
            push @build_list, @blist;
960
            push @locationData, $bscanner->getLocation();
7306 dpurdie 961
 
962
            #
963
            #   Determine max build file depth - just to show user
964
            #
965
            foreach ( @blist)
966
            {
967
                my $count = () = $_->{dir} =~ m~/~g;
968
                $buildFileDepth = $count if ($count > $buildFileDepth)
969
            }
970
 
971
 
6133 dpurdie 972
        }
7306 dpurdie 973
        Message ("Max Build File Depth : " . ($buildFileDepth + 1));
974
        Message ("Build File Scan Depth: ". $scanDepth) if ($SCANDEPTH ne $scanDepth);
6133 dpurdie 975
 
7306 dpurdie 976
 
227 dpurdie 977
        #
6133 dpurdie 978
        #   Save (cache) location information
227 dpurdie 979
        #
6133 dpurdie 980
        FileAppend($cacheFile, @locationData);
227 dpurdie 981
    }
982
 
983
    #
984
    #   Process each build file and extract
985
    #       Name of the Package
986
    #       Dependency list
987
    #   Build up a hash of dependence information
988
    #
989
 
990
    my %depends;
299 dpurdie 991
    my %multi;
245 dpurdie 992
    foreach my $be ( @build_list )
227 dpurdie 993
    {
245 dpurdie 994
        Verbose( DisplayPath ("Build file: " . $be->{dir} . " Name: " . $be->{file} ));
359 dpurdie 995
        #
7301 dpurdie 996
        #   Sandbox 
359 dpurdie 997
        #       Set a suitable display name
998
        #       Set a suitable tag
999
        #
7301 dpurdie 1000
        $be->{dname} = $be->{mname};
1001
        $be->{tag}   = $be->{package};
4184 dpurdie 1002
        $be->{fname} = join ('_', $be->{name}, $be->{version});
7307 dpurdie 1003
        if (length ($be->{dname}) > $maxDname ) {
1004
             $maxDname = length ($be->{dname});
1005
        }
359 dpurdie 1006
 
245 dpurdie 1007
#        DebugDumpData ("be", $be );
227 dpurdie 1008
 
1009
        #
299 dpurdie 1010
        #   Catch multiple builds for the same package
1011
        #   Report later - when we have all
1012
        #
359 dpurdie 1013
        next unless ( $be->{dname} );
7307 dpurdie 1014
        push @{$multi{$be->{dname}}},$be;
227 dpurdie 1015
    }
1016
 
7307 dpurdie 1017
    #
1018
    #   Detect, process and report packages that have multiple builders
1019
    #       An error that can be ignored
1020
    #
359 dpurdie 1021
    foreach my $dname ( sort keys %multi )
299 dpurdie 1022
    {
7307 dpurdie 1023
        my $errFn = $opt_multiBuilders ? \&Warning : \&ReportError;
1024
        if ( scalar @{$multi{$dname}} > 1 )
1025
        {
1026
            my @dirList;
1027
            foreach my $be (@{$multi{$dname}}) {
1028
                push @dirList, $be->{dir};
1029
            }           
1030
            &$errFn("Multiple builders for : $dname", @dirList ) unless $opt_multiBuilders > 1;
1031
        }
1032
        else
1033
        {
1034
            #
1035
            #   Add into dependency struct
1036
            #
1037
            foreach my $be (@{$multi{$dname}}) {
1038
                $depends{$be->{tag}} = $be;
1039
            }
1040
        }
299 dpurdie 1041
    }
7307 dpurdie 1042
    %multi = ();
299 dpurdie 1043
    ErrorDoExit();
1044
 
245 dpurdie 1045
#DebugDumpData ("depends", \%depends );
1046
 
227 dpurdie 1047
    #
255 dpurdie 1048
    #   Remove any dependencies to 'external' packages
227 dpurdie 1049
    #   These will not be met internally and can be regarded as constant
1050
    #
1329 dpurdie 1051
    #   Split 'depends' into internal (ideps) and external (edeps)
1052
    #       edeps : External Dependencies
1053
    #               Key:        Name;Version
1054
    #               Value:      'tag' - index into packages
1055
    #       ideps : Internal Dependencies
1056
    #               Key:        'tag'   - Index into packages
1057
    #               Value:      'dname' - Display Name
1058
    #
227 dpurdie 1059
    foreach my $key ( keys %depends )
1060
    {
1061
        foreach my $build ( keys( %{$depends{$key}{depends}} ))
1062
        {
1063
            unless (exists $depends{$build})
1064
            {
1329 dpurdie 1065
                $depends{$key}{'edeps'}{$depends{$key}{depends}{$build}} = $build;
227 dpurdie 1066
                delete ($depends{$key}{depends}{$build}) ;
1067
                Verbose2( "Not in set: $build");
1068
            }
1069
            else
1070
            {
1329 dpurdie 1071
                $depends{$key}{'ideps'}{$build} = $depends{$build}{dname};
227 dpurdie 1072
            }
1073
        }
1074
    }
359 dpurdie 1075
 
1076
#DebugDumpData ("depends", \%depends );
1077
 
1078
    #
1079
    #   Determine package build order
1080
    #       Scan the list of packages in the build set and determine
1081
    #       those with no dependencies. These can be built.
1082
    #       Remove those packages as dependents from all packages
1083
    #       Repeat.
1084
    #
6133 dpurdie 1085
    #
1086
    #   Determine the build order
1087
    #
1088
    @build_order = ();
1089
    my $more = 1;
1090
    my $level = 0;
1329 dpurdie 1091
    my %found    = map { $_ => 1 } @opt_ignorePackage;
1092
    my %notFound = map { $_ => 1 } @opt_justPackage;
1093
    my $scan_start = 0;
1094
    my $scan_stop = 0;
1095
    my $scan_active = ($opt_fromPackage) ? 0 : 1;
1096
    $scan_active = 0 if ( !$opt_fromPackage && !$opt_fromPackage && !@opt_ignorePackage && @opt_justPackage );
1097
 
227 dpurdie 1098
    while ( $more )
1099
    {
1100
        $more = 0;
1101
        $level++;
1102
        my @build;
1103
 
1104
        #
1105
        #   Locate packages with no dependencies
1106
        #
6133 dpurdie 1107
        foreach my $key ( sort {lc($a) cmp lc($b)} keys %depends )
227 dpurdie 1108
        {
1109
            next if ( keys( %{$depends{$key}{depends}} ) );
1110
            push @build, $key;
1111
        }
1112
 
1113
        foreach my $build ( @build )
1114
        {
1115
            $more = 1;
1329 dpurdie 1116
            my $fe = $depends{$build};
1117
            my $scan_add = $scan_active ? 1 : 0;
1118
 
4184 dpurdie 1119
            if ( $opt_fromPackage && (($fe->{mname} eq $opt_fromPackage) || ($fe->{name} eq $opt_fromPackage) || ($fe->{fname} eq $opt_fromPackage)))
1329 dpurdie 1120
            {
1121
                $scan_add = 1;
1122
                $scan_active = 1;
1123
                $scan_start = 1;
1124
            }
1125
 
4184 dpurdie 1126
            if ( $opt_toPackage && (($fe->{mname} eq $opt_toPackage) || ($fe->{name} eq $opt_toPackage) || ($fe->{fname} eq $opt_toPackage)))
1329 dpurdie 1127
            {
1128
                $scan_add = 0;
1129
                $scan_active = 0;
1130
                $scan_stop = 1;
1131
            }
1132
 
1133
            if ( @opt_justPackage )
1134
            {
1135
                foreach my $pname ( @opt_justPackage )
1136
                {
4184 dpurdie 1137
                    if ( (($fe->{mname} eq $pname) || ($fe->{name} eq $pname) || ($fe->{fname} eq $pname)))
1329 dpurdie 1138
                    {
1139
                        $scan_add = 1;
1140
                        delete $notFound{$pname};
1141
                    }
1142
                }
1143
            }
1144
 
1145
            if ( @opt_ignorePackage )
1146
            {
1147
                foreach my $pname ( @opt_ignorePackage )
1148
                {
4184 dpurdie 1149
                    if ( (($fe->{mname} eq $pname) || ($fe->{name} eq $pname) || ($fe->{fname} eq $pname)))
1329 dpurdie 1150
                    {
1151
                        $scan_add = 0;
1152
                        delete $found{$pname};
1153
                    }
1154
                }
1155
            }
1156
 
6133 dpurdie 1157
            #
1158
            #   Test for a skip marker
1159
            #
1160
            my $skipFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', '_skip.'. $fe->{dname});
1161
            my $skipMachFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', '_skip.' . $GBE_MACHTYPE . '.' . $fe->{dname});
1162
            if ( -f $skipFile || -f $skipMachFile )
1163
            {
1164
                Warning("Package marked for skip: $fe->{dname}, $fe->{dir}") unless $quiet;
1165
                $scan_add = 0;
1166
                $fe->{buildSkip} = 1;
1167
            }
1168
 
227 dpurdie 1169
            $fe->{level} = $level;
1329 dpurdie 1170
            $fe->{buildActive} = $scan_add;
227 dpurdie 1171
            $packages{$build} = $fe;
6133 dpurdie 1172
            push (@build_order, $fe);
227 dpurdie 1173
            delete $depends{$build};
1174
            delete $fe->{depends};                          # remove now its not needed
1175
        }
1176
 
1177
        foreach my $key ( keys %depends )
1178
        {
1179
            foreach my $build ( @build )
1180
            {
1181
                delete $depends{$key}{depends}{$build};
1182
            }
1183
        }
1184
    }
1185
 
1186
    #
1329 dpurdie 1187
    #   Detect bad user specifications
1188
    #
1189
    ReportError ("Specified FromPackage not found: $opt_fromPackage") if ( $opt_fromPackage && !$scan_start );
1190
    ReportError ("Specified ToPackage not found: $opt_toPackage") if ( $opt_toPackage && !$scan_stop );
1191
    ReportError ("Specified ExactPackages not found: ", keys( %notFound) ) if ( %notFound );
1192
    ReportError ("Specified IgnorePackages not found: ", keys( %found) ) if ( %found );
1193
    ErrorDoExit();
1194
 
1195
    #
6133 dpurdie 1196
    #   Just to be sure to be sure
1197
    #
1198
    if ( keys %depends )
1199
    {
1200
        #DebugDumpData ("depends", \%depends );
1201
        Error( "Internal algorithm error: Bad dependancy walk",
1202
               "Possible circular dependency");
1203
    }
1204
 
1205
    #
1206
    #   Determine FULL internal dependency list for each package
1207
    #       Walk packages in build order so that we can leverage the calculations
1208
    #       already done.
1209
    # 
1210
    foreach my $fe ( @build_order )
1211
    {
1212
        my @pkgBuildOrder;
1213
        my %pkgSeen;
1214
        my $key = $fe->{tag};
1215
        if (exists $packages{$key}{'ideps'})
1216
        {
1217
            foreach ( keys %{$packages{$key}{'ideps'}} )
1218
            {
1219
                foreach my $ikey (@{$packages{$_}{'AllIdepsOrder'}})
1220
                {
1221
                    push @pkgBuildOrder, $ikey unless $pkgSeen{$ikey};
1222
                    $pkgSeen{$ikey} = 1;
1223
                }
1224
            }
1225
        }
1226
        push @pkgBuildOrder, $key;
1227
        $fe->{'AllIdepsOrder'} = \@pkgBuildOrder;
1228
 
1229
        #
1230
        #   Is this package in the current directory
1231
        #
1232
        if ($startDir)
1233
        {
1234
            my $matchBase = $startDir . '/'; 
1235
            if ($matchBase =~ m~^$fe->{dir}/~)
1236
            {
1237
                $fe->{buildCurrent} = 1;
1238
                $currentPkgTag = $key;
1239
            }
1240
        }
1241
    }
1242
 
1243
    #
1244
    #   Now that we have a full dependency list for each package we can calculate a full
1245
    #   usage list. This is a complete list of all package that depend on a package both directly 
1246
    #   and inderectly. Useful for regression testing
1247
    #   
1248
    foreach my $fe ( @build_order )
1249
    {
1250
        foreach my $itag (@{$fe->{'AllIdepsOrder'}})
1251
        {
1252
            next if ($itag eq $fe->{tag});
1253
            push @{$packages{$itag}{usedBy}}, $fe->{tag};
1254
        }
1255
    }
1256
 
1257
    #
1258
    #   If the CWD is within a package then limit the build to that package and
1259
    #   its dependents, unless user specifies entire sandbox.
1260
    #   
1261
    if ($currentPkgTag && ! $opt_allSandbox )
1262
    {
1263
        if (!$opt_processUsedBy )
1264
        {
1265
            #
1266
            #   Reform the build_order to reflect the current sandbox
1267
            #   The @build_order is an array of package entries
1268
            #   The per-package build order is an array of keys
1269
            #
1270
            my @pkgOrder;
1271
            foreach ( @{$packages{$currentPkgTag}{AllIdepsOrder}})
1272
            {
1273
                push @pkgOrder,  $packages{$_} ;
1274
            }
1275
 
1276
            # Reform the build order based on original level
1277
            #   Simply done to look pretty - and be consistient when compared with the entire sandbox
1278
            @build_order = sort {$a->{level} <=> $b->{level}} @pkgOrder;
1279
 
1280
        }
1281
        else
1282
        {
1283
            #
1284
            #   Reform the build order to reflect the consumers of the current package
1285
            #   This does not include the current package. The assumption is that the package
1286
            #   has been built. 
1287
            #
1288
            #   The @build_order is an array of package entries
1289
            #   The per-package build order is an array of keys
1290
            #
1291
            my @pkgOrder;
1292
            foreach ( @{$packages{$currentPkgTag}{'usedBy'}})
1293
            {
1294
                push @pkgOrder,  $packages{$_} ;
1295
            }
1296
 
1297
            # Reform the build order based on original level
1298
            #   Simply done to look pretty - and be consistient when compared with the entire sandbox
1299
            @build_order = sort {$a->{level} <=> $b->{level}} @pkgOrder;
1300
        }
1301
    }
1302
    else
1303
    {
1304
        $opt_allSandbox = 1;
1305
    }
1306
 
1307
    #
1329 dpurdie 1308
    #   Calculate the external dependencies
1309
    #       Only process packages that are a part of the build
1310
    #
1311
    #   extern_deps structure
1312
    #       Hash key: 'tag'   - Index into packages
1313
    #          Value: Hash of:
1314
    #                 Key  : Name;Version
1315
    #                 Value: Array of: 'tags' (Index into packages)
1316
    #                                   of packages that use the external
1317
    #                                   component.
1318
    {
6133 dpurdie 1319
        Verbose ("Calculate external dependencies on packages in build");
1329 dpurdie 1320
        %extern_deps = ();
1321
 
6133 dpurdie 1322
        foreach my $pe (@build_order)
1329 dpurdie 1323
        {
6133 dpurdie 1324
                next unless ( $pe->{buildActive} );
1325
                next unless ( $pe->{'edeps'} );
1326
                foreach ( keys %{$pe->{'edeps'}} )
1329 dpurdie 1327
                {
6133 dpurdie 1328
                    push @{$extern_deps{$pe->{'edeps'}{$_}} {$_} }, $pe->{tag};
1329 dpurdie 1329
                }
1330
        }
1331
    }
1332
 
227 dpurdie 1333
 
1329 dpurdie 1334
#   DebugDumpData("Packages", \%packages);
359 dpurdie 1335
#   DebugDumpData ("Order", \@build_order);
1336
#   DebugDumpData("External Depends", \%extern_deps );
227 dpurdie 1337
}
1338
 
1339
#-------------------------------------------------------------------------------
6133 dpurdie 1340
# Function        : calc_rootFingerPrint 
1341
#
1342
# Description     : Calculate a finger print of all the directories in the
1343
#                   sandbox root.
1344
#                   
1345
#                   Used to determine if the user has added or remove a package
1346
#                   from the sandbox
1347
#
1348
# Inputs          : None
1349
#
1350
# Returns         : SHA1 hash
1351
#
1352
sub calc_rootFingerPrint
1353
{
1354
    my $fpSha1 = Digest->new("SHA-1");
1355
 
1356
    foreach my $pname ( glob("*") )
1357
    {
1358
        next if ( $pname =~ m~^\.~ );
1359
        next if ( $pname =~ m~dpkg_archive$~ );
1360
        next if ( $pname =~ m~^CVS$~ );
1361
        next unless ( -d $pname );
1362
 
1363
        $fpSha1->add($pname);
1364
 
1365
        #
1366
        #   Include stop files in fingerprint too
1367
        #
1368
        $fpSha1->add("$pname/stop" ) if ( -f "$pname/stop" ); 
1369
        $fpSha1->add("$pname/stop.$GBE_MACHTYPE" ) if ( -f "$pname/stop.$GBE_MACHTYPE" ); 
1370
 
1371
    }
1372
    return $fpSha1->hexdigest;
1373
}
1374
 
1375
#-------------------------------------------------------------------------------
227 dpurdie 1376
# Function        : cmd
1377
#
1378
# Description     : Execute a command in all the sandboxes
1379
#                       Locate the base of the sandbox
1380
#                       Locate all packages in the sandbox
1381
#                       Locate all build files in each sandbox
1382
#                       Determine build order
1383
#                       Issue commands for each sandbox in order
1384
#
255 dpurdie 1385
# Inputs          : Arguments passed to jats build
227 dpurdie 1386
#
1387
# Returns         : Will exit
1388
#
1389
sub cmd
1390
{
1329 dpurdie 1391
    my ($hcmd, @cmd_opts ) = @_;
7308 dpurdie 1392
    my $opt_reverse;
359 dpurdie 1393
 
1394
    Getopt::Long::Configure('pass_through');
7308 dpurdie 1395
    getOptionsFromArray ( \@cmd_opts,
1396
                          'reverse!' => \$opt_reverse,
1397
                          ) || Error ("Invalid command line" );
359 dpurdie 1398
    SubCommandHelp( $opt_help, $hcmd) if ($opt_help  );
1399
 
227 dpurdie 1400
    #
1401
    #   Determine Sandbox information
1402
    #   Populate global variables
1403
    #
1404
    calc_sandbox_info();
7308 dpurdie 1405
    if ($opt_reverse) {
1406
        @build_order = reverse @build_order;
1407
    }
227 dpurdie 1408
    foreach my $fe ( @build_order )
1409
    {
6133 dpurdie 1410
        my $active = displayHeader($fe, { showPath => 1 });
227 dpurdie 1411
 
6133 dpurdie 1412
        if ($active)
1413
        {
1414
            my $dir = $fe->{dir};
1415
            my $result = JatsCmd( "-cd=$dir", @cmd_opts);
1416
            if ( $result ) {
1417
                if ( $opt_keepgoing ) {
1418
                    Warning ("Cmd failure");
1419
                } else {
1420
                    Error   ("Cmd failure");
1421
                }
2054 dpurdie 1422
            }
1423
        }
227 dpurdie 1424
    }
1425
 
1426
    exit 0;
1427
}
1428
 
1429
#-------------------------------------------------------------------------------
331 dpurdie 1430
# Function        : buildcmd
1431
#
1432
# Description     : Build the entire sandbox
1433
#                   The all and the build are similar.
1434
#                   Its not really useful to do a build without a make
1435
#                   so we don't try
1436
#
1437
# Inputs          : Arguments passed to jats make
1438
#
1439
#
1440
# Returns         : Will exit
1441
#
1442
 
1443
sub buildcmd
1444
{
337 dpurdie 1445
    my ($cmd, @cmd_opts) = @_;
331 dpurdie 1446
    my @build_opts;
337 dpurdie 1447
    my @make_opts;
6133 dpurdie 1448
    my $opt_skip = 1;
1449
    my $opt_clean = 0;
331 dpurdie 1450
 
1451
    #
359 dpurdie 1452
    #   Extract and options
1453
    #
1454
    Getopt::Long::Configure('pass_through');
6133 dpurdie 1455
    getOptionsFromArray ( \@cmd_opts,
1456
                          'skip!' => \$opt_skip,
1457
                          'clean!' => \$opt_clean,
1458
    ) || Error ("Invalid command line" );
359 dpurdie 1459
    SubCommandHelp( $opt_help, "Command $cmd") if ($opt_help );
361 dpurdie 1460
 
359 dpurdie 1461
    #
331 dpurdie 1462
    #   Insert default options
1463
    #
1464
    push @build_opts, '-noforce' if ( $cmd eq 'all' );
6133 dpurdie 1465
    push @build_opts, '-force'   if ( $cmd ne 'all' );
331 dpurdie 1466
 
337 dpurdie 1467
    #
1468
    #   Attempt to split the options into build and make options
1469
    #   Only handle the often used options to build.
1470
    #
1471
    foreach  ( @cmd_opts )
1472
    {
1473
        if ( m/^-cache/ || m/^-package/ || m/^-forcebuildpkg/ || m/-expert/) {
1474
            push @build_opts, $_;
1475
        } else {
1476
            push @make_opts, $_;
1477
        }
1478
    }
1479
 
6133 dpurdie 1480
    push @make_opts, 'all'  unless ( @make_opts );
331 dpurdie 1481
 
1482
    #
1483
    #   Determine Sandbox information
1484
    #   Populate global variables
1485
    #
1486
    calc_sandbox_info();
1487
    foreach my $fe ( @build_order )
1488
    {
6133 dpurdie 1489
        my $active = displayHeader($fe, { showPath => 1 });
1490
        if ($active) {
331 dpurdie 1491
 
6133 dpurdie 1492
            #
1493
            #   Determine build success tag file
1494
            #   If the tag file exists, then see if any files in the files in the package source are more
1495
            #   recent than the tag file
1496
            #
1497
            my $mustBuild = 1;
1498
            my $sigMatch = 0;
1499
            my $tagFile = getPkgFingerPrintFile($fe);
1500
 
1501
            if ( -e $tagFile ) {
1502
                if ( TagFileMatch($tagFile, genPkgFingerPrint($fe, 'Test')) ) {
1503
                    $sigMatch = 1;
1504
                    if ($opt_skip) {
1505
                        $mustBuild = 0;
1506
                    } else {
1507
                        $mustBuild = 2;
1508
                    }
1509
                } else {
1510
                }
1511
            } else {
1512
                    $mustBuild = 2;
1513
                    $sigMatch = -1;
1514
            }
1515
 
7301 dpurdie 1516
Debug0("Skip: $opt_skip, sigMatch: $sigMatch, Build: $mustBuild, Opts: @make_opts",);
6133 dpurdie 1517
            if ($mustBuild)
1518
            {
1519
                if (1)
1520
                {
1521
                    unlink $tagFile;
1522
                    my $dir = $fe->{dir};
1523
                    my $result;
1524
 
1525
                    $result = JatsCmd( "-cd=$dir", 'build', @build_opts);
1526
                    if ($result)
1527
                    {
1528
                        if ($opt_keepgoing)
1529
                        {
1530
                            Warning( "Build Cmd failure - Keep going");
1531
                            next;
1532
                        }
7307 dpurdie 1533
                        Error ("Build Cmd failure: $dir");
6133 dpurdie 1534
                    }
1535
 
1536
                    #
1537
                    #   Skip make if we have a prebuilt package
1538
                    #
1539
                    my $mustMake = 1;
7301 dpurdie 1540
                    if ($mustBuild == 2)
1541
                    {
1542
                        my $pbFound = locatePreBuiltPackage($fe);
1543
                        Debug0("Prebuilt: $pbFound");
1544
                        $mustMake = 0 if $pbFound;
1545
                    }
6133 dpurdie 1546
 
1547
                    if ($mustMake)
1548
                    {
1549
                        JatsCmd( "-cd=$dir", 'make', 'clean') if $opt_clean;
1550
                        $result = JatsCmd( "-cd=$dir", 'make',  @make_opts);
1551
                        if ($result)
1552
                        {
1553
                            if ($opt_keepgoing)
1554
                            {
1555
                                Warning( "Make Cmd failure - Keep going");
1556
                                next;
1557
                            }
7307 dpurdie 1558
                            Error ("Make Cmd failure: $dir");
6133 dpurdie 1559
                        }
1560
                    }
1561
                }
1562
 
7307 dpurdie 1563
                Verbose ("Save fingerprint: $tagFile");
6133 dpurdie 1564
                FileCreate( $tagFile, genPkgFingerPrint($fe,'Generation') );
1565
            }
1566
            else
1567
            {
1568
                Message ("No file changes since last build. Skipping")
1569
            }
1570
        }
331 dpurdie 1571
    }
1572
 
1573
    exit 0;
1574
}
1575
 
1576
#-------------------------------------------------------------------------------
273 dpurdie 1577
# Function        : clean
1578
#
1579
# Description     : Execute a command in all the sandboxes
1580
#                       Locate the base of the sandbox
1581
#                       Locate all packages in the sandbox
1582
#                       Locate all build files in each sandbox
1583
#                       Determine build order
1584
#                       Issue commands for each sandbox in order
1585
#
1586
# Inputs          : Arguments passed to jats build
1587
#
1588
# Returns         : Will exit
1589
#
1590
sub clean
1591
{
1329 dpurdie 1592
    my ($mode, @cmd_opts ) = @_;
359 dpurdie 1593
 
273 dpurdie 1594
    #
359 dpurdie 1595
    #   Extract and options
1596
    #
1597
    Getopt::Long::Configure('pass_through');
1329 dpurdie 1598
    getOptionsFromArray ( \@cmd_opts ) || Error ("Invalid command line" );
359 dpurdie 1599
    SubCommandHelp( $opt_help, "Clean") if ($opt_help );
1600
 
1601
    #
273 dpurdie 1602
    #   Determine Sandbox information
1603
    #   Populate global variables
1604
    #
1605
    calc_sandbox_info();
1606
 
1607
    my @cmd = $mode eq 'clobber' ? ('clobber') : ('make', 'clean' );
1608
 
1609
    #
1610
    #   Clobber and clean need to be done in the reverse order
1611
    #
1612
    foreach my $fe ( reverse @build_order )
1613
    {
6133 dpurdie 1614
        my $active = displayHeader($fe, { showPath => 1 });
1615
        if ($active)
1616
        {
1617
            my $dir = $fe->{dir};
1618
            my $result = JatsCmd( "-cd=$dir", @cmd, @cmd_opts);
1619
            if ($result)
1620
            {
1621
                if ($opt_keepgoing)
1622
                {
1623
                    Warning("Command Failure");
1624
                }
1625
                else
1626
                {
1627
                    Error ("Cmd failure") if ( $result );
1628
                }
1629
            }
1630
        }
273 dpurdie 1631
    }
1632
 
1633
    exit 0;
1634
}
1635
 
1636
 
1637
#-------------------------------------------------------------------------------
337 dpurdie 1638
# Function        : cache
1639
#
1640
# Description     : Cache external packages into the sandbox
1641
#
1642
# Inputs          : @opts                   - User options
1643
#
1644
# Returns         : Nothing
1645
#
1646
sub cache
1647
{
1329 dpurdie 1648
    my (@cmd_opts) = @_;
337 dpurdie 1649
 
1329 dpurdie 1650
    getOptionsFromArray ( \@cmd_opts ) || Error ("Invalid command line" );
1651
    SubCommandHelp( $opt_help, "Cache") if ($opt_help || $#cmd_opts >= 0 );
359 dpurdie 1652
 
337 dpurdie 1653
    #
1654
    #   Determine Sandbox information
1655
    #   Populate global variables
1656
    #
1657
    Message("Cache External Dependencies");
6133 dpurdie 1658
    Error ("GBE_DPKG_CACHE not defined") unless $GBE_DPKG_CACHE;
337 dpurdie 1659
    calc_sandbox_info();
1660
 
6133 dpurdie 1661
    JatsTool ('cache_dpkg', "core_devl/jats2_current" );
1662
 
337 dpurdie 1663
    #
1329 dpurdie 1664
    #   Walk the list of external dependencies and cache each one
337 dpurdie 1665
    #
1666
    foreach my $de ( sort keys %extern_deps )
1667
    {
1668
        my @vlist = keys %{$extern_deps{$de}};
359 dpurdie 1669
        foreach my $pve ( @vlist )
337 dpurdie 1670
        {
359 dpurdie 1671
            my ($pn,$pv) = split( $; , $pve );
1672
            Message ("Cache ${pn} ${pv}");
1673
            JatsTool ('cache_dpkg', "${pn}/${pv}" );
337 dpurdie 1674
        }
1675
    }
361 dpurdie 1676
 
337 dpurdie 1677
    exit 0;
361 dpurdie 1678
 
337 dpurdie 1679
}
1680
 
359 dpurdie 1681
#-------------------------------------------------------------------------------
1682
# Function        : populate
1683
#
1684
# Description     : Populate the sandbox with package versions
1685
#
1686
#
1687
# Inputs          : commands            - Array of command line arguments
1688
#                   Mode-0:
1689
#
1690
#                       pkg_name pkg_version        - Import files for named package
1691
#                       options:
1692
#                           -recurse                - Import dependent packages too
1693
#                           -missing                - Import dependencies not in dpkg_archive
1694
#                           -test                   - Show what would be done
1695
#                           -extractfiles           - Extract file, no view
1696
#
1697
#
1698
#
1699
#
1700
# Returns         : Does not return
1701
#
1702
use JatsRmApi;
1703
use DBI;
337 dpurdie 1704
 
359 dpurdie 1705
#
1706
#   Data Base Interface
1707
#
1708
my $RM_DB;
1709
my $PopLevel = 0;
1710
my %PopPackage;
1711
my @StrayPackages;
1712
my @PopBase;
1713
 
1714
sub populate
1715
{
1329 dpurdie 1716
    my (@cmd_opts ) = @_;
359 dpurdie 1717
    my $opt_missing = 0;
1718
    my $opt_recurse = 0;
1719
    my $opt_test = 0;
1329 dpurdie 1720
    my $opt_show = 0;
359 dpurdie 1721
    my $opt_extractfiles;
1722
    my @opt_extract = qw(-extract);
1723
    my @opt_fnames;
1329 dpurdie 1724
    my @opt_exclude;
1725
    my $opt_all;
359 dpurdie 1726
 
1329 dpurdie 1727
 
359 dpurdie 1728
    Getopt::Long::Configure('pass_through');
1329 dpurdie 1729
    getOptionsFromArray ( \@cmd_opts,
1730
                "all"               => \$opt_all,
1731
                "missing"           => \$opt_missing,
1732
                "test"              => \$opt_test,
1733
                "show"              => \$opt_show,
1734
                "recurse:100"       => \$opt_recurse,
1735
                'excludePackage:s'  => sub{ opts_add2List( \@opt_exclude, @_ )},
359 dpurdie 1736
                ) || Error ("Invalid command line" );
1737
 
1738
    SubCommandHelp( $opt_help, "Populate Sandbox") if ($opt_help );
1739
 
1740
    #
1329 dpurdie 1741
    #   Sanity tests
1742
    #
1743
    Error ("Populate: -missing and -all options are mutually exclusive")
1744
        if ( $opt_missing && $opt_all );
1745
 
1746
    #
359 dpurdie 1747
    #   Extract options for the jats extract utility
1748
    #
1329 dpurdie 1749
    foreach ( @cmd_opts )
359 dpurdie 1750
    {
1751
        if ( m~^-~ ) {
1752
            push ( @opt_extract, $_);
1753
        } else {
1754
            push ( @opt_fnames, $_);
1755
        }
1756
    }
1757
 
1758
    #
1759
    #   Allow exactly zero or two 'bare' arguments
1760
    #   Create an array of package-versions to be processed.
1761
    #
1762
    if ( $#opt_fnames >= 0 )
1763
    {
365 dpurdie 1764
        Error ("Populate: Must specify both a package name and version")
359 dpurdie 1765
            if ( $#opt_fnames != 1 );
1766
        push @PopBase, join( $;, @opt_fnames );
1767
    }
1329 dpurdie 1768
    elsif ( $opt_missing || $opt_all )
359 dpurdie 1769
    {
1770
        #
1771
        #   User has not provided a package name to extract
1329 dpurdie 1772
        #   Assume that the user will want all or missing dependencies
359 dpurdie 1773
        #
1774
        #   Determine packages that are not present
1775
        #
1776
        calc_sandbox_info();
1777
 
1778
        #
1779
        # Scan for missing dependencies
1780
        #
1781
        foreach my $de ( sort keys %extern_deps )
1782
        {
1783
            my @vlist = keys %{$extern_deps{$de}};
1784
            foreach my $pve ( @vlist )
1785
            {
1786
                my ($pn,$pv) = split( $; , $pve );
1329 dpurdie 1787
                unless ($opt_missing && check_package_existance( $pn, $pv ))
359 dpurdie 1788
                {
1789
                    push @PopBase, join( $;, $pn , $pv );
1790
                }
1791
            }
1792
        }
1793
    }
1794
    else
1795
    {
1796
        Error ("No command or option specified. See help for command usage");
1797
    }
1798
 
1799
    #
1800
    #   Process the list of package-versions
1801
    #   These are top level packages. Get details from Release Manager
1802
    #
1803
    #DebugDumpData("Data", \@PopBase );
1804
    $PopLevel = 0;
1805
    foreach my $entry ( @PopBase )
1806
    {
1807
        my ($pname, $pver ) = split( $; , $entry);
1808
 
1809
        my $pv_id = getPkgDetailsByName($pname, $pver);
1810
        Error ("populate: $pname, $pver not found in Release Manager" )
1811
            unless ( $pv_id );
1812
        getPkgDetailsByPV_ID($pv_id);
1813
    }
1814
    #
1815
    #   If recursing then process packages that have yet to
1816
    #   be processed. At the start there will be the initial user specified
1817
    #   packages on the list. Place a marker at the end so that we can
1818
    #   determine how far we are recursing down the dependency tree.
1819
    #
1329 dpurdie 1820
    $opt_recurse = ($opt_all ? 100 : $opt_recurse);
359 dpurdie 1821
    if ( $opt_recurse )
1822
    {
1823
        my $marker = join($; , '_NEXT_LEVEL_', 0, 0 );
1824
        push @StrayPackages, $marker;
1825
        $PopLevel++;
1826
 
1827
        while ( $#StrayPackages >= 0 )
1828
        {
1829
            my ($name, $ver, $pv_id) = split($;, shift @StrayPackages);
1830
 
1831
            #
1832
            #   Marker.
1833
            #   Increment the level of recursion
1834
            #   Detect end conditions
1835
            #
1836
            if ( $name eq '_NEXT_LEVEL_' )
1837
            {
1838
                last unless ($#StrayPackages >= 0 );
1839
                $PopLevel++;
1840
                last if ( $PopLevel > $opt_recurse );
1841
                push @StrayPackages, $marker;
1842
                next;
1843
            }
1844
 
1845
            next if ( exists $PopPackage{$name}{$ver}{done} );
1846
            getPkgDetailsByPV_ID ( $pv_id );
1847
            #print "Stray: $pv_id, $name, $ver\n";
1848
        }
1849
    }
1850
    #DebugDumpData("Data", \%PopPackage );
1851
 
1852
    #
1853
    #   Determine packages that need to be extracted
1329 dpurdie 1854
    #   Sort alphabetically - case insensitive
359 dpurdie 1855
    #
1329 dpurdie 1856
    foreach my $pname ( sort {lc($a) cmp lc($b)} keys %PopPackage )
359 dpurdie 1857
    {
1329 dpurdie 1858
        pkgscan:
359 dpurdie 1859
        foreach my $pver ( sort keys %{$PopPackage{$pname}} )
1860
        {
1861
            #
1862
            #   Create a nice view name for the extraction
365 dpurdie 1863
            #   Will also be used to test for package existence
359 dpurdie 1864
            #
1865
            my $vname = "$pname $pver";
1866
            $vname =~ s~ ~_~g;
1867
            $vname =~ s~__~~g;
1868
 
1869
            if ( -d "$GBE_SANDBOX/$vname" )
1870
            {
1871
                Warning("Package already in sandbox: $pname, $pver");
1872
                next;
1873
            }
1874
 
1875
            #
1876
            #   If scanning for missing packages, then examine archives
1877
            #   for the packages existence. Don't do this on level-0 packages
1878
            #   These have been user specified.
1879
            #
1880
            if ( $opt_missing && $PopPackage{$pname}{$pver}{level}  )
1881
            {
1882
                my $found = check_package_existance( $pname, $pver );
1883
                if ( $found )
1884
                {
1885
                    Verbose ("Package found in archive - skipped: $pname, $pver");
1886
                    next;
1887
                }
1888
            }
1889
 
1890
            #
1329 dpurdie 1891
            #   Has the user specifically excluded this package
1892
            #   Allow three forms
1893
            #       packageName
1894
            #       packageName_Version
1895
            #       packageName.projectName
1896
            #
1897
            my $excluded;
1898
            foreach my $ename ( @opt_exclude )
1899
            {
1900
                if ( $ename eq $pname ) {
1901
                    $excluded = 1;
1902
                } elsif ($ename eq $pname .'_' . $pver ) {
1903
                    $excluded = 1;
1904
                } else {
1905
                    if ( $pver =~ m~(\.[a-z]{2,4})$~ )
1906
                    {
1907
                        $excluded = ($ename eq $pname . $1 );
1908
                    }
1909
                }
1910
 
1911
                if ( $excluded )
1912
                {
1913
                    Message ("Package excluded by user - skipped: $pname, $pver");
1914
                    next pkgscan;
1915
                }
1916
            }
1917
 
1918
            #
359 dpurdie 1919
            #   Generate commands to extract the package
1920
            #
1921
            my $vcstag = $PopPackage{$pname}{$pver}{vcstag};
1922
            my @cmd = qw(jats_vcsrelease);
1923
            push @cmd, "-view=$vname", "-label=$vcstag", @opt_extract;
1329 dpurdie 1924
            if ( $opt_show )
359 dpurdie 1925
            {
1329 dpurdie 1926
                Message ("$pname $pver");
1927
            }
1928
            elsif ( $opt_test )
1929
            {
359 dpurdie 1930
                Message "jats " . QuoteCommand (@cmd );
1931
            }
1932
            else
1933
            {
1934
                Message "Extracting: $pname $pver";
1935
                my $rv = JatsCmd (@cmd);
1936
                Error ("Package version not extracted")
1937
                    if ( $rv );
1938
            }
1939
        }
1940
    }
1941
 
1942
    #
1943
    # This command does not return
1944
    #
1945
    exit (0);
1946
}
1947
 
337 dpurdie 1948
#-------------------------------------------------------------------------------
4197 dpurdie 1949
# Function        : buildfilter 
1950
#
1951
# Description     : Manipulate the sandbox build filter
1952
#
1953
# Inputs          : Optional filter names
1954
#                       +NAME - will add filter
1955
#                       -NAME will remove it
1956
#                       NAME will set it
1957
#                   No args will just display the build filter
1958
#
1959
# Returns         : Does not return
1960
#
1961
sub buildfilter
1962
{
1963
    my (@cmd_opts ) = @_;
1964
    my @filter_list;
1965
    my $first_arg = 1;
1966
    my $modified;
1967
 
1968
    Getopt::Long::Configure('pass_through');
1969
    getOptionsFromArray ( \@cmd_opts ) || Error ("Invalid command line" );
1970
 
1971
    SubCommandHelp( $opt_help, "Buildfilter") if ($opt_help );
1972
 
1973
    #
1974
    #   Set the initial filter list
1975
    #   This will have been parsed by JATS before we get here
1976
    #
1977
    @filter_list = split( /[,\s]+/, join(',', $GBE_BUILDFILTER));
1978
 
1979
    #
1980
    #   Extract options for the jats extract utility
1981
    #
1982
    foreach ( @cmd_opts )
1983
    {
1984
        if (m~^\+(.*)~)
1985
        {
1986
            UniquePush( \@filter_list, $1);
1987
        }
1988
        elsif (m~^\-(.*)~)
1989
        {
1990
            ArrayDelete( \@filter_list, $1);
1991
        }
1992
        else
1993
        {
1994
            @filter_list = () if ($first_arg);
1995
            UniquePush( \@filter_list, $_);
1996
        }
1997
        $first_arg = 0;
1998
        $modified = 1;
1999
    }
2000
 
2001
    #
2002
    #   Display the results to the user
2003
    #
2004
    Message('BuildFilter:', @filter_list);
2005
 
2006
    #
2007
    #   Write out a new file
2008
    #
2009
    if ($modified)
2010
    {
7306 dpurdie 2011
        FileCreate($filterFile, @filter_list);
4197 dpurdie 2012
    }
2013
 
2014
    #
2015
    # This command does not return
2016
    #
2017
    exit (0);
2018
}
2019
 
2020
 
2021
#-------------------------------------------------------------------------------
359 dpurdie 2022
# Function        : getPkgDetailsByName
2023
#
2024
# Description     : Determine the PVID for a given package name and version
2025
#
2026
# Inputs          : $pname          - Package name
2027
#                   $pver           - Package Version
2028
#
361 dpurdie 2029
# Returns         :
359 dpurdie 2030
#
2031
 
2032
sub getPkgDetailsByName
2033
{
2034
    my ($pname, $pver) = @_;
2035
    my $pv_id;
2036
    my (@row);
2037
 
2038
    connectRM(\$RM_DB) unless ($RM_DB);
2039
 
2040
    # First get details for a given package version
2041
 
2042
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION" .
2043
                    " FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
2044
                    " WHERE pkg.PKG_NAME = \'$pname\' AND pv.PKG_VERSION = \'$pver\' AND pv.PKG_ID = pkg.PKG_ID";
2045
    my $sth = $RM_DB->prepare($m_sqlstr);
2046
    if ( defined($sth) )
2047
    {
2048
        if ( $sth->execute( ) )
2049
        {
2050
            if ( $sth->rows )
2051
            {
2052
                while ( @row = $sth->fetchrow_array )
2053
                {
2054
                    $pv_id = $row[0];
2055
                    my $name = $row[1];
2056
                    my $ver = $row[2];
2057
                    Verbose( "getPkgDetailsByName :PV_ID= $pv_id");
2058
                }
2059
            }
2060
            $sth->finish();
2061
        }
2062
    }
2063
    else
2064
    {
2065
        Error("Prepare failure" );
2066
    }
2067
    return $pv_id;
2068
}
2069
 
2070
#-------------------------------------------------------------------------------
2071
# Function        : getPkgDetailsByPV_ID
2072
#
2073
# Description     : Populate the Packages structure given a PV_ID
2074
#                   Called for each package in the SBOM
2075
#
2076
# Inputs          : PV_ID           - Package Unique Identifier
2077
#
2078
# Returns         : Populates Package
2079
#
2080
sub getPkgDetailsByPV_ID
2081
{
2082
    my ($PV_ID) = @_;
2083
    my $foundDetails = 0;
2084
    my (@row);
2085
 
2086
    connectRM(\$RM_DB) unless ($RM_DB);
2087
 
2088
    # First get details from pv_id
2089
 
2090
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION, release_manager.PK_RMAPI.return_vcs_tag($PV_ID)" .
2091
                    " FROM RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg " .
2092
                    " WHERE pv.PV_ID = \'$PV_ID\' AND pv.PKG_ID = pkg.PKG_ID";
2093
 
2094
    my $sth = $RM_DB->prepare($m_sqlstr);
2095
    if ( defined($sth) )
2096
    {
2097
        if ( $sth->execute( ) )
2098
        {
2099
            if ( $sth->rows )
2100
            {
2101
                while ( @row = $sth->fetchrow_array )
2102
                {
2103
                    my $pv_id       = $row[0];
2104
                    my $name        = $row[1];
2105
                    my $ver         = $row[2];
2106
                    my $vcstag      = $row[3] || '';
2107
 
2108
                    $vcstag =~ tr~\\/~/~;
2109
                    Verbose ("getPkgDetailsByPV_ID: $PV_ID, $name, $ver, $vcstag");
2110
 
2111
                    $PopPackage{$name}{$ver}{pvid} = $PV_ID;
2112
                    $PopPackage{$name}{$ver}{done} = 1;
2113
                    $PopPackage{$name}{$ver}{vcstag} = $vcstag;
2114
                    $PopPackage{$name}{$ver}{level} = $PopLevel;
2115
                    getDependsByPV_ID( $pv_id, $name, $ver );
2116
                }
2117
            }
2118
            else
2119
            {
2120
                Warning ("No Package details for: PVID: $PV_ID");
2121
            }
2122
            $sth->finish();
2123
        }
2124
        else
2125
        {
2126
            Error("getPkgDetailsByPV_ID: Execute failure", $m_sqlstr );
2127
        }
2128
    }
2129
    else
2130
    {
2131
        Error("Prepare failure" );
2132
    }
2133
}
2134
 
2135
#-------------------------------------------------------------------------------
2136
# Function        : getDependsByPV_ID
2137
#
2138
# Description     : Extract the dependancies for a given package version
2139
#
2140
# Inputs          : $pvid
2141
#
2142
# Returns         :
2143
#
2144
sub getDependsByPV_ID
2145
{
2146
    my ($pv_id, $pname, $pver) = @_;
2147
 
2148
    connectRM(\$RM_DB) unless ($RM_DB);
2149
 
2150
    #
365 dpurdie 2151
    #   Now extract the package dependencies
359 dpurdie 2152
    #
2153
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pv.PKG_VERSION, pd.DPV_ID" .
2154
                   " FROM RELEASE_MANAGER.PACKAGE_DEPENDENCIES pd, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
2155
                   " WHERE pd.PV_ID = \'$pv_id\' AND pd.DPV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
2156
    my $sth = $RM_DB->prepare($m_sqlstr);
2157
    if ( defined($sth) )
2158
    {
2159
        if ( $sth->execute( ) )
2160
        {
2161
            if ( $sth->rows )
2162
            {
2163
                while ( my @row = $sth->fetchrow_array )
2164
                {
2165
                    my $name = $row[0];
2166
                    my $ver = $row[1];
2167
 
2168
                    Verbose2( "       Depends: $name, $ver");
2169
                    unless ( exists $PopPackage{$name} && exists $PopPackage{$name}{$ver} && exists $PopPackage{$name}{$ver}{done} )
2170
                    {
2171
                        push @StrayPackages, join($;, $name, $ver, $row[2] );
2172
                    }
2173
                }
2174
            }
2175
            $sth->finish();
2176
        }
2177
    }
2178
    else
2179
    {
2180
        Error("GetDepends:Prepare failure" );
2181
    }
2182
}
2183
 
2184
#-------------------------------------------------------------------------------
1329 dpurdie 2185
# Function        : getOptionsFromArray
2186
#
2187
# Description     : Like getOptions, but handles an array
2188
#                   Provided as the version of Perl used does not have one
2189
#
2190
# Inputs          : pArray                  - Ref to array
2191
#                   ....                    - GetOptions arguments
2192
#
2193
# Returns         : 
2194
#
2195
sub getOptionsFromArray
2196
{
2197
    my ($pArray, %args) = @_;
2198
 
2199
    #
7307 dpurdie 2200
    #   Helper to parse --multiBuilders
2201
    #
2202
    my $parseMulti = sub {
2203
        my ($ref, $value) = @_;
2204
        $value = 'error' unless length($value);
2205
        my %valid = (error => 0, report => 1, ignore => 2);
2206
        unless (exists $valid{lc $value}) {
2207
            die ("Invalid option for  --$ref->{name}\n");
2208
        };
2209
        $opt_multiBuilders = $valid{lc $value};
2210
    };
2211
 
2212
 
2213
    #
1329 dpurdie 2214
    #   Common arguments
2215
    #
2216
    my %commonOptions = (
2217
        'help|h:+'          => \$opt_help,
2218
        'manual:3'          => \$opt_help,
2219
        'verbose:+'         => \$opt_verbose,
2220
        'topackage:s'       => \$opt_toPackage,
2221
        'frompackage:s'     => \$opt_fromPackage,
2222
        'justpackage:s'     => sub{ opts_add2List( \@opt_justPackage, @_ )},
2223
        'ignorepackage:s'   => sub{ opts_add2List( \@opt_ignorePackage, @_ )},
6133 dpurdie 2224
        'entireSandBox!'    => \$opt_allSandbox,
2225
        'users!'            => \$opt_processUsedBy,
2226
        'keepgoing!'        => \$opt_keepgoing,
2227
        'rescan!'           => \$opt_reScan,
7307 dpurdie 2228
        'multiBuilders:s'   => $parseMulti, 
1329 dpurdie 2229
        );
2230
 
2231
    #
2232
    #   Merge in the user options
2233
    #
2234
    @commonOptions{keys %args} = values %args;
2235
 
2236
    local ( @ARGV );
2237
    @ARGV = @$pArray;
2238
    my $rv = GetOptions ( %commonOptions );
2239
    @$pArray = @ARGV;
2240
 
2241
    ErrorConfig('verbose' => $opt_verbose );
2242
    return $rv;
2243
}
2244
 
2245
#-------------------------------------------------------------------------------
6133 dpurdie 2246
# Function        : displayHeader 
2247
#
7307 dpurdie 2248
# Description     : Display a build header, if the entry is active
2249
#                   ie: Between a --From and --To
6133 dpurdie 2250
#
2251
# Inputs          : $fe             - Build entry
7307 dpurdie 2252
#                   Hash of options
2253
#                       indent          => Text       - Indent text
2254
#                       showPath        => Bool
2255
#                       showSimplePath  => Bool
2256
#                       testFingerPrint => Bool
6133 dpurdie 2257
#
2258
# Returns         : True if this entry is to be fully process
2259
#                   False if its being skipped 
2260
#
2261
sub displayHeader
2262
{
2263
    my $fe = shift @_;
7307 dpurdie 2264
    if ($fe->{buildActive} || $fe->{buildSkip})
2265
    {
2266
        my $args = pop @_ if (@_ > 0 and UNIVERSAL::isa($_[-1],'HASH'));
2267
        #    my ($fe, %args) = @_;
6133 dpurdie 2268
 
7307 dpurdie 2269
        my $indent = $args->{indent} || '';
2270
        my $showPath = $args->{showPath};
2271
        my $showSimplePath = $args->{showSimplePath};
6133 dpurdie 2272
 
7307 dpurdie 2273
        my ($status, $estatus) = addBuildInfo($fe, $args);
2274
        $estatus = '' if $showSimplePath;
2275
 
2276
        my $msg1 = $indent . sprintf('Level:%02d [%s] Name: %s', $fe->{level}, $status, $fe->{dname} . $estatus );
2277
        if ($showSimplePath) {
2278
            my $msg1Len = length($msg1);
2279
            $msg1 = sprintf("%-*s Path: %s", 26 + $maxDname ,$msg1, $fe->{dir}); 
6133 dpurdie 2280
        }
7307 dpurdie 2281
        if ( $showPath) {
2282
            my $msg1Len = length($msg1);
2283
            if ($msg1Len < 80) {
2284
                $msg1 .= ' ' . '=' x (79 - $msg1Len);
2285
            }
2286
        }
2287
        Message( $msg1 ,  $showPath ? DisplayPath ("        Path: $fe->{dir}" ) : undef);
6133 dpurdie 2288
    }
2289
 
2290
   return $fe->{buildActive};
2291
}
2292
 
2293
#-------------------------------------------------------------------------------
2294
# Function        : addBuildInfo 
2295
#
2296
# Description     : Add some build info status
2297
#                   It will have a .sig file if its been sucessfully built
2298
#
2299
# Inputs          : $fe     - Package info 
2300
#
2301
# Returns         : True - sig file present
2302
#
2303
sub addBuildInfo
2304
{
2305
    my ($fe, $args) = @_;
2306
    my $txt = '';
2307
    my $statusB = ' ';
2308
    my $statusF = ' ';
2309
    my $statusS = ' ';
2310
 
2311
    unless ($fe->{buildActive}) {
2312
        $txt .= ($fe->{buildSkip}) ? ' (Build Skipped)' : ' (Build Suppressed)';
2313
        $statusS = ($fe->{buildSkip}) ? 'S' : 's';
2314
    }
2315
 
2316
    if ($fe->{buildCurrent})
2317
    {
2318
        $statusB = '*';
2319
        $txt .= ' (Current Package)';
2320
    }
2321
 
2322
    my $sigFile = getPkgFingerPrintFile($fe);
2323
    my $tagFile = $sigFile;
2324
    if (-f $sigFile)
2325
    {
2326
        $sigFile =~ s~ffp$~nob~;
2327
        if (-f $sigFile) {
2328
            $txt .= ' [NoBuild]';
2329
            $statusB = '-';
7301 dpurdie 2330
        } elsif (locatePreBuiltPackage($fe)) {
2331
            $txt .= ' [PreBuilt]';
2332
            $statusB = 'P';
6133 dpurdie 2333
        } else {
2334
            $txt .= ' [Built]';
2335
            $statusB = 'B';
2336
        }
2337
 
2338
        if ($args->{testFingerPrint})
2339
        {
2340
            if ( TagFileMatch($tagFile, genPkgFingerPrint($fe, 'Test')) )
2341
            {
2342
                $txt .= ' [GoodFinger]';
2343
                $statusF = 'G';
2344
            } else {
2345
                $txt .= ' [BadFinger]';
2346
                $statusF = 'b';
2347
            }
2348
        }
2349
 
2350
    }
2351
    return "$statusS$statusB$statusF", $txt ;
2352
 
2353
}
2354
 
2355
#-------------------------------------------------------------------------------
1329 dpurdie 2356
# Function        : opts_add2List
2357
#
2358
# Description     : Option processing helper
2359
#                   Add comma separated options to an array
2360
#                   User can then add items one at a time, or several at once
2361
#
2362
# Inputs          : aref        - Ref to an array to extent
2363
#                   arg2        - Option name
2364
#                   arg3        - Option value
2365
#
2366
# Returns         : 
2367
#
2368
sub opts_add2List
2369
{
2370
    my( $ref, $name, $value) = @_;
2371
    if ( $value )
2372
    {
2373
        foreach ( split(/\s*,\s*/,$value) )
2374
        {
2375
            push @{$ref}, $_;
2376
        }
2377
    }
2378
}
2379
 
2380
#-------------------------------------------------------------------------------
6133 dpurdie 2381
# Function        : genPkgFingerPrint 
2382
#
2383
# Description     : Generate a fingerprint over all files in the packages tree as
2384
#                   well as the package dependencies
2385
# 
2386
#                   Only used to detect changes to files in the subdir
2387
# 
2388
#                   This version does not actually generate a fingerprint over
2389
#                   the data file, rather the metadata of the file. This is much (much)
2390
#                   faster as there is no file i/o.
2391
#                   
2392
#                   It does assume that the file metadata will change if the file is changed
2393
#                   Will also detect the addition / deletion of files
2394
#                   
2395
#                   Note: This siganture is not machine - type safe
2396
#                         It will vary between machines (windows/Linux/...)
2397
#
2398
# Inputs          : $fe            - Package entry of the package to process
2399
#                   $mode          - Diagnostic: mode
2400
#
2401
# Returns         : A SHA1 hash over all the files
2402
#                   
2403
#
2404
sub genPkgFingerPrint
2405
{
2406
    my ($fe, $mode) = @_;
2407
    my $genPkgFingerPrintSha1;
2408
    my $genPkgFingerPrintCount;
2409
    my @fpdata;
2410
 
2411
    #
2412
    #   Get the package GbeFiles.cfg file
2413
    #       This is held in the interface directory and is created during the build
2414
    #       Since the fingerprint is only genertated AFTER a successful build the file will always
2415
    #       be available
2416
    #       
2417
    #       All we need from this file is a list of Src directories that were discovered during
2418
    #       the build. Unfortuanatley they are not always below the root of the package.
2419
    #
2420
    my $ifaceDir = getpkgInterface($fe);
2421
    return 0 unless defined $ifaceDir;
2422
    return 0 unless ToolsetFiles::GetDataFile($ifaceDir); 
2423
 
2424
    #
2425
    #   Generate a list of directories in the package
2426
    #   This is the root directory and all other Src directories discovered
2427
    #
2428
    my @dirList = ToolsetFiles::GetSubTrees($ifaceDir);
2429
    Error ("Internal:ToolsetFiles::GetDirList for $fe->{dname} not populated" ) unless @dirList;
2430
 
2431
    #
2432
    #   Create the hash
2433
    #
2434
    $genPkgFingerPrintSha1 = Digest->new("SHA-1");
2435
    push @fpdata, $mode;
2436
 
2437
    #
2438
    #   Include all dependent packages in the fingerprint
2439
    #       We are using the sandbox fingerprint of dependent packages
2440
    #       This will ensure that a change in a package will ripple through
2441
    #
2442
    foreach my $idep ( sort keys %{$fe->{ideps}})
2443
    {
2444
        my $ipkg = $packages{$idep};
2445
        my $tagFile = getPkgFingerPrintFile($ipkg); 
2446
        my $tag = TagFileRead($tagFile);
2447
        my $text = "$tagFile: $tag";
2448
        $genPkgFingerPrintSha1->add($text);
2449
#Debug0("genPkgFingerPrint: $text, ", $genPkgFingerPrintSha1->clone->hexdigest() );
2450
        push @fpdata, $text . ':' . $genPkgFingerPrintSha1->clone->hexdigest();
2451
    }
2452
 
2453
    #
2454
    #   Anonymous sub: findFile wanted function
2455
    #   Unlike the generation of the package signature, we don't need to
2456
    #   exclude any files.
2457
    #
2458
    my $wanted = sub {
2459
        my $item = $File::Find::name;
2460
 
2461
        #
2462
        #   Get file info
2463
        #       Kill of the last access time - not useful
2464
        #       
2465
        #       Need to exclude files that change during a null build
2466
        #           /interface/GbeFiles.cfg
2467
        #           /build.log
2468
        #           
2469
        #       Symlinks present problems.
2470
        #       Some packages generate symlinks as they create file system images. The
2471
        #       links are not designed to be interpreted in the context of the current
2472
        #       computer. As a result.
2473
        #           Some may be broken - on the current machine
2474
        #           Some may address files that change - ie: /proc, /var, /dev
2475
        #           Some may address files that such as /afc, /root
2476
        #       Don't want to discard all symlinks. Many of them will address package
2477
        #       dependencies and we do want to detect changes, but those changes will
2478
        #       be picked up by the packages fingerprint.
2479
        #       
2480
        #       Directories also appear to be a problem
2481
        #       The created and modified date-times appear to be modified for no good reason
2482
        #       
2483
        #       Current solution: Do not include 'stat' data for ANY symlink or directory
2484
        #
2485
        my @data = stat($item);
2486
        my $text;
2487
        if ( $item =~ m~/build.log$~ || $item =~ m~/GbeFiles.cfg$~) {
2488
            $text = "$item : SKIPPED FILE : ";
2489
 
2490
        }  elsif (-d $item ) {
2491
                $text = "$item : DIRECTORY"
2492
        }  elsif (-l $item ) {
2493
            if ( ! @data) {
2494
                $text = "$item : BROKEN SYMLINK : ";
2495
            } else {
2496
                my $linkTarget = readlink($item) || 'Read Error';
2497
                $text = "$item :SYMLINK: $linkTarget";
2498
            }
2499
 
2500
        } else {
2501
            $data[8] = 0;               # atime - will change
2502
            $data[12] = '-';            # blocks - seen to change for unknown reasons
2503
            $text = "$item : @data";
2504
        }
2505
        $genPkgFingerPrintCount++;
2506
        $genPkgFingerPrintSha1->add($text);
2507
#Debug0("genPkgFingerPrint: $text, ", $genPkgFingerPrintSha1->clone->hexdigest() );
2508
        push @fpdata, $text . ':' . $genPkgFingerPrintSha1->clone->hexdigest();
2509
    };
2510
 
2511
    #
2512
    #   Process all files in the package
2513
    #
2514
    $genPkgFingerPrintCount = 0;
2515
    my $dir = $fe->{dir};
2516
    File::Find::find( { wanted => $wanted , no_chdir => 1}, @dirList );
2517
#Debug0("genPkgFingerPrint: $dir, $genPkgFingerPrintCount, ", $genPkgFingerPrintSha1->clone->hexdigest() );
2518
    push @fpdata, $dir . ':'. $genPkgFingerPrintCount . ':' . $genPkgFingerPrintSha1->clone->hexdigest();
2519
 
2520
    #
2521
    #   Debugging - delete later
2522
    #   Save FP data to a file
2523
    #
7301 dpurdie 2524
    my $fpDebugFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', $fe->{name} . '.' . $fe->{prj} . '_' . time() . '.fpd');
2525
Debug0("fpDebugFile: $fpDebugFile");
2526
    FileCreate($fpDebugFile, @fpdata);
6133 dpurdie 2527
 
2528
    return $genPkgFingerPrintSha1->hexdigest;
2529
}
2530
 
2531
 
2532
#-------------------------------------------------------------------------------
2533
# Function        : getPkgFingerPrintFile 
2534
#
2535
# Description     : Return the package file that contains the packages Fast Finger Print
2536
#
2537
# Inputs          : $fe     - Package entry 
2538
#
2539
# Returns         : Full path to the packages fingerprint tag file
2540
#
2541
sub getPkgFingerPrintFile
2542
{
2543
    my ($fe) = @_;
2544
    my $tagFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', $fe->{name}, 'sandbox.' . $fe->{prj} . '.ffp');
2545
    return $tagFile;
2546
}
2547
 
2548
 
2549
#-------------------------------------------------------------------------------
359 dpurdie 2550
# Function        : SubCommandHelp
2551
#
2552
# Description     : Provide help on a subcommand
2553
#
2554
# Inputs          : $help_level             - Help Level 1,2,3
2555
#                   $topic                  - Topic Name
2556
#
2557
# Returns         : This function does not return
2558
#
2559
sub SubCommandHelp
2560
{
2561
    my ($help_level, $topic) = @_;
2562
    my @sections;
2563
    #
2564
    #   Spell out the section we want to display
2565
    #
2566
    #   Note:
2567
    #   Due to bug in pod2usage can't use 'head1' by itself
2568
    #   Each one needs a subsection.
2569
    #
2570
    push @sections, qw( NAME SYNOPSIS ) ;
2571
    push @sections, qw( ARGUMENTS OPTIONS )     if ( $help_level > 1 );
2572
    push @sections, qw( DESCRIPTION EXAMPLES )  if ( $help_level > 2 );
2573
 
2574
    #
2575
    #   Extract section from the POD
2576
    #
2577
    pod2usage({-verbose => 99,
2578
               -noperldoc => 1,
2579
               -sections => $topic . '/' . join('|', @sections) } );
2580
}
2581
 
2582
#-------------------------------------------------------------------------------
227 dpurdie 2583
#   Documentation
359 dpurdie 2584
#   NOTE
227 dpurdie 2585
#
359 dpurdie 2586
#   Each subcommand MUST have
2587
#   head1 section as used by the subcommand
2588
#       This should be empty, as the contents will NOT be displayed
2589
#   head2 sections called
2590
#       NAME SYNOPSIS ARGUMENTS OPTIONS DESCRIPTION EXAMPLES
2591
#
2592
#=head1 xxxxxx
2593
#=head2 NAME
2594
#=head2 SYNOPSIS
2595
#=head2 ARGUMENTS
2596
#=head2 OPTIONS
2597
#=head2 DESCRIPTION
2598
#=head2 EXAMPLES
2599
#
227 dpurdie 2600
 
2601
=pod
2602
 
2603
=head1 NAME
2604
 
2605
jats_sandbox - Build in a Development Sandbox
2606
 
2607
=head1 SYNOPSIS
2608
 
361 dpurdie 2609
  jats sandbox [options] command [command options]
227 dpurdie 2610
 
2611
 Options:
1329 dpurdie 2612
    -help[=n]                  - Display help with specified detail
2613
    -help -help                - Detailed help message
2614
    -man                       - Full documentation
227 dpurdie 2615
 
1329 dpurdie 2616
 Options for recursion control:
2617
    -toPackage=name            - Stop building after package
2618
    -fromPackage=name          - Start building from package
2619
    -justPackage=name[,name]   - Build named packages
2620
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 2621
    -entireSandbox             - Process the entire sandbox
2622
    -users                     - Process package users, not dependencies
7307 dpurdie 2623
 Options common to all commands:
6133 dpurdie 2624
    -[no]keepgoing             - Ignore errors
2625
    -[no]reScan                - Recalculate and cache sandbox structure
7307 dpurdie 2626
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
1329 dpurdie 2627
 
227 dpurdie 2628
 Commands:
2629
    help                - Same as -help
2630
    create              - Create a sandbox in the current directory
359 dpurdie 2631
    populate            - Populate the sandbox with packages
299 dpurdie 2632
    delete              - Delete the sandbox
255 dpurdie 2633
    info [[-v]-v]       - Sandbox information. -v: Be more verbose
4197 dpurdie 2634
    buildfilter         - Modify and display sandbox buildfilter
6133 dpurdie 2635
    [un]skip            - Mark a package to be skipped during the build
2636
    fingerprint         - Various fingerprint operations
7304 dpurdie 2637
    testlinks           - Test / Delete broken package symlinks
7306 dpurdie 2638
    scandepth           - Set/Display the build file scan depth
227 dpurdie 2639
    cmd                 - Do commands in all sandbox components
1329 dpurdie 2640
    all                 - Do 'build', if required, then a make in all components
331 dpurdie 2641
    build               - Force 'build and make' in all sandbox components
275 dpurdie 2642
    make                - Do 'make' in all sandbox components
273 dpurdie 2643
    clean               - Do 'make clean' in all sandbox components
2644
    clobber             - Do 'build clobber' is all sandbox components
337 dpurdie 2645
    cache               - Cache external dependent packages
227 dpurdie 2646
 
359 dpurdie 2647
 Use the command
2648
    jats sandbox 'command' -h
2649
 for command specific help
361 dpurdie 2650
 
227 dpurdie 2651
=head1 OPTIONS
2652
 
2653
=over 8
2654
 
299 dpurdie 2655
=item B<-help[=n]>
227 dpurdie 2656
 
2657
Print a brief help message and exits.
299 dpurdie 2658
There are three levels of help
227 dpurdie 2659
 
299 dpurdie 2660
=over 8
2661
 
361 dpurdie 2662
=item   1
299 dpurdie 2663
 
361 dpurdie 2664
Brief synopsis
299 dpurdie 2665
 
361 dpurdie 2666
=item   2
299 dpurdie 2667
 
361 dpurdie 2668
Synopsis and option summary
2669
 
2670
=item   3
2671
 
2672
Detailed help in man format
2673
 
299 dpurdie 2674
=back 8
2675
 
227 dpurdie 2676
=item B<-help -help>
2677
 
2678
Print a detailed help message with an explanation for each option.
2679
 
2680
=item B<-man>
2681
 
299 dpurdie 2682
Prints the manual page and exits. This is the same a -help=3
227 dpurdie 2683
 
1329 dpurdie 2684
=item B<-toPackage=name>
2685
 
2686
This option is available in all commands that process multiple packages.
2687
Package processing will stop at the named package.
2688
 
4688 dpurdie 2689
The package name can be specified in one of three forms:
1329 dpurdie 2690
 
4184 dpurdie 2691
=over 8
2692
 
2693
=item 1 
2694
 
2695
Just the package name. ie: MyPackage
2696
 
2697
=item 2 
2698
 
2699
The package name and the project suffix. ie: MyPackage.prj
2700
 
2701
=item 3 
2702
 
2703
The package name and version, joined with an underscore: ie: MyPackage_1.0.0000.prj
2704
 
2705
=back 8
2706
 
1329 dpurdie 2707
=item B<-fromPackage=name>
2708
 
2709
This option is available in all commands that process multiple packages.
2710
Package processing will start at the named package.
2711
 
4688 dpurdie 2712
The package name can be specified in one of the three forms described under the '-toPackage' option.
1329 dpurdie 2713
 
2714
=item B<-justPackage=name[,name]>
2715
 
2716
This option is available in all commands that process multiple packages. The
2717
named packages will be processed in the correct build order. Packages that are
2718
not named will be skipped, unless the package is being processed due to
2719
being in the 'fromPackage' to 'toPackage' range.
2720
 
2721
Multiple packages can be named either by separating names with a comma, or
2722
with multiple options.
2723
 
4688 dpurdie 2724
The package names can be specified as a mix of the three forms described under the '-toPackage' option.
4184 dpurdie 2725
 
1329 dpurdie 2726
=item B<-ignorePackage=name[,name]>
2727
 
2728
This option is available in all commands that process multiple packages. The
2729
named packages will not be processed.
2730
 
2731
Multiple packages can be named either by separating names with a comma, or
2732
with multiple options.
2733
 
2734
The exclusion of a package takes precedence over its inclusion.
2735
 
4688 dpurdie 2736
The package names can be specified as a mix of the three forms described under the '-toPackage' option.
4184 dpurdie 2737
 
6133 dpurdie 2738
=item B<-[no]entireSandbox>
2739
 
7307 dpurdie 2740
This option will override the automatic package localisation that will occur if the user starts the command
2741
within a subdirectory of a package within the sandbox and will process the entire sanbbox.
6133 dpurdie 2742
 
2743
If the user start the command within a subdirectory of a package then the sandbox commands will be localised
2744
to the current package and the dependencies of the package.
2745
 
2746
=item B<-[no]users>
2747
 
2748
This option will completely change the packages considered to be built. The normal operation is to consider
2749
the current package and all packages that it depends upon.
2750
 
2751
This option will consider all packages that 'use' the current package, either directly or indirectly. It does not 
2752
include the 'current' pakage in this list. The assumption is that the current package has been sucessfully built 
2753
and needs to tested.
2754
 
2755
This option will work when they is a current package to be processed and not the entire sandbox.
2756
 
2757
The intended purpose of this option is to simplify regression testing.
2758
 
2759
=item B<-[no]keepgoing>
2760
 
2761
This options controls the behaviour of the command when an error is encountered.
2762
 
2763
The default operation is to terminate the command on the package with the
2764
error. This can be modified so that errors are ignored.
2765
 
2766
=item B<-[no]reScan>
2767
 
2768
This option controls the process of locating build files within the sandbox.
2769
 
2770
The default operation is to scan the sandbox and to cache the location of the build files.
2771
 
2772
If a package is added or removed from the sandbox, then the sandbox will need to be rescanned.
2773
Jats will detect when a package has been added or removed, but if the internal structure of the
2774
packages has changed the cached data may be incorrect. 
2775
 
7307 dpurdie 2776
=item B<-multiBuilders=mode>
2777
 
2778
If a package-name can be built by multiple packages then the sandbox processing will
2779
normally report an error.
2780
 
2781
This option allow the error to be reported as a warning or to be ignored altogether. The named package will be 
2782
excluded from the build set.
2783
 
2784
Valid values for 'mode' are: error, report and ignore.  The default mode is 'error'.
2785
 
279 dpurdie 2786
=back
2787
 
227 dpurdie 2788
=head1 DESCRIPTION
2789
 
299 dpurdie 2790
This program is the primary tool for the maintenance of Development Sandboxes.
2791
 
227 dpurdie 2792
More documentation will follow.
2793
 
279 dpurdie 2794
=head2 SANDBOX DIRECTORY
2795
 
299 dpurdie 2796
The sandbox directory is marked as being a sandbox through the use of the
2797
'sandbox create' command. This will create a suitable structure within the
279 dpurdie 2798
current directory.
2799
 
2800
Several JATS commands operate differently within a sandbox. The 'extract' and
365 dpurdie 2801
'release' commands will create static views within the sandbox and not the
279 dpurdie 2802
normal directory. The 'sandbox' sub commands can only be used within a sandbox.
2803
 
2804
The sandbox directory contains sub directories, each should contain a single
359 dpurdie 2805
package. Sub directories may be created with the 'jats extract' command or with the
2806
'jats sandbox populate' command.
279 dpurdie 2807
 
6133 dpurdie 2808
Note: Symbolic links are not supported. They cannot work as the sandbox mechanism
365 dpurdie 2809
requires that all the packages be contained within a sub directory tree so
279 dpurdie 2810
that the root of the sandbox can be located by a simple scan of the directory
2811
tree.
2812
 
325 dpurdie 2813
If a package subdirectory contains a file called 'stop' or 'stop.
2814
<GBE_MACHTYPE>', then that package will not be considered as a part of the
6133 dpurdie 2815
build-set. A 'stop' file will prevent consideration for all build platforms. The 'stop.
325 dpurdie 2816
<GBE_MACHTYPE>' will only prevent consideration if being built on a GBE_MACHTYPE
2817
type of computer.
279 dpurdie 2818
 
3559 dpurdie 2819
If the sandbox contains a file called 'buildfilter', then the contents of the
2820
file will be read and used a buildfilter. The file is processed by reading each
2821
line and:
2822
 
2823
=over 4
2824
 
4184 dpurdie 2825
=item * 
3559 dpurdie 2826
 
4184 dpurdie 2827
Removing white space at both ends of the line
3559 dpurdie 2828
 
4184 dpurdie 2829
=item * 
3559 dpurdie 2830
 
4184 dpurdie 2831
Removing empty lines
3559 dpurdie 2832
 
4184 dpurdie 2833
=item * 
2834
 
2835
Lines that start with a # are comments and are removed
2836
 
2837
=item * 
2838
 
2839
Remaining lines are joined together to form a buildfilter
2840
 
3559 dpurdie 2841
=back
2842
 
359 dpurdie 2843
=head1 Create Sandbox
299 dpurdie 2844
 
359 dpurdie 2845
=head2 NAME
299 dpurdie 2846
 
359 dpurdie 2847
Create Sandbox
2848
 
2849
=head2 SYNOPSIS
2850
 
1329 dpurdie 2851
jats sandbox create [command options]
359 dpurdie 2852
 
2853
 Command Options
2854
    -help[=n]               - Command specific help, [n=1,2,3]
2855
    -verbose[=n]            - Verbose operation
2856
 
2857
=head2 OPTIONS
2858
 
7301 dpurdie 2859
The 'create' command takes no options.
359 dpurdie 2860
 
2861
=head2 DESCRIPTION
2862
 
299 dpurdie 2863
The 'create' command will create a sandbox in the users current directory. It is
2864
not possible to create a sandbox within a sandbox.
2865
 
2866
A sandbox can be created in a directory that contains files and subdirectories.
2867
 
2868
The create command simply places a known directory in the current directory.
359 dpurdie 2869
This directory is used by the sandboxing process. It may be manually deleted, or
299 dpurdie 2870
deleted with the 'delete' command.
2871
 
359 dpurdie 2872
=head1 Populate Sandbox
2873
 
2874
=head2 NAME
2875
 
2876
Populate a Sandbox
2877
 
2878
=head2 SYNOPSIS
2879
 
1329 dpurdie 2880
jats sandbox populate [command options] [packageName packageVersion]
359 dpurdie 2881
 
7307 dpurdie 2882
 Common Options:
2883
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 2884
    -toPackage=name            - Stop building after package
2885
    -fromPackage=name          - Start building from package
2886
    -justPackage=name[,name]   - Build named packages
2887
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 2888
    -entireSandbox             - Process the entire sandbox
2889
    -users                     - Process package users, not dependencies
7307 dpurdie 2890
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
2891
    -[no]keepgoing             - Ignore errors
2892
    -[no]reScan                - Recalculate and cache sandbox structure
2893
 Command Specific Options
1329 dpurdie 2894
    -excludePackage=name[,name]- Do not extract named package
2895
    -recurse[=n]               - Locate dependencies within packages
2896
    -all                       - Populate with all dependencies
2897
    -missing                   - Locate missing packages
2898
    -show                      - Show packages that would be extracted
2899
    -test                      - Do not extract packages
2900
    -<Other>                   - Pass options to jats extract
359 dpurdie 2901
 
2902
=head2 ARGUMENTS
2903
 
2904
The 'populate' command can take a package name and version as arguments. It will
2905
then populate the sandbox with this package. See 'DESCRIPTION' for details.
2906
 
2907
=head2 OPTIONS
2908
 
2909
The 'populate' command takes the following options:
2910
 
2911
=over 4
2912
 
1329 dpurdie 2913
=item -excludePackage=name[,name]
2914
 
2915
This option prevents one, or more, packages from populating the sandbox.
2916
Packages specified with this option will not be extracted from version control
2917
and added to the sandbox.
2918
 
4688 dpurdie 2919
Packages can be identified in three ways:
1329 dpurdie 2920
 
2921
=over 4
2922
 
2923
=item 1. Package Name
2924
 
2925
All package versions matching the named package will be excluded.
2926
 
2927
=item 2. Package Name and Version
2928
 
2929
Only the specified version of the named package will be excluded. The
2930
user specifies the package name and version as a single string separated with
2931
an underscore. ie: core_devl_2.100.5000.cr
2932
 
2933
=item 3. Package Name and Suffix
2934
 
2935
All packages matching the named package and project will be excluded. The
2936
user specifies the package name and project as a single string separated with
2937
a dot. ie: core_devl.cr
2938
 
2939
 
2940
=back
2941
 
359 dpurdie 2942
=item -recurse[=N]
2943
 
2944
This option will modify the operation of the command such that dependencies
2945
of named packages can also be extracted into the sandbox.
2946
 
2947
The default operation is to only extract named packages. If the option is
2948
specified then all dependent packages are processed. An optional numeric argument
2949
can be specified to limit the depth of the recursion.
2950
 
1329 dpurdie 2951
=item -all
2952
 
2953
This option will populate the sandbox will all dependencies of packages that are
2954
currently in the sandbox.
2955
 
2956
The global options that control recursion will affect the packages that are
2957
processed.
2958
 
2959
This option cannot be used with the '-missing' option.
2960
 
359 dpurdie 2961
=item -missing
2962
 
2963
This option will modify the operation of the dependency recursion scanning such
2964
that dependent packages that exist in a package archive will not be extracted.
2965
 
2966
Use of this option allows a sandbox to be populated with packages that are
2967
required by packages in the sandbox, but are not available in a package archive.
2968
 
1329 dpurdie 2969
The global options that control recursion will affect the packages that are
2970
processed.
2971
 
2972
This option cannot be used with the '-all' option.
2973
 
2974
=item -show
2975
 
2976
This option will prevent the command from performing the extraction. It will
2977
simply display the names of the packages that would be extracted.
2978
 
359 dpurdie 2979
=item -test
2980
 
2981
This option will prevent the command from performing the extraction. It will
2982
simply display the JATS commands that can be used to perform the extraction.
2983
 
2984
=item -<Other>
2985
 
2986
Options not understood by the 'populate' sub command will be passed through
2987
the package extraction program. Useful options include:
2988
 
363 dpurdie 2989
=over 4
359 dpurdie 2990
 
361 dpurdie 2991
=item *
359 dpurdie 2992
 
361 dpurdie 2993
-extractfiles
359 dpurdie 2994
 
361 dpurdie 2995
=item *
2996
 
2997
-branch=<branch name>
2998
 
359 dpurdie 2999
=back
3000
 
3001
=back
3002
 
3003
=head2 DESCRIPTION
3004
 
3005
The 'populate' command can be used to assist in populating the sandbox. It has
3006
two modes of operation.
3007
 
363 dpurdie 3008
=over 4
359 dpurdie 3009
 
361 dpurdie 3010
=item 1
359 dpurdie 3011
 
361 dpurdie 3012
Named Package
3013
 
363 dpurdie 3014
If the user specifies both a package name and a package version then the command
359 dpurdie 3015
will populate the sandbox with that package and optionally its dependencies.
3016
 
361 dpurdie 3017
=item 2
359 dpurdie 3018
 
361 dpurdie 3019
Determine missing dependencies
3020
 
359 dpurdie 3021
If the user does not specify a package name and version, but does specify
3022
the '-missing' option,  then the command will examine the current sandbox and
3023
determine missing dependent packages. It will then populate the sandbox with
3024
these packages and optionally there dependencies.
3025
 
3026
=back
3027
 
3028
=head2 EXAMPLES
3029
 
3030
=over 4
3031
 
361 dpurdie 3032
=item *
359 dpurdie 3033
 
361 dpurdie 3034
jats sandbox populate package1 version1
3035
 
359 dpurdie 3036
This command will populate the sandbox with version1 of package1, if it does not
3037
already exist in the sandbox.
3038
 
361 dpurdie 3039
=item *
359 dpurdie 3040
 
361 dpurdie 3041
jats sandbox populate package1 version1 -recurse -missing
3042
 
359 dpurdie 3043
This command will populate the sandbox with version1 of package1, if it does not
3044
already exist in the sandbox, together will all the packages dependencies that
3045
are not available in a package archive.
3046
 
361 dpurdie 3047
=item *
359 dpurdie 3048
 
361 dpurdie 3049
jats sandbox populate -recurse -missing
3050
 
359 dpurdie 3051
This command will examine the current sandbox and populate the sandbox with
3052
packages that are required to build the packages in the sandbox and the
3053
dependencies of these packages, provide the dependent package is not in a
3054
package archive.
3055
 
361 dpurdie 3056
=item *
359 dpurdie 3057
 
361 dpurdie 3058
jats sandbox populate
3059
 
359 dpurdie 3060
This command will examine the current sandbox and populate the sandbox with
3061
packages that are required to build the packages in the sandbox. It will not
3062
examine the dependents of these packages.
3063
 
3064
=back
3065
 
3066
=head1 Delete Sandbox
3067
 
3068
=head2 NAME
3069
 
4688 dpurdie 3070
Delete a sandbox
359 dpurdie 3071
 
3072
=head2 SYNOPSIS
3073
 
3074
jats sandbox [options] delete
3075
 
3076
 Options:
3077
    -help[=n]               - Help message, [n=1,2,3]
3078
    -man                    - Full documentation [-help=3]
3079
    -verbose[=n]            - Verbose command operation
3080
 
3081
=head2 DESCRIPTION
3082
 
299 dpurdie 3083
The 'delete' command will delete the sandbox's marker directory. The command may
3084
be executed anywhere within the sandbox.
3085
 
359 dpurdie 3086
Once the sandbox has been deleted, the user must remove the components within the
299 dpurdie 3087
sandbox.
3088
 
359 dpurdie 3089
=head1 Sandbox Information
299 dpurdie 3090
 
359 dpurdie 3091
=head2 NAME
3092
 
3093
Display Sandbox Information
3094
 
3095
=head2 SYNOPSIS
3096
 
1329 dpurdie 3097
jats sandbox info [command options]
359 dpurdie 3098
 
7307 dpurdie 3099
 Common Options:
3100
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3101
    -toPackage=name            - Stop building after package
3102
    -fromPackage=name          - Start building from package
3103
    -justPackage=name[,name]   - Build named packages
3104
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3105
    -entireSandbox             - Process the entire sandbox
3106
    -users                     - Process package users, not dependencies
7307 dpurdie 3107
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
3108
    -[no]keepgoing             - Ignore errors
3109
    -[no]reScan                - Recalculate and cache sandbox structure
3110
 Command Specific Options
3111
    -verbose[=n]               - Display more information
3112
    -usedby                    - Display package usage information
6133 dpurdie 3113
    -fingerprint               - Display fingerprint information
7306 dpurdie 3114
    -[no]dependencies          - Display external dependencies (default)
3115
    -[no]buildorder            - Display build order (default)
7307 dpurdie 3116
    -[no]path                  - Display path to package
361 dpurdie 3117
 
359 dpurdie 3118
=head2 OPTIONS
3119
 
3120
=over
3121
 
3122
=item B<-verbose[=n]>
3123
 
3124
This options will increase the verbosity of the information being displayed.
3125
Values 1 and 2 are described in the detailed 'DESCRIPTION'. Other values are
3126
reserved for diagnostic use.
3127
 
6133 dpurdie 3128
=item B<-usedby>
3129
 
3130
This option will list all packages that use the current package, both directly and
3131
indirectly. These are packages that should be tested whan changes are made to the 
3132
package.
3133
 
3134
=item B<-fingerprint>
3135
 
3136
This option will cause the information display to include that status of each packages fingerprint.
3137
 
3138
This will slow down the display as the calculation can be time consuming.
3139
 
7306 dpurdie 3140
=item B<-[no]dependencies>
3141
 
3142
This option will cause the information display to include all the external dependencies.
3143
 
3144
=item B<-[no]buildorder>
3145
 
3146
This option will cause the information display to include all the build order.
3147
 
7307 dpurdie 3148
=item B<-[no]path>
3149
 
3150
This option will cause the information display to include all the path to the build file
3151
 
359 dpurdie 3152
=back
3153
 
3154
=head2 DESCRIPTION
3155
 
299 dpurdie 3156
The 'info' command will display information about the build order and the
359 dpurdie 3157
dependencies of packages that it finds within the sandbox.
299 dpurdie 3158
 
359 dpurdie 3159
The command works within various levels of verbosity:
299 dpurdie 3160
 
3161
=over 8
3162
 
361 dpurdie 3163
=item *
299 dpurdie 3164
 
361 dpurdie 3165
No Verbosity
3166
 
299 dpurdie 3167
The basic command will display the build order and the external
335 dpurdie 3168
dependencies. External dependencies may be prefixed with one of the
3169
following indicators:
299 dpurdie 3170
 
335 dpurdie 3171
=over 8
3172
 
361 dpurdie 3173
=item   '+' Multiple versions of this package are being used by sandboxed components.
335 dpurdie 3174
 
361 dpurdie 3175
=item   '*' The package cannot be found in any of the package archives.
335 dpurdie 3176
 
3177
=back
3178
 
361 dpurdie 3179
=item *
299 dpurdie 3180
 
361 dpurdie 3181
Verbosity of 1
3182
 
359 dpurdie 3183
This level of verbosity will display the build order and detailed information
299 dpurdie 3184
on the dependencies. The dependencies will be prefixed with:
3185
 
3186
=over 8
3187
 
361 dpurdie 3188
=item   E Dependent Package is external to the sandbox
299 dpurdie 3189
 
361 dpurdie 3190
=item   I Dependent Package is internal to the sandbox
299 dpurdie 3191
 
3192
=back
3193
 
335 dpurdie 3194
External dependencies may be prefixed with one of the indicators described for
3195
no-verbosity. Additionally the internal consumer of the external package is also
3196
shown. These are prefixed with a 'U'.
299 dpurdie 3197
 
361 dpurdie 3198
=item *
299 dpurdie 3199
 
361 dpurdie 3200
Verbosity of 2
3201
 
6133 dpurdie 3202
Usage information will also be displayed. This is the same as invoking the 
3203
'-usedby' option.
299 dpurdie 3204
 
361 dpurdie 3205
=item *
299 dpurdie 3206
 
361 dpurdie 3207
Verbosity over 2
3208
 
359 dpurdie 3209
This should be considered a debug option. Undocumented internal information will
299 dpurdie 3210
be displayed.
3211
 
3212
=back
3213
 
4197 dpurdie 3214
=head1 Buildfilter
3215
 
3216
=head2 NAME
3217
 
3218
Display and Modify Sandbox buildfilter
3219
 
3220
=head2 SYNOPSIS
3221
 
3222
jats sandbox buildfilter [command options] [TARGETS]+
3223
 
3224
 Command Options
3225
    -help[=n]               - Command specific help, [n=1,2,3]
3226
    -man                    - Same as -help=3
3227
 
3228
 Target Names
3229
    -TARGET                 - Remove target from the current buildfilter
3230
    +TARGET                 - Add target to current buildfilter
3231
    TARGET                  - If first target, then reset buildfilter 
3232
                              and add target, otherwise add target.
3233
 
3234
=head2 OPTIONS
3235
 
3236
The 'buildfilter' command takes the following options:
3237
 
3238
=over 8
3239
 
3240
=item -TARGET
3241
 
3242
If a target name starts with a '-' and is not an option, then that target will be
3243
removed from the current buildfilter. 
3244
 
3245
If the named target is not a part of the current buildfilter then nothing will happen.
3246
 
3247
=item +TARGET
3248
 
3249
If a target name starts with a '+' then that target will be added to the current buildfilter.
3250
 
3251
If the named target is already a part of the current buildfilter then nothing will happen.
3252
 
3253
 
3254
=item TARGET
3255
 
3256
If a target name does not start with either a '-' or a '+' then the target will be added to the
3257
current buildfilter.
3258
 
3259
If this is the first named target then the build filter will be set to this one target.
3260
 
3261
=back
3262
 
3263
=head2 DESCRIPTION
3264
 
3265
The 'buildfilter' command will display and optionally modify the build filter used within
3266
the sandbox.
3267
 
3268
=head2 EXAMPLES
3269
 
3270
The command
3271
 
3272
    jats sandbox buildfilter 
3273
 
3274
will simply display the current buildfilter.
3275
 
3276
The command
3277
 
3278
    jats sandbox buildfilter +COBRA +PPC_603E
3279
 
3280
will append the build targets COBRA and PPC_603E to the current buildfilter.
3281
 
3282
The command
3283
 
3284
    jats sandbox buildfilter -COBRA
3285
 
3286
will remove the build target COBRA from the current buildfilter.
3287
 
3288
The command
3289
 
3290
    jats sandbox buildfilter COBRA +PPC_603E
3291
 or jats sandbox buildfilter COBRA PPC_603E
3292
 
3293
will set the buildfilter to be COBRA and PPC_603E
3294
 
6133 dpurdie 3295
=head1 Skip Build
3296
 
3297
=head2 NAME
3298
 
3299
Mark a package to be skipped during the build
3300
 
3301
=head2 SYNOPSIS
3302
 
3303
jats sandbox [un]skip [command options] [PackageName]+
3304
 
3305
 Command Options
3306
    -help[=n]               - Command specific help, [n=1,2,3]
3307
    -man                    - Same as -help=3
3308
    -[no]machine            - Skip on on this type of machine
3309
 
3310
=head2 ARGUMENTS
3311
 
3312
Arguments to the 'skip' command are the names of packages to be marked.
3313
 
3314
If no packages are named then the command will display all packages that are marked to be skipped.
3315
 
3316
If the named package is '.', then the current package will be excluded.
3317
 
3318
=head2 OPTIONS
3319
 
3320
The 'skip' command takes the following options:
3321
 
3322
=over 8
3323
 
3324
=item -[no]machine
3325
 
3326
This option will flag that the package will be skipped only on this type of build machine.
3327
 
3328
=back
3329
 
3330
=head2 DESCRIPTION
3331
 
3332
The 'skip' command marked the named packages to be skipped during the build, or the mark will be removed.
3333
 
3334
=head2 EXAMPLES
3335
 
3336
The command
3337
 
3338
    jats sandbox skip package1 
3339
 
3340
will mark package1 to be skipped during the following builds.
3341
 
3342
=head1 Sandbox Finger Print
3343
 
3344
=head2 NAME
3345
 
3346
Various fingerprint operations
3347
 
3348
=head2 SYNOPSIS
3349
 
3350
jats sandbox finger[print] [options]
3351
 
3352
 Command Options
3353
    -help[=n]               - Command specific help, [n=1,2,3]
3354
    -man                    - Same as -help=3
3355
    -[no]generate           - Generate a fingerprint over a package
3356
    -[no]delete             - Delete the fingerprint information
3357
 
3358
=head2 ARGUMENTS
3359
 
3360
Arguments to the 'fingerprint' command are the names of packages to be processed.
3361
 
3362
If no packages are named then the command will process the current package, if any.
3363
 
3364
=head2 OPTIONS
3365
 
3366
The 'fingerprint' command takes the following options:
3367
 
3368
=over 8
3369
 
3370
=item -[no]generate
3371
 
3372
This option will cause the fingerprint of the package to be regenerated.
3373
 
3374
=item -[no]delete
3375
 
3376
This option will delete the fingerprint information associated wit a package.
3377
 
3378
=back
3379
 
3380
=head2 DESCRIPTION
3381
 
3382
The 'fingerprint' command, will by default, examine the packages fingerprint and report
3383
if the package has been modified since the fingerprint was created.
3384
 
3385
Options allow different modes of operation.
3386
 
3387
A fingerprint may only be created after the 'build.pl' file has been created. It requires the
3388
build process to generate metadata about the package.
3389
 
3390
=head2 EXAMPLES
3391
 
3392
The command
3393
 
3394
    jats sandbox fingerprint -generate
3395
 
3396
will regenerate the fingerprint of the current package. Useful after trivial edits to 
3397
enable the sandbox builder to bypass the package and not to rebuild it and all of its dependents.
3398
 
359 dpurdie 3399
=head1 Command all
331 dpurdie 3400
 
359 dpurdie 3401
=head2 NAME
3402
 
3403
Build packages in the sandbox
3404
 
3405
=head2 SYNOPSIS
3406
 
1329 dpurdie 3407
jats sandbox all [command options] [arguments]
359 dpurdie 3408
 
7307 dpurdie 3409
 Common Options:
3410
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3411
    -toPackage=name            - Stop building after package
3412
    -fromPackage=name          - Start building from package
3413
    -justPackage=name[,name]   - Build named packages
3414
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3415
    -entireSandbox             - Process the entire sandbox
3416
    -users                     - Process package users, not dependencies
7307 dpurdie 3417
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
6133 dpurdie 3418
    -[no]keepgoing             - Ignore errors
7307 dpurdie 3419
    -[no]reScan                - Recalculate and cache sandbox structure
3420
 Command Specific Options
6133 dpurdie 3421
    -[no]skip                  - Skip if no source change (default:skip)
359 dpurdie 3422
 
6133 dpurdie 3423
 
359 dpurdie 3424
=head2 ARGUMENTS
3425
 
3426
Arguments are passed to the 'make' phase of the process.
3427
 
3428
=head2 OPTIONS
3429
 
6133 dpurdie 3430
=over
359 dpurdie 3431
 
6133 dpurdie 3432
=item B<-[no]skip>
3433
 
3434
This operation overides the default smart building mechanism.
3435
 
3436
By default, a package will not be built if the last build was successful and 
3437
there has not been any change to the source of the package, since the last 
3438
succesful build.
3439
 
3440
=back
3441
 
359 dpurdie 3442
=head2 DESCRIPTION
3443
 
331 dpurdie 3444
The 'all' command will perform build, if the build files are out of date,
3445
followed by a make in each of the packages within the sandbox, in the correct
3446
build order.
3447
 
3448
Any arguments are passed to the 'make' phase of the process.
3449
 
3450
This command may be used to:
3451
 
3452
=over 8
3453
 
361 dpurdie 3454
=item *
331 dpurdie 3455
 
361 dpurdie 3456
Pickup any build file changes.
331 dpurdie 3457
 
361 dpurdie 3458
=item *
3459
 
3460
Resume a failed build.
3461
 
331 dpurdie 3462
=back
3463
 
359 dpurdie 3464
=head1 Command build
331 dpurdie 3465
 
359 dpurdie 3466
=head2 NAME
3467
 
3468
Build packages in the sandbox
3469
 
3470
=head2 SYNOPSIS
3471
 
1329 dpurdie 3472
jats sandbox build [command options] [arguments]
359 dpurdie 3473
 
7307 dpurdie 3474
 Common Options:
3475
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3476
    -toPackage=name            - Stop building after package
3477
    -fromPackage=name          - Start building from package
3478
    -justPackage=name[,name]   - Build named packages
3479
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3480
    -entireSandbox             - Process the entire sandbox
3481
    -users                     - Process package users, not dependencies
7307 dpurdie 3482
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
6133 dpurdie 3483
    -[no]keepgoing             - Ignore errors
7307 dpurdie 3484
    -[no]reScan                - Recalculate and cache sandbox structure
3485
 Command Specific Options
6133 dpurdie 3486
    -[no]skip                  - Skip if no source change (default:skip)
359 dpurdie 3487
 
3488
=head2 ARGUMENTS
3489
 
3490
Arguments are passed to the 'make' phase of the process.
3491
 
3492
=head2 OPTIONS
3493
 
6133 dpurdie 3494
=over
359 dpurdie 3495
 
6133 dpurdie 3496
=item B<-[no]skip>
3497
 
3498
This operation overides the default smart building mechanism.
3499
 
3500
By default, a package will not be built if the last build was successful and 
3501
there has not been any change to the source of the package, since the last 
3502
succesful build.
3503
 
3504
=back
3505
 
359 dpurdie 3506
=head2 DESCRIPTION
3507
 
331 dpurdie 3508
The 'build' command will force a build followed by a make in each of the packages
3509
within the sandbox, in the correct build order.
3510
 
3511
Any arguments are passed to the 'make' phase of the process.
3512
 
3513
In practice, the 'sandbox all' command is quicker.
3514
 
359 dpurdie 3515
=head1 Clean
331 dpurdie 3516
 
359 dpurdie 3517
=head2 NAME
3518
 
3519
Clean all sandbox components
3520
 
3521
=head2 SYNOPSIS
3522
 
1329 dpurdie 3523
jats sandbox clean|clobber [command options]
359 dpurdie 3524
 
7307 dpurdie 3525
 Common Options:
3526
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3527
    -toPackage=name            - Stop building after package
3528
    -fromPackage=name          - Start building from package
3529
    -justPackage=name[,name]   - Build named packages
3530
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3531
    -entireSandbox             - Process the entire sandbox
3532
    -users                     - Process package users, not dependencies
7307 dpurdie 3533
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
6133 dpurdie 3534
    -[no]keepgoing             - Ignore errors
7307 dpurdie 3535
    -[no]reScan                - Recalculate and cache sandbox structure
359 dpurdie 3536
 
3537
=head2 ARGUMENTS
3538
 
3539
None
3540
 
3541
=head2 OPTIONS
3542
 
7307 dpurdie 3543
The are no command specific options.
359 dpurdie 3544
 
3545
=head2 DESCRIPTION
3546
 
3547
The 'clean' command will perform a 'jats make clean' in all components in the
3548
sandbox.
3549
 
3550
The 'clobber' command will perform a 'jats clobber' in all components in the
3551
sandbox.
3552
 
3553
=head1 make
3554
 
3555
=head2 NAME
3556
 
3557
Make packages in the sandbox
3558
 
3559
=head2 SYNOPSIS
3560
 
1329 dpurdie 3561
jats sandbox make [command options] [arguments]
359 dpurdie 3562
 
7307 dpurdie 3563
 Common Options:
3564
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3565
    -toPackage=name            - Stop building after package
3566
    -fromPackage=name          - Start building from package
3567
    -justPackage=name[,name]   - Build named packages
3568
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3569
    -entireSandbox             - Process the entire sandbox
3570
    -users                     - Process package users, not dependencies
7307 dpurdie 3571
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
3572
    -[no]keepgoing             - Ignore errors
3573
    -[no]reScan                - Recalculate and cache sandbox structure
359 dpurdie 3574
 
3575
=head2 ARGUMENTS
3576
 
3577
Arguments are passed to the 'make' phase of the process.
3578
 
3579
=head2 OPTIONS
3580
 
3581
The are no command specific options.
3582
 
3583
=head2 DESCRIPTION
3584
 
331 dpurdie 3585
The 'make' command will perform a 'make' operation in each of the packages
3586
within the sandbox, in the correct build order.
3587
 
3588
Any arguments are passed to the 'make'.
3589
 
359 dpurdie 3590
=head1 cmd
331 dpurdie 3591
 
359 dpurdie 3592
=head2 NAME
3593
 
3594
Process each package with a specified command.
3595
 
3596
=head2 SYNOPSIS
3597
 
1329 dpurdie 3598
jats sandbox cmd [command options] [arguments]
359 dpurdie 3599
 
7307 dpurdie 3600
 Common Options:
3601
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3602
    -toPackage=name            - Stop building after package
3603
    -fromPackage=name          - Start building from package
3604
    -justPackage=name[,name]   - Build named packages
3605
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3606
    -entireSandbox             - Process the entire sandbox
3607
    -users                     - Process package users, not dependencies
7307 dpurdie 3608
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
3609
    -[no]keepgoing             - Ignore errors
3610
    -[no]reScan                - Recalculate and cache sandbox structure
7308 dpurdie 3611
 Command Specific Options
3612
    -[no]reverse               - Reverse the processing order
359 dpurdie 3613
 
3614
=head2 ARGUMENTS
3615
 
3616
Arguments are passed to a JATS command.
3617
 
3618
=head2 OPTIONS
3619
 
7308 dpurdie 3620
The 'cmd' command takes the following options:
359 dpurdie 3621
 
7308 dpurdie 3622
=over 8
3623
 
3624
=item -[no]reverse
3625
 
3626
This option will controlls the order in which the packages will be processed.
3627
 
3628
The default option is 'noreverse'. Packages will be processed in the build order.
3629
 
2054 dpurdie 3630
=back
3631
 
359 dpurdie 3632
=head2 DESCRIPTION
3633
 
331 dpurdie 3634
The 'cmd' command will pass all of its arguments to JATS in the build directory
3635
of each of the packages within the sandbox, in the package build order.
3636
 
4086 dpurdie 3637
=head2 EXAMPLES
3638
 
3639
The following command will update all the Subversion-based packages in the sandbox.
3640
 
3641
    jats sandbox cmd eprog svn update
3642
 
3643
Note the use of 'eprog' in the command string. This tells JATS to run the external
3644
(to JATS) program. Without this the command would run the JATS-internal command
3645
called 'svn' - with different results.
3646
 
3647
The following command will update the dependencies in the build.pl files to match
3648
those of a nominated release. This will only affect the package versions
3649
external to the sandbox, although all version information in the build.pl
3650
files will be updated.
3651
 
3652
    jats sandbox cmd upddep -rtagid=12345
3653
 
359 dpurdie 3654
=head1 Cache
331 dpurdie 3655
 
359 dpurdie 3656
=head2 NAME
331 dpurdie 3657
 
359 dpurdie 3658
Cache dependent packages
331 dpurdie 3659
 
359 dpurdie 3660
jats sandbox [options] cache [command options]
331 dpurdie 3661
 
359 dpurdie 3662
 Options:
3663
    -help[=n]               - Help message, [n=1,2,3]
3664
    -man                    - Full documentation [-help=3]
3665
    -verbose[=n]            - Verbose command operation
337 dpurdie 3666
 
359 dpurdie 3667
 Command Options
3668
    -help[=n]               - Command specific help, [n=1,2,3]
337 dpurdie 3669
 
359 dpurdie 3670
=head2 ARGUMENTS
3671
 
3672
The are no command specific arguments.
3673
 
3674
=head2 OPTIONS
3675
 
3676
The are no command specific options.
3677
 
3678
=head2 DESCRIPTION
3679
 
3680
The 'cache' command will cache all external dependent packages into the users
3681
dpkg_archive_cache as defined through the EnvVar GBE_DPKG_CACHE. The result is
3682
similar to the command 'jats sandbox build -cache', without the overhead of
3683
building the sandbox components.
3684
 
3685
This command allows the simple creation of a small development environment that
3686
is not tied to the larger Development Environment. It may then be used in a
337 dpurdie 3687
disconnected mode to perform development.
3688
 
7304 dpurdie 3689
=head1 Sandbox Test Links
3690
 
3691
=head2 NAME
3692
 
3693
Test and delete sandbox link files
3694
 
3695
=head2 SYNOPSIS
3696
 
3697
jats sandbox testlinks [options]
3698
 
3699
 Command Options
3700
    -help[=n]               - Command specific help, [n=1,2,3]
3701
    -man                    - Same as -help=3
3702
    -[no]delete             - Delete bad links
3703
 
3704
=head2 ARGUMENTS
3705
 
3706
This command does not take any arguments
3707
 
3708
=head2 OPTIONS
3709
 
3710
The 'fingerprint' command takes the following options:
3711
 
3712
=over 8
3713
 
3714
=item -[no]delete
3715
 
3716
This option will delete the link files if they are bad.
3717
 
3718
=back
3719
 
3720
=head2 DESCRIPTION
3721
 
3722
The 'testlinks' command, will by default, examine symbolic links within the sandbox and report on
3723
broken links.
3724
 
7306 dpurdie 3725
An option allows the broken links to be deleted.
7304 dpurdie 3726
 
3727
Each package in the sandbox will have a symbolic link to the packages 'package' area. If a package is removed
3728
from the sandbox the link file may be left in the sandbox and cause a 'build' to fail.
3729
 
3730
=head2 EXAMPLES
3731
 
3732
The command
3733
 
3734
    jats sandbox testlinks
3735
 
3736
will test the symbolic links in the sandbox metadata.
3737
 
7306 dpurdie 3738
=head1 Sandbox Scan Depth
3739
 
3740
=head2 NAME
3741
 
3742
Set and Display the build file scanner depth
3743
 
3744
=head2 SYNOPSIS
3745
 
3746
jats sandbox scandepth [options] [depth]
3747
 
3748
 Command Options
3749
    -help[=n]               - Command specific help, [n=1,2,3]
3750
    -man                    - Same as -help=3
3751
 
3752
=head2 ARGUMENTS
3753
 
3754
This command takes one optional argument. A positive number that control the 
3755
depth of the build filter scanner.
3756
 
3757
The default value is '3'. Deeper scans may be required for sandboxes containing badly formed 
3758
packages. The tradoff is speed for all sandbox operations.
3759
 
3760
Setting the scan depth will force a rescan of the sandbox build files on the next command that
3761
requires the information.
3762
 
3763
=head2 OPTIONS
3764
 
3765
The scandepth command only accepts the standard help and man options.
3766
 
3767
=head2 DESCRIPTION
3768
 
3769
The scandepth command, will by default, display the current value for the build file scanner.
3770
 
3771
If a numeric argument is provided this will set the future build file scan depth.
3772
 
3773
=head2 EXAMPLES
3774
 
3775
The command
3776
 
3777
    jats sandbox scandepth 5
3778
 
3779
will set future build file scan to a maximum of 5 directories below the root of the sandbox.
3780
 
227 dpurdie 3781
=cut
3782