Subversion Repositories DevTools

Rev

Rev 7310 | Rev 7319 | 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 = ' ';
7312 dpurdie 2314
    my $statusP = ' ';
6133 dpurdie 2315
 
2316
    unless ($fe->{buildActive}) {
2317
        $txt .= ($fe->{buildSkip}) ? ' (Build Skipped)' : ' (Build Suppressed)';
2318
        $statusS = ($fe->{buildSkip}) ? 'S' : 's';
2319
    }
2320
 
2321
    if ($fe->{buildCurrent})
2322
    {
2323
        $statusB = '*';
2324
        $txt .= ' (Current Package)';
2325
    }
2326
 
2327
    my $sigFile = getPkgFingerPrintFile($fe);
2328
    if (-f $sigFile)
2329
    {
7312 dpurdie 2330
        my $nobFile = $sigFile;
2331
        $nobFile =~ s~ffp$~nob~;
2332
        if (-f $nobFile) {
6133 dpurdie 2333
            $txt .= ' [NoBuild]';
2334
            $statusB = '-';
2335
        } else {
2336
            $txt .= ' [Built]';
2337
            $statusB = 'B';
2338
        }
2339
 
2340
        if ($args->{testFingerPrint})
2341
        {
7312 dpurdie 2342
            if ( TagFileMatch($sigFile, genPkgFingerPrint($fe, 'Test')) )
6133 dpurdie 2343
            {
2344
                $txt .= ' [GoodFinger]';
2345
                $statusF = 'G';
2346
            } else {
2347
                $txt .= ' [BadFinger]';
2348
                $statusF = 'b';
2349
            }
2350
        }
2351
    }
2352
 
7312 dpurdie 2353
    my $preBuilt = locatePreBuiltPackage($fe);
2354
    if ($preBuilt) {
2355
        $txt .= ' [PreBuilt]';
2356
        $statusP = 'P';
2357
    } 
2358
 
2359
    return "$statusS$statusB$statusP$statusF", $txt ;
2360
 
6133 dpurdie 2361
}
2362
 
2363
#-------------------------------------------------------------------------------
1329 dpurdie 2364
# Function        : opts_add2List
2365
#
2366
# Description     : Option processing helper
2367
#                   Add comma separated options to an array
2368
#                   User can then add items one at a time, or several at once
2369
#
2370
# Inputs          : aref        - Ref to an array to extent
2371
#                   arg2        - Option name
2372
#                   arg3        - Option value
2373
#
2374
# Returns         : 
2375
#
2376
sub opts_add2List
2377
{
2378
    my( $ref, $name, $value) = @_;
2379
    if ( $value )
2380
    {
2381
        foreach ( split(/\s*,\s*/,$value) )
2382
        {
2383
            push @{$ref}, $_;
2384
        }
2385
    }
2386
}
2387
 
2388
#-------------------------------------------------------------------------------
6133 dpurdie 2389
# Function        : genPkgFingerPrint 
2390
#
2391
# Description     : Generate a fingerprint over all files in the packages tree as
2392
#                   well as the package dependencies
2393
# 
2394
#                   Only used to detect changes to files in the subdir
2395
# 
2396
#                   This version does not actually generate a fingerprint over
2397
#                   the data file, rather the metadata of the file. This is much (much)
2398
#                   faster as there is no file i/o.
2399
#                   
2400
#                   It does assume that the file metadata will change if the file is changed
2401
#                   Will also detect the addition / deletion of files
2402
#                   
7312 dpurdie 2403
#                   Note: This signature is not machine - type safe
6133 dpurdie 2404
#                         It will vary between machines (windows/Linux/...)
7312 dpurdie 2405
#                         At the moment the Sandbox is really a single machine tool
6133 dpurdie 2406
#
2407
# Inputs          : $fe            - Package entry of the package to process
2408
#                   $mode          - Diagnostic: mode
2409
#
2410
# Returns         : A SHA1 hash over all the files
2411
#                   
2412
#
2413
sub genPkgFingerPrint
2414
{
2415
    my ($fe, $mode) = @_;
2416
    my $genPkgFingerPrintSha1;
2417
    my $genPkgFingerPrintCount;
2418
    my @fpdata;
2419
 
2420
    #
2421
    #   Get the package GbeFiles.cfg file
2422
    #       This is held in the interface directory and is created during the build
2423
    #       Since the fingerprint is only genertated AFTER a successful build the file will always
2424
    #       be available
2425
    #       
2426
    #       All we need from this file is a list of Src directories that were discovered during
2427
    #       the build. Unfortuanatley they are not always below the root of the package.
2428
    #
2429
    my $ifaceDir = getpkgInterface($fe);
2430
    return 0 unless defined $ifaceDir;
2431
    return 0 unless ToolsetFiles::GetDataFile($ifaceDir); 
2432
 
2433
    #
2434
    #   Generate a list of directories in the package
2435
    #   This is the root directory and all other Src directories discovered
2436
    #
2437
    my @dirList = ToolsetFiles::GetSubTrees($ifaceDir);
2438
    Error ("Internal:ToolsetFiles::GetDirList for $fe->{dname} not populated" ) unless @dirList;
2439
 
2440
    #
7312 dpurdie 2441
    #   Generate a hash of toolset files and toolset-internal directories
2442
    #       These won't be included in the finger print as they are subject
2443
    #       to change by a 'build'.
2444
    #
2445
    my %toolsetFiles = map { $_ => 1 } ToolsetFiles::GetFiles($ifaceDir, 1);
2446
    my %toolsetDirs  = map { $_ => 1 } ToolsetFiles::GetBuildDirs($ifaceDir);
2447
 
2448
    #
6133 dpurdie 2449
    #   Create the hash
2450
    #
2451
    $genPkgFingerPrintSha1 = Digest->new("SHA-1");
2452
    push @fpdata, $mode;
2453
 
2454
    #
2455
    #   Include all dependent packages in the fingerprint
2456
    #       We are using the sandbox fingerprint of dependent packages
2457
    #       This will ensure that a change in a package will ripple through
2458
    #
2459
    foreach my $idep ( sort keys %{$fe->{ideps}})
2460
    {
2461
        my $ipkg = $packages{$idep};
2462
        my $tagFile = getPkgFingerPrintFile($ipkg); 
2463
        my $tag = TagFileRead($tagFile);
2464
        my $text = "$tagFile: $tag";
2465
        $genPkgFingerPrintSha1->add($text);
2466
#Debug0("genPkgFingerPrint: $text, ", $genPkgFingerPrintSha1->clone->hexdigest() );
2467
        push @fpdata, $text . ':' . $genPkgFingerPrintSha1->clone->hexdigest();
2468
    }
2469
 
2470
    #
2471
    #   Anonymous sub: findFile wanted function
2472
    #   Unlike the generation of the package signature, we don't need to
2473
    #   exclude any files.
2474
    #
2475
    my $wanted = sub {
2476
        my $item = $File::Find::name;
2477
 
2478
        #
2479
        #   Get file info
2480
        #       Kill of the last access time - not useful
2481
        #       
2482
        #       Need to exclude files that change during a null build
2483
        #           /interface/GbeFiles.cfg
2484
        #           /build.log
7312 dpurdie 2485
        #           These files are tracked in GbeBuild.cfg
2486
        #       Need to directories that change during a null build
2487
        #           These files are tracked in GbeBuild.cfg
6133 dpurdie 2488
        #           
2489
        #       Symlinks present problems.
2490
        #       Some packages generate symlinks as they create file system images. The
2491
        #       links are not designed to be interpreted in the context of the current
2492
        #       computer. As a result.
2493
        #           Some may be broken - on the current machine
2494
        #           Some may address files that change - ie: /proc, /var, /dev
2495
        #           Some may address files that such as /afc, /root
2496
        #       Don't want to discard all symlinks. Many of them will address package
2497
        #       dependencies and we do want to detect changes, but those changes will
2498
        #       be picked up by the packages fingerprint.
2499
        #       
2500
        #       Directories also appear to be a problem
2501
        #       The created and modified date-times appear to be modified for no good reason
2502
        #       
2503
        #       Current solution: Do not include 'stat' data for ANY symlink or directory
2504
        #
2505
        my @data = stat($item);
2506
        my $text;
7312 dpurdie 2507
 
2508
        if ( exists $toolsetFiles{$item}) {
6133 dpurdie 2509
            $text = "$item : SKIPPED FILE : ";
2510
 
2511
        }  elsif (-d $item ) {
7312 dpurdie 2512
            $text = "$item : DIRECTORY";
2513
            if ( exists $toolsetDirs{$item}) {
2514
                $File::Find::prune = 1;
2515
                $text = "$item : SKIP INTERNAL DIRECTORY";
2516
            }
2517
 
6133 dpurdie 2518
        }  elsif (-l $item ) {
2519
            if ( ! @data) {
2520
                $text = "$item : BROKEN SYMLINK : ";
2521
            } else {
2522
                my $linkTarget = readlink($item) || 'Read Error';
2523
                $text = "$item :SYMLINK: $linkTarget";
2524
            }
2525
 
2526
        } else {
2527
            $data[8] = 0;               # atime - will change
2528
            $data[12] = '-';            # blocks - seen to change for unknown reasons
2529
            $text = "$item : @data";
2530
        }
2531
        $genPkgFingerPrintCount++;
2532
        $genPkgFingerPrintSha1->add($text);
2533
#Debug0("genPkgFingerPrint: $text, ", $genPkgFingerPrintSha1->clone->hexdigest() );
2534
        push @fpdata, $text . ':' . $genPkgFingerPrintSha1->clone->hexdigest();
2535
    };
2536
 
2537
    #
2538
    #   Process all files in the package
2539
    #
2540
    $genPkgFingerPrintCount = 0;
2541
    my $dir = $fe->{dir};
2542
    File::Find::find( { wanted => $wanted , no_chdir => 1}, @dirList );
2543
#Debug0("genPkgFingerPrint: $dir, $genPkgFingerPrintCount, ", $genPkgFingerPrintSha1->clone->hexdigest() );
2544
    push @fpdata, $dir . ':'. $genPkgFingerPrintCount . ':' . $genPkgFingerPrintSha1->clone->hexdigest();
2545
 
2546
    #
2547
    #   Debugging - delete later
2548
    #   Save FP data to a file
2549
    #
7301 dpurdie 2550
    my $fpDebugFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', $fe->{name} . '.' . $fe->{prj} . '_' . time() . '.fpd');
7312 dpurdie 2551
#Debug0("fpDebugFile: $fpDebugFile");
7301 dpurdie 2552
    FileCreate($fpDebugFile, @fpdata);
6133 dpurdie 2553
 
2554
    return $genPkgFingerPrintSha1->hexdigest;
2555
}
2556
 
2557
 
2558
#-------------------------------------------------------------------------------
2559
# Function        : getPkgFingerPrintFile 
2560
#
2561
# Description     : Return the package file that contains the packages Fast Finger Print
2562
#
2563
# Inputs          : $fe     - Package entry 
2564
#
2565
# Returns         : Full path to the packages fingerprint tag file
2566
#
2567
sub getPkgFingerPrintFile
2568
{
2569
    my ($fe) = @_;
2570
    my $tagFile = catdir($GBE_SANDBOX, 'sandbox_dpkg_archive', $fe->{name}, 'sandbox.' . $fe->{prj} . '.ffp');
2571
    return $tagFile;
2572
}
2573
 
2574
 
2575
#-------------------------------------------------------------------------------
359 dpurdie 2576
# Function        : SubCommandHelp
2577
#
2578
# Description     : Provide help on a subcommand
2579
#
2580
# Inputs          : $help_level             - Help Level 1,2,3
2581
#                   $topic                  - Topic Name
2582
#
2583
# Returns         : This function does not return
2584
#
2585
sub SubCommandHelp
2586
{
2587
    my ($help_level, $topic) = @_;
2588
    my @sections;
2589
    #
2590
    #   Spell out the section we want to display
2591
    #
2592
    #   Note:
2593
    #   Due to bug in pod2usage can't use 'head1' by itself
2594
    #   Each one needs a subsection.
2595
    #
2596
    push @sections, qw( NAME SYNOPSIS ) ;
2597
    push @sections, qw( ARGUMENTS OPTIONS )     if ( $help_level > 1 );
2598
    push @sections, qw( DESCRIPTION EXAMPLES )  if ( $help_level > 2 );
2599
 
2600
    #
2601
    #   Extract section from the POD
2602
    #
2603
    pod2usage({-verbose => 99,
2604
               -noperldoc => 1,
2605
               -sections => $topic . '/' . join('|', @sections) } );
2606
}
2607
 
2608
#-------------------------------------------------------------------------------
227 dpurdie 2609
#   Documentation
359 dpurdie 2610
#   NOTE
227 dpurdie 2611
#
359 dpurdie 2612
#   Each subcommand MUST have
2613
#   head1 section as used by the subcommand
2614
#       This should be empty, as the contents will NOT be displayed
2615
#   head2 sections called
2616
#       NAME SYNOPSIS ARGUMENTS OPTIONS DESCRIPTION EXAMPLES
2617
#
2618
#=head1 xxxxxx
2619
#=head2 NAME
2620
#=head2 SYNOPSIS
2621
#=head2 ARGUMENTS
2622
#=head2 OPTIONS
2623
#=head2 DESCRIPTION
2624
#=head2 EXAMPLES
2625
#
227 dpurdie 2626
 
2627
=pod
2628
 
2629
=head1 NAME
2630
 
2631
jats_sandbox - Build in a Development Sandbox
2632
 
2633
=head1 SYNOPSIS
2634
 
361 dpurdie 2635
  jats sandbox [options] command [command options]
227 dpurdie 2636
 
2637
 Options:
1329 dpurdie 2638
    -help[=n]                  - Display help with specified detail
2639
    -help -help                - Detailed help message
2640
    -man                       - Full documentation
227 dpurdie 2641
 
1329 dpurdie 2642
 Options for recursion control:
2643
    -toPackage=name            - Stop building after package
2644
    -fromPackage=name          - Start building from package
2645
    -justPackage=name[,name]   - Build named packages
2646
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 2647
    -entireSandbox             - Process the entire sandbox
2648
    -users                     - Process package users, not dependencies
7307 dpurdie 2649
 Options common to all commands:
6133 dpurdie 2650
    -[no]keepgoing             - Ignore errors
2651
    -[no]reScan                - Recalculate and cache sandbox structure
7307 dpurdie 2652
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
1329 dpurdie 2653
 
227 dpurdie 2654
 Commands:
2655
    help                - Same as -help
2656
    create              - Create a sandbox in the current directory
359 dpurdie 2657
    populate            - Populate the sandbox with packages
299 dpurdie 2658
    delete              - Delete the sandbox
255 dpurdie 2659
    info [[-v]-v]       - Sandbox information. -v: Be more verbose
4197 dpurdie 2660
    buildfilter         - Modify and display sandbox buildfilter
6133 dpurdie 2661
    [un]skip            - Mark a package to be skipped during the build
2662
    fingerprint         - Various fingerprint operations
7304 dpurdie 2663
    testlinks           - Test / Delete broken package symlinks
7306 dpurdie 2664
    scandepth           - Set/Display the build file scan depth
227 dpurdie 2665
    cmd                 - Do commands in all sandbox components
1329 dpurdie 2666
    all                 - Do 'build', if required, then a make in all components
331 dpurdie 2667
    build               - Force 'build and make' in all sandbox components
275 dpurdie 2668
    make                - Do 'make' in all sandbox components
273 dpurdie 2669
    clean               - Do 'make clean' in all sandbox components
2670
    clobber             - Do 'build clobber' is all sandbox components
337 dpurdie 2671
    cache               - Cache external dependent packages
227 dpurdie 2672
 
359 dpurdie 2673
 Use the command
2674
    jats sandbox 'command' -h
2675
 for command specific help
361 dpurdie 2676
 
227 dpurdie 2677
=head1 OPTIONS
2678
 
2679
=over 8
2680
 
299 dpurdie 2681
=item B<-help[=n]>
227 dpurdie 2682
 
2683
Print a brief help message and exits.
299 dpurdie 2684
There are three levels of help
227 dpurdie 2685
 
299 dpurdie 2686
=over 8
2687
 
361 dpurdie 2688
=item   1
299 dpurdie 2689
 
361 dpurdie 2690
Brief synopsis
299 dpurdie 2691
 
361 dpurdie 2692
=item   2
299 dpurdie 2693
 
361 dpurdie 2694
Synopsis and option summary
2695
 
2696
=item   3
2697
 
2698
Detailed help in man format
2699
 
299 dpurdie 2700
=back 8
2701
 
227 dpurdie 2702
=item B<-help -help>
2703
 
2704
Print a detailed help message with an explanation for each option.
2705
 
2706
=item B<-man>
2707
 
299 dpurdie 2708
Prints the manual page and exits. This is the same a -help=3
227 dpurdie 2709
 
1329 dpurdie 2710
=item B<-toPackage=name>
2711
 
2712
This option is available in all commands that process multiple packages.
2713
Package processing will stop at the named package.
2714
 
4688 dpurdie 2715
The package name can be specified in one of three forms:
1329 dpurdie 2716
 
4184 dpurdie 2717
=over 8
2718
 
2719
=item 1 
2720
 
2721
Just the package name. ie: MyPackage
2722
 
2723
=item 2 
2724
 
2725
The package name and the project suffix. ie: MyPackage.prj
2726
 
2727
=item 3 
2728
 
2729
The package name and version, joined with an underscore: ie: MyPackage_1.0.0000.prj
2730
 
2731
=back 8
2732
 
1329 dpurdie 2733
=item B<-fromPackage=name>
2734
 
2735
This option is available in all commands that process multiple packages.
2736
Package processing will start at the named package.
2737
 
4688 dpurdie 2738
The package name can be specified in one of the three forms described under the '-toPackage' option.
1329 dpurdie 2739
 
2740
=item B<-justPackage=name[,name]>
2741
 
2742
This option is available in all commands that process multiple packages. The
2743
named packages will be processed in the correct build order. Packages that are
2744
not named will be skipped, unless the package is being processed due to
2745
being in the 'fromPackage' to 'toPackage' range.
2746
 
2747
Multiple packages can be named either by separating names with a comma, or
2748
with multiple options.
2749
 
4688 dpurdie 2750
The package names can be specified as a mix of the three forms described under the '-toPackage' option.
4184 dpurdie 2751
 
1329 dpurdie 2752
=item B<-ignorePackage=name[,name]>
2753
 
2754
This option is available in all commands that process multiple packages. The
2755
named packages will not be processed.
2756
 
2757
Multiple packages can be named either by separating names with a comma, or
2758
with multiple options.
2759
 
2760
The exclusion of a package takes precedence over its inclusion.
2761
 
4688 dpurdie 2762
The package names can be specified as a mix of the three forms described under the '-toPackage' option.
4184 dpurdie 2763
 
6133 dpurdie 2764
=item B<-[no]entireSandbox>
2765
 
7307 dpurdie 2766
This option will override the automatic package localisation that will occur if the user starts the command
2767
within a subdirectory of a package within the sandbox and will process the entire sanbbox.
6133 dpurdie 2768
 
2769
If the user start the command within a subdirectory of a package then the sandbox commands will be localised
2770
to the current package and the dependencies of the package.
2771
 
2772
=item B<-[no]users>
2773
 
2774
This option will completely change the packages considered to be built. The normal operation is to consider
2775
the current package and all packages that it depends upon.
2776
 
2777
This option will consider all packages that 'use' the current package, either directly or indirectly. It does not 
2778
include the 'current' pakage in this list. The assumption is that the current package has been sucessfully built 
2779
and needs to tested.
2780
 
2781
This option will work when they is a current package to be processed and not the entire sandbox.
2782
 
2783
The intended purpose of this option is to simplify regression testing.
2784
 
2785
=item B<-[no]keepgoing>
2786
 
2787
This options controls the behaviour of the command when an error is encountered.
2788
 
2789
The default operation is to terminate the command on the package with the
2790
error. This can be modified so that errors are ignored.
2791
 
2792
=item B<-[no]reScan>
2793
 
2794
This option controls the process of locating build files within the sandbox.
2795
 
2796
The default operation is to scan the sandbox and to cache the location of the build files.
2797
 
2798
If a package is added or removed from the sandbox, then the sandbox will need to be rescanned.
2799
Jats will detect when a package has been added or removed, but if the internal structure of the
2800
packages has changed the cached data may be incorrect. 
2801
 
7307 dpurdie 2802
=item B<-multiBuilders=mode>
2803
 
2804
If a package-name can be built by multiple packages then the sandbox processing will
2805
normally report an error.
2806
 
2807
This option allow the error to be reported as a warning or to be ignored altogether. The named package will be 
2808
excluded from the build set.
2809
 
2810
Valid values for 'mode' are: error, report and ignore.  The default mode is 'error'.
2811
 
279 dpurdie 2812
=back
2813
 
227 dpurdie 2814
=head1 DESCRIPTION
2815
 
299 dpurdie 2816
This program is the primary tool for the maintenance of Development Sandboxes.
2817
 
227 dpurdie 2818
More documentation will follow.
2819
 
279 dpurdie 2820
=head2 SANDBOX DIRECTORY
2821
 
299 dpurdie 2822
The sandbox directory is marked as being a sandbox through the use of the
2823
'sandbox create' command. This will create a suitable structure within the
279 dpurdie 2824
current directory.
2825
 
2826
Several JATS commands operate differently within a sandbox. The 'extract' and
365 dpurdie 2827
'release' commands will create static views within the sandbox and not the
279 dpurdie 2828
normal directory. The 'sandbox' sub commands can only be used within a sandbox.
2829
 
2830
The sandbox directory contains sub directories, each should contain a single
359 dpurdie 2831
package. Sub directories may be created with the 'jats extract' command or with the
2832
'jats sandbox populate' command.
279 dpurdie 2833
 
6133 dpurdie 2834
Note: Symbolic links are not supported. They cannot work as the sandbox mechanism
365 dpurdie 2835
requires that all the packages be contained within a sub directory tree so
279 dpurdie 2836
that the root of the sandbox can be located by a simple scan of the directory
2837
tree.
2838
 
325 dpurdie 2839
If a package subdirectory contains a file called 'stop' or 'stop.
2840
<GBE_MACHTYPE>', then that package will not be considered as a part of the
6133 dpurdie 2841
build-set. A 'stop' file will prevent consideration for all build platforms. The 'stop.
325 dpurdie 2842
<GBE_MACHTYPE>' will only prevent consideration if being built on a GBE_MACHTYPE
2843
type of computer.
279 dpurdie 2844
 
3559 dpurdie 2845
If the sandbox contains a file called 'buildfilter', then the contents of the
2846
file will be read and used a buildfilter. The file is processed by reading each
2847
line and:
2848
 
2849
=over 4
2850
 
4184 dpurdie 2851
=item * 
3559 dpurdie 2852
 
4184 dpurdie 2853
Removing white space at both ends of the line
3559 dpurdie 2854
 
4184 dpurdie 2855
=item * 
3559 dpurdie 2856
 
4184 dpurdie 2857
Removing empty lines
3559 dpurdie 2858
 
4184 dpurdie 2859
=item * 
2860
 
2861
Lines that start with a # are comments and are removed
2862
 
2863
=item * 
2864
 
2865
Remaining lines are joined together to form a buildfilter
2866
 
3559 dpurdie 2867
=back
2868
 
359 dpurdie 2869
=head1 Create Sandbox
299 dpurdie 2870
 
359 dpurdie 2871
=head2 NAME
299 dpurdie 2872
 
359 dpurdie 2873
Create Sandbox
2874
 
2875
=head2 SYNOPSIS
2876
 
1329 dpurdie 2877
jats sandbox create [command options]
359 dpurdie 2878
 
2879
 Command Options
2880
    -help[=n]               - Command specific help, [n=1,2,3]
2881
    -verbose[=n]            - Verbose operation
2882
 
2883
=head2 OPTIONS
2884
 
7301 dpurdie 2885
The 'create' command takes no options.
359 dpurdie 2886
 
2887
=head2 DESCRIPTION
2888
 
299 dpurdie 2889
The 'create' command will create a sandbox in the users current directory. It is
2890
not possible to create a sandbox within a sandbox.
2891
 
2892
A sandbox can be created in a directory that contains files and subdirectories.
2893
 
2894
The create command simply places a known directory in the current directory.
359 dpurdie 2895
This directory is used by the sandboxing process. It may be manually deleted, or
299 dpurdie 2896
deleted with the 'delete' command.
2897
 
359 dpurdie 2898
=head1 Populate Sandbox
2899
 
2900
=head2 NAME
2901
 
2902
Populate a Sandbox
2903
 
2904
=head2 SYNOPSIS
2905
 
1329 dpurdie 2906
jats sandbox populate [command options] [packageName packageVersion]
359 dpurdie 2907
 
7307 dpurdie 2908
 Common Options:
2909
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 2910
    -toPackage=name            - Stop building after package
2911
    -fromPackage=name          - Start building from package
2912
    -justPackage=name[,name]   - Build named packages
2913
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 2914
    -entireSandbox             - Process the entire sandbox
2915
    -users                     - Process package users, not dependencies
7307 dpurdie 2916
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
2917
    -[no]keepgoing             - Ignore errors
2918
    -[no]reScan                - Recalculate and cache sandbox structure
2919
 Command Specific Options
1329 dpurdie 2920
    -excludePackage=name[,name]- Do not extract named package
2921
    -recurse[=n]               - Locate dependencies within packages
2922
    -all                       - Populate with all dependencies
2923
    -missing                   - Locate missing packages
2924
    -show                      - Show packages that would be extracted
2925
    -test                      - Do not extract packages
2926
    -<Other>                   - Pass options to jats extract
359 dpurdie 2927
 
2928
=head2 ARGUMENTS
2929
 
2930
The 'populate' command can take a package name and version as arguments. It will
2931
then populate the sandbox with this package. See 'DESCRIPTION' for details.
2932
 
2933
=head2 OPTIONS
2934
 
2935
The 'populate' command takes the following options:
2936
 
2937
=over 4
2938
 
1329 dpurdie 2939
=item -excludePackage=name[,name]
2940
 
2941
This option prevents one, or more, packages from populating the sandbox.
2942
Packages specified with this option will not be extracted from version control
2943
and added to the sandbox.
2944
 
4688 dpurdie 2945
Packages can be identified in three ways:
1329 dpurdie 2946
 
2947
=over 4
2948
 
2949
=item 1. Package Name
2950
 
2951
All package versions matching the named package will be excluded.
2952
 
2953
=item 2. Package Name and Version
2954
 
2955
Only the specified version of the named package will be excluded. The
2956
user specifies the package name and version as a single string separated with
2957
an underscore. ie: core_devl_2.100.5000.cr
2958
 
2959
=item 3. Package Name and Suffix
2960
 
2961
All packages matching the named package and project will be excluded. The
2962
user specifies the package name and project as a single string separated with
2963
a dot. ie: core_devl.cr
2964
 
2965
 
2966
=back
2967
 
359 dpurdie 2968
=item -recurse[=N]
2969
 
2970
This option will modify the operation of the command such that dependencies
2971
of named packages can also be extracted into the sandbox.
2972
 
2973
The default operation is to only extract named packages. If the option is
2974
specified then all dependent packages are processed. An optional numeric argument
2975
can be specified to limit the depth of the recursion.
2976
 
1329 dpurdie 2977
=item -all
2978
 
2979
This option will populate the sandbox will all dependencies of packages that are
2980
currently in the sandbox.
2981
 
2982
The global options that control recursion will affect the packages that are
2983
processed.
2984
 
2985
This option cannot be used with the '-missing' option.
2986
 
359 dpurdie 2987
=item -missing
2988
 
2989
This option will modify the operation of the dependency recursion scanning such
2990
that dependent packages that exist in a package archive will not be extracted.
2991
 
2992
Use of this option allows a sandbox to be populated with packages that are
2993
required by packages in the sandbox, but are not available in a package archive.
2994
 
1329 dpurdie 2995
The global options that control recursion will affect the packages that are
2996
processed.
2997
 
2998
This option cannot be used with the '-all' option.
2999
 
3000
=item -show
3001
 
3002
This option will prevent the command from performing the extraction. It will
3003
simply display the names of the packages that would be extracted.
3004
 
359 dpurdie 3005
=item -test
3006
 
3007
This option will prevent the command from performing the extraction. It will
3008
simply display the JATS commands that can be used to perform the extraction.
3009
 
3010
=item -<Other>
3011
 
3012
Options not understood by the 'populate' sub command will be passed through
3013
the package extraction program. Useful options include:
3014
 
363 dpurdie 3015
=over 4
359 dpurdie 3016
 
361 dpurdie 3017
=item *
359 dpurdie 3018
 
361 dpurdie 3019
-extractfiles
359 dpurdie 3020
 
361 dpurdie 3021
=item *
3022
 
3023
-branch=<branch name>
3024
 
359 dpurdie 3025
=back
3026
 
3027
=back
3028
 
3029
=head2 DESCRIPTION
3030
 
3031
The 'populate' command can be used to assist in populating the sandbox. It has
3032
two modes of operation.
3033
 
363 dpurdie 3034
=over 4
359 dpurdie 3035
 
361 dpurdie 3036
=item 1
359 dpurdie 3037
 
361 dpurdie 3038
Named Package
3039
 
363 dpurdie 3040
If the user specifies both a package name and a package version then the command
359 dpurdie 3041
will populate the sandbox with that package and optionally its dependencies.
3042
 
361 dpurdie 3043
=item 2
359 dpurdie 3044
 
361 dpurdie 3045
Determine missing dependencies
3046
 
359 dpurdie 3047
If the user does not specify a package name and version, but does specify
3048
the '-missing' option,  then the command will examine the current sandbox and
3049
determine missing dependent packages. It will then populate the sandbox with
3050
these packages and optionally there dependencies.
3051
 
3052
=back
3053
 
3054
=head2 EXAMPLES
3055
 
3056
=over 4
3057
 
361 dpurdie 3058
=item *
359 dpurdie 3059
 
361 dpurdie 3060
jats sandbox populate package1 version1
3061
 
359 dpurdie 3062
This command will populate the sandbox with version1 of package1, if it does not
3063
already exist in the sandbox.
3064
 
361 dpurdie 3065
=item *
359 dpurdie 3066
 
361 dpurdie 3067
jats sandbox populate package1 version1 -recurse -missing
3068
 
359 dpurdie 3069
This command will populate the sandbox with version1 of package1, if it does not
3070
already exist in the sandbox, together will all the packages dependencies that
3071
are not available in a package archive.
3072
 
361 dpurdie 3073
=item *
359 dpurdie 3074
 
361 dpurdie 3075
jats sandbox populate -recurse -missing
3076
 
359 dpurdie 3077
This command will examine the current sandbox and populate the sandbox with
3078
packages that are required to build the packages in the sandbox and the
3079
dependencies of these packages, provide the dependent package is not in a
3080
package archive.
3081
 
361 dpurdie 3082
=item *
359 dpurdie 3083
 
361 dpurdie 3084
jats sandbox populate
3085
 
359 dpurdie 3086
This command will examine the current sandbox and populate the sandbox with
3087
packages that are required to build the packages in the sandbox. It will not
3088
examine the dependents of these packages.
3089
 
3090
=back
3091
 
3092
=head1 Delete Sandbox
3093
 
3094
=head2 NAME
3095
 
4688 dpurdie 3096
Delete a sandbox
359 dpurdie 3097
 
3098
=head2 SYNOPSIS
3099
 
3100
jats sandbox [options] delete
3101
 
3102
 Options:
3103
    -help[=n]               - Help message, [n=1,2,3]
3104
    -man                    - Full documentation [-help=3]
3105
    -verbose[=n]            - Verbose command operation
3106
 
3107
=head2 DESCRIPTION
3108
 
299 dpurdie 3109
The 'delete' command will delete the sandbox's marker directory. The command may
3110
be executed anywhere within the sandbox.
3111
 
359 dpurdie 3112
Once the sandbox has been deleted, the user must remove the components within the
299 dpurdie 3113
sandbox.
3114
 
359 dpurdie 3115
=head1 Sandbox Information
299 dpurdie 3116
 
359 dpurdie 3117
=head2 NAME
3118
 
3119
Display Sandbox Information
3120
 
3121
=head2 SYNOPSIS
3122
 
1329 dpurdie 3123
jats sandbox info [command options]
359 dpurdie 3124
 
7307 dpurdie 3125
 Common Options:
3126
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3127
    -toPackage=name            - Stop building after package
3128
    -fromPackage=name          - Start building from package
3129
    -justPackage=name[,name]   - Build named packages
3130
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3131
    -entireSandbox             - Process the entire sandbox
3132
    -users                     - Process package users, not dependencies
7307 dpurdie 3133
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
3134
    -[no]keepgoing             - Ignore errors
3135
    -[no]reScan                - Recalculate and cache sandbox structure
3136
 Command Specific Options
3137
    -verbose[=n]               - Display more information
3138
    -usedby                    - Display package usage information
6133 dpurdie 3139
    -fingerprint               - Display fingerprint information
7306 dpurdie 3140
    -[no]dependencies          - Display external dependencies (default)
3141
    -[no]buildorder            - Display build order (default)
7307 dpurdie 3142
    -[no]path                  - Display path to package
361 dpurdie 3143
 
359 dpurdie 3144
=head2 OPTIONS
3145
 
3146
=over
3147
 
3148
=item B<-verbose[=n]>
3149
 
3150
This options will increase the verbosity of the information being displayed.
3151
Values 1 and 2 are described in the detailed 'DESCRIPTION'. Other values are
3152
reserved for diagnostic use.
3153
 
6133 dpurdie 3154
=item B<-usedby>
3155
 
3156
This option will list all packages that use the current package, both directly and
3157
indirectly. These are packages that should be tested whan changes are made to the 
3158
package.
3159
 
3160
=item B<-fingerprint>
3161
 
3162
This option will cause the information display to include that status of each packages fingerprint.
3163
 
3164
This will slow down the display as the calculation can be time consuming.
3165
 
7306 dpurdie 3166
=item B<-[no]dependencies>
3167
 
3168
This option will cause the information display to include all the external dependencies.
3169
 
3170
=item B<-[no]buildorder>
3171
 
3172
This option will cause the information display to include all the build order.
3173
 
7307 dpurdie 3174
=item B<-[no]path>
3175
 
3176
This option will cause the information display to include all the path to the build file
3177
 
359 dpurdie 3178
=back
3179
 
3180
=head2 DESCRIPTION
3181
 
299 dpurdie 3182
The 'info' command will display information about the build order and the
359 dpurdie 3183
dependencies of packages that it finds within the sandbox.
299 dpurdie 3184
 
359 dpurdie 3185
The command works within various levels of verbosity:
299 dpurdie 3186
 
3187
=over 8
3188
 
361 dpurdie 3189
=item *
299 dpurdie 3190
 
361 dpurdie 3191
No Verbosity
3192
 
299 dpurdie 3193
The basic command will display the build order and the external
335 dpurdie 3194
dependencies. External dependencies may be prefixed with one of the
3195
following indicators:
299 dpurdie 3196
 
335 dpurdie 3197
=over 8
3198
 
361 dpurdie 3199
=item   '+' Multiple versions of this package are being used by sandboxed components.
335 dpurdie 3200
 
361 dpurdie 3201
=item   '*' The package cannot be found in any of the package archives.
335 dpurdie 3202
 
3203
=back
3204
 
361 dpurdie 3205
=item *
299 dpurdie 3206
 
361 dpurdie 3207
Verbosity of 1
3208
 
359 dpurdie 3209
This level of verbosity will display the build order and detailed information
299 dpurdie 3210
on the dependencies. The dependencies will be prefixed with:
3211
 
3212
=over 8
3213
 
361 dpurdie 3214
=item   E Dependent Package is external to the sandbox
299 dpurdie 3215
 
361 dpurdie 3216
=item   I Dependent Package is internal to the sandbox
299 dpurdie 3217
 
3218
=back
3219
 
335 dpurdie 3220
External dependencies may be prefixed with one of the indicators described for
3221
no-verbosity. Additionally the internal consumer of the external package is also
3222
shown. These are prefixed with a 'U'.
299 dpurdie 3223
 
361 dpurdie 3224
=item *
299 dpurdie 3225
 
361 dpurdie 3226
Verbosity of 2
3227
 
6133 dpurdie 3228
Usage information will also be displayed. This is the same as invoking the 
3229
'-usedby' option.
299 dpurdie 3230
 
361 dpurdie 3231
=item *
299 dpurdie 3232
 
361 dpurdie 3233
Verbosity over 2
3234
 
359 dpurdie 3235
This should be considered a debug option. Undocumented internal information will
299 dpurdie 3236
be displayed.
3237
 
3238
=back
3239
 
4197 dpurdie 3240
=head1 Buildfilter
3241
 
3242
=head2 NAME
3243
 
3244
Display and Modify Sandbox buildfilter
3245
 
3246
=head2 SYNOPSIS
3247
 
3248
jats sandbox buildfilter [command options] [TARGETS]+
3249
 
3250
 Command Options
3251
    -help[=n]               - Command specific help, [n=1,2,3]
3252
    -man                    - Same as -help=3
3253
 
3254
 Target Names
3255
    -TARGET                 - Remove target from the current buildfilter
3256
    +TARGET                 - Add target to current buildfilter
3257
    TARGET                  - If first target, then reset buildfilter 
3258
                              and add target, otherwise add target.
3259
 
3260
=head2 OPTIONS
3261
 
3262
The 'buildfilter' command takes the following options:
3263
 
3264
=over 8
3265
 
3266
=item -TARGET
3267
 
3268
If a target name starts with a '-' and is not an option, then that target will be
3269
removed from the current buildfilter. 
3270
 
3271
If the named target is not a part of the current buildfilter then nothing will happen.
3272
 
3273
=item +TARGET
3274
 
3275
If a target name starts with a '+' then that target will be added to the current buildfilter.
3276
 
3277
If the named target is already a part of the current buildfilter then nothing will happen.
3278
 
3279
 
3280
=item TARGET
3281
 
3282
If a target name does not start with either a '-' or a '+' then the target will be added to the
3283
current buildfilter.
3284
 
3285
If this is the first named target then the build filter will be set to this one target.
3286
 
3287
=back
3288
 
3289
=head2 DESCRIPTION
3290
 
3291
The 'buildfilter' command will display and optionally modify the build filter used within
3292
the sandbox.
3293
 
3294
=head2 EXAMPLES
3295
 
3296
The command
3297
 
3298
    jats sandbox buildfilter 
3299
 
3300
will simply display the current buildfilter.
3301
 
3302
The command
3303
 
3304
    jats sandbox buildfilter +COBRA +PPC_603E
3305
 
3306
will append the build targets COBRA and PPC_603E to the current buildfilter.
3307
 
3308
The command
3309
 
3310
    jats sandbox buildfilter -COBRA
3311
 
3312
will remove the build target COBRA from the current buildfilter.
3313
 
3314
The command
3315
 
3316
    jats sandbox buildfilter COBRA +PPC_603E
3317
 or jats sandbox buildfilter COBRA PPC_603E
3318
 
3319
will set the buildfilter to be COBRA and PPC_603E
3320
 
6133 dpurdie 3321
=head1 Skip Build
3322
 
3323
=head2 NAME
3324
 
3325
Mark a package to be skipped during the build
3326
 
3327
=head2 SYNOPSIS
3328
 
3329
jats sandbox [un]skip [command options] [PackageName]+
3330
 
3331
 Command Options
3332
    -help[=n]               - Command specific help, [n=1,2,3]
3333
    -man                    - Same as -help=3
3334
    -[no]machine            - Skip on on this type of machine
3335
 
3336
=head2 ARGUMENTS
3337
 
3338
Arguments to the 'skip' command are the names of packages to be marked.
3339
 
3340
If no packages are named then the command will display all packages that are marked to be skipped.
3341
 
3342
If the named package is '.', then the current package will be excluded.
3343
 
3344
=head2 OPTIONS
3345
 
3346
The 'skip' command takes the following options:
3347
 
3348
=over 8
3349
 
3350
=item -[no]machine
3351
 
3352
This option will flag that the package will be skipped only on this type of build machine.
3353
 
3354
=back
3355
 
3356
=head2 DESCRIPTION
3357
 
3358
The 'skip' command marked the named packages to be skipped during the build, or the mark will be removed.
3359
 
3360
=head2 EXAMPLES
3361
 
3362
The command
3363
 
3364
    jats sandbox skip package1 
3365
 
3366
will mark package1 to be skipped during the following builds.
3367
 
3368
=head1 Sandbox Finger Print
3369
 
3370
=head2 NAME
3371
 
3372
Various fingerprint operations
3373
 
3374
=head2 SYNOPSIS
3375
 
3376
jats sandbox finger[print] [options]
3377
 
3378
 Command Options
3379
    -help[=n]               - Command specific help, [n=1,2,3]
3380
    -man                    - Same as -help=3
3381
    -[no]generate           - Generate a fingerprint over a package
3382
    -[no]delete             - Delete the fingerprint information
3383
 
3384
=head2 ARGUMENTS
3385
 
3386
Arguments to the 'fingerprint' command are the names of packages to be processed.
3387
 
3388
If no packages are named then the command will process the current package, if any.
3389
 
3390
=head2 OPTIONS
3391
 
3392
The 'fingerprint' command takes the following options:
3393
 
3394
=over 8
3395
 
3396
=item -[no]generate
3397
 
3398
This option will cause the fingerprint of the package to be regenerated.
3399
 
3400
=item -[no]delete
3401
 
3402
This option will delete the fingerprint information associated wit a package.
3403
 
3404
=back
3405
 
3406
=head2 DESCRIPTION
3407
 
3408
The 'fingerprint' command, will by default, examine the packages fingerprint and report
3409
if the package has been modified since the fingerprint was created.
3410
 
3411
Options allow different modes of operation.
3412
 
3413
A fingerprint may only be created after the 'build.pl' file has been created. It requires the
3414
build process to generate metadata about the package.
3415
 
3416
=head2 EXAMPLES
3417
 
3418
The command
3419
 
3420
    jats sandbox fingerprint -generate
3421
 
3422
will regenerate the fingerprint of the current package. Useful after trivial edits to 
3423
enable the sandbox builder to bypass the package and not to rebuild it and all of its dependents.
3424
 
359 dpurdie 3425
=head1 Command all
331 dpurdie 3426
 
359 dpurdie 3427
=head2 NAME
3428
 
3429
Build packages in the sandbox
3430
 
3431
=head2 SYNOPSIS
3432
 
1329 dpurdie 3433
jats sandbox all [command options] [arguments]
359 dpurdie 3434
 
7307 dpurdie 3435
 Common Options:
3436
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3437
    -toPackage=name            - Stop building after package
3438
    -fromPackage=name          - Start building from package
3439
    -justPackage=name[,name]   - Build named packages
3440
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3441
    -entireSandbox             - Process the entire sandbox
3442
    -users                     - Process package users, not dependencies
7307 dpurdie 3443
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
6133 dpurdie 3444
    -[no]keepgoing             - Ignore errors
7307 dpurdie 3445
    -[no]reScan                - Recalculate and cache sandbox structure
3446
 Command Specific Options
6133 dpurdie 3447
    -[no]skip                  - Skip if no source change (default:skip)
359 dpurdie 3448
 
6133 dpurdie 3449
 
359 dpurdie 3450
=head2 ARGUMENTS
3451
 
3452
Arguments are passed to the 'make' phase of the process.
3453
 
3454
=head2 OPTIONS
3455
 
6133 dpurdie 3456
=over
359 dpurdie 3457
 
6133 dpurdie 3458
=item B<-[no]skip>
3459
 
3460
This operation overides the default smart building mechanism.
3461
 
3462
By default, a package will not be built if the last build was successful and 
3463
there has not been any change to the source of the package, since the last 
3464
succesful build.
3465
 
3466
=back
3467
 
359 dpurdie 3468
=head2 DESCRIPTION
3469
 
331 dpurdie 3470
The 'all' command will perform build, if the build files are out of date,
3471
followed by a make in each of the packages within the sandbox, in the correct
3472
build order.
3473
 
3474
Any arguments are passed to the 'make' phase of the process.
3475
 
3476
This command may be used to:
3477
 
3478
=over 8
3479
 
361 dpurdie 3480
=item *
331 dpurdie 3481
 
361 dpurdie 3482
Pickup any build file changes.
331 dpurdie 3483
 
361 dpurdie 3484
=item *
3485
 
3486
Resume a failed build.
3487
 
331 dpurdie 3488
=back
3489
 
359 dpurdie 3490
=head1 Command build
331 dpurdie 3491
 
359 dpurdie 3492
=head2 NAME
3493
 
3494
Build packages in the sandbox
3495
 
3496
=head2 SYNOPSIS
3497
 
1329 dpurdie 3498
jats sandbox build [command options] [arguments]
359 dpurdie 3499
 
7307 dpurdie 3500
 Common Options:
3501
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3502
    -toPackage=name            - Stop building after package
3503
    -fromPackage=name          - Start building from package
3504
    -justPackage=name[,name]   - Build named packages
3505
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3506
    -entireSandbox             - Process the entire sandbox
3507
    -users                     - Process package users, not dependencies
7307 dpurdie 3508
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
6133 dpurdie 3509
    -[no]keepgoing             - Ignore errors
7307 dpurdie 3510
    -[no]reScan                - Recalculate and cache sandbox structure
3511
 Command Specific Options
6133 dpurdie 3512
    -[no]skip                  - Skip if no source change (default:skip)
359 dpurdie 3513
 
3514
=head2 ARGUMENTS
3515
 
3516
Arguments are passed to the 'make' phase of the process.
3517
 
3518
=head2 OPTIONS
3519
 
6133 dpurdie 3520
=over
359 dpurdie 3521
 
6133 dpurdie 3522
=item B<-[no]skip>
3523
 
3524
This operation overides the default smart building mechanism.
3525
 
3526
By default, a package will not be built if the last build was successful and 
3527
there has not been any change to the source of the package, since the last 
3528
succesful build.
3529
 
3530
=back
3531
 
359 dpurdie 3532
=head2 DESCRIPTION
3533
 
331 dpurdie 3534
The 'build' command will force a build followed by a make in each of the packages
3535
within the sandbox, in the correct build order.
3536
 
3537
Any arguments are passed to the 'make' phase of the process.
3538
 
3539
In practice, the 'sandbox all' command is quicker.
3540
 
359 dpurdie 3541
=head1 Clean
331 dpurdie 3542
 
359 dpurdie 3543
=head2 NAME
3544
 
3545
Clean all sandbox components
3546
 
3547
=head2 SYNOPSIS
3548
 
1329 dpurdie 3549
jats sandbox clean|clobber [command options]
359 dpurdie 3550
 
7307 dpurdie 3551
 Common Options:
3552
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3553
    -toPackage=name            - Stop building after package
3554
    -fromPackage=name          - Start building from package
3555
    -justPackage=name[,name]   - Build named packages
3556
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3557
    -entireSandbox             - Process the entire sandbox
3558
    -users                     - Process package users, not dependencies
7307 dpurdie 3559
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
6133 dpurdie 3560
    -[no]keepgoing             - Ignore errors
7307 dpurdie 3561
    -[no]reScan                - Recalculate and cache sandbox structure
359 dpurdie 3562
 
3563
=head2 ARGUMENTS
3564
 
3565
None
3566
 
3567
=head2 OPTIONS
3568
 
7307 dpurdie 3569
The are no command specific options.
359 dpurdie 3570
 
3571
=head2 DESCRIPTION
3572
 
3573
The 'clean' command will perform a 'jats make clean' in all components in the
3574
sandbox.
3575
 
3576
The 'clobber' command will perform a 'jats clobber' in all components in the
3577
sandbox.
3578
 
3579
=head1 make
3580
 
3581
=head2 NAME
3582
 
3583
Make packages in the sandbox
3584
 
3585
=head2 SYNOPSIS
3586
 
1329 dpurdie 3587
jats sandbox make [command options] [arguments]
359 dpurdie 3588
 
7307 dpurdie 3589
 Common Options:
3590
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3591
    -toPackage=name            - Stop building after package
3592
    -fromPackage=name          - Start building from package
3593
    -justPackage=name[,name]   - Build named packages
3594
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3595
    -entireSandbox             - Process the entire sandbox
3596
    -users                     - Process package users, not dependencies
7307 dpurdie 3597
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
3598
    -[no]keepgoing             - Ignore errors
3599
    -[no]reScan                - Recalculate and cache sandbox structure
359 dpurdie 3600
 
3601
=head2 ARGUMENTS
3602
 
3603
Arguments are passed to the 'make' phase of the process.
3604
 
3605
=head2 OPTIONS
3606
 
3607
The are no command specific options.
3608
 
3609
=head2 DESCRIPTION
3610
 
331 dpurdie 3611
The 'make' command will perform a 'make' operation in each of the packages
3612
within the sandbox, in the correct build order.
3613
 
3614
Any arguments are passed to the 'make'.
3615
 
359 dpurdie 3616
=head1 cmd
331 dpurdie 3617
 
359 dpurdie 3618
=head2 NAME
3619
 
3620
Process each package with a specified command.
3621
 
3622
=head2 SYNOPSIS
3623
 
1329 dpurdie 3624
jats sandbox cmd [command options] [arguments]
359 dpurdie 3625
 
7307 dpurdie 3626
 Common Options:
3627
    -help[=n], -man            - Command specific help, [n=1,2,3]
1329 dpurdie 3628
    -toPackage=name            - Stop building after package
3629
    -fromPackage=name          - Start building from package
3630
    -justPackage=name[,name]   - Build named packages
3631
    -ignorePackage=name[,name] - Do not build named packages
6133 dpurdie 3632
    -entireSandbox             - Process the entire sandbox
3633
    -users                     - Process package users, not dependencies
7307 dpurdie 3634
    -multiBuilders=mode        - Handle conflicting packages. error|report|ignore
3635
    -[no]keepgoing             - Ignore errors
3636
    -[no]reScan                - Recalculate and cache sandbox structure
7308 dpurdie 3637
 Command Specific Options
3638
    -[no]reverse               - Reverse the processing order
359 dpurdie 3639
 
3640
=head2 ARGUMENTS
3641
 
3642
Arguments are passed to a JATS command.
3643
 
3644
=head2 OPTIONS
3645
 
7308 dpurdie 3646
The 'cmd' command takes the following options:
359 dpurdie 3647
 
7308 dpurdie 3648
=over 8
3649
 
3650
=item -[no]reverse
3651
 
3652
This option will controlls the order in which the packages will be processed.
3653
 
3654
The default option is 'noreverse'. Packages will be processed in the build order.
3655
 
2054 dpurdie 3656
=back
3657
 
359 dpurdie 3658
=head2 DESCRIPTION
3659
 
331 dpurdie 3660
The 'cmd' command will pass all of its arguments to JATS in the build directory
3661
of each of the packages within the sandbox, in the package build order.
3662
 
4086 dpurdie 3663
=head2 EXAMPLES
3664
 
3665
The following command will update all the Subversion-based packages in the sandbox.
3666
 
3667
    jats sandbox cmd eprog svn update
3668
 
3669
Note the use of 'eprog' in the command string. This tells JATS to run the external
3670
(to JATS) program. Without this the command would run the JATS-internal command
3671
called 'svn' - with different results.
3672
 
3673
The following command will update the dependencies in the build.pl files to match
3674
those of a nominated release. This will only affect the package versions
3675
external to the sandbox, although all version information in the build.pl
3676
files will be updated.
3677
 
3678
    jats sandbox cmd upddep -rtagid=12345
3679
 
359 dpurdie 3680
=head1 Cache
331 dpurdie 3681
 
359 dpurdie 3682
=head2 NAME
331 dpurdie 3683
 
359 dpurdie 3684
Cache dependent packages
331 dpurdie 3685
 
359 dpurdie 3686
jats sandbox [options] cache [command options]
331 dpurdie 3687
 
359 dpurdie 3688
 Options:
3689
    -help[=n]               - Help message, [n=1,2,3]
3690
    -man                    - Full documentation [-help=3]
3691
    -verbose[=n]            - Verbose command operation
337 dpurdie 3692
 
359 dpurdie 3693
 Command Options
3694
    -help[=n]               - Command specific help, [n=1,2,3]
337 dpurdie 3695
 
359 dpurdie 3696
=head2 ARGUMENTS
3697
 
3698
The are no command specific arguments.
3699
 
3700
=head2 OPTIONS
3701
 
3702
The are no command specific options.
3703
 
3704
=head2 DESCRIPTION
3705
 
3706
The 'cache' command will cache all external dependent packages into the users
3707
dpkg_archive_cache as defined through the EnvVar GBE_DPKG_CACHE. The result is
3708
similar to the command 'jats sandbox build -cache', without the overhead of
3709
building the sandbox components.
3710
 
3711
This command allows the simple creation of a small development environment that
3712
is not tied to the larger Development Environment. It may then be used in a
337 dpurdie 3713
disconnected mode to perform development.
3714
 
7304 dpurdie 3715
=head1 Sandbox Test Links
3716
 
3717
=head2 NAME
3718
 
3719
Test and delete sandbox link files
3720
 
3721
=head2 SYNOPSIS
3722
 
3723
jats sandbox testlinks [options]
3724
 
3725
 Command Options
3726
    -help[=n]               - Command specific help, [n=1,2,3]
3727
    -man                    - Same as -help=3
3728
    -[no]delete             - Delete bad links
3729
 
3730
=head2 ARGUMENTS
3731
 
3732
This command does not take any arguments
3733
 
3734
=head2 OPTIONS
3735
 
3736
The 'fingerprint' command takes the following options:
3737
 
3738
=over 8
3739
 
3740
=item -[no]delete
3741
 
3742
This option will delete the link files if they are bad.
3743
 
3744
=back
3745
 
3746
=head2 DESCRIPTION
3747
 
3748
The 'testlinks' command, will by default, examine symbolic links within the sandbox and report on
3749
broken links.
3750
 
7306 dpurdie 3751
An option allows the broken links to be deleted.
7304 dpurdie 3752
 
3753
Each package in the sandbox will have a symbolic link to the packages 'package' area. If a package is removed
3754
from the sandbox the link file may be left in the sandbox and cause a 'build' to fail.
3755
 
3756
=head2 EXAMPLES
3757
 
3758
The command
3759
 
3760
    jats sandbox testlinks
3761
 
3762
will test the symbolic links in the sandbox metadata.
3763
 
7306 dpurdie 3764
=head1 Sandbox Scan Depth
3765
 
3766
=head2 NAME
3767
 
3768
Set and Display the build file scanner depth
3769
 
3770
=head2 SYNOPSIS
3771
 
3772
jats sandbox scandepth [options] [depth]
3773
 
3774
 Command Options
3775
    -help[=n]               - Command specific help, [n=1,2,3]
3776
    -man                    - Same as -help=3
3777
 
3778
=head2 ARGUMENTS
3779
 
3780
This command takes one optional argument. A positive number that control the 
3781
depth of the build filter scanner.
3782
 
3783
The default value is '3'. Deeper scans may be required for sandboxes containing badly formed 
3784
packages. The tradoff is speed for all sandbox operations.
3785
 
3786
Setting the scan depth will force a rescan of the sandbox build files on the next command that
3787
requires the information.
3788
 
3789
=head2 OPTIONS
3790
 
3791
The scandepth command only accepts the standard help and man options.
3792
 
3793
=head2 DESCRIPTION
3794
 
3795
The scandepth command, will by default, display the current value for the build file scanner.
3796
 
3797
If a numeric argument is provided this will set the future build file scan depth.
3798
 
3799
=head2 EXAMPLES
3800
 
3801
The command
3802
 
3803
    jats sandbox scandepth 5
3804
 
3805
will set future build file scan to a maximum of 5 directories below the root of the sandbox.
3806
 
227 dpurdie 3807
=cut
3808