Subversion Repositories DevTools

Rev

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