Subversion Repositories DevTools

Rev

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

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