Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
263 dpurdie 1
########################################################################
4549 dpurdie 2
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
227 dpurdie 3
#
5499 dpurdie 4
# Module name   : create_dpkg.pl
4549 dpurdie 5
# Module type   : Makefile system
263 dpurdie 6
# Compiler(s)   : Perl
4549 dpurdie 7
# Environment(s): jats
227 dpurdie 8
#
263 dpurdie 9
# Description   : This script is used to create a dpkg_archive.
5527 dpurdie 10
#                 Features:
4549 dpurdie 11
#                   * No user interaction
5527 dpurdie 12
#                   * Generates files list for ReleaseNote integration
13
#                   * Can generate package fragemts as a tarball for build system
227 dpurdie 14
#
4549 dpurdie 15
# Usage:        : See POD
227 dpurdie 16
#
263 dpurdie 17
#......................................................................#
227 dpurdie 18
 
4549 dpurdie 19
 
263 dpurdie 20
require 5.008_002;
227 dpurdie 21
 
22
# Include Standard Perl Functions
23
#
24
use strict;
263 dpurdie 25
use warnings;
227 dpurdie 26
use Cwd;
27
use Getopt::Long;
28
use File::Basename;
29
use File::Find;
30
use File::Path;
31
use File::Copy;
32
use Pod::Usage;
263 dpurdie 33
use Digest::MD5;
4549 dpurdie 34
use XML::Simple;
4633 dpurdie 35
use Encode qw(decode encode);
227 dpurdie 36
 
37
use JatsError;
263 dpurdie 38
use JatsEnv;
227 dpurdie 39
use DescPkg;
40
use FileUtils;
5527 dpurdie 41
use JatsSystem;
227 dpurdie 42
 
363 dpurdie 43
#
44
#   Under Windows we need the Win32::FileSecurity module
45
#   It only exists under windows
46
#
47
my $Win32 = eval "require Win32::FileSecurity";
48
 
227 dpurdie 49
# define Global variables
50
#
4549 dpurdie 51
my $VERSION = "3.0.0";
227 dpurdie 52
my $PROGNAME = "create_dpkg.pl";
53
 
279 dpurdie 54
# Globals imported from environment
55
#
56
our $GBE_MACHTYPE;
57
our $GBE_HOSTNAME;
58
our $USER;
59
our $GBE_ABT;
227 dpurdie 60
 
279 dpurdie 61
# Global variables
62
#
227 dpurdie 63
my $DPKG_NAME     = "";
64
my $DESC_NAME     = "";
65
my $DPKG_VERSION  = "";
66
my $DESCPKG_FILE  = "";
67
my $DESCPKG_TYPE  = "";
68
my $CWD_DIR       = cwd;
69
my $SRC_ROOT;
70
my $DPKG_DIR;
71
my $DPKG_ROOT;
4003 dpurdie 72
my $PKG_BASE;
263 dpurdie 73
my $bad_merge_count = 0;
4424 dpurdie 74
my @bad_symlinks;
4549 dpurdie 75
my @fileList;
76
my $descPkgCount = 0;
227 dpurdie 77
 
78
#
79
#   Option variables
80
#
81
my $opt_help = 0;
82
my $opt_manual = 0;
83
my $opt_verbose = 0;
84
my $opt_quiet = 0;
4549 dpurdie 85
my $opt_delete = 0;
227 dpurdie 86
my $opt_override = 0;
87
my $opt_merge = 0;
88
my $opt_archive;
89
my $opt_generic;
90
my $opt_pname;
91
my $opt_pversion;
92
my $opt_test;
263 dpurdie 93
my $opt_md5 = 1;
4549 dpurdie 94
my $opt_outfile;
95
my $opt_info;
5527 dpurdie 96
my $opt_tarmode;
97
my $opt_testArchive;
227 dpurdie 98
 
99
 
100
#
101
#   Structure to translate -archive=xxx option to archive variable
102
#   These are the various dpkg_archives known to JATS
103
#
4688 dpurdie 104
my %Archive2Var =( 'main'      => 'GBE_DPKG',
105
                   'store'     => 'GBE_DPKG_STORE',
106
                   'cache'     => 'GBE_DPKG_CACHE',
107
                   'local'     => 'GBE_DPKG_LOCAL',
108
                   'sandbox'   => 'GBE_DPKG_SBOX',
109
                   'deploy'    => 'GBE_DPLY',
110
                   'replica'   => 'GBE_DPKG_REPLICA',
227 dpurdie 111
                   );
112
 
113
#------------------------------------------------------------------------------
114
#------------------------------------------------------------------------------
115
# Subroutines
116
#------------------------------------------------------------------------------
117
#------------------------------------------------------------------------------
118
 
119
#------------------------------------------------------------------------------
120
sub LogFileOp
121
#
122
# Description:
123
#       This sub-routine is used to generate a consistent informational log
124
#------------------------------------------------------------------------------
125
{
126
    my ($opr, $file) = @_;
5532 dpurdie 127
    $file =~ s/\Q$DPKG_ROOT\E/DPKG/;
128
    $file =~ s/\Q$SRC_ROOT\E/PKG/;
227 dpurdie 129
 
130
    Information (sprintf( "%-15s [%s]", $opr, $file));
131
}
132
 
4549 dpurdie 133
#-------------------------------------------------------------------------------
134
# Function        : addFile 
135
#
136
# Description     : Add a file to the list of transferred files
137
#
138
# Inputs          : $type           - File type
139
#                   $source         - Source file - full path
140
#                                     Use local copy, not network copy for file ops
141
#                   $target         - Target file name
142
#                   $md5sum         - Precalculated MD5 sum 
143
#
144
# Returns         : 
145
#
146
sub addFile
147
{
148
    my ($type, $source, $target, $md5sum) = @_;
149
    my %data;
150
 
151
    if ((not defined $md5sum) && ($type eq 'file'))
152
    {
153
        Verbose("Calculate MD5 Digest: $source");
154
        open(my $fh , $source) or Error ("Can't open '$source': $!");
155
        binmode $fh, ':crlf';
156
        $md5sum = Digest::MD5->new->addfile($fh)->hexdigest;
157
        close $fh;
158
    }
159
 
5532 dpurdie 160
    $target =~ s~\Q$DPKG_DIR\E~~;
4549 dpurdie 161
    $target =~ s~^/~~;
162
    $target =~ s~/$~~;
163
 
4633 dpurdie 164
    #
165
    #   Convert from iso-8859-1 into utf-8
166
    #
167
    $target = decode( 'iso-8859-1', $target );
168
    $target = encode( 'utf-8', $target );
169
 
4549 dpurdie 170
    if ($type eq 'dir')
171
    {
172
        $data{path} = $target;
173
    }
174
    else
175
    {
176
        $data{path} = StripFileExt($target);
177
        $data{name} = StripDir($target);
178
        if ($type eq 'file')
179
        {
180
            $data{size} = (stat($source))[7];
181
            $data{md5sum} = $md5sum;
182
        }
183
    }
184
 
185
    $data{fullname} = $target;
186
    $data{type} = $type;
187
    $data{machtype} = $GBE_MACHTYPE;
188
    $data{host} = $GBE_HOSTNAME;
189
 
5499 dpurdie 190
    # Put a nice '/' on the end of the path elements
4549 dpurdie 191
    $data{path} .= '/'
192
        if ( exists ($data{path}) && length($data{path}) > 0);
193
 
194
    push @fileList, \%data;
195
}
196
 
197
#-------------------------------------------------------------------------------
198
# Function        : writeFileInfo 
199
#
200
# Description     : Write out an XML file that contains this processes
201
#                   contribution to the output package 
202
#
5527 dpurdie 203
# Inputs          : $targetDir          - Base directory for the file 
4549 dpurdie 204
#
205
# Returns         : 
206
#
207
sub writeFileInfo
208
{
5527 dpurdie 209
    my ($targetDir) = @_;
4549 dpurdie 210
    my $data;
211
    $data->{file} = \@fileList;
212
 
213
    #
214
    #   Write out sections of XML
215
    #       Want control over the output order
216
    #       Use lots of attributes and only elements for arrays
217
    #       Save as one attribute per line - for readability
218
    #
5527 dpurdie 219
    $opt_outfile = $opt_generic ? "built.files.generic.xml" : "built.files.$GBE_HOSTNAME.xml";
220
    $opt_outfile = catfile( $targetDir, $opt_outfile); 
4549 dpurdie 221
 
222
    LogFileOp ('Meta File', $opt_outfile);
223
    my $xs = XML::Simple->new( NoAttr =>0, AttrIndent => 1 );
224
 
225
    open (my $XML, '>', $opt_outfile) || Error ("Cannot create output file: $opt_outfile", $!);
226
    $xs->XMLout($data, 
227
                'RootName' => 'files', 
228
                'XMLDecl'  => '<?xml version="1.0" encoding="UTF-8"?>',
229
                'OutputFile' => $XML);
230
    close $XML;
231
 
232
}
233
 
227 dpurdie 234
#------------------------------------------------------------------------------
235
sub Init
236
#
237
# Description:
238
#     This function is used to process any command line arguements
239
#     and print the start banner.
240
#
241
#------------------------------------------------------------------------------
242
{
243
    # Process any command line arguements...
244
    my $result = GetOptions (
5527 dpurdie 245
                'help:+'        => \$opt_help,              # flag, multiple use allowed
246
                'manual:3'      => \$opt_help,              # flag
247
                'verbose:+'     => \$opt_verbose,           # flag, multiple use allowed
248
                'override!'     => \$opt_override,          # [no]flag (No longer used. Backward compat with build tool)
249
                'delete!'       => \$opt_delete,            # [no]flag
250
                'merge|m!'      => \$opt_merge,             # [no]flag.
251
                'archive=s'     => \$opt_archive,           # string
252
                'quiet+'        => \$opt_quiet,             # Flag
253
                'generic!'      => \$opt_generic,           # [no]Flag
254
                'pname=s'       => \$opt_pname,             # string
255
                'pversion=s'    => \$opt_pversion,          # string
256
                'test!'         => \$opt_test,              # [no]flag
257
                'md5!'          => \$opt_md5,               # [no]flag
258
                'info!'         => \$opt_info,              # [no]flag
259
                'tarmode!'      => \$opt_tarmode,           # [no]flag
260
                'testArchive'   => \$opt_testArchive,       # [no]flag
227 dpurdie 261
                );
262
 
263
 
264
    #
265
    #   Process help and manual options
266
    #
267
    pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
268
    pod2usage(-verbose => 1)  if ($opt_help == 2 );
263 dpurdie 269
    pod2usage(-verbose => 2)  if ($opt_help > 2);
227 dpurdie 270
 
271
    #
272
    #   Init the error and message subsystem
273
    #
274
    ErrorConfig( 'name'    =>'CREATE_DPKG',
275
                 'verbose' => $opt_verbose,
276
                 'quiet'   => $opt_quiet );
277
 
278
    if ($opt_verbose)
279
    {
280
       Verbose ("Program: $PROGNAME");
281
       Verbose ("Version: $VERSION");
282
    }
283
 
284
    #
263 dpurdie 285
    #   Needed EnvVars
286
    #
287
    EnvImport ('GBE_MACHTYPE');
279 dpurdie 288
    EnvImport ('GBE_HOSTNAME');
289
    EnvImport ('USER' );
290
    EnvImportOptional ('GBE_ABT', "");
263 dpurdie 291
 
4003 dpurdie 292
    #
293
    #   Determine the target archive
294
    #   The default archive is GBE_DPKG, but this may be changed
295
    #
296
    $opt_archive = 'main' unless ( $opt_archive );
297
    my $archive_tag = $Archive2Var{$opt_archive};
298
    Error("Unknown archive specified: $opt_archive")
299
        unless ( $archive_tag );
300
    $DPKG_ROOT = $ENV{$archive_tag} || '';
301
    Verbose ("Archive Variable: $archive_tag" );
302
    Verbose2 ("Archive Path: $DPKG_ROOT" );
279 dpurdie 303
 
263 dpurdie 304
    #
5527 dpurdie 305
    #   Append testArchive path
306
    #
307
    $DPKG_ROOT = catdir ($DPKG_ROOT, '.dpkg_archive', 'test_dpkg') if $opt_testArchive;
308
 
309
    #
4003 dpurdie 310
    #   Detect NoBuild marker
311
    #   This will bypass most of the operation of this package
312
    #
313
    if ( -f 'noBuild.gbe' )
314
    {
315
        Verbose ("No Build Marker file found");
316
        Error("Use of noBuild marker should only be done by a build daemon")
317
            unless ( $GBE_ABT );
318
 
319
        $SRC_ROOT = '';
320
        $DPKG_NAME = 'pkg';
321
        $DESCPKG_FILE = 'descpkg';
322
        $PKG_BASE =$CWD_DIR;
323
        return;
324
    }
325
 
326
    #
227 dpurdie 327
    #   Check for a "pkg" directory
328
    #   This may be in:
329
    #       1) The deploy directory (DEPLOY) build/deploy/descpkg
330
    #       2) The build directory (ANT)     build/pkg/descpkg
331
    #       3) The current directory (JATS)  pkg/xxxx/descpkg
332
    #
4003 dpurdie 333
    $PKG_BASE = "$CWD_DIR/build/deploy";
227 dpurdie 334
    Verbose2 ("Looking for descpkg: $PKG_BASE");
335
    if ( -f "$PKG_BASE/descpkg" )
336
    {
337
        #
338
        #   This is a deployment package.
339
        #   Force the use of the GBE_DPLY
340
        #
341
        $opt_archive = 'deploy' unless ( $opt_archive );
342
    }
343
    else
344
    {
345
        $PKG_BASE = "$CWD_DIR/build/pkg";
346
        Verbose ("Looking for descpkg: $PKG_BASE");
347
        if ( ! -f  "$PKG_BASE/descpkg" )
348
        {
349
            $PKG_BASE = "$CWD_DIR/pkg";
350
            Verbose ("Looking for descpkg: $PKG_BASE");
351
            Error("Failed to find a package to transfer. Looked in:",
352
                  "./build/deploy",
353
                  "./build/pkg",
354
                  "./pkg"
355
                  )
356
                unless( -d $PKG_BASE );
357
        }
358
    }
359
    Verbose("Package directory: $PKG_BASE");
360
 
361
    Error("Repository location not specified: $archive_tag")
362
        unless $DPKG_ROOT;
363
 
364
    Error("Failed to find Repository: $DPKG_ROOT")
365
        unless ( -d $DPKG_ROOT );
366
 
367
    #   Locate the package
368
    #   Packages are located by looking for a file called descpkg within the
369
    #   main package directory.
370
    #
371
    #   This installation process only handles one such file
372
    #
4549 dpurdie 373
    $descPkgCount = 0;
227 dpurdie 374
    File::Find::find( \&pkgFind, $PKG_BASE);
4549 dpurdie 375
 
376
    if ($descPkgCount > 1 )
377
    {
378
        Warning ("Package contains multiple ($descPkgCount) descpkg files");
379
    }
4003 dpurdie 380
}
227 dpurdie 381
 
4003 dpurdie 382
#-------------------------------------------------------------------------------
383
# Function        : CheckDescPkg
384
#
385
# Description     : Check the descpkg file
386
#
387
# Inputs          : Globals
388
#
389
# Returns         : Will not return on error
390
#
391
sub CheckDescPkg
392
{
227 dpurdie 393
    # Get the dpkg_archive version number we are  going to create.
394
    #
395
    Error("Descpkg file not found in package directory: $PKG_BASE")
396
        unless ( -f "$DESCPKG_FILE" );
397
 
398
    #
399
    #   Read in the package description and validate essential fields
400
    #
401
    GetDpkgArchiveVersion($DESCPKG_FILE);
402
    unless ( "$DPKG_VERSION" )
403
    {
404
        Error ("Incorrect descpkg content detected.",
405
               "Check JATS build.pl config.");
406
    }
407
 
408
    #
409
    #   Need to support two forms of pkg subdirectory
410
    #       1) packages are in a named subdir within 'pkg'
411
    #       2) package is within 'pkg' or 'deploy'
412
    #
413
    if ( $DPKG_NAME eq 'pkg' || $DPKG_NAME eq 'deploy' )
414
    {
415
        $DPKG_NAME = $DESC_NAME;
416
        unless ( $DESC_NAME )
417
        {
418
            Error ("Cannot determine package name",
419
                   "The packages 'descpkg' file is bad or missing");
420
        }
421
    }
422
    elsif ( $DESC_NAME ne $DPKG_NAME )
423
    {
424
        Error ("Package name MUST match package description",
425
               "Check build.pl and package.pl",
426
               "Package name: $DPKG_NAME",
427
               "Description : $DESC_NAME" );
428
    }
429
 
430
    #
431
    # lets just check to see if we have a version number before
432
    # we proceed.
433
    #
434
    unless ( $DPKG_VERSION )
435
    {
436
        Error("Cannot determine dpkg_archive version number.",
437
              "Check JATS build config.");
438
    }
439
 
440
    #
441
    #   Sanity test package name and version, if provided
442
    #
443
    if ( $opt_pname )
444
    {
445
        ReportError ("Package Name does not match expected name",
446
                     "Expected: '$opt_pname'",
447
                     "Descpkg : '$DPKG_NAME'") unless ( $DPKG_NAME eq $opt_pname );
448
    }
449
    if ( $opt_pversion )
450
    {
451
        ReportError ("Package Version does not match expected version",
452
                     "Expected: '$opt_pversion'",
453
                     "Descpkg : '$DPKG_VERSION'") unless ( $DPKG_VERSION eq $opt_pversion );
454
    }
455
    ErrorDoExit();
4003 dpurdie 456
}
227 dpurdie 457
 
4003 dpurdie 458
#-------------------------------------------------------------------------------
459
# Function        : ShowInfo
460
#
461
# Description     : Show info to the user
462
#
463
# Inputs          : 
464
#
465
# Returns         : 
466
#
467
sub ShowInfo
468
{
227 dpurdie 469
    #
470
    #   Set up the target directory path and name
471
    #   It will be created later
472
    #
5527 dpurdie 473
    if ($opt_tarmode)
474
    {
475
        $DPKG_DIR = catdir($DPKG_ROOT, '.dpkg_archive', 'fragments');
476
    }
477
    else
478
    {
479
        $DPKG_DIR = catdir($DPKG_ROOT, $DPKG_NAME, $DPKG_VERSION );
480
    }
4003 dpurdie 481
 
227 dpurdie 482
    #
483
    #   Information for the user
484
    #
485
    Information ("---------------------------------------------------------------");
486
    Information ("Dpkg archive creation tool...");
487
    Information ("Version: $VERSION");
488
    Information ("");
489
    Information ("Information:");
490
    Information ("Working dir   = [$CWD_DIR]");
491
    Information ("Package Root  = [$SRC_ROOT]");
4549 dpurdie 492
    Information ("Repository    = [$DPKG_ROOT]");
493
    Information ("                *Non Standard archive") unless $opt_archive eq 'main';
227 dpurdie 494
    Information ("Target dir    = [$DPKG_DIR]");
495
    Information1("DPKG_NAME     = [$DPKG_NAME]");
496
    Information1("DPKG_VERSION  = [$DPKG_VERSION]");
497
    Information1("GBE_MACHTYPE  = [$GBE_MACHTYPE]");
279 dpurdie 498
    Information1("GBE_HOSTNAME  = [$GBE_HOSTNAME]");
499
    Information1("GBE_ABT       = [$GBE_ABT]");
500
    Information1("USER          = [$USER]");
5527 dpurdie 501
    Information ("")                                if ( $opt_merge || $opt_delete || $opt_info || $opt_tarmode || $opt_testArchive);
502
    Information ("Opt:TarMode       = Enabled")     if ( $opt_tarmode );
503
    Information ("Opt:Delete        = Enabled")     if ( $opt_delete );
504
    Information ("Opt:Merge         = Enabled")     if ( $opt_merge );
505
    Information ("Opt:testArchive   = Enabled")     if ( $opt_testArchive );
506
    Information ("Opt:TestMode      = Enabled. No Package Transferred") if ( $opt_test );
507
    Information ("Opt:Info          = Enabled. No Package Transferred") if ( $opt_info );
508
    Warning     ("Sandbox Build     = Yes") if ($ENV{GBE_DPKG_SBOX}) ;
227 dpurdie 509
    Information ("---------------------------------------------------------------");
510
 
369 dpurdie 511
    #
512
    #   If the environment variable GBE_DPKG_SBOX is defined then the package
513
    #   is being built within a development sandbox. In such a sandbox the
514
    #   version numbers of the packages are ignored. Publishing a package
5499 dpurdie 515
    #   from such an environment is certainly not reproducible - so don't allow
369 dpurdie 516
    #   it to happen
517
    #
518
    #   Allow versions of 99.99.99 as these are known to be test versions
519
    #
520
    unless ( $opt_archive eq 'local' || $opt_archive eq 'sandbox' )
521
    {
522
        if ( $ENV{GBE_DPKG_SBOX} )
523
        {
524
            unless ( $DPKG_VERSION =~ /^99.99.99/ )
525
            {
526
                Error("Cannot not publish a package that has been generated",
527
                   "within a Sandbox as the version of dependent packages",
528
                   "is not guaranteed.",
529
                   "Only version 99.99.99 is allowed");
530
            }
531
        }
532
    }
4003 dpurdie 533
}
369 dpurdie 534
 
535
 
227 dpurdie 536
#------------------------------------------------------------------------------
537
sub pkgFind
538
#
539
# Description:
235 dpurdie 540
#     This subroutine is used to locate the FIRST descpkg file in
227 dpurdie 541
#     the local pkg dir.
542
#
543
#------------------------------------------------------------------------------
544
{
545
    my($item)= "$File::Find::name";
546
    my($file)= File::Basename::basename($item);
547
 
548
    # we get the absolute path from the find, but we only require
549
    # a relative path from the starting dir.
550
    # so our start dir.
551
 
552
    # we need to determine which file we are dealing with
235 dpurdie 553
    if ( ! -d $item && $file =~ /^descpkg$/ )
227 dpurdie 554
    {
4549 dpurdie 555
        $descPkgCount++;
556
 
235 dpurdie 557
        #
558
        #   Only grab the first one
559
        #
560
        if ( $DESCPKG_FILE )
561
        {
5532 dpurdie 562
            $item =~ s~\Q$PKG_BASE\E/~~;
4549 dpurdie 563
            Verbose ("Multiple descpkg files:", $item );
235 dpurdie 564
            return;
565
        }
566
 
227 dpurdie 567
        $DESCPKG_FILE = $item;
568
        my($dir)= File::Basename::dirname($item);
569
        $DPKG_NAME = File::Basename::basename($dir);
570
        $SRC_ROOT = $dir;
571
    }
572
}
573
 
574
 
575
#------------------------------------------------------------------------------
576
sub GetDpkgArchiveVersion
577
#
578
# Description:
579
#     This subroutine is used to determine the version of the dpkg_archive.
580
#     We assume that the version number is in the descpkg file.
581
#
582
#     Need to allow for two forms of descpkg. Some one decided that a Java
583
#     Manifest would be a good descpkg file - a long time after the rest of the
584
#     world had been using an existing file format.
585
#
586
#     Lines are tagged
587
#
588
#     Once the version number is determined we set the
589
#     global DPKG_VERSION variable.
590
#
591
#------------------------------------------------------------------------------
592
{
593
    my ($path) = @_;
594
    my $line;
595
    my $type;
596
 
597
    #
598
    #   Use a common routine to parse the package descriptor
599
    #   There are several forms that may need to be processed
600
    #
601
    my $pkg_data = ReadDescpkg( $path );
602
    Error("Failed to open file [$path].") unless $pkg_data;
603
 
604
    $DESC_NAME    = $pkg_data->{'NAME'};
605
    $DPKG_VERSION = $pkg_data->{'VERSION_FULL'};
606
}
607
 
608
#-------------------------------------------------------------------------------
609
# Function        : TransferDescpkg
610
#
611
# Description     : Copy and process the descpkg file to the target
612
#
613
# Inputs          :
614
#
615
# Returns         :
616
#
617
sub TransferDescpkg
618
{
619
    my $result = CopyDescpkg( @_ );
620
    Error("Transfer descpkg: $result") if ( $result );
621
}
622
 
623
#------------------------------------------------------------------------------
624
sub CreateDpkgArchive
625
#
626
# Description:
627
#     This subroutine is used to create the dpkg_archive in the $DPKG_ROOT
628
#     location 
629
#
4969 dpurdie 630
#     We use the global DPKG_ROOT, DPKG_DIR, DPKG_NAME, and DPKG_VERSION
227 dpurdie 631
#     to create the required directory structure.
632
#
633
#     If the dpkg_archive is new (ie not a new version) it is assumed the user
634
#     has access to create the top level dir for the new dpkg_archive.
635
#
636
#     The new dpkg_archive is created with the permission of the user 
637
#     executing this script.
638
#
639
#     If an error ocurs during the dpkg_archive creation the script
640
#     will terminate.
641
#
642
#------------------------------------------------------------------------------
643
{
263 dpurdie 644
    #
227 dpurdie 645
    # first we need to ensure we have the top level directory
646
    #
647
    if ( -d $DPKG_DIR )
648
    {
649
        Warning("Detected previous dpkg_archive [$DPKG_DIR]");
4549 dpurdie 650
        Error ("Package already exists and Package merging not selected")
651
            unless ( $opt_delete || $opt_merge );
263 dpurdie 652
 
653
        #
654
        #   Target exists
655
        #   Unless we are merging, we need to blow the entire tree away
656
        #
657
        unless ( $opt_merge )
658
        {
659
            LogFileOp("Remove Prev Pkg",$DPKG_DIR);
660
            rmtree($DPKG_DIR);
661
 
662
            #
663
            #   At this point the target directory 'should not' exist
664
            #   but it may. Some packges (like JATS) have Unix links within
665
            #   dpkg_archive filesystem. These cannot be deleted under windows
666
            #
667
            #   Not nice, but we live with it.
668
            #
669
            Warning ("Unable to delete previous instance of the package")
670
                if ( -d $DPKG_DIR );
671
        }
227 dpurdie 672
    }
673
    Information("");
674
 
675
    #
676
    #   Create the top level directory
677
    #
678
    mkpath($DPKG_DIR, 0, 0775);
679
 
680
    #
4003 dpurdie 681
    #   Transfer source directory, unless this is a noBuild
682
    #
683
    if ( $SRC_ROOT ne '' )
227 dpurdie 684
    {
4003 dpurdie 685
        # Process the files
686
        #
687
        if ( -d $SRC_ROOT )
688
        {
689
            File::Find::find( \&pkgFind2, $SRC_ROOT );
263 dpurdie 690
 
4424 dpurdie 691
            if (@bad_symlinks)
692
            {
693
                my $msg = "Bad Symlinks: " . scalar @bad_symlinks;
694
                $opt_test ? ReportError($msg, @bad_symlinks) : Warning($msg, @bad_symlinks);
695
            }
696
 
4003 dpurdie 697
            if ( $bad_merge_count )
698
            {
699
                my $msg = "Merged files that differ: $bad_merge_count";
4424 dpurdie 700
                $opt_md5 ? ReportError($msg) : Warning($msg);
4003 dpurdie 701
            }
4424 dpurdie 702
            ErrorDoExit();
4003 dpurdie 703
        }
704
        else
263 dpurdie 705
        {
4003 dpurdie 706
            Error("Failed to find dir [$SRC_ROOT]",
707
                  "Check JATS config.");
263 dpurdie 708
        }
227 dpurdie 709
    }
710
 
711
    #
712
    #   Transfer of data is complete
4424 dpurdie 713
    #       Mark the archive with the build machine to indicate which parts of
714
    #       a multi-machine build have been performed
227 dpurdie 715
    #
5527 dpurdie 716
    my $touchfile = createBuiltFile($DPKG_DIR);
4634 dpurdie 717
    addFile('file', $touchfile, $touchfile);
227 dpurdie 718
 
719
    #
720
    #   If there is a .lnk file in the archive then remove it now that the
721
    #   archive has been transferred. The .lnk files are created in 'local'
722
    #   archives in order to simplify multi-package builds
723
    #
724
    my $link_file = "$DPKG_ROOT/$DPKG_NAME/$DPKG_VERSION.lnk";
725
    if ( -f $link_file )
726
    {
727
        LogFileOp("Removing Link",$link_file);
728
        unlink $link_file;
729
    }
730
 
4969 dpurdie 731
    #
5527 dpurdie 732
    #   Create the MD5 info file
733
    #   
734
    writeFileInfo($DPKG_DIR);
227 dpurdie 735
    return 1;
736
}
737
 
738
#------------------------------------------------------------------------------
739
sub pkgFind2
740
#
741
# Description:
742
#   This subroutine is used to locate all associated pkg files in
743
#   the local pkg dir.
744
#
745
#   This routine is called for each file and directory within the package
746
#   Some files and directories are treated in a special manner
747
#       - Top level directory is ignored
748
#
749
#
750
#
751
#------------------------------------------------------------------------------
752
{
753
    my $item = $File::Find::name;
754
    my $base = File::Basename::basename($item);
755
 
756
    #
757
    #   Calculate the target directory name
758
    #
759
    my $target = $item;
241 dpurdie 760
    $target = $DPKG_DIR . substr ( $item, length ($SRC_ROOT) );
227 dpurdie 761
 
762
    if ( -d $item )
763
    {
764
        #
765
        #   Ignore the top level directory
766
        #   It has already been created
767
        #
768
        return
769
            if ( $item eq $SRC_ROOT );
770
 
771
        #
772
        #   Directories are handled differently
773
        #       - Directories are created with nice permissions
263 dpurdie 774
        #       - If the directory already exists then it is being merged.
227 dpurdie 775
        #
776
        if ( ! -d "$target" )
777
        {
778
            LogFileOp("Creating Dir", $target);
779
            mkpath("$target", 0, 0775);
4549 dpurdie 780
            addFile('dir', $item , $target);
227 dpurdie 781
        }
782
    }
783
    else
784
    {
785
        #
786
        #   File copy
787
        #   If merging then do not overwrite an existing file
788
        #
789
        unless ( $opt_merge && -f $target )
790
        {
791
            if ( $item =~ m~/descpkg$~ )
792
            {
793
                LogFileOp("Rewrite File",$target);
4549 dpurdie 794
                TransferDescpkg( $item, $target );
363 dpurdie 795
                CORE::chmod oct("0664"), $target;
4549 dpurdie 796
                addFile('file', $item, $target);
227 dpurdie 797
            }
798
            else
799
            {
800
                #
801
                #   Copy file to destination
802
                #   If the file is a link, then duplicate the link contents
803
                #   Use: Unix libraries are created as two files:
804
                #        lib.xxxx.so -> libxxxx.so.vv.vv.vv
805
                #
806
                if ( -l $item )
807
                {
4424 dpurdie 808
                    if (-f $item)
227 dpurdie 809
                    {
4424 dpurdie 810
                        LogFileOp("Copying Link", $target);
811
                        my $link = readlink $item;
812
                        Verbose( "Link: $item, $link");
813
                        symlink ($link, $target );
814
                        unless ( $link && -l $target )
815
                        {
816
                            Error("Failed to copy link [$item] to [$target]: $!");
817
                        }
4549 dpurdie 818
                        addFile('link', $item , $target);
227 dpurdie 819
                    }
4424 dpurdie 820
                    else
821
                    {
822
                        # Don't copy broken Symlinks
823
                        # Perhaps this should be an error - but is will break escrow builds
824
                        #
825
                        LogFileOp("Broken SymLink", $target);
826
                        push @bad_symlinks, substr ( $item, 1+length ($SRC_ROOT) );
827
                    }
227 dpurdie 828
                }
829
                elsif (File::Copy::copy($item, $target))
830
                {
831
                    LogFileOp("Copying File",$target);
363 dpurdie 832
                    #
833
                    #   Mark the file as executable by all
834
                    #   Under windows, this is tricky
835
                    #
836
                    if ( $Win32 )
837
                    {
838
                        my %hash;
839
                        $hash{Everyone} = Win32::FileSecurity::MakeMask( qw( FULL  ) );
840
                        Win32::FileSecurity::Set( $target, \%hash );
841
                    }
842
                    else
843
                    {
844
                        CORE::chmod oct("0775"), $target;
845
                    }
4549 dpurdie 846
                    addFile('file', $item, $target);
227 dpurdie 847
                }
848
                else
849
                {
850
                    Error("Failed to copy file [$item] to [$target]: $!");
851
                }
852
            }
853
        }
854
        else
855
        {
856
            #
857
            #   Merging packages
858
            #   Ensure that the descpkg file is "touched" so that caches
859
            #   that use this file as a timestamp can be updated
860
            #
861
            if ( $item =~ m~/descpkg$~ )
862
            {
863
                LogFileOp("Touch File",$target);
864
                TouchFile( $target ) && Error ( "Failed to touch: $target" );
4549 dpurdie 865
                addFile('merge', $item, $target);
227 dpurdie 866
            }
867
            else
868
            {
263 dpurdie 869
                #
870
                #   MD5 digest the files that are being merged
871
                #   Ignore version_*.h files as these are generated
872
                #   and may contain different dates and line endings
873
                #
267 dpurdie 874
                #   Don't put the files into 'binmode'
875
                #   Need to handle some level of Unix/DOS file endings
876
                #
877
                #
263 dpurdie 878
                my $msg = "Merge Skip File";
879
                unless ( $target =~ m~/version[^/]*\.h$~ )
880
                {
881
                    $msg = "Merge Test File";
882
                    #
883
                    #   Compare the two files with an MD5
884
                    #
885
                    local *FILE;
886
                    open(FILE, $target) or Error ("Can't open '$target': $!");
267 dpurdie 887
                    binmode FILE, ':crlf';
263 dpurdie 888
                    my $target_md5 = Digest::MD5->new->addfile(*FILE)->hexdigest;
889
                    close FILE;
890
 
891
                    open(FILE, $item) or Error ("Can't open '$item': $!");
267 dpurdie 892
                    binmode FILE, ':crlf';
263 dpurdie 893
                    my $source_md5 = Digest::MD5->new->addfile(*FILE)->hexdigest;
894
                    close FILE;
895
 
896
                    unless ( $source_md5 eq $target_md5 )
897
                    {
898
                        $msg = "DIFF: Merge Test File";
899
                        $bad_merge_count ++;
900
                    }
4549 dpurdie 901
                    addFile('merge', $item, $target, $target_md5);
263 dpurdie 902
                }
903
                LogFileOp($msg,$target);
227 dpurdie 904
            }
905
        }
906
    }
907
}
908
 
909
#-------------------------------------------------------------------------------
5527 dpurdie 910
# Function        : CreateDpkgArchiveTarBall 
911
#
912
# Description     : Similar to CreateDpkgArchive, but it will create a tar file within the target
913
#                   directory.
914
#                   
915
#                   This is used by the build system to:
916
#                       1) Greatly speedup the transfer of packages with a very large number of files
917
#                       2) Remove the need for an multi-filesytem, multi OS atomic lock on the package
918
#                       
919
#                   The build system will process the tarball and create the package archive
920
#                   In doing so it will handle merge errors
921
#
922
# Inputs          : 
923
#
924
# Returns         : 
925
#
926
sub CreateDpkgArchiveTarBall
927
{
928
    Information("");
929
    InitFileUtils();
930
 
931
 
932
    #
933
    #   Locate the tar utility
934
    #   Use gtar if its available otherwise use tar
935
    #   
936
    my $tarProg = LocateProgInPath('gtar', '--All');
937
    $tarProg = LocateProgInPath('tar', '--All') unless $tarProg;
938
    Error ("Tar utility not found in path") unless $tarProg;
939
 
940
    #
941
    #   If a 'noBuild' then create a dummy package directory simply
942
    #   to contain the metadata. 
943
    #   Delete any existing dir of the same name to ensure its clean.
944
    #
945
    if ( $SRC_ROOT eq '' )
946
    {
947
        $SRC_ROOT = AbsPath('pkg/noBuild');
948
        RmDirTree ($SRC_ROOT);
949
        mkpath($SRC_ROOT, 0, 0775);
950
    }
951
 
952
    #
953
    #   Mark the archive with the build machine to indicate which parts of
954
    #   a multi-machine build have been performed
955
    #
956
    createBuiltFile($SRC_ROOT);
957
 
958
    #   Process the source directory
959
    #   A NoBuild will contain one metafile
960
    #
961
    if ( -d $SRC_ROOT )
962
    {
963
        File::Find::find( \&pkgFindTarBall, $SRC_ROOT );
964
 
965
        if (@bad_symlinks)
966
        {
967
            my $msg = "Bad Symlinks: " . scalar @bad_symlinks;
968
            $opt_test ? ReportError($msg, @bad_symlinks) : Warning($msg, @bad_symlinks);
969
        }
970
        ErrorDoExit();
971
    }
972
    else
973
    {
974
        Error("Failed to find dir [$SRC_ROOT]",
975
              "Check JATS config.");
976
    }
977
 
978
    #
979
    #   Create the MD5 info file
980
    #   
981
    writeFileInfo($SRC_ROOT);
982
 
983
    #
984
    #   Create the target path in the target archive
985
    #
986
    LogFileOp ('Creating', $DPKG_DIR);
987
    mkpath($DPKG_DIR, 0, 0775);
988
 
989
 
990
    #
991
    #   Create the TAR file
992
    #   Use gzip compression (tar.gz) as it provides a good compromise bewteen speed and size
993
    #
994
    my $tarTarget = join('_', $DPKG_NAME, $DPKG_VERSION, $GBE_HOSTNAME) . '.tar.gz';
995
    my $tarPath = catfile($DPKG_DIR, $tarTarget);
996
    LogFileOp ('TarZip', $tarPath);
997
    my @tarArgs;
998
    push @tarArgs, '-v' if IsVerbose(1);
999
    my $rv = System ('--NoShell', '--NoExit',$tarProg, @tarArgs, '-czf', $tarPath, '-C', $SRC_ROOT, '.' );
1000
    if ($rv)
1001
    {
1002
        unlink $tarPath;
1003
        unlink $opt_outfile; 
1004
        Error ('Cannot create tarball', "Path:$tarPath");
1005
    }
1006
 
1007
    return 1;
1008
}
1009
 
1010
#-------------------------------------------------------------------------------
1011
# Function        : pkgFindTarBall 
1012
#
1013
# Description     : Used by CreateDpkgArchiveTarBall
1014
#                   File::Find processing function
1015
#                   
1016
#                   This routine is called for each file and directory within the package
1017
#
1018
# Inputs          : As per File::Find 
1019
#
1020
# Returns         : Nothing
1021
#
1022
sub pkgFindTarBall
1023
{
1024
    my $item = $File::Find::name;
1025
    my $base = File::Basename::basename($item);
1026
    my $type;
1027
 
1028
    #
1029
    #   Ignore the top level directory
1030
    #
1031
    return
1032
        if ( $item eq $SRC_ROOT );
1033
 
1034
    #
1035
    #   Determine type of this item
1036
    #       file
1037
    #       link, badlink
1038
    #       dir
1039
    if ( -l $item)
1040
    {
1041
        if (-f $item) {
1042
            $type = 'link';
1043
        }
1044
        else
1045
        {
1046
            # Broken symlink
1047
            #   Remove it from the 'pkg'
1048
            #   Could try other ways of excluding it from the tar, but this is the simplest  
1049
            LogFileOp("Broken SymLink", $item);
1050
            push @bad_symlinks, substr ( $item, 1+length ($SRC_ROOT) );
1051
            $type = 'badlink';
1052
            unlink $item;
1053
            return;
1054
        }
1055
    } elsif ( -f $item) {
1056
        $type = 'file';
1057
    } elsif ( -d $item) {
1058
        $type = 'dir';
1059
    } else {
1060
        Error("Unknown file type. Cannot be packaged");
1061
    }
1062
 
1063
    #
1064
    #   Calculate the target directory name
1065
    #
1066
    my $target = $item;
1067
    $target = $DPKG_DIR . substr ( $item, length ($SRC_ROOT) );
1068
 
1069
    addFile($type, $item, $target);
1070
    LogFileOp('Process',$item);
1071
}
1072
 
1073
#-------------------------------------------------------------------------------
227 dpurdie 1074
# Function        : TestDpkgArchive
1075
#
1076
# Description     : Test the structure of the source achive
1077
#                   Ensure that it has some files
1078
#                   Warn if files are present in the root directory
1079
#
1080
# Inputs          : None
1081
#
1082
# Returns         : Warnings
1083
#
1084
my $test_dir_count = 0;
1085
my $test_file_count = 0;
1086
my @test_root_file = ();
1087
sub TestDpkgArchive
1088
{
1089
    $test_dir_count = 0;
1090
    $test_file_count = 0;
1091
    @test_root_file = ();
1092
 
4003 dpurdie 1093
    if ( $SRC_ROOT ne '' )
1094
    {
1095
        Error("Failed to find dir [$SRC_ROOT]",
1096
              "Check JATS config.") unless ( -d $SRC_ROOT );
1097
 
1098
 
1099
        #
1100
        #   Scan the package counting files and folders
1101
        #
1102
        File::Find::find( \&pkgFind3, $SRC_ROOT );
1103
    }
1104
 
227 dpurdie 1105
    Information ("Package contains:",
1106
                 "Files: $test_file_count",
1107
                 "Dirs: $test_dir_count",
1108
                 );
1109
    #
1110
    #   There shouldn't be any files in the root directory
1111
    #   other than the descpkg and incpkg.
1112
    #
1113
    Warning ("Unexpected files in package root:", @test_root_file)
1114
        if ( @test_root_file  );
4424 dpurdie 1115
 
1116
    Error ("Bad symbolic links found:", @bad_symlinks)
1117
            if ( @bad_symlinks );
1118
 
227 dpurdie 1119
}
1120
 
1121
sub pkgFind3
1122
{
1123
 
1124
    #
1125
    #   Calculate the target directory name
1126
    #
1127
    my $target = $File::Find::dir;
263 dpurdie 1128
    $target = substr ( $target, length ($SRC_ROOT) );
1129
    $target =~ s~^.~~;
227 dpurdie 1130
 
1131
    if ( -d $_ ) {
1132
        $test_dir_count++;
1133
    } else {
1134
        $test_file_count++;
1135
        unless ( $target )
1136
        {
241 dpurdie 1137
            #
1138
            #   Locate files in the package root directory that
1139
            #   are not expected to be there.
1140
            #
263 dpurdie 1141
            unless ((  $_ eq 'descpkg' ) || ( $_ eq 'incpkg' ))
1142
            {
1143
                push @test_root_file, $_;
1144
            }
227 dpurdie 1145
        }
4424 dpurdie 1146
        if (-l $_ && ! -f $_)
1147
        {
1148
            push @bad_symlinks, substr ( $File::Find::name, 1+length ($SRC_ROOT) );
1149
        }
227 dpurdie 1150
    }
1151
}
1152
 
5527 dpurdie 1153
#-------------------------------------------------------------------------------
1154
# Function        : createBuiltFile 
1155
#
1156
# Description     : Create the packages built.xxxx file
1157
#                   Used to track which build machines have contributed to the build 
1158
#
1159
# Inputs          : $targetDir          - Base directory for the file 
1160
#
1161
# Returns         : Full pathname of the generatde file
1162
#
1163
sub createBuiltFile
1164
{
1165
    my ($targetDir) = @_;
1166
 
1167
    #
1168
    #   Mark the archive with the build machine to indicate which parts of
1169
    #   a multi-machine build have been performed
1170
    #
1171
    my $touchfile = catfile( $targetDir, $opt_generic ? 'built.generic' : "built.$GBE_HOSTNAME");
1172
 
1173
    #
1174
    #   Create a string to be appended to the 'built' file
1175
    #   Comma seperated list of (possibly) useful info
1176
    #       Date-Time ( Local and GMT)
1177
    #       machine type, machine name and the user
1178
    #       GBE_ABT value
1179
    #
1180
    #   Having build issues where the file is not seen for a very long time
1181
    #
1182
    my $built_info = localtime() ."," . gmtime() . " GMT,$GBE_MACHTYPE,$GBE_HOSTNAME,$USER,$GBE_ABT";
1183
    LogFileOp("Mark File",$touchfile);
1184
    FileAppend ( $touchfile, $built_info );
1185
 
1186
    return $touchfile;
1187
}
1188
 
1189
 
227 dpurdie 1190
# ---------------------------------------------------------
1191
# ---------------------------------------------------------
1192
# Main
1193
# ---------------------------------------------------------
1194
# ---------------------------------------------------------
1195
 
1196
 
1197
# Initialise our world
1198
#
1199
Init();
4003 dpurdie 1200
CheckDescPkg();
1201
ShowInfo();
4549 dpurdie 1202
unless ($opt_info)
227 dpurdie 1203
{
4549 dpurdie 1204
    unless ( $opt_test )
227 dpurdie 1205
    {
5527 dpurdie 1206
        if ($opt_tarmode)
1207
        {
1208
            Information("Creating dpkg_archive tarball:", $DPKG_DIR);
1209
            CreateDpkgArchiveTarBall();
1210
        }
1211
        else
1212
        {
1213
            Information("Creating dpkg_archive package:", $DPKG_DIR);
1214
            CreateDpkgArchive();
1215
        }
227 dpurdie 1216
    }
4549 dpurdie 1217
    else
1218
    {
1219
        Information("Testing user package.");
1220
        TestDpkgArchive();
1221
    }
227 dpurdie 1222
}
1223
 
1224
# Done
1225
#
1226
Information ("Done.");
1227
exit 0;
1228
 
1229
 
1230
#-------------------------------------------------------------------------------
1231
#   Documentation
1232
#
1233
 
1234
=pod
1235
 
361 dpurdie 1236
=for htmltoc    SYSUTIL::
1237
 
227 dpurdie 1238
=head1 NAME
1239
 
1240
create_dpkg - Create a dpkg_archive entry
1241
 
1242
=head1 SYNOPSIS
1243
 
1244
 jats create_dpkg [options]
1245
 
1246
 Options:
1247
    -help              - Brief help message
1248
    -help -help        - Detailed help message
1249
    -man               - Full documentation
1250
    -quiet             - Suppress progress messages, then warning messages
1251
    -verbose           - Display additional progress messages
4549 dpurdie 1252
    -override          - Deprecated option
1253
    -delete            - Delete any previous version of the package
263 dpurdie 1254
    -[no]merge         - merge with existing version of the package
227 dpurdie 1255
    -archive=name      - Specify archive (cache, local, main, store, sandbox, deploy)
1256
    -pname=name        - Ensure package is named correctly
1257
    -pversion=version  - Ensure package version is correct
1258
    -generic           - Create a built.generic file
5527 dpurdie 1259
    -[no]tarmode       - Transfer package as tarball
4549 dpurdie 1260
    -[no]md5           - Use MD5 comparison of merged files(enabled)
5527 dpurdie 1261
 
1262
  Debug and Testing:
263 dpurdie 1263
    -[no]test          - Test package. Do not transfer.
4549 dpurdie 1264
    -[no]info          - Display packaging info. Do not transfer.
5527 dpurdie 1265
    -[no]testArchive   - Perform operations within a test archive
227 dpurdie 1266
 
1267
=head1 OPTIONS
1268
 
1269
=over 8
1270
 
1271
=item B<-help>
1272
 
1273
Print a brief help message and exits.
1274
 
1275
=item B<-help -help>
1276
 
1277
Print a detailed help message with an explanation for each option.
1278
 
1279
=item B<-man>
1280
 
1281
Prints the manual page and exits.
1282
 
1283
=item B<-quiet>
1284
 
1285
This option will suppress almost all of the progress messages, except for a single
1286
copy message. It is intended to be used when the program is called from another
1287
script.
1288
 
1289
=item B<-override>
1290
 
4549 dpurdie 1291
If this option has been deprecated. It has no effect.
1292
 
1293
It is still present to preserve backward compatability with the automated 
1294
build system.
1295
 
1296
=item B<-delete>
1297
 
227 dpurdie 1298
If this option is enabled then any previous version of the target package will
4549 dpurdie 1299
be deleted.
227 dpurdie 1300
 
1301
=item B<-merge>
1302
 
1303
If this option is enabled then the package will be merged with any existing
4549 dpurdie 1304
package. This option is used by the auto build tool to assemble multi-machine 
1305
packages in dpkg_archive.
227 dpurdie 1306
 
1307
=item B<-archive=name>
1308
 
1309
This option specifies the destination archive to be used. The following names
1310
are supported:
1311
 
361 dpurdie 1312
=over 8
1313
 
1314
=item cache
1315
 
1316
The location of the target archive will be taken from C<GBE_DPKG_CACHE>.
1317
 
1318
=item local
1319
 
1320
The location of the target archive will be taken from C<GBE_DPKG_LOCAL>.
1321
 
1322
=item main (default)
1323
 
1324
The location of the target archive will be taken from C<GBE_DPKG>. This is the
1325
default target archive.
1326
 
1327
=item store
1328
 
1329
The location of the target archive will be taken from C<GBE_DPKG_STORE>.
1330
 
4688 dpurdie 1331
=item replica
1332
 
1333
The location of the target archive will be taken from C<GBE_DPKG_REPLICA>.
1334
 
361 dpurdie 1335
=item sandbox
1336
 
1337
The location of the target archive will be taken from C<GBE_DPKG_SBOX>.
1338
 
1339
=item deploy
1340
 
1341
The location of the target archive will be taken from C<GBE_DPLY>. This is the
1342
default target archive is a deployment package is detected.
1343
 
1344
=back
1345
 
227 dpurdie 1346
=item B<-pname=name>
1347
 
1348
If this option is provided, the utility will ensure that the package is named
1349
correctly.
1350
 
1351
=item B<-pversion=version>
1352
 
1353
If this option is provided, the utility will ensure that the package version is
1354
that expected.
1355
 
4549 dpurdie 1356
=item B<-generic>
227 dpurdie 1357
 
4549 dpurdie 1358
This option will create a built.generic file, instead of one based on the machine
1359
that actually built the package. This is used by the AutoBuilder toolchain.
227 dpurdie 1360
 
5527 dpurdie 1361
=item B<-[no]tarmode>
1362
 
1363
This option will cause the package to be transferred into the package archive as
1364
a tar ball. Used in the build system to address two issues:
1365
 
1366
=over 4
1367
 
1368
=item 1 
1369
 
1370
Slow speed in copying lots of files from the build machine to the package server.
1371
 
1372
=item 2 
1373
 
1374
Need for cross platform file lock in order to prevent copy collisions.  
1375
 
1376
=back
1377
 
263 dpurdie 1378
=item B<-[no]md5>
1379
 
1380
If package builds are being merged then a validity check is performed using
1381
an MD5 digest over the current and the existing file.
1382
 
1383
By default, it is an error for the user file to differ from the merged file.
1384
 
1385
This option disabled the error. The test is still done and the results are
1386
reported.
1387
 
4549 dpurdie 1388
=item B<-test>
227 dpurdie 1389
 
4549 dpurdie 1390
If this option is enabled the utility will perform initial sanity testing, but
1391
it will not perform the copy.
227 dpurdie 1392
 
4549 dpurdie 1393
=item B<-[no]info>
1394
 
1395
This option will cause the program to display information about the packaging 
1396
process and then exit. 
1397
 
1398
No data will be transferred to the archive.
1399
 
5527 dpurdie 1400
=item B<-[no]testArchive>
1401
 
1402
If this option is enabled then the assembly operation is performed within a test area within
1403
the currently configured dpkg_archive. The test area is a subdirectory 
1404
called C<.dpkg_archive/test_dpkg>
1405
 
1406
This option is intended for testing use only.
1407
 
227 dpurdie 1408
=back
1409
 
1410
=head1 DESCRIPTION
1411
 
1412
This utility program is used to transfer a package that has been built into
1413
dpkg_archive. The package is then available for general consumption.
1414
 
4549 dpurdie 1415
The utility will perform several operations in the transfer process. These incude:
1416
 
1417
=over 4
1418
 
1419
=item * 
1420
 
1421
Create a tag file to indicate the machine that has performed the transfer
1422
 
1423
=item * 
1424
 
1425
Create an XML file of files that have been transferred. This file contains information
1426
used by the build system when it releases the package, including: name, size and MD5SUM.
1427
 
1428
=item *
1429
 
1430
Detect file conflicts when different builds are merged into a single package. Header files are 
1431
allowed to differ in line ending style, but other files must not conflict. The package will not be 
1432
reproducible if file conflicts exist.
1433
 
5527 dpurdie 1434
In 'tarmode' the package merging needs to be done by another utility.
1435
 
4549 dpurdie 1436
=item *
1437
 
1438
Suppress dead symbolic links. A valid symlink will be preserved, but invalid links will be 
1439
removed from the transferred image.
1440
 
1441
=back
1442
 
227 dpurdie 1443
=head2 PACKAGE LOCATION
1444
 
1445
The utility will locate a package by examining the following directores for
1446
the package description file(descpkg).
1447
 
1448
=over 8
1449
 
1450
=item ./build/deploy
1451
 
1452
This format is generated by the deployment builds. The default target archive
1453
will be taken from the environment variable GBE_DPLY.
1454
 
1455
=item ./pkg
1456
 
1457
This format is generated by JATS builds.
1458
 
1459
=item ./build/pkg
1460
 
1461
This format is generated by ANT builds.
1462
 
5527 dpurdie 1463
=item ./pkg/noBuild
1464
 
1465
This format is used internally by this utilty. It will be generated by the build system 
1466
in cases where there is no build to be performs on the current machine.
1467
 
227 dpurdie 1468
=back
1469
 
1470
The program should be run in the same directory as the build control files as
1471
the package subdirectory will be created in that directory.
1472
 
1473
=head1 EXAMPLE
1474
 
1475
=head2 jats create_dpkg
1476
 
1477
This will locate a generated package and install it into the dpkg_archive repository.
1478
 
1479
=cut
1480