Subversion Repositories DevTools

Rev

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