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
 
4552 dpurdie 561
    Verbose2('ExecuteQuery:', $fname);
4550 dpurdie 562
    #
563
    #   Create the full SQL statement
564
    #
565
    my $sth = $RM_DB->prepare($m_sqlstr);
566
    if ( defined($sth) )
567
    {
568
        if ( $sth->execute() )
569
        {
570
            $sth->finish();
571
        }
572
        else
573
        {
574
            Error("$fname: Execute failure: $m_sqlstr", $sth->errstr() );
575
        }
576
    }
577
    else
578
    {
579
        Error("$fname: Prepare failure");
580
    }
581
}
582
 
583
 
584
#-------------------------------------------------------------------------------
4455 dpurdie 585
#   Documentation
586
#
587
 
588
=pod
589
 
590
=for htmltoc    SYSUTIL::
591
 
592
=head1 NAME
593
 
4550 dpurdie 594
jats_gen_releasenote - Generate a Release Note
4455 dpurdie 595
 
596
=head1 SYNOPSIS
597
 
4550 dpurdie 598
 jats jats_gen_releasenote [options]
4455 dpurdie 599
 
600
 Options:
601
    -help              - Brief help message
602
    -help -help        - Detailed help message
603
    -man               - Full documentation
604
    -verbose           - Display additional progress messages
605
    -outfile=name      - [Optional] Name of the output XML file
4468 dpurdie 606
    -archive=name      - [Optional] Name package archive
607
    -releasenote=path  - Path to the Release Note Data
4550 dpurdie 608
    -UpdateRmFiles     - Update the Files list in Release Manager
4455 dpurdie 609
 
610
 
611
=head1 OPTIONS
612
 
613
=over 8
614
 
615
=item B<-help>
616
 
617
Print a brief help message and exits.
618
 
619
=item B<-help -help>
620
 
621
Print a detailed help message with an explanation for each option.
622
 
623
=item B<-man>
624
 
625
Prints the manual page and exits.
626
 
627
=item B<-pvid=nn>
628
 
629
This option provides identifies the PackageVersion to be processed.
630
 
631
This option is mandatory.
632
 
633
=item B<-outfile=name>
634
 
635
This option specifies the output file name.
636
 
637
If not provided by the user the output filename will be created in the current directory
638
and it will be named after the package name and package version.
639
 
640
If the filename does not end in .xml, then .xml will be appended to the file name.
641
 
4550 dpurdie 642
=item B<-UpdateRmFiles>
643
 
644
This option will case the utility to ppdate the Files list in Release Manager.
645
 
646
The existinf file list will be replaced by the one within the package.
647
 
648
Note: Write Access to Release Manager is required.
649
 
4455 dpurdie 650
=back
651
 
652
=head1 DESCRIPTION
653
 
654
This utility program is used to extract sufficient information from Release Manager and other
655
associated databases so that a Release Note can be created.
656
 
657
The extracted data is stored in an XML format. The intent is that XSLT will be used to create
658
an HTML based release note.
659
 
660
 
661
=head1 EXAMPLE
662
 
663
=head2 jats get_releasenote_data -pvid=983058 -outfile=tmpdata.xml
664
 
665
This will locate a package-version with an id of 983058, extrat required information and create
666
an XML file called tmpdata.xml.
667
 
668
=cut