Subversion Repositories DevTools

Rev

Rev 3967 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
########################################################################
281 dpurdie 2
# Copyright ( C ) 2008-2009 ERG Limited, All rights reserved
227 dpurdie 3
#
263 dpurdie 4
# Module name   : jats_rewrite.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
227 dpurdie 7
# Environment(s): jats
8
#
9
# Description   : Rewrite a build.pl file
10
#                 Use an external configuration file to provide a common
11
#                 source of configuration information
12
#
263 dpurdie 13
# Usage         : See POD
227 dpurdie 14
#
15
#......................................................................#
16
 
255 dpurdie 17
require 5.006_001;
227 dpurdie 18
use strict;
19
use warnings;
20
 
21
use JatsError;
22
use BuildName;
23
use Getopt::Long;
24
use Pod::Usage;                             # required for help support
25
 
26
 
27
################################################################################
28
#   Option variables
29
#
30
 
281 dpurdie 31
my $VERSION = "1.4.0";                      # Update this
227 dpurdie 32
my $opt_verbose = 0;
33
my $opt_datafile = "";
34
my $opt_ofile  = "auto.pl";
35
my $opt_infile = "build.pl";
36
my $opt_help = 0;
37
my $opt_errors = 0;
38
my $opt_xml;
39
my $opt_oldproject;
40
my $opt_newproject;
263 dpurdie 41
my $opt_noconfig;
281 dpurdie 42
my $opt_validate;
323 dpurdie 43
my $opt_mode = 0;
44
my $opt_work_file = 'auto.new';
227 dpurdie 45
 
46
#
47
#   Globals
48
#
49
my %component =  ();
50
my %component_use =  ();
51
my $not_use_count = 0;
52
my $suffix_count = 0;
281 dpurdie 53
my @pkg_errors;
54
my @pkg_errors_val;
55
my $max_pkglen = 10;
227 dpurdie 56
 
247 dpurdie 57
#
58
#   Known extended fields
59
#   Only these values may be configured with the value=tag syntax
60
#   These may not be used as package names
61
#
62
my %fields = (
63
    'releasemanager.releasename' => undef,
64
    'releasemanager.projectname' => undef,
65
);
227 dpurdie 66
 
67
my $result = GetOptions (
281 dpurdie 68
                "help:+"        => \$opt_help,          # flag, multiple use allowed
69
                "manual:3"      => \$opt_help,          # flag
70
                "verbose:+"     => \$opt_verbose,       # flag
71
                "config=s"      => \$opt_datafile,      # string
72
                "noconfig"      => \$opt_noconfig,      # flag
73
                "outfile=s"     => \$opt_ofile,         # string
74
                "infile=s"      => \$opt_infile,        # string
75
                "errors"        => \$opt_errors,        # flag
76
                "xml!"          => \$opt_xml,           # flag
77
                "oldproject=s"  => \$opt_oldproject,    # string
78
                "newproject=s"  => \$opt_newproject,    # string
79
                "validate"      => \$opt_validate,      # flag
323 dpurdie 80
                "mode=s"        => \$opt_mode,          # Flag
227 dpurdie 81
                );
82
 
83
#
84
#   Process help and manual options
85
#
86
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
87
pod2usage(-verbose => 1)  if ($opt_help == 2 );
263 dpurdie 88
pod2usage(-verbose => 2)  if ($opt_help > 2);
227 dpurdie 89
 
90
#
91
#   Configure the error reporting process now that we have the user options
92
#
93
ErrorConfig( 'name'    =>'REWRITE',
94
             'verbose' => $opt_verbose );
95
 
96
Error ("Must specify both Old and New project tags")
97
    if ( $opt_newproject xor $opt_oldproject );
98
 
263 dpurdie 99
Error ("Conflicting options -config=file and -noconfig")
100
    if ( $opt_datafile && $opt_noconfig );
101
 
227 dpurdie 102
Error ("No configuration file specified")
263 dpurdie 103
    unless ( $opt_datafile || $opt_newproject || $opt_noconfig );
227 dpurdie 104
 
323 dpurdie 105
Warning ("Input and output file are the same" )
106
    if ( ! $opt_mode && $opt_infile eq $opt_ofile );
227 dpurdie 107
 
108
#
109
#   Auto detect XML files
110
#
111
$opt_xml = 1
112
    if ( $opt_infile =~ m~\.xml$~i );
113
 
114
#
323 dpurdie 115
#   When opt_mode is invoked, allow reuse auto.xxx files
116
#   if they are present. The user may be changing the file
117
#
118
if ( $opt_mode )
119
{
120
    #
341 dpurdie 121
    #   Use later of build.pl or auto.pl for input
323 dpurdie 122
    #
123
    my $bstamp = -M "build.pl";
124
    my $astamp = -M "auto.pl";
125
    $opt_infile = 'auto.pl'
126
        if ( $astamp && $astamp < $bstamp );
127
 
128
    $opt_infile = 'auto.xml' if ( -f 'auto.xml' );
129
    Message ("Using: $opt_infile");
130
}
131
 
132
#
227 dpurdie 133
#   Process config and input files
134
#
135
read_config_file()          if $opt_datafile;
136
process_build_file()        unless( $opt_xml);
137
process_xml_build_file()    if ( $opt_xml);
138
 
139
Verbose ("Number of project extensions changed: $suffix_count")
140
    if ( $ opt_newproject );
141
 
142
Warning("No project extensions changed")
143
    if ( !$suffix_count && $opt_newproject);
144
 
323 dpurdie 145
#
146
#   Report errors or warnings for packages that are not in the configuration
147
#   File. These will not have been updated inthe output file.
148
#
281 dpurdie 149
if ( @pkg_errors || @pkg_errors_val)
150
{
323 dpurdie 151
    my $report = $opt_mode ? \&Warning : \&ReportError;
152
    $report->("Errors encountered in the following packages:");
153
    $report->( @pkg_errors );
154
    $report->( @pkg_errors_val );
155
    $report->( "Package Names and Versions in build files may not match Release Manager");
281 dpurdie 156
}
157
 
158
ReportError("Unused packages found: $not_use_count")
227 dpurdie 159
    if ( $opt_errors && $not_use_count && $opt_datafile);
160
 
161
 
281 dpurdie 162
ErrorDoExit();
227 dpurdie 163
exit 0;
164
 
165
#-------------------------------------------------------------------------------
166
# Function        : read_config_file
167
#
168
# Description     : Read and store config file information
169
#
170
# Inputs          :
171
#
172
# Returns         :
173
#
174
 
175
sub read_config_file
176
{
177
    open ( FILE, "<$opt_datafile" ) or Error ("Config file ($opt_datafile) not found" );
178
    while ( <FILE> )
179
    {
180
        #
181
        #   Clean up lines
182
        #   Skip comments and blank lines
183
        #   Remove leading and training white space
184
        #
185
        chomp;
186
        s~^\s*~~;
187
        s~#.*$~~;
188
        s~\s*$~~;
189
        next if ( length( $_) <= 0 );
190
 
191
#        Verbose ($_);
192
 
193
        #
247 dpurdie 194
        #   Extract special fields
195
        #   These are not dependent packages and are not mandatory
196
        #   These are of the form tag = name
359 dpurdie 197
        #       Note: Must allow for package-versions like: "SUNWj6rt 1.6.0,REV=2006.11.29.05.03"
198
        #             Solution: tag must not conatin whitespace
247 dpurdie 199
        #
359 dpurdie 200
        if ( m{^\s*(\S+)\s*=\s*(.+)} )
247 dpurdie 201
        {
359 dpurdie 202
            Error ("Unsupported named field: $1")  unless ( exists $fields{$1} );
247 dpurdie 203
            $fields{$1} = $2;
204
            Verbose ("Field: $1, \"$2\"");
205
            next;
206
        }
207
 
208
        #
227 dpurdie 209
        #   Process LinkPkgArchive and BuildPkgArchive statements
210
        #   These allow simple updating of the config file from Release manager
211
        #
212
        if ( m/LinkPkgArchive/ or m/BuildPkgArchive/ )
213
        {
214
            m/'(.*)'[^']*'(.*)'/;
215
 
216
            my $comp = $1;
217
            my $ver = $2;
218
 
219
#print "Got Archive stuff: $_ : $comp, $ver\n";
220
 
221
            Error "Version not specified for: $comp" unless ( $ver );
347 dpurdie 222
            Warning "Suspect version format for: $comp ($ver)" unless ( $opt_mode || $ver =~ m~^\w+\.\w+\.\w+.\w+$~ || $ver =~ m~^\w+\.\w+\.\w+$~ || $ver =~ m~\.cots$~);
227 dpurdie 223
 
224
            save_package( $comp, $ver );
225
            next;
226
        }
227
 
228
 
229
 
230
        #
231
        #   Process line as
232
        #       component version
233
        #
234
        my ( $comp, $ver, $opt ) = split( /[\s,]+/, $_, 3);
235
        Error "Version not specified for: $comp" unless ( $ver );
347 dpurdie 236
        Warning "Suspect version format for: $comp ($ver)" unless ( $opt_mode || $ver =~ m~^\w+\.\w+\.\w+.\w+$~ || $ver =~ m~^\w+\.\w+\.\w+$~ || $ver =~ m~\.cots$~);
227 dpurdie 237
        save_package( $comp, $ver );
238
    }
239
    close FILE;
240
 
241
#    DebugDumpData ("component", \%component );
242
}
243
 
244
#-------------------------------------------------------------------------------
245
# Function        : print_update
246
#
247
# Description     : Generate a display line tracking the changes made
248
#
249
# Inputs          :
250
#                   $title          - Update Type
251
#                   $name           - Package name
252
#                   $version        - Original version of package
253
#                   $new_version    - New version
254
#
255
# Returns         :
256
#
257
sub print_update
258
{
259
    my ($title, $name, $version, $new_version ) = @_;
260
    my $diff = ( $version ne $new_version ) ? '*' : '';
261
 
262
    #
263
    #   Always display diffs
264
    #   Display all if verbose
265
    #
323 dpurdie 266
    if ( $diff || $opt_verbose || $opt_mode  )
227 dpurdie 267
    {
268
        $title = 'Package' unless ( $title );
281 dpurdie 269
        Message( sprintf("%-8s: %-${max_pkglen}s, Version: %-15s %1.1s-> %-15s\n", $title, $name ,$version, $diff, $new_version));
227 dpurdie 270
    }
271
}
272
 
273
#-------------------------------------------------------------------------------
274
# Function        : process_build_file
275
#
276
# Description     : Rewrite one file
323 dpurdie 277
#                   build.pl -> auto.pl
227 dpurdie 278
#
279
# Inputs          :
280
#
281
# Returns         :
282
#
283
sub process_build_file
284
{
285
    Verbose ("Processing build file: $opt_infile");
286
 
3559 dpurdie 287
    my $build_info;
288
    my $release_name;
289
    my $release_version;
290
 
227 dpurdie 291
    #
292
    #   Unlink any OLD output file
293
    #
323 dpurdie 294
    unlink $opt_work_file;
227 dpurdie 295
 
296
    #
3559 dpurdie 297
    #   Open the output file
227 dpurdie 298
    #
323 dpurdie 299
    open ( OUTFILE, ">$opt_work_file" ) || Error( "Cannot create $opt_work_file", $! );
227 dpurdie 300
 
3559 dpurdie 301
    #
302
    #   Read input file and process as an array of lines
303
    #
304
    foreach ( getInputLines($opt_infile) )
227 dpurdie 305
    {
263 dpurdie 306
        next if ( $opt_noconfig );       # Nothing to do
227 dpurdie 307
        next if ( m~^\s*#~ );            # Skip comments
3559 dpurdie 308
 
227 dpurdie 309
        #
310
        #   Process BuildName
311
        #
323 dpurdie 312
        if ( m~\s*BuildName[\s\(]~  )
227 dpurdie 313
        {
314
            #   Build names come in many flavours
315
            #   Must support a number of different formats
316
            #       "name nn.nn.nn prj"
317
            #       "name nn.nn.nn.prj"
318
            #
319
            #       "name nn.nn.nn prj", "nn.nn.nn"
320
            #       "name nn.nn.nn.prj", "nn.nn.nn"
321
            #
322
            #       "name", "nn.nn.nn.prj"
323
            #
324
            m~\(\s*(.*?)\s*\)~;
325
            my @args = split /\s*,\s*/, $1;
326
            $build_info = parseBuildName( @args );
323 dpurdie 327
            my $new_ver;
227 dpurdie 328
 
323 dpurdie 329
            #
330
            #   In Special Mode, don't change the version of this package
331
            #   Assume that the user has fiddled with it.
332
            #
333
            if ( $opt_mode ) {
334
                $new_ver = $build_info->{BUILDVERSION};
335
            } else {
336
                $new_ver = get_package ( $build_info->{BUILDNAME_PACKAGE}, $build_info->{BUILDVERSION} );
337
            }
227 dpurdie 338
            my $build_args = genBuildName( $build_info, $new_ver );
339
 
340
            #
341
            #   Rewrite the body of the directive
342
            #
343
            s~\(\s*(.*?)\s*\)~( $build_args )~;
323 dpurdie 344
            print_update( 'Name', $build_info->{BUILDNAME_PACKAGE}, $build_info->{BUILDVERSION}, $new_ver );
227 dpurdie 345
 
346
        }
347
 
348
        #
349
        #   Process BuildPreviousVersion
350
        #   Save the current version information in this directive
351
        #
323 dpurdie 352
        if ( m/^\s*BuildPreviousVersion/ && ! $opt_mode )
227 dpurdie 353
        {
354
            Error ("BuildPreviousVersion directive before BuildName") unless ( $build_info );
355
            m/['"](.*?)['"]/;
356
            my $prev = $1;
281 dpurdie 357
            my $new_ver = $opt_validate ? $prev : $build_info->{BUILDVERSION};
227 dpurdie 358
 
359
            s/['"](.*?)['"]/'$build_info->{BUILDVERSION}'/;
281 dpurdie 360
            print_update( 'PrevVer', '', $prev, $new_ver );
227 dpurdie 361
        }
362
 
363
        #
364
        #   Process BuildPkgArchive and LinkPkgArchive
365
        if ( m/^\s*LinkPkgArchive/ or m/^\s*BuildPkgArchive/ )
366
        {
367
            m/['"](.*?)['"][^'"]*['"](.*?)['"]/;
368
 
369
            my $comp = $1;
370
            my $ver = $2;
371
            my $new_ver = get_package ( $comp, $ver );
372
            s/['"](.*?)['"]([^'"]*)['"](.*?)['"]/'$comp'$2'$new_ver'/;
373
            print_update ('', $comp ,$ver, $new_ver );
374
        }
375
 
376
 
377
    } continue
378
    {
379
        #
380
        #   Always output the resultant line
381
        #
382
        print OUTFILE $_;
383
    }
384
 
385
    #
386
    #   Cleanup
387
    #
388
    close OUTFILE;
3967 dpurdie 389
    unlink( $opt_ofile);
390
    rename ($opt_work_file ,$opt_ofile);
227 dpurdie 391
    display_unused();
392
}
393
 
394
#-------------------------------------------------------------------------------
395
# Function        : process_xml_build_file
396
#
397
# Description     : Rewrite one depends.xml file
398
#                   depends.xml -> auto.xml
399
#
400
#                   A very cheap and nasty XML (not)parser
401
#                   It assumes that entries are all on one line so that we can
402
#                   do trivial substitutions
403
#
404
#                   Processes
405
#                       <using ... >
247 dpurdie 406
#                       <property name="packagename" value="...">
407
#                       <property name="packageversion" value="...">
408
#                       <property name="releasemanager.releasename" value="...">
409
#                       <property name="releasemanager.projectname" value="...">
227 dpurdie 410
#                       <import file=...>
411
#
247 dpurdie 412
#                  Note: This function handles a wider scope of XML files
413
#                        than it really needs to. All thats needed is
249 dpurdie 414
#                        the <property name= value=> fields.
227 dpurdie 415
#
416
# Inputs          :
417
#
418
# Returns         :
419
#
420
sub process_xml_build_file
421
{
422
    Verbose ("$opt_infile");
423
 
3559 dpurdie 424
    my $release_name;
425
    my $release_version;
426
 
227 dpurdie 427
    #
428
    #   Unlink any OLD output file
429
    #
323 dpurdie 430
    unlink $opt_work_file;
227 dpurdie 431
 
432
    #
3559 dpurdie 433
    #   Open the output file
227 dpurdie 434
    #
323 dpurdie 435
    open ( OUTFILE, ">$opt_work_file" ) || Error( "Cannot create $opt_work_file", $! );
227 dpurdie 436
 
3559 dpurdie 437
    #
438
    #   Read input file and process as an array of lines
439
    #
440
    foreach ( getInputLines($opt_infile) )
227 dpurdie 441
    {
263 dpurdie 442
        next if ( $opt_noconfig );       # Nothing to do
227 dpurdie 443
        #
444
        #   Process "project" statement
445
        #
446
        if ( m~<project~ )
447
        {
448
            #   Extract the package name
449
            #   this to determine the required version of the package
450
            #
249 dpurdie 451
            if ( m~name="([^"]*)"~ )
233 dpurdie 452
            {
453
                $release_name = $1;
454
                Error ("Empty 'name' attribute not found in 'project'") unless ( $release_name );
455
                Verbose2 ("Project: $release_name");
456
            }
227 dpurdie 457
        }
458
 
459
        #
460
        #   Process "property" statements
461
        #
462
        elsif ( m~<property~ )
463
        {
464
            #
247 dpurdie 465
            #   Extract name and value
466
            #   Both must exist
227 dpurdie 467
            #
247 dpurdie 468
            my $name;
469
            my $value;
227 dpurdie 470
 
249 dpurdie 471
            if ( m~name="([^"]*)"~  )
247 dpurdie 472
            {
473
                $name = $1;
474
            }
475
            else
476
            {
477
                Error ("Name attribute not found in 'property'");
478
            }
479
 
249 dpurdie 480
            if ( m~value="([^"]*)"~ )
247 dpurdie 481
            {
482
                $value = $1;
483
            }
484
            else
485
            {
486
                Error ("Value attribute not found in $name 'property'");
487
            }
488
            Verbose2 ("Property: $name, Value: $value");
489
 
227 dpurdie 490
            #
323 dpurdie 491
            #   Examine the property name
247 dpurdie 492
            #   Some of the them are special, others will be package names
227 dpurdie 493
            #
494
            if ( $name eq 'packagename' )
495
            {
247 dpurdie 496
                $release_name = $value;
227 dpurdie 497
                Error ("Value attribute not found in packagename 'property'") unless ( $release_name );
498
            }
499
            elsif ( $name eq 'packageversion' )
500
            {
247 dpurdie 501
                $release_version = $value;
227 dpurdie 502
 
503
                #
504
                #   Ensure that we already have the package name
505
                #
506
                Error ("packageversion before packagename") unless ( $release_name );
507
 
508
                my $new_ver = get_package ( $release_name, $release_version );
249 dpurdie 509
                s~(.*)value="([^"]*)"~$1value=\"$new_ver\"~;
323 dpurdie 510
                print_update( 'Name', $release_name ,$release_version, $new_ver );
227 dpurdie 511
            }
247 dpurdie 512
            elsif ( defined $fields{$name} )
227 dpurdie 513
            {
514
                #
247 dpurdie 515
                #   Use tagged values in preference to packages
516
                #   There are very few tagged values.
227 dpurdie 517
                #
247 dpurdie 518
                my $new_value = $fields{$name};
519
                Error ("Release attribute not found: $name") unless ( $new_value );
520
 
249 dpurdie 521
                s~(.*)value="([^"]*)"~$1value=\"$new_value\"~;
247 dpurdie 522
                print_update( 'Release', $name ,$value, $new_value );
227 dpurdie 523
            }
524
            else
525
            {
247 dpurdie 526
                my $new_ver = get_package ( $name, $value );
249 dpurdie 527
                s~(.*)value="([^"]*)"~$1value=\"$new_ver\"~;
247 dpurdie 528
                print_update( '', $name ,$value, $new_ver );
227 dpurdie 529
            }
530
        }
531
 
532
        #
533
        #   Process "using" statements
534
        #
535
        elsif ( m~<using~ )
536
        {
537
            #
538
            #   Extract the package name and version
539
            #   and use this to determine the required version of the package
540
            #
249 dpurdie 541
            m~name="([^"]*)"~;
227 dpurdie 542
            my $name = $1;
543
            Error ("Name attribute not found in 'using'") unless ( $name );
544
            Verbose2 ("Using: $name");
545
 
546
            #
547
            #   Extract the version
548
            #
249 dpurdie 549
            m~version="([^"]*)"~;
227 dpurdie 550
            $release_version = $1;
551
            Error ("Version attribute not found in package 'using' : $name") unless ( $release_version );
552
 
553
            my $new_ver = get_package ( $name, $release_version );
249 dpurdie 554
            s~(.*)version="([^"]*)"~$1version=\"$new_ver\"~;
227 dpurdie 555
            print_update( '', $name ,$release_version, $new_ver );
556
        }
557
 
558
        #
559
        #   Import File
247 dpurdie 560
        #   Only used to import ant-using
227 dpurdie 561
        #
562
        elsif ( m~<import~ )
563
        {
564
            #
565
            #   Extract the file
566
            #
249 dpurdie 567
            m~file="([^"]*)"~;
227 dpurdie 568
            my $file = $1;
569
            Error ("File attribute not found in 'import'") unless ( $file );
570
 
571
            #
572
            #   Extract the package name and version from the file
573
            #   Will be of the form /package/version/filename
574
            #
575
            $file =~ m~(.*?)/([^/]+)/([^/]+)/([^/]+)$~;
576
            my $prefix = $1;
577
            my $pname = $2;
578
            my $pver = $3;
579
            my $fname = $4;
580
            Error ("Package details not found in import file") unless ( $fname );
581
 
582
            my $new_ver = get_package ( $pname, $pver );
583
 
584
            #
585
            #   Rewrite the body of the directive
586
            #
249 dpurdie 587
            s~(.*)file="([^"]*)"~$1file=\"$prefix/$pname/$new_ver/$fname\"~;
227 dpurdie 588
            print_update( '', $pname ,$pver, $new_ver );
589
        }
590
 
591
    } continue
592
    {
593
        #
594
        #   Always output the resultant line
595
        #
596
        print OUTFILE $_;
597
    }
598
 
599
    #
600
    #   Cleanup
601
    #
602
    close OUTFILE;
323 dpurdie 603
    unlink $opt_ofile;
604
    rename $opt_work_file ,$opt_ofile;
227 dpurdie 605
    display_unused();
606
}
607
 
608
#-------------------------------------------------------------------------------
3559 dpurdie 609
# Function        : getInputLines
610
#
611
# Description     : Slurp into the input file and create an array of lines
612
#                   Must handle files with a mix of line endings
613
#
614
#
615
# Inputs          : File to slurp
616
#
617
# Returns         : An array of lines
618
#                   Line endings preserved
619
#
620
sub getInputLines
621
{
622
    my ($infile) = @_;
623
    my @lines;
624
 
625
    #
626
    #   Open the input file
627
    #
628
    open ( INFILE, "<$infile" ) || Error( "Cannot read from $infile", $! );
629
 
630
    #   Read the entire file and break into lines
631
    #   Need to handle files that are a mix of Unix and Windows line endings
632
    #   Attempt to preserve the line style
633
 
634
    while ( <INFILE> )
635
    {
636
        s~([\n\r]+)$~~;
637
        my $eol = $1;
638
        if ( my @line = split(/[\r\n]+/, $_) ) {
639
            push @lines, $_ . $eol foreach (@line );
640
        } else {
641
            push @lines, $eol;
642
        }
643
    }
3967 dpurdie 644
    close INFILE;
3559 dpurdie 645
    return @lines;
646
}
647
 
648
#-------------------------------------------------------------------------------
227 dpurdie 649
# Function        : display_unused
650
#
651
# Description     : Generate warnings about config items that were not used
652
#
653
# Inputs          :
654
#
655
# Returns         :
656
#
657
sub display_unused
658
{
323 dpurdie 659
    return
660
        if ( $opt_mode );
661
 
227 dpurdie 662
    foreach my $comp ( sort keys %component_use )
663
    {
664
        foreach my $suf ( keys %{$component_use{$comp}} )
665
        {
666
            my $ver = get_version( $comp, $suf );
667
            Warning("Unused package: ${comp}_${ver}");
668
            $not_use_count++;
669
        }
670
    }
671
}
672
 
673
#-------------------------------------------------------------------------------
674
# Function        : save_package
675
#
676
# Description     : Save the package name and version
677
#
678
# Inputs          : $package
679
#                   $version
680
#
681
# Returns         : Nothing
682
#
683
sub save_package
684
{
685
    my ($package, $version) = @_;
686
 
687
    #
281 dpurdie 688
    #   Determine longest package name
689
    #
690
    my $len = length $package;
691
    $max_pkglen = $len
692
        if ( $len > $max_pkglen );
693
 
694
    #
227 dpurdie 695
    #   Split the suffix off the version
696
    #
697
    my ($rel, $suf ) = extract_version( $package, $version);
698
 
699
    Error ("Multiple definitions for $package $version" )
700
        if ( $component{$package}{$suf} );
701
 
247 dpurdie 702
    Error ("Package Name is a reserved key field: $package" )
703
        if ( exists $fields{$package} );
704
 
227 dpurdie 705
    $component{$package}{$suf} = $rel;
706
    $component_use{$package}{$suf} = $rel;
707
 
708
    Verbose2 ("Package: $package, $version, $rel, $suf");
709
 
710
}
711
 
712
#-------------------------------------------------------------------------------
713
# Function        : get_package
714
#
281 dpurdie 715
# Description     : Get the package version
716
#                   Validates package-version if required
227 dpurdie 717
#
281 dpurdie 718
#                   Does not generate errors, but will generate error information
719
#                   to be reported later.
720
#
227 dpurdie 721
# Inputs          : $package
722
#                   $version ( suffix is used only )
723
#
724
# Returns         : Replacement version
725
#
726
 
727
sub get_package
728
{
729
    my ($package, $version) = @_;
730
 
731
    #
732
    #   Split the suffix off the version
733
    #       Suffixes are not numeric
734
    #   Must allow for
735
    #       9.9.9
736
    #       9.9.cots
737
    #       9.9.9.cots
738
    #
739
    my ($rel, $suf ) = extract_version( $package, $version);
740
 
741
    Verbose2 ("Get Package: $package, $version, $rel, $suf");
742
 
743
    #
744
    #   If the CFG file has 'new' project extensions then we
745
    #   must transform them before attempting to look up the versions
746
    #
747
    if ( $opt_oldproject && $suf eq $opt_oldproject )
748
    {
749
        $suf = $opt_newproject;
750
        $suffix_count++;
751
    }
752
 
753
    #
754
    #   If a datafile was provided, then the packages MUST be present
755
    #
756
    if ( $opt_datafile )
757
    {
281 dpurdie 758
        unless ( exists $component{$package} )
759
        {
760
            push @pkg_errors, "No definitions for package '$package'";
761
            return $version;
762
        }
227 dpurdie 763
 
764
    #    print Data::Dumper->Dump ( [\%component], ["Component" ]);
765
 
281 dpurdie 766
        unless ( exists $component{$package}{$suf} )
767
        {
768
            push @pkg_errors, "No definitions for '$package' '$version' '$suf'";
769
            return $version;
770
        }
227 dpurdie 771
    }
772
 
773
    #
774
    #   remove used packages from the "use" hash
775
    #
776
    delete $component_use{$package}{$suf};
777
    delete $component_use{$package} unless ( keys %{$component_use{$package}} );
778
 
779
    #
780
    #   Was the suffix real
781
    #
281 dpurdie 782
    my $new_version = get_version( $package, $suf, $rel );
783
    if ( $opt_validate )
784
    {
785
        if ( $new_version ne $version )
786
        {
787
            push @pkg_errors_val, sprintf("Validation mismatch: %-${max_pkglen}s, %-15s != %-15s", $package ,$version,  $new_version);
788
            return $version;
789
        }
790
    }
791
    return $new_version;
227 dpurdie 792
}
793
 
794
#-------------------------------------------------------------------------------
795
# Function        : extract_version
796
#
797
# Description     : Extracts a version and project suffix from a string
798
#
799
# Inputs          : $1  - Package name
800
#                   $2  - Package Version Input string
801
#
802
# Returns         : $1  - Vesrion part
803
#                   $2  - Suffix (project) part
804
#
805
sub extract_version
806
{
807
    my ($package, $version) = @_;
808
 
809
    my $rel;
810
    my $suf;
811
 
347 dpurdie 812
    #
813
    #   Cots packages are special. They end in '.cots'
814
    #
815
    if ( $version =~ m~(.*)[\.\s](cots)$~ )
227 dpurdie 816
    {
817
        $rel = $1;
347 dpurdie 818
        $suf = $2
819
    }
820
    elsif ( $version =~ m~^(.*?)([\.\s]([^0-9]+))$~ )
821
    {
822
        $rel = $1;
227 dpurdie 823
        $suf = $3;
824
        $suf = '' unless ( $suf );
825
    }
826
    else
827
    {
828
        $rel = $version;
829
        $suf = '';
830
    }
831
    return ( $rel, $suf );
832
}
833
 
834
#-------------------------------------------------------------------------------
835
# Function        : get_version
836
#
837
# Description     : Create a nice package version
838
#
839
# Inputs          : $package
840
#                   $suf
841
#
842
# Returns         :
843
#
844
sub get_version
845
{
846
    my ($package,$suf, $version) = @_;
847
 
848
    if ( exists( $component{$package}{$suf} ) )
849
    {
850
        $version = $component{$package}{$suf};
851
    }
852
 
853
    if ( $opt_oldproject && $suf eq $opt_oldproject )
854
    {
855
        $suf = $opt_newproject;
856
        $suffix_count++;
857
    }
858
 
859
    $version .= '.' . $suf if ( length( $suf) );
860
    return  $version;
861
 
862
}
863
 
864
#-------------------------------------------------------------------------------
865
# Function        : genBuildName
866
#
867
# Description     : Generate a BuildName argument string
868
#
869
# Inputs          : build_info      - Hash of buildname arguments
870
#                   new_ver         - New version
871
#
872
# Returns         : A string of quoted BuildName arguemnts
873
#
874
sub genBuildName
875
{
876
    my ( $build_info, $new_ver ) = @_;
877
    my @args;
878
 
879
    #
880
    #   Remove the project part from the new version name
881
    #
882
    my $prj = $build_info->{BUILDNAME_PROJECT};
883
 
884
    $prj = $opt_newproject
885
        if ( $opt_oldproject && $prj eq $opt_oldproject );
886
 
887
    $new_ver =~ s~\.$prj$~~ if ( $prj );
888
 
889
    #
890
    #   Determine the format of the BuildName
891
    #
892
    if ( $build_info->{RELAXED_VERSION} )
893
    {
894
        #
895
        #   Relaxed format
896
        #
897
        push @args, $build_info->{BUILDNAME_PACKAGE};
898
        push @args, $new_ver;
899
        push @args, $prj if ( $prj );
900
        push @args, '--RelaxedVersion';
901
    }
902
    else
903
    {
904
        #
905
        #   Generate two field version as some of the deployment scripts
906
        #   need this format.
907
        #
908
        push @args, "$build_info->{BUILDNAME_PACKAGE} $new_ver $prj";
909
    }
910
 
911
    #
912
    #   Common arguments
913
    #
914
    push @args, "--PatchNum=$build_info->{DEPLOY_PATCH}"
915
        if ( $build_info->{DEPLOY_PATCH} );
916
 
917
    push @args, @{$build_info->{EXTRA_ARGS}} if exists ($build_info->{EXTRA_ARGS});
918
 
919
 
920
    #
921
    #   Format the arguments
922
    #
923
    return join ", ", map { "'$_'" } @args;
924
}
925
 
926
#-------------------------------------------------------------------------------
927
#   Documentation
928
#
929
 
930
=pod
931
 
361 dpurdie 932
=for htmltoc    SYSUTIL::
933
 
227 dpurdie 934
=head1 NAME
935
 
936
jats_rewrite - Rewrite a build.pl file
937
 
938
=head1 SYNOPSIS
939
 
940
  jats etool jats_rewrite [options]
941
 
942
 Options:
943
    -help               - brief help message
944
    -help -help         - Detailed help message
945
    -man                - Full documentation
946
    -verbose            - Verbose operation
947
    -config xxx         - Configuration file. Full file name
263 dpurdie 948
    -noconfig           - No configuration file
227 dpurdie 949
    -oldproject         - Old project extension (optional)
950
    -newproject         - New project extension (optional)
951
    -infile xxx         - Input file (build.pl)
952
    -outfile xxx        - Output file (auto.pl)
953
    -errors             - Generate errors for unused config items
954
    -xml                - Process a build.xml file
281 dpurdie 955
    -validate           - Validate dependencies only
323 dpurdie 956
    -mode=nn            - Special operational modes
227 dpurdie 957
 
958
=head1 OPTIONS
959
 
960
=over 8
961
 
962
=item B<-help>
963
 
964
Print a brief help message and exits.
965
 
966
=item B<-help -help>
967
 
968
Print a detailed help message with an explanation for each option.
969
 
970
=item B<-man>
971
 
972
Prints the manual page and exits.
973
 
974
=item B<-verbose>
975
 
247 dpurdie 976
Increases program output. This option may be specified multiple times
227 dpurdie 977
 
978
=item B<-config=xxx>
979
 
980
This option specifies the name of a configuration file that will provide the
981
transformation between of version numbers. The format of the config file is
982
described later.
983
 
984
The option is not required if -newproject and -oldproject are specified
985
 
263 dpurdie 986
=item B<-noconfig>
987
 
281 dpurdie 988
This option indicates that no config file is present and that the output file
263 dpurdie 989
is to be created without reference to the configuration.
990
 
227 dpurdie 991
=item B<-oldproject=xxx>
992
 
993
This option, in conjunction with B<-oldproject=xxx> allows the project
247 dpurdie 994
extensions to be modified. ie: .syd projects can be converted into .bej
227 dpurdie 995
projects.
996
 
247 dpurdie 997
If this option is present then the config data file is not required, although
227 dpurdie 998
it will be sued if it is present.
999
 
1000
=item B<-newproject=xxx>
1001
 
1002
See B<-oldproject=xxx>
1003
 
1004
 
1005
=item B<-infile=xxx>
1006
 
1007
The name of the input file. The default file is build.pl
1008
 
1009
=item B<-outfile=xxx>
1010
 
1011
The name of the output file. The default is auto.pl, even if an XML file is
1012
being processed.
1013
 
1014
=item B<-errors>
1015
 
1016
This option will force the program to generate an error message if there are
1017
packages in the config file that were not used by the re-write process.
1018
 
1019
=item B<-xml>
1020
 
1021
Process a build.xml file instead of a build.pl file.
247 dpurdie 1022
This option will be set internally if the infile extension is '.xml'
227 dpurdie 1023
 
281 dpurdie 1024
=item B<-validate>
1025
 
1026
This option will validate the build files against the configuration file. This
1027
option is used by build tools to validate dependency information.
1028
 
323 dpurdie 1029
=item B<-mode=n>
1030
 
1031
This option is used internally, by JATS, to indicate that the utility is being
1032
used to perform controlled rewrite operations. Currently only a value of 1 is
1033
supported. This will:
1034
 
361 dpurdie 1035
=over 4
323 dpurdie 1036
 
361 dpurdie 1037
=item *
323 dpurdie 1038
 
361 dpurdie 1039
Suppress warnings about unused packages. The config file may is expected to
1040
contain many more packages than required by the rewrite.
323 dpurdie 1041
 
361 dpurdie 1042
=item *
323 dpurdie 1043
 
361 dpurdie 1044
Suppress warnings about badly formatted config entries.
323 dpurdie 1045
 
361 dpurdie 1046
=item *
1047
 
1048
Will reuse an auto.pl or auto.xml file if its present. Allows user changes to be
1049
made to made to working copies of the build files.
1050
 
1051
=item *
1052
 
1053
Will use build.pl as a template if it is newer than auto.pl. Allows user changes
1054
to be made to build.pl.
1055
 
1056
=item *
1057
 
1058
Will not modify the packages own version number, or the previous version number.
323 dpurdie 1059
Only the package dependencies will be modified.
1060
 
361 dpurdie 1061
=item *
323 dpurdie 1062
 
361 dpurdie 1063
Package-Version that are not in the Release will not be treated as an error.
331 dpurdie 1064
 
361 dpurdie 1065
=item *
1066
 
1067
Package-Versions that are in dpkg_archive will generate a warning
1068
 
227 dpurdie 1069
=back
1070
 
323 dpurdie 1071
=back
1072
 
227 dpurdie 1073
=head1 DESCRIPTION
1074
 
247 dpurdie 1075
This utility is used within the automated build system to rewrite build files
1076
so that they contain suitable version numbers.
227 dpurdie 1077
 
247 dpurdie 1078
The program takes a configuration file, described below, that contains package
1079
and version information for the build.
1080
 
1081
The program takes a JATS build.pl file, or an ANT style dependency file, and
1082
will create a file that is similar, but contains modified package-version
1083
information.
1084
 
1085
The build tools are designed to use this I<auto> file, in preference to the
1086
original build file.
1087
 
1088
=head2 Format of the Configuration File
1089
 
227 dpurdie 1090
The format of the configuration file is defined below.
1091
 
247 dpurdie 1092
The file is a line oriented text file.
227 dpurdie 1093
 
247 dpurdie 1094
Comments begin with a # and go the end of the line.
227 dpurdie 1095
 
247 dpurdie 1096
There are three types of configuration line:
227 dpurdie 1097
 
247 dpurdie 1098
=over 8
1099
 
1100
=item Assigned Items
1101
 
1102
These are of the form: B<tag = value> and are used to specify the value of
361 dpurdie 1103
the following special properties:
247 dpurdie 1104
 
1105
=over 8
1106
 
1107
=item releasemanager.projectname
1108
 
1109
The name of the Release Manager project used for the build.
1110
 
1111
=item releasemanager.releasename
1112
 
1113
The name of the Release Manager release, within the project, used for the build.
1114
 
1115
=back
1116
 
1117
These may be used to brand installer programs with Release Information.
1118
Currently the use of these tags is only supported by the XML build files.
1119
 
1120
=item Package Version
1121
 
1122
Specifies the version of a package to use as two, space separated words of the
1123
form C<package_name package_version> where package version is of the form:
1124
 
1125
=over 8
1126
 
361 dpurdie 1127
=item   *
247 dpurdie 1128
 
361 dpurdie 1129
nn.nn.nnnn.aaa
247 dpurdie 1130
 
361 dpurdie 1131
=item   *
247 dpurdie 1132
 
361 dpurdie 1133
nn.nn.nnnn
1134
 
1135
=item   *
1136
 
1137
Other
1138
 
247 dpurdie 1139
=back
1140
 
1141
=item LinkPkgArchive or BuildPkgArchive
1142
 
1143
These are standard JATS LinkPkgArchive or BuildPkgArchive statements.
1144
 
1145
=back
1146
 
1147
=head2 XML File Rewrite
1148
 
1149
This program will process an ERG style ANT build dependency definition file
1150
and replace the values of the properties seen within the file.
1151
 
1152
The following properties are special within the rewrite process:
1153
 
1154
=over 8
1155
 
1156
=item	packagename
1157
 
1158
This is the name of the package. It is not modified, but it
1159
is used in conjunction with the C<packageversion> to identify the package, such
1160
that the packageversion can be updated. This property is mandatory and must
1161
appear before the C<packageversion>.
1162
 
1163
=item	packageversion
1164
 
1165
This is the version of the package. It can be rewritten by this program. This
1166
property is mandatory.
1167
 
1168
=item	releasemanager.projectname
1169
 
361 dpurdie 1170
If this property is found the value will be replaced with an
1171
L<assigned item|Assigned_Items> of the same name.
247 dpurdie 1172
 
1173
=item	releasemanager.releasename
1174
 
361 dpurdie 1175
If this property is found the value will be replaced with an
1176
L<assigned item|Assigned_Items> of the same name.
247 dpurdie 1177
 
1178
=back
1179
 
361 dpurdie 1180
Properties that are not special will be treated as the name of a package and
247 dpurdie 1181
the value will be updated to reflect the required version of the package.
1182
 
1183
The XML rewrite process does not, and cannot handle, instances of packages
1184
that have the same name, but different project suffixes. This is a limitation of
1185
the ERG ANT build system and not a limitation of this utility.
1186
 
1187
=head2 JATS Build File Rewrite
1188
 
1189
This program will process a JATS style build.pl file and modify some
1190
directives to update the file.
1191
 
1192
The following directives will be processed:
1193
 
1194
=over 8
1195
 
1196
=item BuildName
1197
 
1198
The existing version in the BuildName directive will be retained and may be used
1199
in any BuildPreviousVersion directive that is seen.
1200
 
1201
=item BuildPreviousVersion
1202
 
1203
This will be updated to contain the version from the BuildName. This is
1204
intended to be used by deployment scripts.
1205
 
1206
=item LinkPkgArchive
1207
 
1208
The version will be updated to reflect the configured package versions. The
1209
project suffix, if present, will be used to identify the correct package.
1210
 
1211
=item BuildPkgArchive
1212
 
1213
The version will be updated to reflect the configured package versions. The
1214
project suffix, if present, will be used to identify the correct package.
1215
 
1216
=back
1217
 
1218
The JATS build file rewrite process, unlike the ANT process, does handle, instances of packages
1219
that have the same name, but different project suffixes. This allows the use
1220
of packages such as C<sysbasetypes.cr> and C<sysbasetypes.prj> within the one
1221
package.
1222
 
1223
Currently the JATS build file rewrite process does pass the
1224
releasemanager.projectname and the releasemanager.releasename items through to
1225
the underlying system. If present in the config file they will be unused. This
1226
is not an error.
1227
 
227 dpurdie 1228
=cut
1229