Subversion Repositories DevTools

Rev

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

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