Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6887 dpurdie 1
########################################################################
2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
3
#
4
# Module name   : rmMerge_suck.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Insert Extacted package-version data into a different RM instance
10
#
11
# Usage         : See POD at the end of this file
12
#
13
#......................................................................#
14
 
15
require 5.008_002;
16
use strict;
17
use warnings;
18
 
19
use Pod::Usage;
20
use Getopt::Long;
21
 
22
use JatsError;
23
use JatsRmApi;
24
use JatsSystem;
25
use FileUtils;
26
use ConfigurationFile;
27
use File::Copy;
28
use DBI;
29
my $RM_DB;
30
my $VERSION = "1.0";
31
my @testRMCred = ('TST', 'jdbc:oracle:thin:@relmanu3.coidtfba5ouc.ap-southeast-2.rds.amazonaws.com:1521:relmanu3', 'RELEASE_MANAGER', 'MPM0$U74');
32
my @oldRMCred =  ('OLD', 'jdbc:oracle:thin:@auawsards001:1521:RELEASEM', 'RELEASE_MANAGER', 'ske2k0se');
33
my @useRmCred;
34
my $defaultRtagId = 6883;                                   # Used when an RRTAG_ID cannot be translated
35
my $defaultRtagIdText = 'CORE Software Product Line';       # Could look it up, but ...
36
 
37
 
38
my $opt_reuse=1;
39
my $opt_help=0;
40
my $opt_verbose=0;
41
my $opt_debug=0;
42
my $opt_live = 1;
43
my $opt_previous = '';
44
my $opt_placeKeeper;
45
my $opt_history = 1;
46
my $opt_toHistory;
47
my $opt_infile;
48
my $opt_newPackage;
49
 
50
my $pname;
51
my $pversion;
52
my $pvid;
53
our %rmData;
54
my %keyFieldsData;
55
my %buildIdMap;
56
my @historySummary;
57
my @historyShortSummary;
58
my $nonRipple;
59
 
60
 
61
#-------------------------------------------------------------------------------
62
# Function        : Mainline Entry Point
63
#
64
# Description     :
65
#
66
# Inputs          :
67
#
68
my $result = GetOptions (
69
                "help:+"        => \$opt_help,
70
                "manual:3"      => \$opt_help,
71
                "verbose:+"     => \$opt_verbose,
72
                "debug:+"       => \$opt_debug,
73
                "previous:s"    => \$opt_previous,
74
                "live!"         => \$opt_live,
75
                "placekeeper!"  => \$opt_placeKeeper,
76
                "history!"      => \$opt_history,
77
                "toHistory:s"   => \$opt_toHistory,
78
                "infile:s"      => \$opt_infile,
79
                "newPackage"    => \$opt_newPackage,
80
                );
81
 
82
                #
83
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
84
                #
85
 
86
#
87
#   Process help and manual options
88
#
89
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
90
pod2usage(-verbose => 1) if ( $opt_help == 2 );
91
pod2usage(-verbose => 2) if ( $opt_help > 2 );
92
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ( $#ARGV != 1 );
93
 
94
#
95
#   Configure the error reporting rmMerge_process now that we have the user options
96
#
97
ErrorConfig( 'name'    =>'SPIT',
98
             'verbose' => $opt_verbose,
99
             'debug' => $opt_debug,
100
            );
101
 
102
#
103
# 
104
$pname = $ARGV[0];  
105
$pversion = $ARGV[1];
106
 
107
if ($opt_live) {
108
    Message("Using Live Database");
109
    @useRmCred = @oldRMCred;
110
} else  {
111
    @useRmCred = @testRMCred;
112
}
113
 
114
#   Generate the output filename
115
#   
116
$opt_infile = join('.', $pname, $pversion, 'rminfo', 'txt') unless $opt_infile; 
117
my $localDataStore = $opt_infile;
118
 
119
$ENV{GBE_RM_LOCATION} = $useRmCred[1];
120
$ENV{GBE_RM_USERNAME} = $useRmCred[2];
121
$ENV{GBE_RM_PASSWORD} = $useRmCred[3];
122
connectRM(\$RM_DB) unless ( $RM_DB );
123
Message("Insert: $pname $pversion");
124
Message("After $opt_previous") if defined $opt_previous;
125
 
126
$pvid = GetPvid();
127
Error ("Package Version already exists: $pname, $pversion") if defined $pvid;
128
 
129
#
130
#   Get the data saved by rmMerge_suck
131
#
132
restoreLocalData();
133
 
134
#
135
#   May need to create a new package name entry
136
#   
137
CheckPackageName();
138
 
139
#
140
#   Potentially massage the data a bit
141
#
142
FudgeRtagId();
143
MassageHistory();
144
MassagePreviousPackageVersion();
145
MassagePlaceKeeper();
146
InsertActionLogEntry();
147
CalcRippleType();
148
 
149
#
150
#   Generate Cross reference information for the various tables
151
#   Need to have all the cross references in place first
152
#
153
GetXrefsUsers(qw(CREATOR_ID MODIFIER_ID OWNER_ID USER_ID));
154
GetXrefsPvid(qw(PV_ID LAST_PV_ID DPV_ID));
155
GetXrefsPkg(qw(PKG_ID DPKG_ID ));
156
GetXrefsActType(qw( ACTTYPE_ID ));
157
GetXrefsRtagId(qw( RTAG_ID ));
158
GetXrefsLicence(qw( LICENCE ));
159
ErrorDoExit();
160
 
161
#GetXrefsIgnore(qw( TEST_ID TESTRUN_ID DOC_ID BUILD_ID));        # Primary keys - ignore
162
#GetXrefsIgnore(qw( BE_ID BM_ID BSA_ID BS_ID VCS_TYPE_ID));      # Assume these have not changed
163
 
164
#
165
#   Now insert data into tables in the target database
166
#   Need to MAP some fields
167
#
168
Message ("Flag as non-Ripple") if $nonRipple;
169
Message ("Flag as a Ripple") unless $nonRipple;
170
CreateNewPvId();
171
CreatePackageVersion('PACKAGE_VERSIONS');
172
CreatePackageData('PACKAGE_DEPENDENCIES');
173
CreatePackageData('ACTION_LOG');
174
CreatePackageData('JIRA_ISSUES');
175
CreatePackageData('PACKAGE_BUILD_ENV');
176
CreatePackageData('PACKAGE_DOCUMENTS');
177
CreatePackageData('PACKAGE_BUILD_INFO');
178
CreatePackageData('PACKAGE_METRICS');
179
CreatePackageData('RELEASE_COMPONENTS');
180
CreateAdditionalNotes('ADDITIONAL_NOTES');
181
CreateBuildInstances('BUILD_INSTANCES');
182
CreatePackageData('LICENCING');
183
CreateUnitTests('UNIT_TESTS');
184
CreateTestRun('TEST_RUN');
185
 
186
disconnectRM(\$RM_DB);
187
#DebugDumpData("keyFieldsData",\%keyFieldsData);
188
exit 0;
189
 
190
#-------------------------------------------------------------------------------
191
# Function        : CalcRippleType 
192
#
193
# Description     : Have a guess as to the type of this package-version
194
#                   If its a 'Ripple' then we want to flag it as a non-ripple
195
#                   Checks:
196
#                       If there is extended history - then assume in nonRipple
197
#                       If its  new Package - then its a non ripple
198
#                       Then examine the previous version numbers.
199
#                        
200
#
201
# Inputs          : 
202
#
203
# Returns         : 
204
#
205
sub CalcRippleType
206
{
207
    return if $nonRipple;
208
    if ($opt_newPackage) {
209
        $nonRipple = 1;
210
        return;
211
    }
212
 
213
    # Examine the previous version numbers.
214
    #
215
    if ($opt_previous) {
216
        my $prevBase;
217
        my $prevPatch;
218
        my $prevRipple = 0;
219
 
220
        my $base;
221
        my $patch;
222
        my $ripple = 0;
223
 
224
        if ( $opt_previous =~ m~^(.*)\.([0-9]+)\.([a-zA-Z]+)$~) {
225
            $prevBase = $1;
226
            $prevPatch = $2;
227
Debug("Previous:$opt_previous - $prevBase, $prevPatch");
228
 
229
            if ($pversion =~ m~^(.*)\.([0-9]+)\.([a-zA-Z]+)$~ ) {
230
                $base = $1;
231
                $patch = $2;
232
Debug0("Previous:$pversion - $base, $patch");
233
 
234
                if ( $prevBase ne $base) {
235
                    $nonRipple = 1;
236
                    Debug0("Base version differs. $prevBase ne $base");
237
                    return;
238
                }
239
 
240
                if (length($prevPatch) > 3) {
241
                    $prevRipple = $prevPatch % 1000;
242
                    $prevPatch =  int($prevPatch / 1000);
243
                }
244
 
245
                if (length($patch) > 3) {
246
                    $ripple = $patch % 1000;
247
                    $patch =  int($patch / 1000);
248
                }
249
 
250
                if ( $prevPatch ne $patch) {
251
                    $nonRipple = 1;
252
                    Debug0("Patch version differs. $prevPatch ne $patch");
253
                    return;
254
                }
255
 
256
                return;
257
            } elsif ($pversion =~ m~^\((.*)\)\.([a-zA-Z]+)$~ ) {
258
                Debug0("WIP Detected");
259
                $nonRipple = 0;
260
                return;
261
            }
262
        } 
263
        Error("Could not parse version numbers: $opt_previous, $pversion" );
264
    }
265
}
266
 
267
 
268
#-------------------------------------------------------------------------------
269
# Function        : FudgeRtagId 
270
#
271
# Description     : Ensure that the $defaultRtagId is in the RTAG lookup tables
272
#                   Only used in BUILD_INSTANCES
273
#                   Could 'look' for all occurences
274
#
275
# Inputs          : 
276
#
277
# Returns         : 
278
#
279
sub FudgeRtagId
280
{
281
    my $entry = $rmData{BUILD_INSTANCES_XREF};
282
    return unless $entry;
283
 
284
    $entry = $entry->{RTAG_ID};
285
    if ($entry) {
286
        unless (exists $entry->{$defaultRtagId}) {
287
            $entry->{$defaultRtagId} = $defaultRtagIdText;
288
        }
289
    } else {
290
        Warning ("FudgeRtagId - cannot find expected table - BUILD_INSTANCES_XREF:RTAG_ID","Possibly NULL rtagId");
291
    }
292
}
293
 
294
#-------------------------------------------------------------------------------
295
# Function        : MassageHistory 
296
#
297
# Description     : If required, create a nice textual history of the package
298
#                   dating back to the Release Managr split
299
#
300
# Inputs          : 
301
#
302
# Returns         : 
303
#
304
sub MassageHistory
305
{
306
    return unless $opt_history;
307
    return unless exists $rmData{PV_HISTORY_DATA};
308
 
309
    #
310
    #   Locate the history section
311
    #
312
    my $history = $rmData{PV_HISTORY_DATA};
313
 
314
    # Get useful indexes
315
    my $idxVersion = getIndex('PV_HISTORY', 'PKG_VERSION');
316
    my $idxDate    = getIndex('PV_HISTORY', 'MODIFIED_STAMP');
317
    my $idxUser    = getIndex('PV_HISTORY', 'USER_NAME');
318
    my $idxText    = getIndex('PV_HISTORY', 'COMMENTS');
319
 
320
    #
321
    #   Scan entries looking for max length of user name
322
    #   Simply for a pretty picture
323
    #
324
    my $maxUlen = 1;
325
    foreach my $item ( @{$history}) {
326
        my $ulen = length ($item->[$idxUser]);
327
        if ($ulen > $maxUlen) {
328
            $maxUlen = $ulen;
329
        }
330
    }
331
 
332
    #
333
    #   Process each history item
334
    #   Don't include my own history entry
335
    #   Stop when we get to the 'previous' version as we know the history from there.
336
    #
337
    my $histCharCount = 0;
338
    my $histShortCharCount = 0;
339
    foreach my $item ( @{$history}) {
340
        my $lastEntry = 0;
341
        next if  $item->[$idxVersion] eq $pversion;
342
        if ($opt_previous) {
343
            last if $item->[$idxVersion] eq $opt_previous;
344
            last unless isVersionGreater( $item->[$idxVersion], $opt_previous ) ;
345
        }
346
        if ($opt_toHistory) {
347
            $lastEntry = 1 if ($item->[$idxVersion] eq $opt_toHistory);
348
        }
349
print("MassageHistory: $pversion, $opt_previous, $item->[$idxVersion]\n");
350
 
351
        my $etext = $item->[$idxText];
352
        $etext =~ s~(%0D%0A)+$~~;
353
        $etext =~ s~\s+$~~;
354
        $etext =~ s~^\s+~~;
355
        $etext =~ s~^\s+~~;
356
 
357
        my $text = sprintf("%-${maxUlen}.${maxUlen}s %s (%s) %s", $item->[$idxUser], $item->[$idxDate], $item->[$idxVersion], $etext);
358
        push @historySummary, $text;
359
        $histCharCount += length($text);
360
 
361
        $text =~ s~%0D.*$~ ...~;
362
        push @historyShortSummary, $text;
363
        $histShortCharCount += length($text);
364
 
365
Debug0(length($text), ":", $text);
366
 
367
        #
368
        #   We have history from major versions
369
        #   Force this insert to be a non-ripple
370
        #
371
        $nonRipple = 1;
372
 
373
        last if $lastEntry;
374
    }
375
    Message("History Text Length: $histCharCount");
376
}
377
 
378
#-------------------------------------------------------------------------------
379
# Function        : isVersionGreater 
380
#
381
# Description     : Test two versions
382
#
383
# Inputs          : $v1, $v2
384
#
385
# Returns         : 2 : Cannot parse
386
#                   1 : v1 >= v2
387
#                   0 : v1 < v2 or chnage in project
388
#                   
389
sub isVersionGreater
390
{
391
    my ($v1, $v2) = @_;
392
    my $rv = isVersionGreaterWrapper(@_);
393
    Debug0("isVersionGreater: $v1, $v2 :: $rv");
394
    return $rv;
395
}
396
sub isVersionGreaterWrapper
397
{
398
    my ($v1, $v2) = @_;
399
    return 1 if $v1 eq $v2;
400
 
401
    my ($v10, $v11, $v12, $v13, $v14, $v15 ) = SplitVersion( $v1);
402
    my ($v20, $v21, $v22, $v23, $v24, $v25 ) = SplitVersion( $v2);
403
 
404
    return 2 if (! defined($v10) || !defined($v20));
405
    return 2 if $v10 != $v20;
406
 
407
    return 0 unless $v15 eq $v25;
408
 
409
    #
410
    #   Cots type packages
411
    #
412
    if ($v10 == 2) {
413
        my $a = ($v11 cmp $v21); 
414
        if ($a > 0) {
415
            return 1;
416
        } elsif ($a < 0 ){
417
            return 0;
418
        } else {
419
            if ($v12 > $v22) {
420
                return 1;
421
            } elsif($v12 == $v22) {
422
                if ($v13 > $v23) {
423
                    return 1;
424
                } elsif ($v13 == $v23) {
425
                    if ($v14 >= $v24) {
426
                        return 1;
427
                    } else {
428
                        return 0;
429
                    }
430
                }
431
            }
432
        }
433
        return 0;
434
    }
435
 
436
    #
437
    #   Standard version scheme
438
    #
439
    if ($v11 > $v21) {
440
        return 1;
441
    } elsif ($v11 == $v21) {
442
        if ($v12 > $v22) {
443
            return 1;
444
        } elsif ($v12 == $v22) {
445
            if ($v13 > $v23) {
446
                return 1;
447
            } elsif ($v13 == $v23) {
448
                if ($v13 > $v23) {
449
                    return 1;
450
                } elsif ($v13 == $v23) {
451
                    if ($v13 > $v23) {
452
                        return 1;
453
                    } elsif ($v14 == $v24) {
454
                        return 1;
455
                    }
456
                }
457
            }
458
        }
459
    }
460
    return 0;
461
}
462
 
463
#-------------------------------------------------------------------------------
464
# Function        : SplitVersion 
465
#
466
# Description     : Spit a 'nice' version number into bits
467
#
468
# Inputs          : $vn - version number
469
#
470
# Returns         : An array of bits or UNDEF
471
#
472
sub SplitVersion
473
{
474
    my ($vn) = @_;
475
    if ($vn =~ m~^(\d+)\.(\d+)\.(\d+)(\d{3})\.(\w+)$~) {
476
        return 1,$1,$2,$3,$4,$5;
477
    } elsif ($vn =~ m~^(.*)\.(\d+)(\d{3})\.(\w+)$~) {
478
        return 2,$1,0,$2,$3,$4;
479
    } else {
480
        return undef;
481
    }
482
}
483
 
484
#-------------------------------------------------------------------------------
485
# Function        : getIndex 
486
#
487
# Description     : Get the index of a data item from specified meta data
488
#
489
# Inputs          : $table  - Name of table to access
490
#                   $field  - Name of field to locate
491
#
492
# Returns         : Will generte an error if not found 
493
#
494
sub getIndex
495
{
496
    my ($table,$field) = @_;
497
    my $rv;
498
    my $tableName = $table . "_NAMES";
499
    Error ("Internal: getIndex. Metadata not found for: $table") unless exists $rmData{$tableName};
500
 
501
    my $pvMetaData = $rmData{$tableName};
502
 
503
    foreach ( @{$pvMetaData} ) {
504
        next unless $_->[0] eq $field;
505
        $rv =  $_->[3] - 1;
506
        last;
507
    }
508
 
509
    Error("Internal: getIndex. Cannot find metadata for field($field) in table($table)") unless $rv;
510
    return $rv;
511
}
512
 
513
#-------------------------------------------------------------------------------
514
# Function        : MassagePlaceKeeper 
515
#
516
# Description     : Massage the data for creation of a place keeper
517
#
518
# Inputs          : 
519
#;
520
# Returns         : 
521
#
522
sub MassagePlaceKeeper
523
{
524
    return unless $opt_placeKeeper;
525
    Message("Generate Place Keeper Package Version");
526
 
527
    # Empty the a few tables
528
    delete $rmData{ACTION_LOG_DATA};
529
    delete $rmData{PACKAGE_DEPENDENCIES_DATA};
530
    delete $rmData{PACKAGE_METRICS_DATA};
531
    #delete $rmData{RELEASE_COMPONENTS_DATA};
532
    delete $rmData{BUILD_INSTANCES_DATA};
533
    delete $rmData{UNIT_TESTS_DATA};
534
    delete $rmData{TEST_RUN_DATA};
535
 
536
    delete $rmData{ACTION_LOG_XREF};
537
    delete $rmData{PACKAGE_DEPENDENCIES_XREF};
538
    delete $rmData{PACKAGE_METRICS_XREF};
539
    #delete $rmData{RELEASE_COMPONENTS_XREF};
540
    delete $rmData{BUILD_INSTANCES_XREF};
541
    delete $rmData{UNIT_TESTS_XREF};
542
    delete $rmData{TEST_RUN_XREF};
543
}
544
 
545
#-------------------------------------------------------------------------------
546
# Function        : MassagePreviousPackageVersion 
547
#
548
# Description     : The previous package version may not exist in the target
549
#                   release manager
550
#                   
551
#                   Allow the user to specify the previous package version
552
#                   The point at which the package will be inserted 
553
#
554
# Inputs          : 
555
#
556
# Returns         : 
557
#
558
sub MassagePreviousPackageVersion
559
{
560
    return unless $opt_previous || $opt_newPackage;
561
 
562
    my $pvData = $rmData{PACKAGE_VERSIONS_DATA};
563
    my $pvMetaData = $rmData{PACKAGE_VERSIONS_NAMES};
564
    my $idxPrevVer;
565
    my $prevPvid;
566
 
567
    #
568
    #   Find the 'LAST_PV_ID' index
569
    #
570
    foreach ( @{$pvMetaData} ) {
571
        next unless $_->[0] eq 'LAST_PV_ID';
572
        $idxPrevVer =  $_->[3] - 1;
573
        last;
574
    }
575
    Error ("Internal: Cannot find index of the LAST_PV_ID field") unless defined $idxPrevVer;
576
    $prevPvid = $pvData->[0][$idxPrevVer]; 
577
    Message("Previous version was:" . $prevPvid);
578
 
579
    #
580
    #   Fudge the 'XREF_PV_ID' entry
581
    # 
582
    Error("No 'XREF_PV_ID' entry for previous version") unless exists $rmData{PACKAGE_VERSIONS_XREF}{PV_ID}{$prevPvid};
583
 
584
    if ($opt_newPackage) {
585
        delete $rmData{PACKAGE_VERSIONS_XREF}{PV_ID}{$prevPvid} unless ( $rmData{METADATA}{PV_ID} eq $prevPvid);
586
        $prevPvid = $pvData->[0][$idxPrevVer] = $rmData{METADATA}{PV_ID};
587
 
588
    } else {
589
        $rmData{PACKAGE_VERSIONS_XREF}{PV_ID}{$prevPvid} = join($;, $pname, $opt_previous);
590
    }
591
}
592
 
593
#-------------------------------------------------------------------------------
594
# Function        : InsertActionLogEntry 
595
#
596
# Description     : Add an action log to mark the migration of this package
597
#                   Assume the format of the action log
598
#                       'USER_ID', 'ACTION_DATETIME' 'PV_ID' 'DESCRIPTION' 'ACTTYPE_ID' 'ACTION_TIMESTAMP'
599
#
600
# Inputs          : 
601
#
602
# Returns         : 
603
#
604
sub InsertActionLogEntry
605
{
606
   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
607
   my $timeStamp = sprintf("%4.4d-%02d-%02d %02d:%02d:%02d.0", $year + 1900, $mon+1, $mday, $hour,$min,$sec);
608
   my $txt = $opt_placeKeeper ? "Version migrated from Pulse as a placekeeper. This version will not build" : "Version migrated from Pulse";
609
    push @{$rmData{ACTION_LOG_DATA}}, [
610
             3768,                      # buildadm
611
             $timeStamp,                # 2017-06-12 10:04:10.0
612
             $rmData{METADATA}{PV_ID},  # PV_ID
613
             $txt,
614
             66,                        # Action ID = 'Version Control System Converted'
615
             $timeStamp                 # 2017-6-12.10.4. 10. 155886000
616
        ];
617
 
618
        # Kludge in action type
619
        $rmData{ACTION_LOG_XREF}{USER_ID}{3768} = 'buildadm';
620
        $rmData{ACTION_LOG_XREF}{ACT_TYPE}{66} = 'VcsConversion';
621
 
622
        #DebugDumpData("Action_LOG", $rmData{ACTION_LOG_DATA});
623
}
624
 
625
 
626
#-------------------------------------------------------------------------------
627
# Function        : CheckPackageName 
628
#
629
# Description     : Check that the package name exists
630
#                   If not then create it
631
#                   Need to insert the generated pkg_id into the rmData so that
632
#                   it can be mapped correctly    
633
#
634
# Inputs          : 
635
#
636
# Returns         : 
637
#
638
sub CheckPackageName
639
{
640
    my $pkgName = $rmData{METADATA}{NAME};
641
    my @row = GetOneSqlRow("select pkg_id, pkg_name from packages p where p.pkg_name = '$pkgName'");
642
    if (!defined $row[0]) {
643
        #
644
        #   Need to create a new package_name
645
        #
646
        my $newPkgId = GetNextSeqNum('seq_pkg_id');
647
        Message("Need to create a new Package Name with pkg_id: $newPkgId");
648
        my $m_sqlstr = "insert into packages (pkg_id, pkg_name) values($newPkgId, '$pkgName' )";
649
        @row = GetOneSqlRow($m_sqlstr);
650
    }
651
}
652
 
653
#-------------------------------------------------------------------------------
654
# Function        : CreateTestRun  
655
#
656
# Description     : Create the entry in the TEST_RUN table
657
#                   Need to create a unique TESTRUN_ID for each entry
658
#
659
# Inputs          : $tableName      - Not sure it will be used
660
#
661
# Returns         : 
662
#
663
sub CreateTestRun
664
{
665
    my ($tableName) = @_;
666
    my $tableData = $tableName. '_DATA';
667
 
668
    #
669
    #   Get one row of data and massage it into a form suitable for insertion
670
    #
671
    my $data = $rmData{$tableData}[0];
672
    foreach my $data (@{$rmData{$tableData}}) {
673
        InsertTableRow($tableName, $data,{
674
            'TESTRUN_ID' => sub {return GetNextSeqNum('seq_testrun_id');},
675
            'BUILD_ID' => sub { 
676
                            my ($fname, $value) = @_;
677
                            my $newValue = $buildIdMap{$value};
678
                            Error ("Internal: Can't map build_id for $value") unless defined $newValue;
679
                            return $newValue;
680
                        }
681
        });
682
    }
683
}
684
 
685
#-------------------------------------------------------------------------------
686
# Function        : CreateUnitTests  
687
#
688
# Description     : Create the entry in the BUILD_INSTANCES table
689
#                   Need to create a unique BUILD_ID for each entry
690
#
691
# Inputs          : $tableName      - Not sure it will be used
692
#
693
# Returns         : 
694
#
695
sub CreateUnitTests
696
{
697
    my ($tableName) = @_;
698
    my $tableData = $tableName. '_DATA';
699
 
700
    #
701
    #   Get one row of data and massage it into a form suitable for insertion
702
    #
703
    my $data = $rmData{$tableData}[0];
704
    foreach my $data (@{$rmData{$tableData}}) {
705
        InsertTableRow($tableName, $data,{
706
            'TEST_ID' => sub {return GetNextSeqNum('seq_unit_tests');}
707
        });
708
    }
709
}
710
 
711
#-------------------------------------------------------------------------------
712
# Function        : CreateBuildInstances  
713
#
714
# Description     : Create the entry in the BUILD_INSTANCES table
715
#                   Need to create a unique BUILD_ID for each entry
716
#                   
717
#                   Complication. Need to create a map of build_id's
718
#                                 so that the build_id is available when rmMerge_processing the TEST_RUN table
719
#
720
# Inputs          : $tableName      - Not sure it will be used
721
#
722
# Returns         : 
723
#
724
sub CreateBuildInstances
725
{
726
    my ($tableName) = @_;
727
    my $tableData = $tableName. '_DATA';
728
 
729
    #
730
    #   Get one row of data and massage it into a form suitable for insertion
731
    #
732
    my $data = $rmData{$tableData}[0];
733
    foreach my $data (@{$rmData{$tableData}}) {
734
        InsertTableRow($tableName, $data,{
735
            'BUILD_ID' => sub {
736
                            my ($fname, $value) = @_;
737
                            my $build_id = GetNextSeqNum('seq_build_instance');
738
                            $buildIdMap{$value} = $build_id;
739
                            return $build_id;
740
                        }
741
        });
742
    }
743
}
744
 
745
#-------------------------------------------------------------------------------
746
# Function        : CreateAdditionalNotes  
747
#
748
# Description     : Create the entry in the ADDITIONAL_NOTES table
749
#                   Need to create a unique NOTE_ID for each note entered
750
#
751
# Inputs          : $tableName      - Not sure it will be used
752
#
753
# Returns         : 
754
#
755
sub CreateAdditionalNotes
756
{
757
    my ($tableName) = @_;
758
    my $tableData = $tableName. '_DATA';
759
 
760
    #
761
    #   Get one row of data and massage it into a form suitable for insertion
762
    #
763
    my $data = $rmData{$tableData}[0];
764
    foreach my $data (@{$rmData{$tableData}}) {
765
        InsertTableRow($tableName, $data,{
766
            'NOTE_ID' => sub {return GetNextSeqNum('seq_additional_notes');}
767
        });
768
    }
769
}
770
 
771
#-------------------------------------------------------------------------------
772
# Function        : GetNextSeqNum 
773
#
774
# Description     : Get the next sequence numbber froom a named sequence 
775
#
776
# Inputs          : $seqName 
777
#
778
# Returns         : A number
779
#
780
sub GetNextSeqNum
781
{
782
    my ($seqName) = @_;
783
    my @row = GetOneSqlRow("SELECT $seqName.NEXTVAL from DUAL");
784
    #Debug0("Generate $seqName: $row[0]");
785
    return $row[0];
786
}
787
 
788
 
789
#-------------------------------------------------------------------------------
790
# Function        : CreateNewPvId 
791
#
792
# Description     : Generate a new PV_ID and insert it into the cross reference
793
#                   information so tha it will be correctly substituted. 
794
#
795
# Inputs          : 
796
#
797
# Returns         : 
798
#
799
sub CreateNewPvId
800
{
801
    $pvid = GetNextSeqNum('seq_pv_id');
802
    Message("PackageVersion: PV_ID: $pvid");
803
 
804
    #
805
    #   PV_ID in the origin
806
    #   
807
    my $pvidOrigin = $rmData{METADATA}{PV_ID};
808
    $keyFieldsData{PV_ID}{$pvidOrigin} = $pvid;
809
}
810
 
811
#-------------------------------------------------------------------------------
812
# Function        : CreatePackageData  
813
#
814
# Description     : Insert one or more rows into a table
815
#                   Assumes no data massaging needs to be done
816
#
817
# Inputs          : $tableName      - Not sure it will be used
818
#
819
# Returns         : 
820
#
821
sub CreatePackageData
822
{
823
    my ($tableName) = @_;
824
    my $tableData = $tableName. '_DATA';
825
 
826
    #
827
    #   Get one row of data and massage it into a form suitable for insertion
828
    #
829
    foreach my $data (@{$rmData{$tableData}}) {
830
        InsertTableRow($tableName, $data);
831
    }
832
 
833
}
834
 
835
#-------------------------------------------------------------------------------
836
# Function        : CreatePackageVersion  
837
#
838
# Description     : Create the entry in the PACKAGE_VESRIONS table
839
#                   Need to create a unique PV_ID
840
#                   Need to MAP some entries
841
#                   Need to NULL some entries 
842
#
843
# Inputs          : $tableName      - Not sure it will be used
844
#
845
# Returns         : 
846
#
847
sub CreatePackageVersion
848
{
849
    my ($tableName) = @_;
850
    my $tableData = $tableName. '_DATA';
851
 
852
    #
853
    #   Get one row of data and massage it into a form suitable for insertion
854
    #
855
    my $data = $rmData{$tableData}[0];
856
 
857
    InsertTableRow($tableName, $data, {
858
        #'PKG_VERSION' => sub {my ($fname, $value) = @_; return $value .= $opt_live ? '' : '.TEST';},
859
        'SRC_PATH' => sub {my ($fname, $value) = @_; $value =~ s~AUPERASVN02~AUPERASVN0X~; return $value;},
860
        'PKG_IDEXT' => sub {my ($fname, $value) = @_; return 'PulseImport';},
861
        'BUILD_TYPE' => sub {
862
                my ($fname, $value) = @_;
863
                if ($opt_placeKeeper) {
864
                    return 'U';
865
                }
866
                if ($nonRipple && ($value eq 'Y')) {
867
                    return 'A';
868
                }
869
 
870
                return $value;
871
            },
872
        'COMMENTS' => sub {
873
                my ($fname, $value) = @_;
874
                $value =~ s~^(%0D%0A)~~;
875
                $value =~ s~(%0D%0A)+$~~;
876
 
877
                if (length($value)> 0) {
878
                    $value .= "%0D%0A" ; 
879
                }
880
                $value .= "Version Imported from Pulse" unless $opt_placeKeeper; 
881
                $value .= "Version Imported from Pulse as a placeholder" if $opt_placeKeeper;
882
 
883
                if (@historySummary) {
884
                    my $text = '. Previous History' . "%0D%0A" . join("%0D%0A", @historySummary);
885
                    if ((length($text) + length($value)) > 4000 ) {
886
                        $text = '. Previous History' . "%0D%0A" . join("%0D%0A", @historyShortSummary);
887
                        Warning("Using abbreviated history");
888
                    }
889
                    $value .= $text;
890
                }
891
                if (length($value) > 4000) {
892
                    $value = substr ($value, 0, 4000);
893
                    $value .= "%0D%0AChopped ...";
894
Warning("Chopping comment string. Was " . length($value));
895
                }
896
                return $value;
897
            }
898
        });
899
}
900
 
901
#-------------------------------------------------------------------------------
902
# Function        : InsertTableRow 
903
#
904
# Description     : Insert a row into a table
905
#   
906
# Inputs          : $tableName
907
#                   $data   - Ref to data
908
#                   $metaData - REf to meta data    
909
#                   $callBacks - Hash of FieldNames, functions
910
#
911
# Returns         : 
912
#
913
sub InsertTableRow
914
{
915
    my ($tableName, $data, $callBacks) = @_;
916
    my $tableMetaData = $tableName. '_NAMES';
917
    my $metaData = $rmData{$tableMetaData};
918
 
919
    my @insertFields;
920
    my @insertValues;
921
 
922
    #
923
    #   Scan the metadata and fiddle the data
924
    #
925
    foreach my $entry ( @$metaData) {
926
        my $fname = $entry->[0];
927
        my $ftype = $entry->[1];
928
        my $isNullable = $entry->[2] eq 'Y';
929
        my $findex = $entry->[3]-1;
930
        my $value = $data->[$findex] || '';
931
 
932
        # Does this field need to be mapped
933
        if ($value ne '') {
934
            if (exists $rmData{XREF_MAP}{$fname}) {
935
                my $mapTable = $rmData{XREF_MAP}{$fname}; 
936
                Error ("Mapping table not found: $mapTable","Need: $value") unless exists $keyFieldsData{$mapTable};
937
 
938
                unless (exists $keyFieldsData{$mapTable}{$value}) {
939
                    DebugDumpData("keyFieldsData",\%keyFieldsData);
940
                    DebugDumpData("Data",$data);
941
                    Error ("Mapping value not found: $mapTable, $value, while rmMerge_processing $tableName, $fname") ;
942
                }
943
                my $newValue = $keyFieldsData{$mapTable}{$value};
944
                unless (defined $newValue) {
945
                    DebugDumpData("keyFieldsData",\%keyFieldsData);
946
                    DebugDumpData("Data",$data);
947
                    Error("Undefined map for: $tableName, $fname, $value");
948
                }
949
                if ($newValue ne $value) {
950
    Verbose("Mapping $tableName:$mapTable:$fname:$value -> $newValue");
951
                    $value = $newValue;
952
                }
953
            }
954
        }
955
 
956
        #
957
        #   Does the field need to be massaged
958
        #
959
        if (defined $callBacks && $callBacks->{$fname}) {
960
            my $newValue = $callBacks->{$fname}->($fname, $value);
961
            if ($newValue ne $value) {
962
Verbose("Massage $tableName:$fname:$value -> $newValue");
963
                $value = $newValue;
964
            }
965
        }
966
 
967
        #
968
        #   Does the field need to be quoted
969
        #   Assume that the 'suck' rmMerge_process has quoted special characters
970
        #   %0D -> return
971
        #   %0A -> newLine
972
        #   %09 -> Tab
973
        #   %25 -> As a percent
974
        #   %27 -> Single Quote
975
        #   Also need to handle a single quote char
976
        #
977
        if ($ftype =~ m~CHAR|VARCHAR~) {
978
            $value =~ s~'~'||chr(39)||'~g;
979
            $value =~ s~%0D~'||chr(13)||'~g;
980
            $value =~ s~%0A~'||chr(10)||'~g;
981
            $value =~ s~%09~'||chr(9)||'~g;
982
            $value =~ s~%27~'||chr(39)||'~g;
983
            $value =~ s~%25~%~g;
984
            $value = "'" . $value . "'";
985
#print("String Length ($fname):", length($value),"\n");
986
 
987
        } elsif ($ftype =~ m~DATE|TIMESTAMP~) {
988
            $value = "TO_TIMESTAMP('$value','YYYY-MM-DD HH24:MI:SS.FF')"
989
        }
990
 
991
        # Null item if we are allowed to
992
        if ($isNullable && length($value) <= 0) {
993
            $value = 'null';
994
        }
995
 
996
        push @insertFields, $fname;
997
        push @insertValues, $value;
998
    }
999
 
1000
    #
1001
    #   Generate the SQL
1002
    #
1003
    my $m_sqlstr = "insert into $tableName (" . join(',', @insertFields) . ")" . " VALUES (". join(',', @insertValues) .")";
1004
    Debug("$m_sqlstr");
1005
 
1006
    my $sth = $RM_DB->prepare($m_sqlstr);
1007
    my @row;
1008
    if ( defined($sth) )
1009
    {
1010
        if ( $sth->execute( ) )
1011
        {
1012
            if ( $sth->rows )
1013
            {
1014
                while ( @row = $sth->fetchrow_array )
1015
                {
1016
                    print("@row\n");
1017
                }
1018
            }
1019
            $sth->finish();
1020
        }
1021
        else
1022
        {
1023
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
1024
        }
1025
    }
1026
    else
1027
    {
1028
        Error("Prepare failure" );
1029
    }
1030
}
1031
 
1032
#-------------------------------------------------------------------------------
1033
# Function        : GetXrefCommon 
1034
#
1035
# Description     : Common code for fetch XREF data from the database 
1036
#
1037
# Inputs          : $name       - Tag name
1038
#                   $sql        - sql fragment to do the work    
1039
#                   $options    - Ref to a hack of options
1040
#                                   'default' - Value to use when not found
1041
#
1042
# Returns         : 
1043
#
1044
sub GetXrefCommon
1045
{
1046
    my ($name,$sql, $options) = @_;
1047
 
1048
    my (@fields) = @_;
1049
    my %idList;
1050
    my %data;
1051
    $options = {} unless $options;
1052
 
1053
    #
1054
    #   Generate a hash of items that we need
1055
    #
1056
    foreach my $tableName ( keys %rmData ) {
1057
        next unless $tableName =~ m~_XREF$~;
1058
        next unless exists $rmData{$tableName}{$name};
1059
        foreach my $id (keys %{ $rmData{$tableName}{$name} }) {
1060
            $idList{ $rmData{$tableName}{$name}{$id} } = $id;
1061
        }
1062
    }
1063
 
1064
    #DebugDumpData("GetXrefCommon, $name", \%idList);
1065
    return unless %idList;
1066
 
1067
    #
1068
    #   Get all the table data
1069
    #
1070
    my @row;   
1071
    my $m_sqlstr =  $sql . " in (". quoteList(keys %idList) .")";
1072
#Debug0("GetXrefCommon: $m_sqlstr");
1073
    my $sth = $RM_DB->prepare($m_sqlstr);
1074
    if ( defined($sth) )
1075
    {
1076
        if ( $sth->execute( ) )
1077
        {
1078
            if ( $sth->rows )
1079
            {
1080
                while ( @row = $sth->fetchrow_array )
1081
                {
1082
                    #print("GetXrefCommon: @row\n");
1083
                    $data{$row[1]} = $row[0];
1084
                }
1085
            }
1086
            $sth->finish();
1087
        }
1088
        else
1089
        {
1090
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
1091
        }
1092
    }
1093
    else
1094
    {
1095
        Error("Prepare failure" );
1096
    }
1097
 
1098
    #
1099
    #   Check that all required values have been found
1100
    #
1101
    foreach my $id (keys %idList) {
1102
        if (exists $data{$id}) {
1103
            $keyFieldsData{$name}{$idList{$id}} = $data{$id};
1104
        } elsif (defined $options->{default}) {
1105
            $keyFieldsData{$name}{$idList{$id}} = $options->{default};
1106
        } else {
1107
            ReportError("No Crossref for $name matching: $id");
1108
            #DebugDumpData("RmData", \%rmData);
1109
        }
1110
    }
1111
 
1112
    #
1113
    #   Keep the raw data in the output hash - possibly for debugging purposes
1114
    $keyFieldsData{$name . '_DEBUG'} = \%data;
1115
}
1116
 
1117
#-------------------------------------------------------------------------------
1118
# Function        : GetXrefsLicence
1119
#
1120
# Description     : Get cross references to other entites     
1121
#
1122
# Inputs          : list of keyFieldData keys to rmMerge_process
1123
#
1124
# Returns         : 
1125
#
1126
sub GetXrefsLicence
1127
{
1128
    my (@fields) = @_;
1129
    GetXrefCommon('LICENCE', 'select licence, name from release_manager.licences where name');
1130
}
1131
 
1132
#-------------------------------------------------------------------------------
1133
# Function        : GetXrefsRtagId 
1134
#
1135
# Description     : Get cross references to other entites     
1136
#
1137
# Inputs          : list of keyFieldData keys to rmMerge_process
1138
#
1139
# Returns         : 
1140
#
1141
sub GetXrefsRtagId
1142
{
1143
    my (@fields) = @_;
1144
    GetXrefCommon('RTAG_ID', 'select rtag_id, rtag_name from release_tags where rtag_name', {default => $defaultRtagId});
1145
}
1146
 
1147
#-------------------------------------------------------------------------------
1148
# Function        : GetXrefsActType 
1149
#
1150
# Description     : Get cross references to other entites     
1151
#
1152
# Inputs          : list of keyFieldData keys to rmMerge_process
1153
#
1154
# Returns         : 
1155
#
1156
sub GetXrefsActType
1157
{
1158
    my (@fields) = @_;
1159
    GetXrefCommon('ACT_TYPE', 'select acttype_id, name from release_manager.action_type where name');
1160
}
1161
 
1162
#-------------------------------------------------------------------------------
1163
# Function        : GetXrefsPkg 
1164
#
1165
# Description     : Get cross references to other entites     
1166
#
1167
# Inputs          : list of keyFieldData keys to rmMerge_process
1168
#
1169
# Returns         : 
1170
#
1171
sub GetXrefsPkg
1172
{
1173
    my (@fields) = @_;
1174
    GetXrefCommon('PKG_ID', 'select p.pkg_id, p.pkg_name from release_manager.packages p where p.pkg_name');
1175
}
1176
 
1177
#-------------------------------------------------------------------------------
1178
# Function        : GetXrefsPvid 
1179
#
1180
# Description     : Get cross references to other entites     
1181
#
1182
# Inputs          : list of keyFieldData keys to rmMerge_process
1183
#
1184
# Returns         : 
1185
#
1186
sub GetXrefsPvid
1187
{
1188
    my (@fields) = @_;
1189
 
1190
    #
1191
    #   Need to delete my PV_ID from the XREF tables 'PV_ID' tables
1192
    #   as I will never be found
1193
    #
1194
    foreach my $tableName ( keys %rmData ) {
1195
        next unless $tableName =~ m~_XREF$~;
1196
        next unless exists $rmData{$tableName}{PV_ID};
1197
        delete $rmData{$tableName}{PV_ID}{$rmData{METADATA}{PV_ID}};
1198
    }
1199
 
1200
    GetXrefCommon('PV_ID', "select pv.pv_id, p.pkg_name || '$;' ||pv.pkg_version from release_manager.packages p, release_manager.package_versions pv" . 
1201
                   " where p.pkg_id = pv.pkg_id and p.pkg_name || '$;' || pv.pkg_version");
1202
 
1203
}
1204
 
1205
#-------------------------------------------------------------------------------
1206
# Function        : GetXrefsUsers 
1207
#
1208
# Description     : Get cross references to other entites     
1209
#
1210
# Inputs          : list of keyFieldData keys to rmMerge_process
1211
#
1212
# Returns         : 
1213
#
1214
sub GetXrefsUsers
1215
{
1216
    my (@fields) = @_;
1217
    GetXrefCommon('USER_ID', 'select user_id, user_name from access_manager.users where user_name');
1218
}
1219
 
1220
#-------------------------------------------------------------------------------
1221
# Function        : quoteList  
1222
#
1223
# Description     : Convert an array of strings into a quoted comma-sep string
1224
#                   Used in sql of the form select ... in ( 'aaa','bbb',ccc') 
1225
#
1226
# Inputs          : An array of strings 
1227
#
1228
# Returns         : quoted comma-sep string
1229
#
1230
 
1231
sub quoteList
1232
{
1233
    my $rv = '';
1234
    my $join = '';
1235
    foreach  (@_) {
1236
        $rv .= $join . "'" . $_ . "'";
1237
        $join = ',';
1238
    }
1239
    return $rv;
1240
}
1241
 
1242
#-------------------------------------------------------------------------------
1243
# Function        : GetOneSqlRow 
1244
#
1245
# Description     : Execute a simple SQL statement and return to the user the first row of data
1246
#
1247
# Inputs          : $sql - statement to execute 
1248
#
1249
# Returns         : And array of data
1250
#
1251
sub GetOneSqlRow
1252
{
1253
    my ($m_sqlstr) = @_;
1254
#Debug0("GetOneSqlRow: $m_sqlstr");
1255
    my (@row);
1256
    my $sth = $RM_DB->prepare($m_sqlstr);
1257
    if ( defined($sth) ) {
1258
        if ( $sth->execute( ) ) {
1259
            if ( $sth->rows ) {
1260
#Debug0("GetOneSqlRow: @row");
1261
                @row = $sth->fetchrow_array;
1262
            }
1263
            $sth->finish();
1264
 
1265
        } else {
1266
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
1267
        }
1268
    } else {
1269
        Error("Prepare failure" );
1270
    }
1271
 
1272
    return @row;
1273
}
1274
 
1275
#-------------------------------------------------------------------------------
1276
# Function        : GetPvid 
1277
#
1278
# Description     : Get the packages pvid
1279
#
1280
# Inputs          : 
1281
#
1282
# Returns         : The pvid 
1283
#
1284
sub GetPvid
1285
{
1286
    my @row = GetOneSqlRow("select pv_id from packages p, package_versions pv where p.pkg_name = 'TEST_$pname' and pv.pkg_version = '$pversion' and p.pkg_id = pv.pkg_id");
1287
    return $row[0];
1288
}
1289
 
1290
#-------------------------------------------------------------------------------
1291
# Function        : saveLocalData 
1292
#
1293
# Description     : Saves a hash of data to disk 
1294
#
1295
# Inputs          : 
1296
#
1297
# Returns         : 
1298
#
1299
sub saveLocalData
1300
{
1301
    #
1302
    #   Dump out the configuration information
1303
    #
1304
    my $fh = ConfigurationFile::New( $localDataStore);
1305
 
1306
    $fh->DumpData( "\n# rmData\n#\n", "rmData", \%rmData );
1307
    $fh->Close();
1308
 
1309
    DebugDumpData("rmData", \%rmData);
1310
}
1311
 
1312
#-------------------------------------------------------------------------------
1313
# Function        : restoreLocalData 
1314
#
1315
# Description     : Read in the locally preserved data 
1316
#
1317
# Inputs          : 
1318
#
1319
# Returns         : 
1320
#
1321
sub restoreLocalData
1322
{
1323
    if (-f $localDataStore) {
1324
        require ( $localDataStore );
1325
    } else {
1326
        Error ("Extracted data not found: $localDataStore");
1327
    }
1328
}
1329
 
1330
#-------------------------------------------------------------------------------
1331
#   Documentation
1332
#
1333
 
1334
=pod
1335
 
1336
=for htmltoc    GENERAL::ClearCase::
1337
 
1338
=head1 NAME
1339
 
1340
rmMerge_suck - Inject Package-Version info into RM from a previous extraction
1341
 
1342
=head1 SYNOPSIS
1343
 
1344
jats rmMerge_spit [options] PackageName PackageVersion
1345
 
1346
 Options:
1347
    -help              - brief help message
1348
    -help -help        - Detailed help message
1349
    -man               - Full documentation
1350
    -live              - Operation on Live data
1351
    -prev=txt          - Prevous package version
1352
    -[no]placeKeeper   - Only partial package creation
1353
    -[no]history       - Append a text summary of the package history
1354
    -newPackage        - Special Handling for a new package
1355
    -infile=path       - Path to input file
1356
 
1357
=head1 OPTIONS
1358
 
1359
=over 8
1360
 
1361
=item B<-help>
1362
 
1363
Print a brief help message and exits.
1364
 
1365
=item B<-help -help>
1366
 
1367
Print a detailed help message with an explanation for each option.
1368
 
1369
=back
1370
 
1371
=head2 OPTIONS
1372
 
1373
=over
1374
 
1375
=item -placeKeeper
1376
 
1377
This mode will only insert some of the package information. Suffiecient to preserve the
1378
version number.
1379
 
1380
The dependencies are not imported. The package will not build.
1381
 
1382
Used to capture package-versions with some history.
1383
 
1384
=item -history
1385
 
1386
This option will cause a textual summary of the packages history to be added created.
1387
 
1388
The summary track non-ripple builds back to the Release Manager split.
1389
 
1390
=item -newPackage
1391
 
1392
Enable special handling of a new package. In particular the Previous version will be set to null.
1393
 
1394
=back
1395
 
1396
=head1 EXAMPLE
1397
 
1398
jats eprog rmMerge_spit PackageName PackageVersion
1399
 
1400
=cut
1401
 
1402