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
    #
121
    #   Use later of build.pl or auto.pl
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 );
323 dpurdie 220
            Warning "Suspect version format for: $comp ($ver)" unless ( $opt_mode || $ver =~ m~^\w+\.\w+\.\w+.\w+$~ || $ver =~ m~^\w+\.\w+\.\w+$~ );
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 );
323 dpurdie 234
        Warning "Suspect version format for: $comp ($ver)" unless ( $opt_mode || $ver =~ m~^\w+\.\w+\.\w+.\w+$~ || $ver =~ m~^\w+\.\w+\.\w+$~ );
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
 
768
    if ( $version =~ m~^(.*?)([\.\s]([^0-9]+))$~ )
769
    {
770
        $rel = $1;
771
        $suf = $3;
772
        $suf = '' unless ( $suf );
773
    }
774
    else
775
    {
776
        $rel = $version;
777
        $suf = '';
778
    }
779
 
780
    return ( $rel, $suf );
781
}
782
 
783
#-------------------------------------------------------------------------------
784
# Function        : get_version
785
#
786
# Description     : Create a nice package version
787
#
788
# Inputs          : $package
789
#                   $suf
790
#
791
# Returns         :
792
#
793
sub get_version
794
{
795
    my ($package,$suf, $version) = @_;
796
 
797
    if ( exists( $component{$package}{$suf} ) )
798
    {
799
        $version = $component{$package}{$suf};
800
    }
801
 
802
    if ( $opt_oldproject && $suf eq $opt_oldproject )
803
    {
804
        $suf = $opt_newproject;
805
        $suffix_count++;
806
    }
807
 
808
    $version .= '.' . $suf if ( length( $suf) );
809
    return  $version;
810
 
811
}
812
 
813
#-------------------------------------------------------------------------------
814
# Function        : genBuildName
815
#
816
# Description     : Generate a BuildName argument string
817
#
818
# Inputs          : build_info      - Hash of buildname arguments
819
#                   new_ver         - New version
820
#
821
# Returns         : A string of quoted BuildName arguemnts
822
#
823
sub genBuildName
824
{
825
    my ( $build_info, $new_ver ) = @_;
826
    my @args;
827
 
828
    #
829
    #   Remove the project part from the new version name
830
    #
831
    my $prj = $build_info->{BUILDNAME_PROJECT};
832
 
833
    $prj = $opt_newproject
834
        if ( $opt_oldproject && $prj eq $opt_oldproject );
835
 
836
    $new_ver =~ s~\.$prj$~~ if ( $prj );
837
 
838
    #
839
    #   Determine the format of the BuildName
840
    #
841
    if ( $build_info->{RELAXED_VERSION} )
842
    {
843
        #
844
        #   Relaxed format
845
        #
846
        push @args, $build_info->{BUILDNAME_PACKAGE};
847
        push @args, $new_ver;
848
        push @args, $prj if ( $prj );
849
        push @args, '--RelaxedVersion';
850
    }
851
    else
852
    {
853
        #
854
        #   Generate two field version as some of the deployment scripts
855
        #   need this format.
856
        #
857
        push @args, "$build_info->{BUILDNAME_PACKAGE} $new_ver $prj";
858
    }
859
 
860
    #
861
    #   Common arguments
862
    #
863
    push @args, "--PatchNum=$build_info->{DEPLOY_PATCH}"
864
        if ( $build_info->{DEPLOY_PATCH} );
865
 
866
    push @args, @{$build_info->{EXTRA_ARGS}} if exists ($build_info->{EXTRA_ARGS});
867
 
868
 
869
    #
870
    #   Format the arguments
871
    #
872
    return join ", ", map { "'$_'" } @args;
873
}
874
 
875
#-------------------------------------------------------------------------------
876
#   Documentation
877
#
878
 
879
=pod
880
 
881
=head1 NAME
882
 
883
jats_rewrite - Rewrite a build.pl file
884
 
885
=head1 SYNOPSIS
886
 
887
  jats etool jats_rewrite [options]
888
 
889
 Options:
890
    -help               - brief help message
891
    -help -help         - Detailed help message
892
    -man                - Full documentation
893
    -verbose            - Verbose operation
894
    -config xxx         - Configuration file. Full file name
263 dpurdie 895
    -noconfig           - No configuration file
227 dpurdie 896
    -oldproject         - Old project extension (optional)
897
    -newproject         - New project extension (optional)
898
    -infile xxx         - Input file (build.pl)
899
    -outfile xxx        - Output file (auto.pl)
900
    -errors             - Generate errors for unused config items
901
    -xml                - Process a build.xml file
281 dpurdie 902
    -validate           - Validate dependencies only
323 dpurdie 903
    -mode=nn            - Special operational modes
227 dpurdie 904
 
905
=head1 OPTIONS
906
 
907
=over 8
908
 
909
=item B<-help>
910
 
911
Print a brief help message and exits.
912
 
913
=item B<-help -help>
914
 
915
Print a detailed help message with an explanation for each option.
916
 
917
=item B<-man>
918
 
919
Prints the manual page and exits.
920
 
921
=item B<-verbose>
922
 
247 dpurdie 923
Increases program output. This option may be specified multiple times
227 dpurdie 924
 
925
=item B<-config=xxx>
926
 
927
This option specifies the name of a configuration file that will provide the
928
transformation between of version numbers. The format of the config file is
929
described later.
930
 
931
The option is not required if -newproject and -oldproject are specified
932
 
263 dpurdie 933
=item B<-noconfig>
934
 
281 dpurdie 935
This option indicates that no config file is present and that the output file
263 dpurdie 936
is to be created without reference to the configuration.
937
 
227 dpurdie 938
=item B<-oldproject=xxx>
939
 
940
This option, in conjunction with B<-oldproject=xxx> allows the project
247 dpurdie 941
extensions to be modified. ie: .syd projects can be converted into .bej
227 dpurdie 942
projects.
943
 
247 dpurdie 944
If this option is present then the config data file is not required, although
227 dpurdie 945
it will be sued if it is present.
946
 
947
=item B<-newproject=xxx>
948
 
949
See B<-oldproject=xxx>
950
 
951
 
952
=item B<-infile=xxx>
953
 
954
The name of the input file. The default file is build.pl
955
 
956
=item B<-outfile=xxx>
957
 
958
The name of the output file. The default is auto.pl, even if an XML file is
959
being processed.
960
 
961
=item B<-errors>
962
 
963
This option will force the program to generate an error message if there are
964
packages in the config file that were not used by the re-write process.
965
 
966
=item B<-xml>
967
 
968
Process a build.xml file instead of a build.pl file.
247 dpurdie 969
This option will be set internally if the infile extension is '.xml'
227 dpurdie 970
 
281 dpurdie 971
=item B<-validate>
972
 
973
This option will validate the build files against the configuration file. This
974
option is used by build tools to validate dependency information.
975
 
323 dpurdie 976
=item B<-mode=n>
977
 
978
This option is used internally, by JATS, to indicate that the utility is being
979
used to perform controlled rewrite operations. Currently only a value of 1 is
980
supported. This will:
981
 
982
=over 8
983
 
984
* Suppress warnings about unused packages. The config file may is expected to contain
985
  many more packages than required by the rewrite.
986
 
987
* Suppress warnings about badly formatted config entries.
988
 
989
* Will reuse an auto.pl or auto.xml file if its present. Allows user changes
990
to be made to made to working copies of the build files.
991
 
992
* Will use build.pl as a template if it is newer than auto.pl. Allows user
993
changes to be made to build.pl.
994
 
995
* Will not modify the packages own version number, or the previous version number.
996
Only the package dependencies will be modified.
997
 
998
* Package-Version that are not in the Release will not be treated as an error.
999
 
331 dpurdie 1000
* Package-Versions that are in dpkg_archive will generate a warning
1001
 
227 dpurdie 1002
=back
1003
 
323 dpurdie 1004
=back
1005
 
227 dpurdie 1006
=head1 DESCRIPTION
1007
 
247 dpurdie 1008
This utility is used within the automated build system to rewrite build files
1009
so that they contain suitable version numbers.
227 dpurdie 1010
 
247 dpurdie 1011
The program takes a configuration file, described below, that contains package
1012
and version information for the build.
1013
 
1014
The program takes a JATS build.pl file, or an ANT style dependency file, and
1015
will create a file that is similar, but contains modified package-version
1016
information.
1017
 
1018
The build tools are designed to use this I<auto> file, in preference to the
1019
original build file.
1020
 
1021
=head2 Format of the Configuration File
1022
 
227 dpurdie 1023
The format of the configuration file is defined below.
1024
 
247 dpurdie 1025
The file is a line oriented text file.
227 dpurdie 1026
 
247 dpurdie 1027
Comments begin with a # and go the end of the line.
227 dpurdie 1028
 
247 dpurdie 1029
There are three types of configuration line:
227 dpurdie 1030
 
247 dpurdie 1031
=over 8
1032
 
1033
=item Assigned Items
1034
 
1035
These are of the form: B<tag = value> and are used to specify the value of
1036
the following B<special> properties:
1037
 
1038
=over 8
1039
 
1040
=item releasemanager.projectname
1041
 
1042
The name of the Release Manager project used for the build.
1043
 
1044
=item releasemanager.releasename
1045
 
1046
The name of the Release Manager release, within the project, used for the build.
1047
 
1048
=back
1049
 
1050
These may be used to brand installer programs with Release Information.
1051
Currently the use of these tags is only supported by the XML build files.
1052
 
1053
=item Package Version
1054
 
1055
Specifies the version of a package to use as two, space separated words of the
1056
form C<package_name package_version> where package version is of the form:
1057
 
1058
=over 8
1059
 
1060
=item   * nn.nn.nnnn.aaa
1061
 
1062
=item   * nn.nn.nnnn
1063
 
1064
=item   * Other
1065
 
1066
=back
1067
 
1068
=item LinkPkgArchive or BuildPkgArchive
1069
 
1070
These are standard JATS LinkPkgArchive or BuildPkgArchive statements.
1071
 
1072
=back
1073
 
1074
=head2 XML File Rewrite
1075
 
1076
This program will process an ERG style ANT build dependency definition file
1077
and replace the values of the properties seen within the file.
1078
 
1079
The following properties are special within the rewrite process:
1080
 
1081
=over 8
1082
 
1083
=item	packagename
1084
 
1085
This is the name of the package. It is not modified, but it
1086
is used in conjunction with the C<packageversion> to identify the package, such
1087
that the packageversion can be updated. This property is mandatory and must
1088
appear before the C<packageversion>.
1089
 
1090
=item	packageversion
1091
 
1092
This is the version of the package. It can be rewritten by this program. This
1093
property is mandatory.
1094
 
1095
=item	releasemanager.projectname
1096
 
1097
If this property is found the value will be replaced with an B<Assigned Item> of the
1098
same name.
1099
 
1100
=item	releasemanager.releasename
1101
 
1102
If this property is found the value will be replaced with an B<Assigned Item> of the
1103
same name.
1104
 
1105
=back
1106
 
1107
Properties that are not B<special> will be treated as the name of a package and
1108
the value will be updated to reflect the required version of the package.
1109
 
1110
The XML rewrite process does not, and cannot handle, instances of packages
1111
that have the same name, but different project suffixes. This is a limitation of
1112
the ERG ANT build system and not a limitation of this utility.
1113
 
1114
=head2 JATS Build File Rewrite
1115
 
1116
This program will process a JATS style build.pl file and modify some
1117
directives to update the file.
1118
 
1119
The following directives will be processed:
1120
 
1121
=over 8
1122
 
1123
=item BuildName
1124
 
1125
The existing version in the BuildName directive will be retained and may be used
1126
in any BuildPreviousVersion directive that is seen.
1127
 
1128
=item BuildPreviousVersion
1129
 
1130
This will be updated to contain the version from the BuildName. This is
1131
intended to be used by deployment scripts.
1132
 
1133
=item LinkPkgArchive
1134
 
1135
The version will be updated to reflect the configured package versions. The
1136
project suffix, if present, will be used to identify the correct package.
1137
 
1138
=item BuildPkgArchive
1139
 
1140
The version will be updated to reflect the configured package versions. The
1141
project suffix, if present, will be used to identify the correct package.
1142
 
1143
=back
1144
 
1145
The JATS build file rewrite process, unlike the ANT process, does handle, instances of packages
1146
that have the same name, but different project suffixes. This allows the use
1147
of packages such as C<sysbasetypes.cr> and C<sysbasetypes.prj> within the one
1148
package.
1149
 
1150
Currently the JATS build file rewrite process does pass the
1151
releasemanager.projectname and the releasemanager.releasename items through to
1152
the underlying system. If present in the config file they will be unused. This
1153
is not an error.
1154
 
227 dpurdie 1155
=cut
1156