Subversion Repositories DevTools

Rev

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