Subversion Repositories DevTools

Rev

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