Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4455 dpurdie 1
########################################################################
2
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
3
#
4
# Module name   : jats_gen_releasenote.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Generate the package Release Note
10
#                 Requires
11
#                   1) Release Note data generated by jats_get_releasenote_data.pl
12
#                   2) Target package in dpkg_archive
13
#                   3) One or more built.files.xxx.xml
14
#
15
#                 Will:
16
#                   Merge built.files..xml files into the release note data
17
#                   Insert build meta data
18
#                   Save the Release Note MetaData within the package
19
#                   Generate the HTML release note - save within the package
20
#
21
# Usage:        See POD
22
#
23
#......................................................................#
24
 
25
require 5.008_002;
26
use strict;
27
use warnings;
28
 
29
use Pod::Usage;
30
use Getopt::Long;
31
use XML::Simple;
32
use File::Path;
33
use File::Copy;
34
use XML::Simple;
4546 dpurdie 35
use Digest::MD5;
36
use File::Find;
4455 dpurdie 37
 
38
use JatsError;
39
use JatsSystem;
40
use Getopt::Long;
41
use Pod::Usage;
42
use FileUtils;
43
use JatsEnv;
4550 dpurdie 44
use JatsRmApi;
4455 dpurdie 45
 
4550 dpurdie 46
use DBI;
47
 
4455 dpurdie 48
my $VERSION = "1.0.0";                                      # Update this. Inserted into meta data field
49
 
50
# User options
51
my $opt_verbose = 1;
52
my $opt_help = 0;
53
my $opt_archive;
54
my $archive_tag;
55
my $opt_pname;
56
my $opt_pversion;
57
my $opt_release_note;
58
my $opt_pvid;
59
my $opt_outname;
4550 dpurdie 60
my $opt_updateRmFiles;
4455 dpurdie 61
 
62
#   Global vars
4546 dpurdie 63
our $GBE_HOSTNAME;
4455 dpurdie 64
our $GBE_TOOLS;
65
my $DPKG_ROOT;
66
my $DPKG_DOC;
67
my $JATS_RN;
68
 
69
 
70
#
71
#   Structure to translate -archive=xxx option to archive variable
72
#   These are the various dpkg_archives known to JATS
73
#
74
my %Archive2Var =( 'main'       =>  'GBE_DPKG',
75
                   'store'      =>  'GBE_DPKG_STORE',
76
                   'cache'      =>  'GBE_DPKG_CACHE',
77
                   'local'      =>  'GBE_DPKG_LOCAL',
78
                   'sandbox'    =>  'GBE_DPKG_SBOX',
79
                   'deploy'     =>  'GBE_DPLY',
80
                   );
81
 
82
#-------------------------------------------------------------------------------
83
# Function        : Main Entry
84
#
85
# Description     :
86
#
87
# Inputs          :
88
#
89
# Returns         :
90
#
91
{
92
    my $result = GetOptions (
4550 dpurdie 93
                    "help+"         => \$opt_help,              # flag, multiple use allowed
94
                    "manual:3"      => \$opt_help,              # flag, set value
95
                    "verbose:+"     => \$opt_verbose,           # flag, increment
96
                    "archive=s"     => \$opt_archive,           # string
97
#                    "pname=s"       => \$opt_pname,            # string
98
#                    "pversion=s"    => \$opt_pversion,         # string
99
                    "releasenote=s" => \$opt_release_note,      # string
100
                    "UpdateRmFiles" =>  \$opt_updateRmFiles     # flag
4455 dpurdie 101
                    );
102
 
103
    #
104
    #   Process help and manual options
105
    #
106
    pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
107
    pod2usage(-verbose => 1)  if ($opt_help == 2 );
108
    pod2usage(-verbose => 2)  if ($opt_help > 2);
109
 
110
    ErrorConfig( 'name'    =>'GenRn', 'verbose' => $opt_verbose );
111
 
112
    #
113
    #   Needed EnvVars
114
    #
4546 dpurdie 115
    EnvImport ('GBE_HOSTNAME');
4455 dpurdie 116
    EnvImport ('GBE_TOOLS');
117
    $JATS_RN = catdir($GBE_TOOLS, 'RELEASENOTES');
118
    Error("Release Note tools not found", $JATS_RN)
119
        unless (-d $JATS_RN);
120
 
121
 
122
    #
123
    #   Sanity Check
124
    #
125
#    Error("Package Name not provided") unless $opt_pname;
126
#    Error("Package Version not provided") unless $opt_pversion;
127
    Error("Release Note data not provided") unless $opt_release_note;
128
    Error("Release Note data not found") unless -f $opt_release_note;
129
 
130
 
131
    #
132
    #   Determine the target archive
133
    #   The default archive is GBE_DPKG, but this may be changed
134
    #
135
    $opt_archive = 'main' unless ( $opt_archive );
136
    my $archive_tag = $Archive2Var{$opt_archive};
137
    Error("Unknown archive specified: $opt_archive")
138
        unless ( $archive_tag );
139
    $DPKG_ROOT = $ENV{$archive_tag} || '';
140
    Verbose ("Archive Variable: $archive_tag" );
141
    Verbose2 ("Archive Path: $DPKG_ROOT" );
142
 
143
    #
144
    #   Process the release note and extract essential information
145
    #
146
    processReleaseNote();
147
 
148
    #
149
    #   Locate the target package
150
    #
151
    $DPKG_ROOT = catdir($DPKG_ROOT, $opt_pname, $opt_pversion);
4546 dpurdie 152
    Verbose ("Package Path: ", DisplayPath($DPKG_ROOT) );
4455 dpurdie 153
    Error ("Package not found in archive", $DPKG_ROOT) unless -d $DPKG_ROOT;
154
 
155
    #
156
    #   Locate the release note data file
157
    #   This was created as a prerequisite to the build
158
    #   Note: windows requires '/' in the file list
159
    #
160
    my @filesList;
161
    foreach my $item ( glob(catdir($DPKG_ROOT, 'built.files.*.xml'))) {
162
        $item =~ s~\\~/~g;
163
        push @filesList, $item;
164
    }
4546 dpurdie 165
    unless (scalar @filesList > 0)
166
    {
167
        #
168
        #   No filelist found in the package
169
        #   This may occur for packages that did not go though the build system
170
        #   Create a package-list
171
        #
172
        my $item = generateFileList();
173
        $item =~ s~\\~/~g;
174
        push @filesList, $item;
175
    }
4455 dpurdie 176
    Error("No file list found within the package") unless (scalar @filesList > 0);
177
 
178
    #
179
    #   Generate the name of the release note
180
    #       RELEASE_NOTES_PVID_PKGNAME_CLEANV.html
181
    #
182
    my $cleanv = $opt_pversion;
183
    $cleanv =~ s~\.~_~g;
184
    $opt_outname = join('_',
185
                        'RELEASE_NOTES',
186
                        $opt_pvid,
187
                        $opt_pname,
188
                        $cleanv,    
189
                        ) . '.html';
190
    Verbose("Note Name: $opt_outname");
191
 
192
    #
193
    #   Create output directory within the package
194
    #
195
    $DPKG_DOC = catdir($DPKG_ROOT, 'doc');
196
    mkpath($DPKG_DOC, 0, 0775);
197
 
198
    #
199
    #   Merge the Release Note and the various file lists into a single
200
    #   XML file. Keep the file local
201
    #
202
    System('--NoShell', '--Exit', 'java', '-jar', 
203
           catdir($JATS_RN, 'saxon9he.jar'), 
204
           '-xsl:' . catdir($JATS_RN, 'merge.xslt'),
205
           "-s:$opt_release_note",
206
           'fileList=' . join(',', @filesList),
207
           '-o:' . 'built.files.releasenote.xml'
208
            );
209
 
210
    #
211
    #   Generate the HTML Release Note
212
    #   Output directly to the body of the package
213
    #
214
    System('--NoShell', '--Exit', 'java', '-jar', 
215
           catdir($JATS_RN, 'saxon9he.jar'), 
216
           '-xsl:' . catdir($JATS_RN, 'releaseNote2html.xslt'),
217
           '-s:' . 'built.files.releasenote.xml',
218
           "-o:" . catdir($DPKG_DOC, $opt_outname)
219
            );
220
 
221
    #
222
    #   Transfer the XML database directly into the package
223
    #
224
    unless( File::Copy::copy('built.files.releasenote.xml', catdir($DPKG_DOC, 'release_note.xml')) )
225
    {
226
        Error("Cannot transfer XML release note", $!);
227
    }
228
 
229
    #
4550 dpurdie 230
    #   Update the Release Manager entry - File Data
231
    #
232
    if ($opt_updateRmFiles)
233
    {
234
        updateRmFiles();
235
        updateRmNoteInfo();
236
    }
237
 
238
    #
4455 dpurdie 239
    #   All done
240
    #
4546 dpurdie 241
    Verbose ("Release Note:", DisplayPath(catdir($DPKG_DOC, $opt_outname)));
4455 dpurdie 242
    exit 0;
243
}
244
 
245
#-------------------------------------------------------------------------------
246
# Function        : processReleaseNote 
247
#
4546 dpurdie 248
# Description     : Extract essential information from the Release Note Data
4455 dpurdie 249
#
250
# Inputs          : 
251
#
4546 dpurdie 252
# Returns         : Populates global variables 
4455 dpurdie 253
#
254
sub processReleaseNote
255
{
256
    my $xml = XMLin($opt_release_note);
257
 
258
    foreach my $item ( qw (name version pvid) ) {
259
        Error("Unexpected ReleaseNote format: package $item")
260
            unless (exists $xml->{package}{$item});
261
    }
262
 
263
    $opt_pname = $xml->{package}{name};
264
    $opt_pversion = $xml->{package}{version};
265
    $opt_pvid = $xml->{package}{pvid};
266
 
267
    Verbose("Package Name: $opt_pname") ;
268
    Verbose("Package Version: $opt_pversion") ;
269
    Verbose("Package Pvid: $opt_pvid") ;
270
}
271
 
4546 dpurdie 272
#-------------------------------------------------------------------------------
273
# Function        : generateFileList
274
#                   generateFileListProc 
275
#
276
# Description     : A fileList has not been found in the target package
277
#                   Perhaps the package was not created by the build system
278
#                   
279
#                   Generate a fileList        
280
#
281
# Inputs          : None
282
#
283
# Returns         : Path to the generated file list
284
#
285
my @generateFileListData;
286
my $baseLength;
287
sub generateFileList
288
{
289
    my $outXmlFile;
290
    Verbose("Generate internal filelist - none found in package");
4455 dpurdie 291
 
4546 dpurdie 292
    #
293
    #   Scan the package and process each file
294
    #
295
    $baseLength = length($DPKG_ROOT);
296
    File::Find::find( \&generateFileListProc, $DPKG_ROOT );
297
 
298
    #
299
    #   Write out XML of the Generated file list
300
    #
301
    my $data;
302
    $data->{file} = \@generateFileListData;
303
 
304
    #
305
    #   Write out sections of XML
306
    #       Want control over the output order
307
    #       Use lots of attributes and only elements for arrays
308
    #       Save as one attribute per line - for readability
309
    #
310
    $outXmlFile = catdir($DPKG_ROOT,"built.files.$GBE_HOSTNAME.xml");
311
 
312
    Verbose2('Meta File', $outXmlFile);
313
    my $xs = XML::Simple->new( NoAttr =>0, AttrIndent => 1 );
314
 
315
    open (my $XML, '>', $outXmlFile) || Error ("Cannot create output file: $outXmlFile", $!);
316
    $xs->XMLout($data, 
317
                'RootName' => 'files', 
318
                'XMLDecl'  => '<?xml version="1.0" encoding="UTF-8"?>',
319
                'OutputFile' => $XML);
320
    close $XML;
321
 
322
    return $outXmlFile;
323
}
324
 
325
sub generateFileListProc
326
{
327
    my %data;
328
    my $md5sum;
329
    my $source = $File::Find::name;
330
    my $type = 'dir';
331
 
332
    my $target = substr($source, $baseLength);
333
    $target =~ s~^/~~;
334
    $target =~ s~/$~~;
335
    Verbose2("GenFileList: $source, $target");
336
    return if (length ($target) == 0);
337
 
338
    if (-l $source)
339
    {
340
        $type = 'link';
341
    }
342
    elsif ( -f $source)
343
    {
344
        $type = 'file';
345
        Verbose2("Calculate MD5 Digest: $source");
346
        open(my $fh , $source) or Error ("Can't open '$source': $!");
347
        binmode $fh, ':crlf';
348
        $md5sum = Digest::MD5->new->addfile($fh)->hexdigest;
349
        close $fh;
350
    }
351
 
352
 
353
    if (-d $source)
354
    {
355
        $data{path} = $target;
356
    }
357
    else
358
    {
359
        $data{path} = StripFileExt($target);
360
        $data{name} = StripDir($target);
361
        if (defined $md5sum)
362
        {
363
            $data{size} = (stat($source))[7];
364
            $data{md5sum} = $md5sum;
365
        }
366
    }
367
 
368
    $data{fullname} = $target;
369
    $data{type} = $type;
370
    $data{machtype} = 'unknown';
371
    $data{host} = $GBE_HOSTNAME;
372
 
373
    # Put a nice '/' on the end of the patch elements
374
    $data{path} .= '/'
375
        if ( exists ($data{path}) && length($data{path}) > 0);
376
 
377
    push @generateFileListData, \%data;
378
}
379
 
4550 dpurdie 380
#-------------------------------------------------------------------------------
381
# Function        : updateRmFiles 
382
#
383
# Description     : 
384
#
385
# Inputs          : 
386
#
387
# Returns         : 
388
#
389
my $RM_DB;
390
my  $updateRmFilesData;
391
sub updateRmFiles
392
{
393
    my $eCount = 0;
394
    #
395
    #   If in use the the autobuilder - which it should be, then
396
    #   modify the user name
397
    #
398
    #$ENV{GBE_RM_LOCATION} = 'jdbc:oracle:thin:@auperaora07:1521:RELMANU1';
399
    #$ENV{GBE_RM_USERNAME} = 'build_user'; 
400
    #$ENV{GBE_RM_PASSWORD} = 'frog123';
4546 dpurdie 401
 
4550 dpurdie 402
    $ENV{GBE_RM_LOCATION} = 'jdbc:oracle:thin:@auperaora07:1521:RELMANU1';
403
    $ENV{GBE_RM_USERNAME} = 'release_manager'; 
404
    $ENV{GBE_RM_PASSWORD} = 'release_manager';
405
 
406
    if ($ENV{ABT})
407
    {
408
        $ENV{GBE_RM_USERNAME} = $ENV{GBE_RM_USERNAME} . '[release_manager]'; 
409
    }
410
 
411
    #
412
    #   Read in the release note data base
413
    #
414
    my $rnDataBase = catdir($DPKG_DOC, 'release_note.xml');
415
    if (! -f $rnDataBase )
416
    {
417
        Error("Release Note XML database not found: $!", $rnDataBase);
418
    }
419
    my $xml = XMLin($rnDataBase);
420
 
421
    #
422
    #   Sanity Test the data
423
    #
424
    Error("Sanity Check Failure. PVID") unless($opt_pvid eq $xml->{package}{pvid});
425
    Error("Sanity Check Failure. Name") unless($opt_pname eq $xml->{package}{name});
426
    Error("Sanity Check Failure. Version") unless($opt_pversion eq $xml->{package}{version});
427
    Error("Sanity Check Failure. File Section") unless(exists $xml->{files}{file});
428
#    DebugDumpData("XML DATA", \$xml);
429
 
430
    #
431
    #   Delete any existing entry(s)
432
    #
433
    updateRmFilesDelete();
434
 
435
    #
436
    #   Scan each entry and pump required data into the RM Database
437
    #
438
    $updateRmFilesData = ""; 
439
    foreach my $entry (@{$xml->{files}{file}})
440
    {
441
        #DebugDumpData("Entry", $entry);
442
 
443
        #
444
        #   Clean up the data
445
        #
446
        my $fname = $entry->{name} || '';
447
        my $fpath  = $entry->{path} || '';
448
        my $fsize  = $entry->{size} || 0;
449
        my $fmd5  = $entry->{md5sum} || '';
450
 
451
        $fpath =~ s~/$~~ unless $fname;
452
 
453
        #
454
        #   Create SQL fragment for the insert
455
        #
456
        $eCount++;
457
        my $entry = " INTO release_manager.release_components ( pv_id, file_name, file_path, byte_size, crc_cksum, crc_modcrc ) " .
458
                    " VALUES ( $opt_pvid, '$fname', '$fpath',$fsize , '$fmd5', '')";
459
        $updateRmFilesData .= $entry;
460
 
461
        # The size of the aggregation is key to performance
462
        # Too big is as bad as too small
463
        if (length($updateRmFilesData) > 10000)
464
        {
465
            updateRmFilesInsert();
466
        }
467
    }
468
    updateRmFilesInsert();
469
    Verbose ("Inserted $eCount entries into Release_Components");
470
}
471
 
4455 dpurdie 472
#-------------------------------------------------------------------------------
4550 dpurdie 473
# Function        : updateRmFilesInsert 
474
#
475
# Description     : Insert entries using the partial SQL statement 
476
#                   Must be called when the partial SQL buffer get large
477
#                   as well as at the end to fluch any outstanding inserts
478
#
479
# Inputs          : 
480
#
481
# Returns         : 
482
#
483
sub updateRmFilesInsert
484
{
485
    if (length($updateRmFilesData) > 0)
486
    {
487
        executeRmQuery(
488
            'updateRmFilesInsert',
489
            'INSERT ALL' .$updateRmFilesData . ' SELECT 1 FROM DUAL'
490
            );
491
 
492
        $updateRmFilesData = ""; 
493
    }
494
}
495
#-------------------------------------------------------------------------------
496
# Function        : updateRmFilesDelete 
497
#
498
# Description     : Delete ALL entires in the 'release_components' table associated
499
#                   with the current pvid
500
#                   
501
#                   Needs to be done before new entries are added.    
502
#
503
# Inputs          : 
504
#
505
# Returns         : 
506
#
507
sub updateRmFilesDelete
508
{
509
    executeRmQuery(
510
        'updateRmFilesDelete',
511
        'delete from release_components where pv_id=' . $opt_pvid
512
        );
513
}
514
 
515
#-------------------------------------------------------------------------------
516
# Function        : updateRmNoteInfo 
517
#
518
# Description     : Insert Release Note Info into the Release Manager Database
519
#                   This has the side effect that RM will see the Release Note
520
#                   as being fully generated.
521
#
522
# Inputs          : 
523
#
524
# Returns         : 
525
#
526
sub updateRmNoteInfo
527
{
528
    #
529
    #   Determine the path to the Release Note in a form that is suitable for the Release Manager
530
    #   Database. This expects: /dpkg_archive/PkgName/PkgVer/doc/pkgFileName
531
    #
532
    my $rnPath = join('/', '', 'dpkg_archive', $opt_pname, $opt_pversion, 'doc', $opt_outname);
533
    Verbose("RN_INFO:", $rnPath);
534
 
535
    # Into the database
536
    executeRmQuery (
537
        'updateRmNoteInfo', 
538
        'update release_manager.package_versions set release_notes_info=\'' . $rnPath . '\' where pv_id=' . $opt_pvid
539
        );
540
}
541
 
542
#-------------------------------------------------------------------------------
543
# Function        : executeRmQuery 
544
#
545
# Description     : Execute a simple RM query. One that does not expect any return data
546
#
547
# Inputs          : $fname           - OprName, for error reporting
548
#                   $m_sqlstr        - SQL String
549
#
550
# Returns         : Will exit on error
551
#
552
sub executeRmQuery
553
{
554
    my ($fname, $m_sqlstr) = @_;
555
 
556
    #
557
    #   Connect to the Database - once
558
    #
559
    connectRM(\$RM_DB, 0) unless $RM_DB;
560
 
561
    #
562
    #   Create the full SQL statement
563
    #
564
    my $sth = $RM_DB->prepare($m_sqlstr);
565
    if ( defined($sth) )
566
    {
567
        if ( $sth->execute() )
568
        {
569
            $sth->finish();
570
        }
571
        else
572
        {
573
            Error("$fname: Execute failure: $m_sqlstr", $sth->errstr() );
574
        }
575
    }
576
    else
577
    {
578
        Error("$fname: Prepare failure");
579
    }
580
}
581
 
582
 
583
#-------------------------------------------------------------------------------
4455 dpurdie 584
#   Documentation
585
#
586
 
587
=pod
588
 
589
=for htmltoc    SYSUTIL::
590
 
591
=head1 NAME
592
 
4550 dpurdie 593
jats_gen_releasenote - Generate a Release Note
4455 dpurdie 594
 
595
=head1 SYNOPSIS
596
 
4550 dpurdie 597
 jats jats_gen_releasenote [options]
4455 dpurdie 598
 
599
 Options:
600
    -help              - Brief help message
601
    -help -help        - Detailed help message
602
    -man               - Full documentation
603
    -verbose           - Display additional progress messages
604
    -outfile=name      - [Optional] Name of the output XML file
4468 dpurdie 605
    -archive=name      - [Optional] Name package archive
606
    -releasenote=path  - Path to the Release Note Data
4550 dpurdie 607
    -UpdateRmFiles     - Update the Files list in Release Manager
4455 dpurdie 608
 
609
 
610
=head1 OPTIONS
611
 
612
=over 8
613
 
614
=item B<-help>
615
 
616
Print a brief help message and exits.
617
 
618
=item B<-help -help>
619
 
620
Print a detailed help message with an explanation for each option.
621
 
622
=item B<-man>
623
 
624
Prints the manual page and exits.
625
 
626
=item B<-pvid=nn>
627
 
628
This option provides identifies the PackageVersion to be processed.
629
 
630
This option is mandatory.
631
 
632
=item B<-outfile=name>
633
 
634
This option specifies the output file name.
635
 
636
If not provided by the user the output filename will be created in the current directory
637
and it will be named after the package name and package version.
638
 
639
If the filename does not end in .xml, then .xml will be appended to the file name.
640
 
4550 dpurdie 641
=item B<-UpdateRmFiles>
642
 
643
This option will case the utility to ppdate the Files list in Release Manager.
644
 
645
The existinf file list will be replaced by the one within the package.
646
 
647
Note: Write Access to Release Manager is required.
648
 
4455 dpurdie 649
=back
650
 
651
=head1 DESCRIPTION
652
 
653
This utility program is used to extract sufficient information from Release Manager and other
654
associated databases so that a Release Note can be created.
655
 
656
The extracted data is stored in an XML format. The intent is that XSLT will be used to create
657
an HTML based release note.
658
 
659
 
660
=head1 EXAMPLE
661
 
662
=head2 jats get_releasenote_data -pvid=983058 -outfile=tmpdata.xml
663
 
664
This will locate a package-version with an id of 983058, extrat required information and create
665
an XML file called tmpdata.xml.
666
 
667
=cut