Subversion Repositories DevTools

Rev

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

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