Subversion Repositories DevTools

Rev

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