Subversion Repositories DevTools

Rev

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