Subversion Repositories DevTools

Rev

Rev 2319 | Rev 2393 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
392 dpurdie 1
########################################################################
2
# Copyright (C) 1998-2012 Vix Technology, All rights reserved
3
#
4
# Module name   : cc2svn_importpackage.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : Get package information for a package name specified on the
10
#                 command line.
11
#
12
#                 Determine the package id
13
#                 Locate all packages that have the same package name
14
#                 Determine essential packages
15
#                 Prune uneeded packages
16
#
17
#                 Pump it into SVN
18
#
19
#                 Project Based Pumping, creating branches as needed
20
#
21
#......................................................................#
22
 
23
require 5.006_001;
24
use strict;
25
use warnings;
26
use JatsError;
27
use JatsRmApi;
28
use FileUtils;
29
use JatsSystem;
30
use HTTP::Date;
31
use JatsProperties;
32
use JatsEnv;
33
use ConfigurationFile;
34
use JatsSvn qw(:All);
1197 dpurdie 35
use JatsLocateFiles;
392 dpurdie 36
 
37
 
38
#use Data::Dumper;
39
use Fcntl ':flock'; # import LOCK_* constants
40
use Cwd;
41
use DBI;
42
use Getopt::Long;
43
use Pod::Usage;                             # required for help support
1342 dpurdie 44
use Encode;
392 dpurdie 45
 
46
#
47
#   Options
48
#
49
my $opt_help = 0;
50
my $opt_manual = 0;
51
my $opt_verbose = 0;
52
my $opt_repo_base = 'AUPERASVN01/';
53
my $opt_repo = '';
54
my $opt_flat;
55
my $opt_test;
56
my $opt_reuse;
57
my $opt_age;
58
my $opt_dump = 0;
59
my $opt_images = 0;
60
my $opt_retaincount = 2;
61
my $opt_pruneModeString;
62
my $opt_listTags;
63
my $opt_name;
64
my $opt_log = 0;
65
my @opt_tip;
66
my $opt_postimage = 1;
67
my $opt_workDir = '/work';
68
my $opt_vobMap;
1197 dpurdie 69
my $opt_preserveProjectBase;
70
my $opt_ignoreProjectBaseErrors;
1270 dpurdie 71
my $opt_delete;
1272 dpurdie 72
my $opt_recentAge = 14;             # Days
392 dpurdie 73
 
74
################################################################################
75
#   List of Projects Suffixes and Branch Names to be used within SVN
76
#
77
#       Name        - Name of branch for the project
78
#       Trunk       - Can be a trunk project
79
#                     First one seen will be placed on the trunk
80
#                     Others will create project branches
81
#
82
my $ProjectTrunk;
83
my %ProjectsBaseCreated;
84
my %Projects = (
85
    '.sea'      => { Name => 'Seattle' },
86
    '.coct'     => { Name => 'CapeTown' },
87
    '.sls'      => { Name => 'Stockholm' },
88
    '.syd'      => { Name => 'Sydney' },
89
    '.vtk'      => { Name => 'Vasttrafik' },
90
    '.bei'      => { Name => 'Beijing' },
91
    '.bkk'      => { Name => 'Bangkok' },
92
    '.ndl'      => { Name => 'NewDelhi' },
93
    '.nzs'      => { Name => 'NewZealandStageCoach' },
94
    '.wdc'      => { Name => 'Washington' },
95
    '.oso'      => { Name => 'Oslo' },
96
    '.lvs'      => { Name => 'LasVegas' },
97
    '.mlc'      => { Name => 'BeijingMlc' },
98
    '.sfo'      => { Name => 'SanFrancisco' },
99
    '.sg'       => { Name => 'Singapore' },
100
    '.gmp'      => { Name => 'GmpteProject' },
101
    '.ssw'      => { Name => 'UkStageCoach' },
102
    '.uk'       => { Name => 'UkProject' },
103
    '.pmb'      => { Name => 'Pietermaritzburg' },
104
    '.vps'      => { Name => 'VixPayments' },
105
    '.ncc'      => { Name => 'NSWClubCard' },
106
    '.rm'       => { Name => 'Rome' },
2354 dpurdie 107
    '.vss'      => { Name => 'SmartSite' },
392 dpurdie 108
    'unknown'   => { Name => 'UnknownProject' },
109
 
110
    '.ebr'      => { Name => 'eBrio' , Trunk => 1 },
111
    '.mas'      => { Name => 'Mass'  , Trunk => 1 },
112
    '.cr'       => { Name => 'Core'  , Trunk => 1 },
113
    '.cots'     => { Name => 'Cots'  , Trunk => 1 },
114
    '.tool'     => { Name => 'Tools' , Trunk => 1 },
115
);
116
 
117
my %suffixFixup = (
118
    '.sf'           => '.sfo',
119
    '.vt'           => '.vtk',
120
    '.lv'           => '.lvs',
121
    '.was'          => '.wdc',
122
    '.uk.1'         => '.uk',
123
    '.ssts.demo'    => '.ssts',
124
    '.u244.syd'     => '.syd',
125
    '.pxxx.sea'     => '.sea',
126
    '.pxxx.syd'     => '.syd',
127
    '.pxxx.sydddd'  => '.syd',
128
    '.oslo'         => '.oso',
1272 dpurdie 129
    '.osl'          => '.oso',
392 dpurdie 130
);
131
 
2354 dpurdie 132
my @excludeFromImport = (
133
 
134
    # 22-Oct-12: Excluded on request from Kasun Sirikumara
135
    # Pending VSS work
136
    'agency_website',
137
    'alx',
138
    'alx-api',
139
    'cardholder_website',
140
    'loginmodule-ad',
141
    'ols-enquiry',
142
    'ols-enquiry-api',
143
    'olsrpc4j',
144
    'orca-middleware',
145
    'orca-middleware-api',
146
    'orca-salesEngine',
147
    'orca-web-api',
148
    'orca-web-utils',
149
    'TestPaymentGateway',
150
    'tgen4j',
151
    'web-cd-client',
152
);
153
 
392 dpurdie 154
my %specialPackages = (
2319 dpurdie 155
    'core_devl'           =>  ',all,protected,',
156
    'daf_utils_mos'       => ',flat,',
157
    'mos_packager'        => ',all,',
158
    'cfmgr-cfmgr'         => ',flat,',
159
    'daf_utils_button_st' => ',flat,',
2354 dpurdie 160
    'ReleaseName'         => ',flat,',
395 dpurdie 161
 
162
    # Need to be handled in a special manner
163
    # Not done by this utility
164
    #
165
    'linux_drivers_eb5600'  => ',protected,',
166
    'linux_drivers_viper'   => ',protected,',
167
    'linux_drivers_cobra'   => ',protected,',
168
    'linux_drivers_bcp4600' => ',protected,',
169
    'linux_drivers_etx86'   => ',protected,',
170
    'linux_drivers_tp5600'  => ',protected,',
171
 
2016 dpurdie 172
# Not in the ukHops migration at the moment
173
    'cs'                        => ',protected,',
1453 dpurdie 174
 
2016 dpurdie 175
    'DBA-Common'                => ',protected,',
176
    'DBA-DatabaseInstall'       => ',protected,',
177
    'DBA-ExternalPerlModules'   => ',protected,',
178
    'DBA-OraUserBuild'          => ',protected,',
179
    'DBA-OST'                   => ',protected,',
180
    'orahops-install'           => ',protected,',
181
    'orahops-patch'             => ',protected,',
182
    'orahops-ssw-install'       => ',protected,',
183
    'orahops-ssw-patch'         => ',protected,',
184
# End of ukHops migration exclussion
185
 
1197 dpurdie 186
    'ftp'                   => 'SetProjectBase,',
187
 
188
    'icl'                   => 'IgnoreProjectBase,',
189
    'itso'                  => 'IgnoreProjectBase,',
190
    'daf_osa_mos'           => 'IgnoreProjectBase,',
191
    'daf_utils_mos'         => 'IgnoreProjectBase,',
192
    'itso_ud'               => 'IgnoreProjectBase,',
193
#    'mos_api'               => 'IgnoreProjectBase,',
194
#    'mos_fonts'             => 'IgnoreProjectBase,',
195
#    'sntp'                  => 'IgnoreProjectBase,',
196
#    'time_it'               => 'IgnoreProjectBase,',
392 dpurdie 197
);
198
 
199
my %notCots = (
200
    'isl'       => 1,
201
);
202
 
1451 dpurdie 203
my $ukHopsMode = 0;
204
my %ukHopsReleases = (
205
    '6222'      => { name => 'MainLine', 'trunk' => 1 },
1453 dpurdie 206
    '14503'     => { name => 'Hops3' },
207
    '21864'     => { name => 'Hops3.6' },
208
    '22303'     => { name => 'Hops3.7' },
1451 dpurdie 209
    '17223'     => { name => 'Hops4' },
210
);
211
 
2016 dpurdie 212
# The following packages will have the version in the specified release forced to be on the trunk
213
# A trunk will be forced and the version will be on it.
214
#   May only work if the version in the release is also a TIP
215
my %ukHopsTip = (
216
    'ItsoMessaging'         => '6222',
217
    'MessageProcessor'      => '6222',
218
    'StrongNameKey'         => '6222',
219
);
220
 
392 dpurdie 221
################################################################################
222
#   Global data
223
#
224
my $VERSION = "1.0.0";
225
my $RM_DB;
226
my $last_pv_id;
227
my %pkg_ids;
228
my $first_pkg_id;
229
my %versions;
230
my %suffixes;
231
my @processOrder;
232
my @startPoints;
233
my @allStartPoints;
234
my @endPoints;
235
my $now = time();
236
my $logSummary;
237
my $firstVersionCreated;
238
my @EssentialPackages;
239
my $createBranch;
240
my $createSuffix;
241
my $currentBranchName;
242
my $singleProject;
243
my $pruneCount = 0;
244
my $trimCount = 0;
245
my $badVcsCount = 0;
246
my $ProjectCount = 0;
247
my $totalVersions = 0;
248
my $initialTrees = 0;
249
my $globalError;
250
my @unknownProjects;
251
my %knownProjects;
252
my $badSingletonCount = 0;
253
my @flatOrder;
254
my $pruneMode;
255
my $pruneModeString;
256
my $threadId = 0;
257
my $threadCount;
258
my %tipVersions;
259
my $allSvn;
260
my @multiplePaths;
261
my @badEssentials;
262
my %svnData;
263
my $cwd;
264
 
265
my $packageNames;
266
my @packageNames;
267
my $multiPackages = -1;
268
my $visitId = 0;
269
my $noTransfer;
270
my $rippleCount = 0;
271
my $svnRepo;
1270 dpurdie 272
my $processCount = 0;
273
my $processTotal = 0;
1272 dpurdie 274
my $recentCount = 0;
392 dpurdie 275
 
276
our $GBE_RM_URL;
277
my $UNIX = $ENV{'GBE_UNIX'};
278
 
279
my $result = GetOptions (
280
                "help+"         => \$opt_help,          # flag, multiple use allowed
281
                "manual:3"      => \$opt_help,
282
                "verbose:+"     => \$opt_verbose,       # Versose
283
                "repository:s"  => \$opt_repo,          # Name of repository
1272 dpurdie 284
                'rbase:s'       => \$opt_repo_base,     # Base of the repo
392 dpurdie 285
                "flat!"         => \$opt_flat,          # Flat structure
286
                "test!"         => \$opt_test,          # Test operations
287
                "reuse!"        => \$opt_reuse,         # Reuse ClearCase views
288
                "age:i"         => \$opt_age,           # Only recent versions
289
                "dump:1"        => \$opt_dump,          # Dump Data
290
                "images:1"      => \$opt_images,        # Create DOT images
291
                "retain:i"      => \$opt_retaincount,   # Retain N packages
292
                "pruneMode:s"   => \$opt_pruneModeString,
293
                "listtags:i"    => \$opt_listTags,
294
                "name:s"        => \$opt_name,          # Alternate output
295
                "tip:s"         => \@opt_tip,           # Force tip version(s)
296
                "log!"          => \$opt_log,
1270 dpurdie 297
                "delete!"       => \$opt_delete,
392 dpurdie 298
                "postimage!"    => \$opt_postimage,
299
                'workdir:s'     => \$opt_workDir,
300
                );
301
 
302
#
303
#   Process help and manual options
304
#
305
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
306
pod2usage(-verbose => 1)  if ($opt_help == 2 );
307
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));
308
 
309
#
310
#   Configure the error reporting process now that we have the user options
311
#
312
SystemConfig ('ExitOnError' => 1);
313
ErrorConfig( 'name'    =>'CC2SVN_IMPORT',
314
             'verbose' => $opt_verbose,
315
              );
316
 
317
Error("Workdir does not exist" ) unless ( -d $opt_workDir );
318
Error("Specify a package as 'name'" ) unless ( defined $ARGV[0] );
319
EnvImport('GBE_RM_URL');
320
$cwd = Getcwd();
321
 
322
#
323
#   Init the pruning mode
324
#
325
setPruneMode( $opt_pruneModeString || 'ripple');
326
 
327
#
328
#   Get data for all packages
329
#
330
foreach my $packageName ( @ARGV )
331
{
332
    next unless ( $packageName );
333
    Verbose( "Base Package: $packageName");
334
 
335
    my $pkg_id = GetPkgIdByName ( $packageName );
336
    GetData_by_pkg_id ( $pkg_id, $packageName  );
337
    $pkg_ids{$pkg_id} = 1;
338
    $first_pkg_id = $pkg_id unless ( $first_pkg_id );
339
    push @packageNames, $packageName;
340
    $multiPackages++;
341
}
342
 
343
{
344
    #
345
    #   Delete entries that have been created as we read in
346
    #   data, but don't exist in RM. They will not have a pvid.
347
    #
348
    foreach my $entry ( keys(%versions) )
349
    {
350
        delete $versions{$entry}
351
            unless ( exists $versions{$entry}{pvid} );
352
    }
353
}
354
 
355
$totalVersions = scalar keys %versions;
356
Error ("No packages specified") unless ( $multiPackages >= 0 );
357
Warning ("Multiple Packages being processed") if ( $multiPackages > 1 );
358
$packageNames = join ('_', @packageNames );
359
$packageNames = $opt_name if ( defined $opt_name );
360
Message ("PackageName: $packageNames" );
361
 
362
#
363
#   Save logging data
364
#
365
if ( $opt_log )
366
{
367
    my $opt_logfile = $packageNames . '.import';
368
    Message ("Logging outout: $opt_logfile" );
369
    open STDOUT, '>', $opt_logfile  or die "Can't redirect STDOUT: $!";
370
    open STDERR, ">&STDOUT"         or die "Can't dup STDOUT: $!";
371
}
372
 
373
#
374
#   Prepare tip version hash
375
#
376
$tipVersions{$_} = 1 foreach ( @opt_tip );
377
 
378
#
379
#   Read in external data and massage it all
380
#
381
getEssenialPackageVersions();
382
getVobMapping();
383
smartPackageType();                 # Determine special prune mode
384
ReportPathVariance();
385
massageData();
386
getSvnData();
387
smartPackageType();                 # Have another go
388
 
389
my @missedTips = keys %tipVersions;
390
Error ("Specified tip version not found: @missedTips") if ( @missedTips );
391
 
392
if ( $opt_flat )
393
{
394
#    @flatOrder = sort {$versions{$a}{version} cmp $versions{$b}{version}} keys(%versions);
395
#    @flatOrder = sort {$versions{$a}{created} cmp $versions{$b}{created}} keys(%versions);
396
    @flatOrder = sort {$a <=> $b} keys(%versions);
397
    my $tip = $flatOrder[-1];
398
    $versions{$tip}{Tip} = 1 if $tip;
399
}
400
 
401
#
402
#   Generate dumps and images
403
#
404
if ( $opt_images )
405
{
406
    createImages();
407
}
408
 
409
if ( $opt_dump )
410
{
411
    DebugDumpData ("Versions", \%versions );
412
    DebugDumpData ("Starts", \@startPoints );
413
    DebugDumpData ("Ends", \@endPoints );
414
    DebugDumpData ("Suffixes", \%suffixes );
415
}
416
 
417
 
418
#   Display VCS tags
419
#
420
if ( $opt_listTags )
421
{
422
    foreach my $entry (sort {$versions{$a}{version} cmp $versions{$b}{version}} keys(%versions) )
423
    {
424
        print $versions{$entry}{vcsTag} || '-' ,"\n";
425
    }
426
}
427
exit if ( ($opt_dump > 1) || ($opt_images > 1) );
428
 
429
transferPackageToSvn();
430
 
431
if ( $opt_postimage )
432
{
433
    getSvnData();
434
    createImages();
435
}
436
 
437
exit 0;
438
 
439
#-------------------------------------------------------------------------------
440
# Function        : transferPackageToSvn
441
#
442
# Description     : Transfer the package to SVN
443
#
444
# Inputs          : 
445
#
446
# Returns         : 
447
#
448
sub transferPackageToSvn
449
{
450
    Error ("Repository Path not setup")
451
        unless ( $svnRepo );
452
 
453
    #
454
    #   Going to do serious work
455
    #   Need to ensure we have more arguments
456
    #
457
    if ( $noTransfer )
458
    {
459
        Warning("Protected Package not transferred: $packageNames[0]");
460
        exit 0;
461
    }
462
 
463
    #
464
    #   Perform all the work in a package specific subdirectory
465
    #
466
    my $workDir = $opt_workDir . '/' . $packageNames;
467
    mkdir $workDir unless ( -d $workDir );
468
    chdir $workDir || Error ("Cannot cd to $workDir");
469
 
470
    #
471
    #   Process all packages
472
    #       Going to create versions based on RM structure
473
    #       May have several starting points: Process each
474
    #
475
    newPackage();
476
    if ( $opt_flat )
477
    {
478
        newProject();
479
        foreach my $entry (@flatOrder )
480
        {
481
            newPackageVersion( $entry, $versions{$entry}{suffix} );
482
        }
483
    }
484
    else
485
    {
486
        processBranch(@allStartPoints);
487
    }
488
    endPackage();
489
 
490
    chdir $cwd || Error ("Cannot cd back to $cwd");
491
    rmdir $workDir;
492
    Warning ("Work Directory still exists: $workDir");
493
    saveData();
494
}
495
 
496
#-------------------------------------------------------------------------------
497
# Function        : setPruneMode
498
#
499
# Description     : Set the pruning mode
500
#
501
# Inputs          : mode                    - Text mode value
502
#
503
# Returns         : Nothing
504
#
505
sub setPruneMode
506
{
507
    my ($mode) = @_;
508
    my $value;
509
    if ( $mode )
510
    {
511
        if ( $mode =~ m/none/i) {
512
            $value = 0;
513
        } elsif ( $mode =~ m/ripple/i) {
514
            $value = 1;
515
        } elsif ( $mode =~ m/retain/i) {
516
            $value = 2;
517
        } elsif ( $mode =~ m/severe/i) {
518
            $value = 3;
519
        } else {
520
            Error ("Unknown pruning mode", "Use: none, ripple, retain or severe");
521
        }
522
 
523
        $pruneModeString = $mode;
524
        $pruneMode = $value;
525
    }
526
}
527
 
528
#-------------------------------------------------------------------------------
529
# Function        : smartPackageType
530
#
531
# Description     : Have a look at the projects in the package set and
532
#                   attempt to determine what sort of mechanism to use
533
#
534
# Inputs          : Uses %suffixes data
535
#
536
# Returns         : 
537
#
538
my $packageType = 'UNKNOWN';
539
sub smartPackageType
540
{
541
    #
542
    #   Rebuild suffixes hash based on  post massaged versions
543
    #
544
    my %suffixes;
545
    my @unknown;
546
    foreach my $entry ( keys %versions )
547
    {
548
        my $suffix = $versions{$entry}{suffix} || '';
549
        push (@unknown, $entry) if ($suffix eq 'unknown');
550
 
551
        next if ( exists $suffixes{$suffix} );
552
        next if ( $versions{$entry}{badSingleton} );
553
        next if ( $versions{$entry}{locked} eq 'N' || $versions{$entry}{isaWip} );
554
        $suffixes{$suffix} = 1;
555
        $knownProjects{$suffix}{seen} = 1;
556
 
557
    }
558
 
559
    #
560
    #   The 'unknown' suffix is really an 'empty' suffix
561
    #   Try to be clever
562
    #       Map unknown to 'cr' or 'mas' if present
563
    #
564
    #
565
    if ( exists $suffixes{'unknown'}  )
566
    {
567
        my $new_suffix;
568
        if ( exists $suffixes{'.cr'} ) {
569
            $new_suffix = '.cr';
570
        } elsif ( exists $suffixes{'.mas'} ) {
571
            $new_suffix = '.mas';
572
        }
573
 
574
        if ( $new_suffix )
575
        {
576
            foreach my $entry ( @unknown )
577
            {
578
                $versions{$entry}{suffix} = $new_suffix;
579
            }
580
            delete $suffixes{'unknown'};
581
            delete $knownProjects{'unknown'}{seen};
582
        }
583
    }
584
 
585
    if ( exists $suffixes{'.cots'} && !exists ($notCots{$packageNames}) ) {
586
        $packageType = 'COTS';
587
        $Projects{'.cots'}{Trunk} = 1;
588
        $singleProject = 1;
589
        $opt_flat = 1 unless defined $opt_flat;
590
        setPruneMode('none') unless (defined $opt_pruneModeString);
591
 
592
    } elsif ( exists $suffixes{'.tool'} ) {
593
        $packageType = 'TOOL';
2016 dpurdie 594
        $Projects{'.tool'}{Trunk} = 1;
392 dpurdie 595
        $singleProject = 1;
596
        setPruneMode('none') unless (defined $opt_pruneModeString);
597
#        $opt_flat = 1;
598
 
599
    } elsif ( scalar (keys %suffixes ) == 1 ) {
600
        $packageType = 'SINGLE_PROJECT';
601
        $singleProject = 1;
602
 
603
    } else {
604
        $packageType = 'MULTIPLE_PROJECT';
605
    }
606
 
607
    #
608
    #   Some packages are special
609
    #
610
 
611
    if ( $packageNames[0] =~ m'^br_applet_' )
612
    {
613
        $opt_flat = 1 unless defined $opt_flat;
614
    }
615
 
2354 dpurdie 616
    foreach  ( @excludeFromImport )
617
    {
618
         $specialPackages{$_} .= 'protected,';
619
    }
620
 
392 dpurdie 621
    if ( exists $specialPackages{$packageNames[0]} )
622
    {
623
        my $data = $specialPackages{$packageNames[0]};
624
        if ( index( $data, ',all' ) >= 0) {
625
            setPruneMode('none') unless (defined $opt_pruneModeString);
626
        }
627
 
628
        if ( index( $data, 'protected,' ) >= 0) {
629
            $noTransfer = 1;
630
        }
631
 
632
        if ( index( $data, 'flat,' ) >= 0) {
633
            $opt_flat = 1;
634
        }
1197 dpurdie 635
 
636
        if ( index( $data, 'SetProjectBase,' ) >= 0) {
637
            $opt_preserveProjectBase = 1;
638
            $opt_ignoreProjectBaseErrors = 1;
639
            Message ("Preserving ProjectBase");
640
        }
641
 
642
        if ( index( $data, 'IgnoreProjectBase,' ) >= 0) {
643
            $opt_ignoreProjectBaseErrors = 1;
644
            Message ("Ignore ProjectBase Errors");
645
        }
646
 
392 dpurdie 647
    }
648
 
649
    Message("Package Type: $packageType, $pruneModeString");
650
}
651
 
652
 
653
#-------------------------------------------------------------------------------
654
# Function        : massageData
655
#
656
# Description     : Massage all the data to create a tree of package versions
657
#                   that can be used to create images as well as an import order
658
#
659
# Inputs          : 
660
#
661
# Returns         : 
662
#
663
my $reprocess=0;
664
sub calcLinks
665
{
666
    #
667
    #   Process the 'versions' hash and:
668
    #   Add back references
669
    #   Find starts and ends
670
    #       Entry with no previous
671
    #       Entry with no next
672
    #
673
    $reprocess = 0;
674
    foreach my $entry ( keys(%versions) )
675
    {
676
        foreach ( @{ $versions{$entry}{next}} )
677
        {
678
            $versions{$_}{last} = $entry;
679
        }
680
    }
681
    @allStartPoints = ();
682
    @startPoints = ();
683
    @endPoints = ();
684
    foreach my $entry ( keys(%versions) )
685
    {
686
        push @startPoints, $entry
687
            unless ( exists $versions{$entry}{last} || $versions{$entry}{badSingleton} );
688
 
689
        push @allStartPoints, $entry
690
            unless ( exists $versions{$entry}{last} );
691
 
692
        push @endPoints, $entry
693
            unless ( @{$versions{$entry}{next}} > 0  )
694
    }
695
}
696
 
697
sub massageData
698
{
699
    #
700
    #   Report unknown suffixes
701
    #   Handle bad, or little known project suffixes by creating them
702
    #
703
    foreach my $suffix ( keys %suffixes )
704
    {
705
        if ( exists $Projects{$suffix} )
706
        {
707
            next;
708
        }
709
        Message ("Unknown project suffix: '$suffix'");
710
        push @unknownProjects, $suffix;
711
        my $cleanSuffix = ucfirst(lc(substr( $suffix, 1)));
712
        $Projects{$suffix}{Name} = 'Project_' . $cleanSuffix;
713
    }
714
 
715
    calcLinks();
716
 
717
    $initialTrees = scalar @allStartPoints;
718
    Message ('Total RM versions: ' . $totalVersions );
719
    Message ('Initial trees: ' . $initialTrees );
720
    #
721
    #   Attempt to glue all the start points into one chain.
722
    #   This should allow us to track projects that branch from each other
723
    #   in cases where the RM data is incorrect/incomplete
724
    #       Strays are those that have no next or last
725
    #
726
    #   Glue based on Name, then PVID (Creation Order)
727
    #
728
    {
729
        #
730
        #   Examine threads. If it is a single entry thats bad then drop it
731
        #   This is simple to do. Should examine all entries, but thats a
732
        #   bit harder. Perhaps later.
733
        #
734
        if (1) {
735
            Message ("Dropping Bad Singletons");
736
            my $badSingletons;
737
            foreach my $entry ( sort {$a <=> $b} @startPoints )
738
            {
739
                my $ep = $versions{$entry};
740
                unless ( $ep->{last} || $ep->{next}[0] )
741
                {
742
#                    if (  $ep->{isaWip}  )
743
                    if ( (exists $ep->{badVcsTag} && $ep->{badVcsTag}) || $ep->{isaWip}  )
744
                    {
745
                        $ep->{badSingleton} = 1;
746
                        $reprocess = 1;
747
                        $badSingletonCount++;
748
 
749
                        # Add to a list of its own.
750
                        if ( $badSingletons )
751
                        {
752
                            push @{$versions{$badSingletons}{next}}, $entry;
753
                        }
754
                        $badSingletons = $entry;
755
                    }
756
                }
757
            }
758
            calcLinks()
759
                if ( $reprocess );
760
        }
761
 
762
        #
763
        #   Create simple trees out of the chains
764
        #   Tree is based on suffix (project) and version
765
        #
766
        {
767
            my %trees;
768
            Message ("Entries into trees");
769
            foreach my $single ( @startPoints )
770
            {
771
                my $suffix = $versions{$single}{suffix} || '';
772
                push @{$trees{$suffix}}, $single;
773
            }
774
 
775
            foreach  ( keys %trees )
776
            {
777
                my $last;
778
                foreach my $entry ( sort { $versions{$a}{version} cmp $versions{$b}{version}  } @{$trees{$_}} )
779
                {
780
                    if ( $last )
781
                    {
782
                        $versions{$last}{MakeTree} = 1;
783
                        push @{$versions{$last}{next}}, $entry;
784
                        $reprocess = 1;
785
                    }
786
                    $last = $entry;
787
                }
788
            }
789
            calcLinks()
790
                if ( $reprocess );
791
        }
792
 
793
        #
794
        #   Have a number of trees that are project related
795
        #   Attempt to create a single tree by inserting
796
        #   Secondary trees into the main line at suitable points
797
        #
798
        my @AllVersions = sort { $a <=> $b } @startPoints;
799
        my $lastEntry = shift @AllVersions;
800
        Error ("Oldest entry has a previous version") if ( $versions{$lastEntry}{last}  );
801
#print "Oldest: $lastEntry\n";
802
        #
803
        #   Insert remaining entries into out list, which is now sorted
804
        #
805
        my @completeList;
806
        foreach my $base ( @AllVersions  )
807
        {
808
            push @completeList, recurseList($lastEntry);
809
            @completeList = sort {$a <=> $b} @completeList;
810
#            Message("Complete List: ", @completeList);
811
#            Message("Complete List($completeList[0]) Length: " . scalar @completeList);
812
            $lastEntry = $base;
813
 
814
            my $last;
815
            foreach my $entry ( @completeList )
816
            {
817
                if ( $entry > $base )
818
                {
819
                    Error ("Not expecting last to be empty. $base, $entry") unless ( $last );
820
                    last;
821
                }
822
                $last = $entry;
823
            }
824
 
825
            #
826
            #   Insert at end if point not yet found
827
            #
828
#print "Inserting $base at $last\n";
829
            push @{$versions{$last}{next}}, $base;
830
            $versions{$base}{GluedIn} = 1;
831
            $reprocess = 1;
832
        }
833
 
834
        #
835
        #   Recalc basic links if any processing done
836
        #
837
        calcLinks()
838
            if ( $reprocess );
839
 
840
    }
841
 
842
 
843
    #
844
    #   Remove Dead Ends
845
    #   Packages that were never released
846
    #       Not locked, unless essential or a branchpoint
847
    #   Won't consider these to be mainline path.
848
    #
849
    {
850
        Message ("Remove Dead Ends");
851
        foreach my $entry ( @endPoints )
852
        {
853
            my $deadWood;
854
            while ( $entry )
855
            {
856
                last if ( $versions{$entry}{Essential} );
857
 
858
                my @next = @{$versions{$entry}{next}};
859
                my $count = @next;
860
                last if ( $count > 1 );
861
 
862
                last unless ( $versions{$entry}{locked} eq 'N' || $versions{$entry}{isaWip} );
863
 
864
                $versions{$entry}{DeadWood} = 1;
865
                $trimCount++;
866
            } continue {
867
                $entry = $versions{$entry}{last};
868
            }
869
        }
870
    }
871
 
872
    #
873
    #   Walk each starting point list and determine new Projects
874
    #   branchpoints.
875
    #
876
    Message ("Locate Projects branch points");
877
    foreach my $bentry ( keys(%versions) )
878
    {
879
        my $baseSuffix = $versions{$bentry}{suffix};
880
        foreach my $entry ( @{$versions{$bentry}{next}} )
881
        {
882
            if ( $baseSuffix ne $versions{$entry}{suffix})
883
            {
884
                unless ( exists $versions{$entry}{DeadWood} || $versions{$entry}{badSingleton} )
885
                {
886
#print "--- Project Branch $versions{$entry}{vname}\n";
887
                    $versions{$entry}{branchPoint} = 1;
888
                    $versions{$entry}{newSuffix} = 1;
889
                }
890
            }
891
        }
892
    }
1451 dpurdie 893
 
894
    #
895
    #   Mark UkHops special points
896
    #
897
    foreach my $entry ( keys(%versions) ) {
898
        foreach my $rtag_id ( keys %{$versions{$entry}{Releases}}  ) {
899
            next unless ( exists $ukHopsReleases{$rtag_id} );
900
            next unless ( $svnRepo =~ m~/ITSO_TRACS$~ );
901
 
902
            #
903
            #   This package is current in a special ukHops release
904
            #   Need to handle the differently
905
            #
906
            my $ukData =  $ukHopsReleases{$rtag_id};
907
 
908
            # Mark version we want on the trunk
909
            # Will calculate tip later
910
            if ( $ukData->{trunk} )
911
            {
912
                #
913
                #   Can only place on trunk IFF its a tip
914
                #   May have a WIP.
915
                #   Solution. Walk to the tip, but only if there is one
916
                #             path.
917
                #
918
                my $end = $entry;
919
                my $last;
920
                while ( $end )
921
                {
922
                    $last = $end;
923
                    if ( @{$versions{$end}{next}} > 1)
924
                    {
925
                        Warning ("Uk Release. Preferred trunk is not a tip: $versions{$entry}{vname}");
926
                        last;
927
                    }
928
 
929
                    $end = @{$versions{$end}{next}}[0];
930
                }
931
                $versions{$last}{ukTrunk} = 1 ;
932
            }
933
 
934
            #
935
            #   What to do if the version is in more than one release
936
            #
937
            $versions{$entry}{ukBranch}++;
938
            if ( $versions{$entry}{ukBranch} > 1 )
939
            {
940
                Warning ("Version found in multiple Uk Releases - don't know what to do");
941
            }
942
 
943
            #
944
            #   What to do if the package has multiple version in a release
945
            #
946
            $ukData->{count}++;
947
            if ( $ukData->{count} > 1 )
948
            {
949
                Warning ("Package has multiple versions in the one Uk Release: $versions{$entry}{Releases}{$rtag_id}{rname}");
950
            }
951
        }
952
    }
392 dpurdie 953
 
954
    #
955
    #   Prune
956
    #   Marks paths to root for all essential packages
957
    #   Marks the last-N from all essential packages
958
    #
959
    if ( $pruneMode )
960
    {
961
        Message ("Prune Tree: $pruneModeString");
962
        foreach ( @EssentialPackages )
963
        {
964
            #next unless ( exists $versions{$_} );      # Aleady deleted
965
 
966
            # Mark previous-N to be retained as well
967
            my $entry = $_;
968
            my $count = 0;
969
            while ( $entry )
970
            {
971
                last if ( $versions{$entry}{KeepMe} );
1453 dpurdie 972
#                unless ( $versions{$entry}{isaRipple} )
392 dpurdie 973
                {
974
                    my $keepFlag = ($count++ < $opt_retaincount);
975
                    last unless ( $keepFlag );
976
                    $versions{$entry}{KeepMe} = $keepFlag;
977
                }
978
                $entry = $versions{$entry}{last}
979
            }
980
        }
981
 
982
        #
1272 dpurdie 983
        #   Keep recent versions
984
        #       Keep versions created in the last N days
985
        #       Will keep recent ripples too
986
        #
987
        if ( $pruneMode == 1 )
988
        {
989
            foreach my $entry ( keys(%versions) )
990
            {
991
                next unless ( $versions{$entry}{Age} <= $opt_recentAge  );
992
                $versions{$entry}{keepRecent} = 1;
993
                $recentCount++;
994
#print "--- Recent version $versions{$entry}{vname}, $versions{$entry}{Age} <= $opt_recentAge\n";
995
            }
996
 
997
#            #
998
#            #   Keep the tip of each branch
999
#            #
1000
#            foreach my $entry ( @endPoints )
1001
#            {
1002
#                next if exists $versions{$entry}{keepRecent};
1003
#                $versions{$entry}{keepRecent} = 1;
1004
##print "--- Tip version $versions{$entry}{vname}\n";
1005
#            }
1006
        }
1007
 
1008
        #
392 dpurdie 1009
        #   Keep versions that are common parents to Essential Versions
1010
        #       Mark paths through the tree to essential versions
1011
        #       Mark nodes with the number of essential versions that they sprout
1012
        #   Don't do it if we are ripple pruning
1013
        #
1014
        Message ("Prune Tree keep common parents");
1015
        if ( $pruneMode != 1 )
1016
        {
1017
            foreach my $entry ( @endPoints )
1018
            {
1019
                my $hasEssential = 0;
1020
                $visitId++;
1021
                while ( $entry )
1022
                {
1023
                    $hasEssential = 1 if ( exists ($versions{$entry}{Essential}) && $versions{$entry}{Essential} );
1024
                    if ( $hasEssential )
1025
                    {
1026
                        if ( @{$versions{$entry}{next}} > 1 )
1027
                        {
1028
                            $versions{$entry}{EssentialSplitPoint}++;
1029
                        }
1030
                        last if ( exists $versions{$entry}{EssentialPath} );
1031
                        $versions{$entry}{EssentialPath} = 1;
1032
                    }
1033
 
1034
                    if ( ($versions{$entry}{visitId} || 0) == $visitId )
1035
                    {
1036
                        DebugDumpData ("Versions", \%versions );
1037
                        Warning ("Circular dependency");
1038
                        last;
1039
                    }
1040
                    $versions{$entry}{visitId} = $visitId;
1041
 
1042
                    $entry = $versions{$entry}{last};
1043
                }
1044
            }
1045
        }
1046
 
1047
        #
1048
        #   Keep first version of each ripple. Must keep first
1049
        #   Group ripples together so that they can be proccessed at the same time
1050
        #
1051
        calcRippleGroups()
1052
            if ( $pruneMode == 1);
1053
 
1054
        #
1055
        #   Delete all nodes that are not marked for retention
1056
        #   This is rough on the tree
1057
        #
1058
        Message ("Prune Tree Deleting");
1059
 
1060
        # 0 - Keep me
1061
        # 1 - Prune me
1062
        sub pruneMe
1063
        {
1064
            my ($entry) = @_;
1065
 
1066
            return 0 unless ( exists $versions{$entry} );
1067
            return 0 unless ( $versions{$entry}{last} );
1454 dpurdie 1068
#            return 0 if ( ($pruneMode == 2) && exists $versions{$entry}{KeepMe} );
1069
            return 0 if ( exists $versions{$entry}{KeepMe} );
392 dpurdie 1070
            return 0 if ( exists $versions{$entry}{Essential} );
1071
            return 0 if ( $versions{$entry}{newSuffix} );
1072
            return 0 if ( $versions{$entry}{newSuffix} && (exists $versions{$entry}{EssentialPath}) );
1073
#            return 1 if ( exists $versions{$entry}{DeadWood} );
1074
            return 0 if ( exists $versions{$entry}{EssentialSplitPoint} && $versions{$entry}{EssentialSplitPoint} > 1 );
1075
            return 0 if ( exists $versions{$entry}{keepLowestRipple} &&  $versions{$entry}{keepLowestRipple} );
1076
            return 0 if ( ($pruneMode == 1) && ! $versions{$entry}{isaRipple} );
1272 dpurdie 1077
            return 0 if ( exists $versions{$entry}{keepRecent} && $versions{$entry}{keepRecent} );
392 dpurdie 1078
            return 1;
1079
        }
1080
 
1081
        foreach my $entry ( keys(%versions) )
1082
        {
1083
#last;
1084
            next unless ( pruneMe($entry) );
1085
#print "--- Prune: $versions{$entry}{vname}\n";
1086
 
1087
            # Delete the current node
1088
            #
1089
            my @newNext;
1090
            $pruneCount++;
1091
            my $last = $versions{$entry}{last};
1092
            foreach ( @{$versions{$last}{next}} )
1093
            {
1094
                next if ( $_ == $entry );
1095
                push @newNext, $_;
1096
            }
1097
            foreach ( @{$versions{$entry}{next}} )
1098
            {
1099
                push @newNext, $_;
1100
                $versions{$_}{last} = $last;
1101
            }
1102
 
1103
            @{$versions{$last}{next}} = @newNext;
1104
            delete $versions{$entry};
1105
        }
1106
 
1107
        # Recalculate endpoints
1108
        calcLinks();
1109
    }
1110
    else
1111
    {
1112
        #   No rippling happening
1113
        #   Some process still need to happen
1114
        #
1115
        calcRippleGroups();
1116
    }
1117
 
1118
    #
2016 dpurdie 1119
    #   Want some versions to be forced to tip trunk
1120
    #
1121
    foreach my $name ( keys %ukHopsTip )
1122
    {
1123
        foreach my $entry ( keys(%versions) )
1124
        {
1125
            next unless ( $versions{$entry}{name} eq $name  );
1126
            next unless ( exists $versions{$entry}{Releases}{$ukHopsTip{$name}} );
1127
 
1128
            #
1129
            #   Force this suffix to be the trunk
1130
            #   Remove all others
1131
            #
1132
            foreach my $suffix ( keys %Projects )
1133
            {
1134
                delete $Projects{$suffix}{Trunk};
1135
            }
1136
            my $suffix = $versions{$entry}{suffix};
1137
            $Projects{$suffix}{Trunk} = 1;
1138
        }
1139
    }
1140
 
1141
    #
392 dpurdie 1142
    #   Calculate best through-path for branches in the tree
1143
    #   Attempt to keep that 'max' version on the mainline
1144
    #   May be modified by -tip=nnnn
1145
    #
1146
    #   For each leaf (end point), walk backwards and mark each node with the
1147
    #   max version see. If we get to a node which already has been marked then
1148
    #   stop if our version is greater. We want the value to be the max version
1149
    #   to a leaf
1150
    #
1151
    #   Account for 'suffix'. When suffix changes, then the 'max' version must
1152
    #   be recalculated
1153
    #
1154
 
1155
    Message ("Calculate Max Version");
1156
    my $maxVersion;
1157
    foreach my $entry ( @endPoints )
1158
    {
1159
        my $lastSuffix;
1160
        my $forceTip;
1161
        while ( $entry )
1162
        {
1163
            if (!defined($lastSuffix) || ($versions{$entry}{suffix} ne $lastSuffix) )
1164
            {
1165
                $maxVersion = '0';
1166
                $visitId++;
1167
                $forceTip = ( exists $tipVersions{$versions{$entry}{vname}} );
1451 dpurdie 1168
                $forceTip = 1 if $versions{$entry}{ukTrunk};
392 dpurdie 1169
                delete $tipVersions{$versions{$entry}{vname}};
1170
                $maxVersion = '999.999.999.999.zzz' if ( $forceTip );
1171
                $lastSuffix = $versions{$entry}{suffix};
1172
#print "---Tip Found\n" if $forceTip;
1173
            }
1174
 
1175
            # Detect circular dependencies
1176
            if ( ($versions{$entry}{visitId} || 0) == $visitId )
1177
            {
1178
                DebugDumpData ("Circular dependency: Versions", \%versions );
1179
                Warning ("Circular dependency");
1180
                last;
1181
            }
1182
            $versions{$entry}{visitId} = $visitId;
1183
 
1184
            my $thisVersion = $versions{$entry}{version} || '';
1185
            if ( $thisVersion gt $maxVersion )
1186
            {
1187
                $maxVersion = $thisVersion;
1188
            }
1189
 
1190
            if ( exists $versions{$entry}{maxVersion} )
1191
            {
1192
                if ( $versions{$entry}{maxVersion} gt $maxVersion )
1193
                {
1194
                    last;
1195
                }
1196
            }
1197
 
1198
            $versions{$entry}{maxVersion} = $maxVersion;
1199
            $entry = $versions{$entry}{last};
1200
        }
1201
    }
1202
 
1203
 
1204
    #
1205
    #   Locate all instances where a package-version branches
1206
    #   Determine the version that should be on the non-branching path
1207
    #
1208
    #   Reorder the 'next' list so that the first item is the non-branching
1209
    #   path. This will be used in the data-insertion phase to simplify the
1210
    #   processing.
1211
    #
1212
    Message ("Calculate package version branches");
1213
    foreach my $entry ( sort {$a <=> $b} keys(%versions) )
1214
    {
1215
        calculateWalkOrder($entry);
1216
    }
1217
 
1218
    #
1219
    #   Mark Project Branch Tips as they will be in the Repository
1220
    #   Find each project head and walk primary entry to the end.
1221
    #
1222
    foreach my $entry ( keys(%versions) )
1223
    {
1224
        #
1225
        #   Root of each tree is 'new'
1226
        #
1227
        unless ( defined $versions{$entry}{last})
1228
        {
1229
            unless ( $versions{$entry}{badSingleton} )
1230
            {
1231
                $versions{$entry}{newSuffix} = 1;
1232
            }
1233
        }
1234
 
1235
        #
1236
        #   Update stats
1237
        #
1238
        $badVcsCount++ if ( $versions{$entry}{badVcsTag} );
1239
        $ProjectCount++ if ( $versions{$entry}{newSuffix} );
1240
        next if ( $opt_flat );
1241
 
1242
        next unless ($versions{$entry}{newSuffix} );
1243
#print "--- Project new Suffix $versions{$entry}{vname}\n";
1244
 
1245
 
1246
        my $suffix = $versions{$entry}{suffix};
1247
        $knownProjects{$suffix}{count}++;
1248
 
1249
        my $next = $versions{$entry}{next}[0];
1250
        my $tip;
1251
        while ( $next )
1252
        {
1253
            last if ( $suffix ne $versions{$next}{suffix} );
1254
            $tip = $next unless (exists ($versions{$next}{DeadWood}) || $versions{$next}{badSingleton});
1255
            $next = $versions{$next}{next}[0];
1256
        }
1257
 
1258
        $versions{$tip}{Tip} = 1 if $tip;
1259
    }
1260
 
1261
    unless ( $opt_flat )
1262
    {
1263
        my $finalTrees = scalar @startPoints;
1264
        Warning ("Still have multiple trees: $finalTrees") unless ( $finalTrees == 1 );
1265
    }
1266
 
1267
    #
1268
    #   Display warnings about multiple
1269
    #
1270
    foreach ( sort keys %knownProjects )
1271
    {
1272
        my $count = $knownProjects{$_}{count} || 0;
1273
        Warning ("Multiple Project Roots: $_ ($count)" )
1274
            if ( $count > 1 );
1275
    }
1276
 
1277
    #
1278
    #   Display warnings about Bad Essential Packages
1279
    #
1280
    $allSvn = 1;
1281
    foreach my $entry ( keys(%versions) )
1282
    {
1283
        $rippleCount++ if ( exists($versions{$entry}{isaRipple}) && $versions{$entry}{isaRipple} );
1284
        $allSvn = 0 unless ( $versions{$entry}{isSvn} );
1285
        next unless ( exists $versions{$entry}{Essential}  );
1286
        next unless ( $versions{$entry}{badVcsTag}  );
1287
        push @badEssentials, $entry;
1288
        Warning ("BadVCS Essential: " . GetVname($entry))
1289
    }
1290
 
1291
    #
1292
    #   All done
1293
    #
1270 dpurdie 1294
    $processTotal = scalar keys %versions;
1295
    Message("Retained entries: $processTotal" );
392 dpurdie 1296
    Message("Pruned entries: $pruneCount");
1297
    Message("Deadwood entries: $trimCount");
1298
    Message("Bad Singletons: $badSingletonCount");
1299
    Message("Ripples: $rippleCount");
1272 dpurdie 1300
    Message("Recent entries: $recentCount");
392 dpurdie 1301
}
1302
 
1303
sub calculateWalkOrder
1304
{
1305
    my ($entry) = @_;
1306
    my @next = @{$versions{$entry}{next}};
1307
    my $count = @next;
1308
    my @ordered;
1309
    my $main;
1310
 
1311
    if ( $count > 1 )
1312
    {
1313
        # Array to hash to simplify removal
1314
        my %nexts = map { $_ => 1 } @next;
1315
        foreach my $e ( @next )
1316
        {
1317
 
1318
            #
1319
            #   Locate branch points that are not a part of a new project
1320
            #   These will not be preferred paths for walking
1321
            #
1322
            if ( !defined($versions{$e}{branchPoint}) && $versions{$entry}{suffix} ne $versions{$e}{suffix} )
1323
            {
1324
                unless ( exists $versions{$e}{DeadWood} || $versions{$e}{badSingleton}  )
1325
                {
1326
#print "--- Project Branch (1) $versions{$e}{vname}\n";
1327
                    $versions{$e}{branchPoint} = 1;
1328
                    $versions{$e}{newSuffix} = 1;
1329
                }
1330
            }
1331
 
1332
            #
1333
            #   Remove those that already have a branch,
1334
            #
1335
            if ( $versions{$e}{branchPoint} || $versions{$e}{newSuffix} || $versions{$e}{DeadWood}  )
1336
            {
1337
                push @ordered, $e;
1338
                delete $nexts{$e};
1339
            }
1340
        }
1341
        #
1342
        #   Select longest arm as the non-branching path
1343
        #   Note: Reverse sort order
1344
        #         Done so that 'newest' item is given preference
1345
        #         to the main trunk in cases where all subtrees are
1346
        #         the same length
1347
        #
1348
        my $maxData = '';
1349
        my $countEntry;
1350
        foreach my $e ( sort {$b <=> $a} keys %nexts )
1351
        {
1352
            if ( $versions{$e}{maxVersion} gt $maxData )
1353
            {
1354
                $maxData = $versions{$e}{maxVersion};
1355
                $countEntry = $e;
1356
            }
1357
        }
1358
        if ($countEntry)
1359
        {
1360
            $main = $countEntry;
1361
            delete $nexts{$countEntry};
1362
        }
1363
 
1364
        #
1365
        #   Append the remaining
1366
        #
1367
        push @ordered, keys %nexts;
1368
 
1369
        #
1370
        #   Re-order 'next' so that the main path is first
1371
        #   Sort (non main) by number
1372
        #
1373
        @ordered = sort {$a <=> $b} @ordered;
1374
        unshift @ordered, $main if ( $main );
1375
        @{$versions{$entry}{next}} = @ordered;
1376
 
1377
        #
1378
        #   Ensure all except the first are a branch point
1379
        #   First may still be a branch point
1380
        #
1381
        shift @ordered;
1382
        foreach my $e ( @ordered )
1383
        {
1384
            $versions{$e}{branchPoint} = 1;
1385
        }
1386
    }
1387
}
1388
 
1389
#-------------------------------------------------------------------------------
1390
# Function        : calcRippleGroups
1391
#
1392
# Description     : Locate and mark ripple groups
1272 dpurdie 1393
#                   packages that are ripples of each other
392 dpurdie 1394
#                       Keep first version of each ripple. Must keep first
1395
#                       Group ripples together so that they can be
1396
#                       proccessed at the same time
1397
#
1398
# Inputs          : 
1399
#
1400
# Returns         : 
1401
#
1402
sub calcRippleGroups
1403
{
1404
    my %rippleVersions;
1405
    foreach my $entry ( keys(%versions) )
1406
    {
1407
        my $ep = $versions{$entry};
1408
        if ( defined $ep->{buildVersion} )
1409
        {
1410
            my $suffix = $ep->{suffix};
1411
            my ($major, $minor, $patch, $build) = @{$ep->{buildVersion}};
1412
#print "--- $major, $minor, $patch, $build, $suffix\n";
1413
            $rippleVersions{$suffix}{"$major.$minor.$patch"}{count}++;
1414
            my $rp = $rippleVersions{$suffix}{"$major.$minor.$patch"};
1415
            $rp->{list}{$entry} = 1;
1416
 
1417
            next if ( $ep->{badVcsTag} );
1418
            next if ( $ep->{locked} eq 'N');
1419
            if (!defined ($rp->{min}) || $rp->{min} > $build )
1420
            {
1421
                $rp->{pvid} = $entry;
1422
                $rp->{min} = $build;
1423
            }
1424
        }
1425
    }
1426
#            DebugDumpData("rippleVersions", \%rippleVersions );
1427
 
1428
    while ( my($suffix, $e1) = each %rippleVersions )
1429
    {
1430
        while ( my( $mmp, $e2) = each %{$e1} )
1431
        {
1432
            next unless ( exists  $e2->{pvid} );
1433
            my $entry = $e2->{pvid};
1434
            if ( !exists $versions{$entry} )
1435
            {
1436
                Error ("Internal: Expected entry not found: $entry, $mmp");
1437
            }
1438
 
1439
            $versions{$entry}{keepLowestRipple} = 1;
1440
#print "--- Keep Riple $versions{$entry}{vname}\n";
1441
 
1442
            #
1443
            #   Update entry with list of associated ripples, removing lowest
1444
            #
1445
            delete $e2->{list}{$entry};
1446
            my @rippleList = sort keys %{$e2->{list}};
1447
            if ( @rippleList)
1448
            {
1449
#DebugDumpData("LIST: $entry", $e2->{list}, \@rippleList  );
1450
                @{$versions{$entry}{rippleList}} = @rippleList;
1451
            }
1452
        }
1453
    }
1454
}
1455
 
1456
#-------------------------------------------------------------------------------
1457
# Function        : processBranch
1458
#
1459
# Description     : Process one complete branch within the tree of versions
1460
#                   May be called recursivly to walk the tree
1461
#
1462
# Inputs          : Array of package-version ID to process
1463
#
1464
# Returns         : Nothing
1465
#
1466
 
1467
sub processBranch
1468
{
1469
    foreach my $entry ( @_ )
1470
    {
1471
        #
1472
        #   Do we need to create a branch before we can process this package
1473
        #
1474
        if ( $versions{$entry}{newSuffix} || $versions{$entry}{branchPoint} )
1475
        {
1476
            newProject();
1477
            $createBranch = 1;
1478
            $createSuffix = 1 if $versions{$entry}{newSuffix};
1479
        }
1480
 
1481
        newPackageVersion( $entry );
1482
no warnings "recursion";
1483
        processBranch (@{$versions{$entry}{next}});
1484
    }
1485
}
1486
 
1487
#-------------------------------------------------------------------------------
1488
# Function        : newPackageVersion
1489
#
1490
# Description     : Create a package version
1491
#
1492
# Inputs          : $entry              - Ref to entry being proccessed
1493
#
1494
# Returns         :
1495
#
1496
sub newPackageVersion
1497
{
1498
    my ($entry) = @_;
1499
    my %data;
1500
    my $flags = 'e';
1501
    my $rv = 1;
1502
    my $startTime = time();
1503
    my $timestamp = localtime;
1504
 
1505
    $data{rmRef} = 'ERROR';
1506
    $data{tag} = 'ERROR';
1507
 
1508
    #
1509
    #   If its been processed then fake that its been done
1510
    #   May have been a ripple that we processed
1511
    #
1270 dpurdie 1512
    return if ($versions{$entry}{Processed});
1513
    $processCount++;
392 dpurdie 1514
    Message ("------------------------------------------------------------------" );
1270 dpurdie 1515
    Message ("Package $processCount of $processTotal");
1516
 
392 dpurdie 1517
    Message ("New package-version: " . GetVname($entry) . " Tag: " . $versions{$entry}{vcsTag} );
1518
 
1328 dpurdie 1519
    #
1520
    #   Detect user abort
1521
    #
1522
    if ( -f $cwd . '/stopfile' )
1523
    {
1524
        $globalError = 1;
1525
        Message ("Stop file located");
1526
    }
392 dpurdie 1527
 
1528
    #
1529
    #   If we have a global error,then we pretend to process, but we
1530
    #   report errors for the logging system
1531
    #
1342 dpurdie 1532
    if ( $globalError )
392 dpurdie 1533
    {
1342 dpurdie 1534
        Message ("Global error prevents futher importation");
1535
    }
1536
    else
1537
    {
392 dpurdie 1538
        #
1539
        #   Call worker function
1540
        #   It will exist on any error so that it can be logged
1541
        #
1542
        $rv = newPackageVersionBody( \%data, @_ );
1543
        $globalError = 1 if ( $rv >= 10 );
1544
    }
1545
 
1546
    #
1547
    #   Highlight essential packages that failed to transfer
1548
    #
1549
    if ( $globalError ) {
1550
        $flags = 'e';
1551
    } elsif ( $rv && ( exists $versions{$entry}{Essential} ) ) {
1552
        $flags = 'X';
1553
    } elsif ( $rv ) {
1554
        $flags = 'E';
1555
    } else {
1556
        $flags = 'G';
1557
    }
1558
 
1559
    #
1560
    #   Always log results to a file
1561
    #   Flags:
1562
    #       e - Error: Global Fatal causes other versions to be ignored
1563
    #       X - Essential Package NOT proccessed
1564
    #       E - Error processing package
1565
    #       G - Good
1566
    #
1567
    my $duration = time() - $startTime;
1568
    my $line = join(';',
1569
            $flags,
1570
            $entry,
1571
            $packageNames,
1572
            $versions{$entry}{vname},
1573
            $data{rmRef},
1574
            $data{tag},
1575
            $timestamp,
1576
            $duration,
1577
            $data{errStr} || ''
1578
            );
1579
    logToFile( $cwd . '/importsummary.txt', ";$line;");
1580
    #
1581
    #   Sava data
1582
    #
1270 dpurdie 1583
    $data{errFlags} = $flags;
1584
    $data{duration} = $duration;
392 dpurdie 1585
    $versions{$entry}{rmRef} = $data{rmRef};
1270 dpurdie 1586
    delete $data{rmRef};
1587
    delete $data{tag};
1340 dpurdie 1588
    ##delete $data{ViewRoot};
1270 dpurdie 1589
    $versions{$entry}{data} = \%data;
1590
 
392 dpurdie 1591
    #
1592
    #   Delete the created view
1593
    #   Its just a directory, so delete it
1594
    #
1595
    if ( $data{ViewRoot} && -d $data{ViewRoot})
1596
    {
2354 dpurdie 1597
        if ( !$opt_reuse || ($rv && ($rv != 4 && $rv != 12 )) )
1340 dpurdie 1598
        {
1599
            Message ("Delete View: $data{ViewRoot}");
1600
            RmDirTree ($data{ViewRoot} );
1601
        }
1602
        else
1603
        {
1604
            Message ("Retaining View: $data{ViewRoot}");
1605
        }
1606
 
392 dpurdie 1607
    }
1340 dpurdie 1608
    else
1609
    {
1610
        Message ("No view to delete");
1611
    }
392 dpurdie 1612
 
1613
 
1614
    #
1615
    #   If this version has any 'ripples' then process them while we have the
1616
    #   main view. Note the ripple list may contain entries that do not
1617
    #   exist - they will have been pruned.
1618
    #
2354 dpurdie 1619
if(1) {
392 dpurdie 1620
    foreach my $rentry ( @{$versions{$entry}{rippleList}} )
1621
    {
1622
        next unless( exists $versions{$rentry} );
1623
 
1624
        if ($versions{$rentry}{Processed})
1625
        {
1626
            Warning ("Ripple Processed before main entry");
1627
            $versions{$rentry}{rippleProcessed} = 1;
1628
        }
1629
 
1630
        Message ("Proccessing associated Ripple: " . GetVname($rentry));
1631
        newPackageVersion($rentry);
1632
    }
1633
}
2029 dpurdie 1634
}
392 dpurdie 1635
 
1636
#-------------------------------------------------------------------------------
1637
# Function        : newPackageVersionBody
1638
#
1639
# Description     : Perform the bulk of the work in creating a new PackageVersion
1640
#                   Designed to return on error and have error processing
1641
#                   performed by caller
1642
#
1643
# Inputs          : $data               - Shared data
1644
#                   $entry              - Package entry to process
1645
#
1646
# Returns         : Error Code
1647
#                         0 - All is well
1272 dpurdie 1648
#                       <10 - Recoverable error
392 dpurdie 1649
#                       >10 - Fatal error
1650
#
1651
sub newPackageVersionBody
1652
{
1653
    my ($data, $entry) = @_;
1654
    my $rv;
1655
    my $cc_label;
1656
    my $cc_path;
2354 dpurdie 1657
    my $cc_path_original;
392 dpurdie 1658
 
1659
    #
1660
    #   Init Data
1661
    #
1662
    $data->{rmRef} = 'ERROR';
1663
    $data->{tag} = '';
1664
    $data->{ViewRoot} = undef;
1665
    $data->{ViewPath} = undef;
1666
    $data->{errStr} = '';
1667
    $versions{$entry}{Processed} = 1;
1668
 
1669
 
1670
    SystemConfig ('ExitOnError' => 0);
1671
 
1672
    push @processOrder, $entry;
1673
    return 0 if ( $opt_test );
1674
 
1675
#   Keep DeadWood. May be a WIP
1676
#    if ( exists $versions{$entry}{DeadWood} && $versions{$entry}{DeadWood} )
1677
#    {
1678
#        $data->{errStr} = 'Package is DeadWood';
1679
#        return 3;
1680
#    }
1681
 
1682
    #
1683
    #   Determine version information
1684
    #
1685
    $data->{tag} = $versions{$entry}{vcsTag} || '';
1686
    if ( $versions{$entry}{badVcsTag} )
1687
    {
1688
        Warning ("Error: Bad VcsTag for: " . GetVname($entry),
1689
                 "Tag: $data->{tag}" );
1690
        $data->{errStr} = 'VCS Tag Marked as Bad';
1691
        return 1;
1692
    }
1693
 
1694
 
1695
    $data->{tag} =~ m~^(.+?)::(.*?)(::(.+))?$~;
1696
    $cc_label = $4;
1697
    $cc_path = $2;
1698
    $cc_path = '/' . $cc_path;
1699
    $cc_path =~ tr~\\/~/~s;
2354 dpurdie 1700
    $cc_path_original = $cc_path;
392 dpurdie 1701
 
1702
    #
1703
    #   Correct well known path mistakes
1704
    #
2312 dpurdie 1705
    $cc_path =~ s~/build.pl$~~i;
1706
    $cc_path =~ s~/src$~~i;
2354 dpurdie 1707
    $cc_path =~ s~/cpp$~~i;
2071 dpurdie 1708
    $cc_path =~ s~/MASS_Dev/Infra/~/MASS_Dev_Infra/~i;
1709
    $cc_path =~ s~/MASS_Dev/Tools/~/MASS_Dev_Tools/~i;
394 dpurdie 1710
    $cc_path =~ s~/MASS_Dev/Bus/~/MASS_Dev_Bus/~i;
392 dpurdie 1711
    $cc_path =~ s~/MASS_Dev_Bus/Cbp/~/MASS_Dev_Bus/CBP/~i;
1712
    $cc_path =~ s~/MREF_Package/ergpostmongui$~/MREF_Package/ergpostmongui~i;
2354 dpurdie 1713
    $cc_path =~ s~/MREF_../MREF_Package/~/MREF_Package/~i;
1714
    $cc_path =~ s~/MREF_Package/mass_ergocdp/~/MREF_Package/ergocdp/~i;
1715
    $cc_path =~ s~/MASS_Dev_Bus/CBP/systemCD.ejb~/MASS_Dev_Bus/CBP/systemCD/ejb~i;
1716
    $cc_path =~ s~/MASS_Dev_Bus/Financial/cpp/paymentmanager~/MASS_Dev_Bus/Financial/cpp/paymentmanager~i;
1717
    $cc_path =~ s~/MASS_Dev_Bus/WebServices~/MASS_Dev_Bus/WebServices~i;
1718
    $cc_path =~ s~/MASS_Dev_Bus/CBP/nullAdapter~//MASS_Dev_Bus/CBP/nullAdaptor~i;
392 dpurdie 1719
 
2354 dpurdie 1720
    $cc_path = '/MASS_Dev_Bus' if ( $cc_path =~ m~/MASS_Dev_Bus/ImageCapture(/|$)~i );
1721
    $cc_path = '/MASS_Dev_Bus/CBP/enquiry' if ( $versions{$entry}{name} eq 'EJBEnqPxyConnector');
1722
    $cc_path = '/MASS_Dev_Bus/CBP/enquiry' if ( $versions{$entry}{name} eq 'proxyif4j');
1723
    $cc_path = '/MASS_Dev_Bus' if ( $versions{$entry}{name} eq 'ImageCaptureTomcatDeployment');
1724
    $cc_path = '/MASS_Dev_Bus/WebServices/MassWS' if ( $versions{$entry}{name} eq 'MassWebServicesImpl');
1197 dpurdie 1725
 
2354 dpurdie 1726
    if (   $versions{$entry}{name} =~ m/^ERGagency$/i
1727
        || $versions{$entry}{name} =~ m/^ERGavm$/i
1728
        || $versions{$entry}{name} =~ m/^ERGboi$/i
1729
        || $versions{$entry}{name} =~ m/^ERGcallcenter$/i
1730
        || $versions{$entry}{name} =~ m/^ERGcardholder$/i
1731
        || $versions{$entry}{name} =~ m/^ERGcdaimports$/i
1732
        || $versions{$entry}{name} =~ m/^ERGcda$/i
1733
        || $versions{$entry}{name} =~ m/^ERGcscedit$/i
1734
        || $versions{$entry}{name} =~ m/^ERGcs$/i
1735
        || $versions{$entry}{name} =~ m/^ERGofs$/i
1736
        || $versions{$entry}{name} =~ m/^ERGols$/i
1737
        || $versions{$entry}{name} =~ m/^ERGtpf$/i
1738
        || $versions{$entry}{name} =~ m/^ERGorasys$/i
1739
        || $versions{$entry}{name} =~ m/^ERGoracs$/i
1740
        || $versions{$entry}{name} =~ m/^ERGpxyif$/i
1741
        || $versions{$entry}{name} =~ m/^ERGtp5upg$/i
1742
        || $versions{$entry}{name} =~ m/^ERGinstitutional$/i
1743
        || $versions{$entry}{name} =~ m/^ERGinfra$/i
1744
        || $versions{$entry}{name} =~ m/^ERGcrrpts$/i
1745
        || $versions{$entry}{name} =~ m/^ERGmiddle$/i
1746
        || $versions{$entry}{name} =~ m/^ERGmiddleapi$/i
1747
        || $versions{$entry}{name} =~ m/^ERGwebapi$/i
1748
        || $versions{$entry}{name} =~ m/^ERGwebtestui$/i
1749
        || $versions{$entry}{name} =~ m/^ERGwebesbui$/i
1750
        || $versions{$entry}{name} =~ m/^ERGwspiv$/i
1751
        || $versions{$entry}{name} =~ m/^ERGwscst$/i
1752
        || $versions{$entry}{name} =~ m/^sposMUG$/i
1753
        || $versions{$entry}{name} =~ m/^ERGfinman$/i
1754
        || $versions{$entry}{name} =~ m/^ERGkm$/i
1755
        || $versions{$entry}{name} =~ m/^ERGxml$/i
1756
        || $versions{$entry}{name} =~ m/^ERGoradacw$/i
1757
        || $versions{$entry}{name} =~ m/^ERGtru$/i
1758
        )
1759
    {
1760
        $cc_path = '/MREF_Package';
1761
    }
1762
 
1763
    if (   $versions{$entry}{name} =~ m/^tp5000_MUG$/i )
1764
    {
1765
        if ( $versions{$entry}{version} =~ m~vtk$~ )
1766
        {
1767
            $cc_path = '/MREF_Package';
1768
        }
1769
    }
1770
 
1771
    if ( $cc_path_original ne $cc_path )
1772
    {
1773
            Message ("Package: $versions{$entry}{name}. Forcing CC path to: $cc_path" );
1774
    }
1775
 
392 dpurdie 1776
#print "--- Path: $cc_path, Label: $cc_label\n";
1777
 
1778
    #
1779
    #   Create CC view
1780
    #   Import into Subversion View
1781
    #
1782
    $data->{ViewRoot} = $opt_name ? $opt_name : "$cc_label";
1197 dpurdie 1783
    $data->{ViewPath} =  $data->{ViewRoot} . $cc_path;
1784
 
1785
    if ( $opt_preserveProjectBase )
1786
    {
1787
        my $cc_vob = $cc_path;
1788
        $cc_vob =~ s~^/~~;
1789
        $cc_vob =~ s~/.*~~;
1790
        $data->{ViewPath} =  $data->{ViewRoot} . '/' . $cc_vob;
1791
        Message ("Preserving Project Base");
1792
    }
392 dpurdie 1793
    $data->{ViewPath} =~  tr~/~/~s;
1794
 
1795
    if ( $opt_reuse && -d $data->{ViewPath}  )
1796
    {
1797
        Message ("Reusing view: $cc_label");
1798
    }
1799
    else
1800
    {
1801
        my @args;
1802
        push (@args, '-view', $opt_name ) if ( defined $opt_name );
1803
        $rv = JatsToolPrint ( 'jats_ccrelease', '-extractfiles', '-root=.' , '-noprefix',
1804
                    "-label=$cc_label" ,
1805
                    "-path=$cc_path",
1806
                    @args
1807
                    );
1808
 
2354 dpurdie 1809
        if ( $rv == 10 ) {
1810
            $data->{errStr} = 'No Files in the extracted view';
1811
            $data->{errCode} = '0';
1812
            return 2;
1813
        }
1814
        elsif ( $rv == 11 ) {
1815
            $data->{errStr} = 'Label not found';
1816
            $data->{errCode} = 'L';
1817
            return 2;
1818
        }
1819
 
392 dpurdie 1820
        unless ( -d $data->{ViewPath}  )
1821
        {
1822
            $data->{errStr} = 'Failed to extract files from CC';
1823
            return 2;
1824
        }
1825
    }
1826
 
1197 dpurdie 1827
 
392 dpurdie 1828
    #
1197 dpurdie 1829
    #   Some really ugly packages make use of a Jats feature called 'SetProjectBase'
1830
    #   Detect such packages as we will need to handle them differently
1831
    #   Can't really handle it on the fly
1453 dpurdie 1832
    #   All we can do is detect it and report it - at the moment
1197 dpurdie 1833
    #
1834
    if (detectProjectBaseUsage($data, $cc_path) )
1835
    {
1836
        unless ( $opt_ignoreProjectBaseErrors )
1837
        {
1838
            $data->{BadProjectBase}++;
1839
            $data->{errStr} = 'Bad usage of ProjectBase detected';
2319 dpurdie 1840
            return 4;           # Lets see what the others look like too
1841
#            return 14;
1197 dpurdie 1842
        }
1843
    }
1844
 
1270 dpurdie 1845
 
1197 dpurdie 1846
    #
1270 dpurdie 1847
    #   Developers have been slack
1848
    #       Sometime the mark the source path as 'GMTPE2005'
1849
    #       Sometimes as 'GMTPE2005/Package/Fred/Jill/Harry'
1850
    #
1851
    #   Attempt to suck up empty directories below the specified
1852
    #   source path
1853
    #
1854
    unless ( $opt_preserveProjectBase )
1855
    {
1856
        #
1857
        #   Look in ViewPath
1858
        #   If it contains only ONE directory then we can suck it up
1859
        #
1860
        my $testDir = findDirWithStuff( $data->{ViewPath} );
1328 dpurdie 1861
 
1270 dpurdie 1862
        unless ( $data->{ViewPath} eq $testDir  )
1863
        {
1864
            Message ("Adjust Base Dir: $testDir");
1865
            $data->{adjustedPath} = $data->{ViewPath};
1866
            $data->{ViewPath} = $testDir;
1867
        }
1868
    }
1869
 
1870
 
1871
    #
392 dpurdie 1872
    #   Have a CC view
1873
    #   Now we can create the SVN package and branching point before we
1874
    #   import the CC data into SVN
1875
    #
1876
    my @args;
1877
 
1878
    #
1879
    #   Calculate args for functions
1880
    #
1881
    my $author = $versions{$entry}{created_id};
1882
    if ( $author )
1883
    {
1884
        push @args, '-author', $author;
1885
    }
1886
    my $created = $versions{$entry}{created};
1887
    if ( $created )
1888
    {
1889
        $created =~ s~ ~T~;
1890
        $created .= '00000Z';
1891
        push @args, '-date', $created;
1892
    }
1893
 
1894
    my $log = $versions{$entry}{comment};
1895
    if ( $log )
1896
    {
1897
        push @args, '-log', $log;
1898
    }
1899
 
1900
    #
1901
    #   Create package skeleton if needed
1902
    #
1903
    $rv = createPackage( $author, $created);
1904
    if ( $rv )
1905
    {
1906
        $data->{errStr} = 'Failed to create Package';
1907
        return 10;
1908
    }
1909
 
1910
    #
1911
    #   Calculate the label for the target package
1912
    #   Use format <packageName>_<PackageVersion>
1913
    #   Need to handle WIPs too.
1914
    #
1915
    my $import_label = saneLabel($entry);
1916
 
1917
    #
1918
    #   May need to create the branchpoint
1919
    #   The process is delayed until its needed so avoid creating unneeded
1920
    #   branch points
1921
    #
1922
    if ( $createBranch )
1923
    {
1924
        $rv = createBranchPoint ($entry, $author, $created);
1925
        $createBranch = 0;
1926
        $createSuffix = 0;
1927
        if ( $rv )
1928
        {
1929
            $data->{errStr} = 'Failed to create Branch Point';
1930
            return 11;
1931
        }
1932
    }
1933
    push @args, "-branch=$currentBranchName" if ( defined $currentBranchName );
1934
 
1935
    my $datafile = "importdata.$import_label.properties";
1936
    $rv = JatsToolPrint ( 'jats_svn', 'import', '-reuse' ,
1937
                    "-package=$svnRepo/$packageNames",
1938
                    "-dir=$data->{ViewPath}",
1939
                    "-label=$import_label",
1940
                    "-datafile=$datafile",
1941
                    @args,
1942
                     );
1943
 
1944
    if ( $rv )
1945
    {
1946
        $data->{errStr} = 'Failed to import to SVN';
1947
        return 12;
1948
    }
1949
 
1950
    $versions{$entry}{TagCreated} = 1;
1951
    $firstVersionCreated = $entry unless ( $firstVersionCreated );
1952
 
1953
    #
1954
    #   Read in the Rm Reference
1955
    #   Retain entries in a global file
1956
    #
1957
    if ( -f $datafile  )
1958
    {
1959
        my $rmData = JatsProperties::New($datafile);
1960
        $data->{rmRef} = 'SVN::' . $rmData->getProperty('subversion.tag');
1961
    }
1962
 
1963
    unless ( $data->{rmRef}  )
1964
    {
1272 dpurdie 1965
        $data->{errStr} = 'Failed to determine Rm Reference';
392 dpurdie 1966
        return 13;
1967
    }
1968
 
1380 dpurdie 1969
######################## Deleted ###############################################
1970
#
1971
#
1972
#    #
1973
#    #   Add supplemental tags if this version is in a 'Release'
1974
#    #   But only for some packages - else looks like a mess
1975
#    #   Just a solution for the ITSO guys
1976
#    #
1977
#    foreach my $rtag_id ( keys %{$versions{$entry}{Releases}}  )
1978
#    {
1979
#        next unless ( $svnRepo =~ m~/ITSO_TRACS(/|$)~);
1980
#
1981
#        my $prog_id = $versions{$entry}{Releases}{$rtag_id}{proj_id};
1982
#        Message ("Adding Release Tag:$prog_id:$rtag_id");
1983
#
1984
#        my $rtext = 'Release_' . saneString($versions{$entry}{Releases}{$rtag_id}{rname});
1985
#        my @comment;
1986
#        push @comment, "Tagged by ClearCase to Subversion import";
1987
#        push @comment, "Project:$prog_id:$versions{$entry}{Releases}{$rtag_id}{pname}";
1988
#        push @comment, "Release:$rtag_id:$versions{$entry}{Releases}{$rtag_id}{rname}";
1989
#
1990
#        $data->{ReleaseTag}{$prog_id}{$rtag_id}{name} = $rtext;
1991
#
1992
#        $rv = JatsToolPrint ( 'jats_svnlabel' ,
1993
#                    '-comment', encode('UTF-8', join("\n", @comment), Encode::FB_DEFAULT),
1994
#                    $data->{rmRef},
1995
#                    '-clone',
1996
#                    $rtext,
1997
##                    @args,
1998
#                    '-author=buildadm',
1999
#                     );
2000
#        $data->{ReleaseTag}{$prog_id}{$rtag_id}{eState} = $rv;
2001
#        $data->{ReleaseTag}{tCount}++;
2002
#
2003
#        if ( $rv )
2004
#        {
2005
#            $data->{ReleaseTag}{eCount}++;
2006
#            Warning("Failed to add Release Tag: $rtext");
2007
#        }
2008
#    }
2009
#
2010
######################## Deleted ###############################################
1341 dpurdie 2011
 
392 dpurdie 2012
    Message ("RM Ref: $data->{rmRef}");
2013
    unlink $datafile;
2014
 
2015
    #
2016
    #   All is good
2017
    #
2018
    $data->{errStr} = '';
2019
    return 0;
2020
}
2021
 
2022
 
2023
#-------------------------------------------------------------------------------
2024
# Function        : newProject
2025
#
2026
# Description     : Start a new project within a package
2027
#
2028
# Inputs          : 
2029
#
2030
# Returns         : 
2031
#
2032
sub newProject
2033
{
2034
#    Message ("---- New Project");
2035
    $createSuffix = 0;
2036
 
2037
    #
2038
    #   New project
2039
    #   Kill the running import directory
2040
    #
2041
    RmDirTree ('SvnImportDir');
2042
}
2043
 
2044
#-------------------------------------------------------------------------------
2045
# Function        : newPackage
2046
#
2047
# Description     : Start processing a new package
2048
#
2049
# Inputs          : 
2050
#
2051
# Returns         : 
2052
#
2053
my $createPackageDone;
2054
sub newPackage
2055
{
2056
#    Message( "---- New Package");
2057
 
2058
    #
2059
    #   Create a package specific log file
2060
    #
2061
    $logSummary = $packageNames . ".summary.log";
2062
    unlink $logSummary;
2063
    Message( "PackageName: $packageNames");
2064
    $createPackageDone = 1;
2065
    $createBranch = 0;
2066
    $createSuffix = 0;
2067
 
2068
    #
2069
    #   First entry being created
2070
    #   Prime the work area
2071
    #
2072
    RmDirTree ('SvnImportDir');
2073
}
2074
 
2075
#-------------------------------------------------------------------------------
2076
# Function        : createPackage
2077
#
2078
# Description     : Create a new Package in SVN
2079
#                   Called before any serious SVN operation to ensure that the
2080
#                   package has been created. Don't create a package until
2081
#                   we expect to put something into it.
2082
#
2083
#                   Will only create a package once
2084
 
2085
#
2086
# Inputs          : $author         - Who done it
2087
#                   $date           - When
2088
#
2089
# Returns         : 
2090
#
2091
sub createPackage
2092
{
2093
    my ($author, $date) = @_;
2094
    my @opts;
2095
    push (@opts, '-date', $date) if ( $date );
2096
    push (@opts, '-author', $author) if ( $author );
2097
    #
2098
    #   Only do once
2099
    #
2100
    return unless ( $createPackageDone );
2101
    $createPackageDone = 0;
2102
 
1197 dpurdie 2103
    #
2104
    #   Real import
2105
    #       Do not Delete package if it exists
2106
    #       Package must NOT exist
2107
    #
392 dpurdie 2108
    Message ("Creating new SVN package: $packageNames");
1270 dpurdie 2109
    if ( $opt_delete )
2110
    {
2111
        Message ("Delete existing version of package: $packageNames");
2112
        JatsToolPrint ( 'jats_svn', 'delete-package', '-noerror',  "$svnRepo/$packageNames" );
2113
    }
1197 dpurdie 2114
    JatsToolPrint ( 'jats_svn', 'create', "$svnRepo/$packageNames", '-new', @opts );
392 dpurdie 2115
}
2116
 
2117
 
2118
#-------------------------------------------------------------------------------
2119
# Function        : createBranchPoint
2120
#
2121
# Description     : Create a branch point for the current work
2122
#                   Perform the calculation to determine the details of
2123
#                   the branch point. The work will only be done when its
2124
#                   needed. This will avoid the creation of branchpoints
2125
#                   that are not used.
2126
#
2127
# Inputs          : $entry                  Entry being processed
2128
#                   $author         - Who done it
2129
#                   $date           - When
2130
#
2131
# Returns         : 
2132
#
2133
sub createBranchPoint
2134
{
2135
    my ($entry, $author, $date) = @_;
2136
    my $forceNewProject;
2137
 
2138
#    Message ("---- Create Branch Point");
2139
 
2140
    #
2141
    #   Find previous good tag
2142
    #   We are walking a tree so something should have been created, but
2143
    #   the one we want may have had an error
2144
    #
2145
    #   Walk backwards looking for one that has been created
2146
    #
2147
    my $last = $versions{$entry}{last};
2148
    while ( $last )
2149
    {
2150
        unless ( $versions{$last}{TagCreated} )
2151
        {
2152
            $last = $versions{$last}{last};
2153
        }
2154
        else
2155
        {
2156
            last;
2157
        }
2158
    }
2159
 
2160
    #
2161
    #   If we have walked back to the base of the tree
2162
    #   If we transferred any software at all, then use the first
2163
    #   version as the base for this disconnected version
2164
    #
2165
    #   Otherwise we create a new, and empty, view
2166
    #
2167
    unless ( $last )
2168
    {
2169
        if ( $firstVersionCreated )
2170
        {
2171
            Warning ("Cannot find previous version to branch. Use first version");
2172
            $last = $firstVersionCreated;
2173
        }
2174
        else
2175
        {
2176
            Warning ("Forcing First instance of a Project");
2177
            $forceNewProject = 1;
2178
        }
2179
    }
2180
 
2181
    #
2182
    #   Determine source name
2183
    #   This MUST have been created before we can branch
2184
    #
2185
    my $src_label;
2186
    $src_label = saneLabel($last) if $last;
2187
 
2188
    #
2189
    #   Create target name
2190
    #
2191
    my $tgt_label;
2192
    if ( $forceNewProject || $versions{$entry}{newSuffix} || $createSuffix || !defined $src_label )
2193
    {
2194
        #
2195
        #   Create target name based on project
2196
        #
2197
        return if ( $singleProject );
2198
 
2199
        my $suffix = $versions{$entry}{suffix};
2200
        if ( $suffix )
2201
        {
2202
            Error ("Unknown Project: $suffix") unless ( defined $Projects{$suffix} );
2203
 
2204
            #
2205
            #   If this project can be considered to be a truck, then 'claim' the
2206
            #   truck for the first created element.
2207
            #
2208
            if ( $Projects{$suffix}{Trunk} )
2209
            {
2210
                # This project can use the trunk, if it has not been allocated.
2211
                $ProjectTrunk = $suffix unless ( defined $ProjectTrunk );
2212
 
2213
                #
2214
                #   If this package has multiple instances of the potential
2215
                #   trunk, then don't place either of them on the trunk as it
2216
                #   may cause confusion
2217
                #
2218
                if ($knownProjects{$suffix}{count} < 2 )
2219
                {
2220
                    if ( $suffix eq $ProjectTrunk )
2221
                    {
2222
                        return unless $currentBranchName;
2223
                    }
2224
                }
2225
            }
2226
 
2227
            $tgt_label = $Projects{$suffix}{Name};
2228
            $tgt_label = $versions{$entry}{name} . '_' . $tgt_label if ($multiPackages);
2229
            if ( !exists $ProjectsBaseCreated{$tgt_label}  )
2230
            {
2231
                $ProjectsBaseCreated{$tgt_label} = 1;
2232
            }
2233
            else
2234
            {
2235
                #   Project Base Already taken
2236
                #   Have disjoint starting points
2237
                $tgt_label .= '.' . $ProjectsBaseCreated{$tgt_label} ++;
2238
            }
2239
        }
2240
        else
2241
        {
2242
            #
2243
            #   No suffix in use
2244
            #
2245
            #   Currently not handled
2246
            #   May have to force the use of the trunk
2247
            #
2248
            Error ("INTERNAL ERROR: No suffix present");
2249
        }
2250
    }
2251
    else
2252
    {
2253
        $tgt_label = saneLabel($entry, $src_label . '_for_');
2254
    }
2255
 
2256
    #
2257
    #   Save branch name for use when populating sandbox
2258
    #
2259
    $currentBranchName = $tgt_label;
2260
 
2261
    #
2262
    #   Perform the branch
2263
    #
2264
    if ( defined $src_label )
2265
    {
1328 dpurdie 2266
        #
1341 dpurdie 2267
        #   The 'clone' operation will backtrack the branch point
2268
        #   to the source of the label. This will make the output version
2269
        #   tree much prettier
1328 dpurdie 2270
        #
392 dpurdie 2271
        my @opts;
2272
        push (@opts, '-date', $date) if ( $date );
2273
        push (@opts, '-author', $author) if ( $author );
2274
 
2275
        JatsToolPrint ( 'jats_svnlabel',
2276
                        '-packagebase', "$svnRepo/$packageNames",
1341 dpurdie 2277
                        'tags/' . $src_label,
392 dpurdie 2278
                        '-branch',
2279
                        '-clone', $tgt_label,
2280
                        @opts
2281
                      );
2282
    }
2283
}
2284
 
2285
 
2286
#-------------------------------------------------------------------------------
2287
# Function        : endPackage
2288
#
2289
# Description     : End of package processing
2290
#                   Clean up and display problems
2291
#
2292
# Inputs          : 
2293
#
2294
# Returns         : 
2295
#
2296
sub endPackage
2297
{
2354 dpurdie 2298
    Message ("-- Import Summary ------------------------------------------------" );
392 dpurdie 2299
    RmDirTree ('SvnImportDir');
2300
 
2301
    #
2302
    #   Display versions that did get captured
2303
    #
2304
    foreach my $entry ( @processOrder )
2305
    {
2306
        $versions{$entry}{Scanned} = 1;
2307
        next unless ( $versions{$entry}{TagCreated} );
2308
        Warning ("Processed: " . GetVname($entry) . ' :: ' . $versions{$entry}{rmRef} || $versions{$entry}{errStr} || '???' );
2309
    }
2310
 
2311
    #
2312
    #   Display versions that did not get created
2313
    #
2314
    foreach my $entry ( @processOrder )
2315
    {
2316
        $versions{$entry}{Scanned} = 1;
2317
        next if ( $versions{$entry}{TagCreated} );
2354 dpurdie 2318
        my $reason = $versions{$entry}{data}{errStr} || '';
2319
        my $tag = $versions{$entry}{vcsTag}|| 'No Tag';
2320
        Warning ("Not Processed: " . GetVname($entry) . ':' . $tag . ' : ' . $reason );
392 dpurdie 2321
    }
2322
 
2323
    foreach my $entry ( keys(%versions) )
2324
    {
2325
        next if ( $versions{$entry}{Scanned} );
2326
        Warning ("(E) INTERNAL ERROR. Package Not Processed: " . GetVname($entry) );
2327
    }
2328
 
2329
    Message ("All Done");
2330
}
2331
 
1197 dpurdie 2332
#-------------------------------------------------------------------------------
2333
# Function        : detectProjectBaseUsage
2334
#
2335
# Description     : Detect and report usage of the SetProjectBase directive
2336
#
2337
# Inputs          : $data               - Ref to a hash of bits
2338
#                   $cc_path            - Packages cc_path
2339
#
2340
# Returns         : true    - Bad usage (Really good usage not detected)
2341
#                   false   - Good usage detected
2342
#
2343
sub detectProjectBaseUsage
2344
{
2345
    my ($data, $cc_path) = @_;
2346
    my $retval = 0;
2347
    my $eSuf = $opt_ignoreProjectBaseErrors ? '' : 'Error';
2348
 
2349
    #
2350
    #   Find makefile.pl
2351
    #
2352
    Message ("Locate JATS makefiles");
2353
    my $usesProjectBase = 0;
2354
    my $definesProjectBase = 0;
2355
    my $definitionError = 0;
2356
 
2357
    my $search = JatsLocateFiles->new("--Recurse=1",
2358
                                       "--FilterIn=makefile.pl",
2359
                                       );
2360
    my @makefiles = $search->search($data->{ViewRoot});
2361
    foreach my $file ( @makefiles )
2362
    {
2363
        if ( open( my $fh, '<', "$data->{ViewRoot}/$file" ) )
2364
        {
2365
            while ( <$fh> )
2366
            {
2367
                s~\s+$~~;
2368
                s~^\s+~~;
2369
                next if ( m~^#~ );
2370
 
2371
                if ( m~\$ProjectBase~ )
2372
                {
2373
                    $usesProjectBase++;
2374
                    Message ("Project Base Use: $_");
2375
                    $data->{UsesProjectBase}++;
2376
                }
2377
 
2378
                if ( m~^SetProjectBase~ )
2379
                {
2380
                    $definesProjectBase++;
2381
                    $data->{DefinesProjectBase}++;
2312 dpurdie 2382
                    Warning ("Package initialises SetProjectBase:",
1197 dpurdie 2383
                             "Line: " . $_,
2384
                             "Root: " . "$data->{ViewRoot}",
2385
                             "File: " . "$data->{ViewRoot}/$file",
2386
                            );
2387
 
2388
                    # The only problem is if the user attempts to escape
2389
                    # from the root of the view.
2390
                    #
2391
                    # Examine the depth of the makefile with the directive
2392
                    # Examine the depth of the view base
2393
                    #
2394
                    #
2395
                    # Locate the build.pl file
2396
                    # This is the basis for for the directive
2397
                    #
2398
                    my $blevel;
2399
                    my @bpaths = split ('/', $file );
2400
                    while ( @bpaths )
2401
                    {
2402
                        $bpaths[-1] = 'build.pl';
2403
                        my $bfile = join '/', @bpaths ;
2404
                        if ( -f "$data->{ViewRoot}/$bfile" )
2405
                        {
2406
                            $blevel = scalar @bpaths;
2407
                            last;
2408
                        }
2409
                        pop @bpaths;
2410
                    }
2411
                    unless (defined $blevel)
2412
                    {
2413
                        Warning ("SetProjectBase$eSuf calculation failed - can't find build.pl");
2312 dpurdie 2414
#                        $retval = 1;
2415
                         $definitionError++;
1197 dpurdie 2416
                    }
2417
                    else
2418
                    {
2419
                        #
2420
                        #   Determine the depth of the view root
2421
                        #   This is given by cc_path, but cc_path has a leading /
2422
                        #
2423
                        my @cpaths = split ('/', $cc_path );
2424
                        my $clevel = (scalar @cpaths) - 1;
2425
                        my $max_up = $blevel - $clevel - 1;
2426
 
2427
                        m~--Up=(\d+)~i;
2428
                        my $ulevel = $1;
2429
                        if ( defined $ulevel )
2430
                        {
2431
                            my @paths = split ('/', $file );
2432
                            my $plevel = scalar @paths;
2433
 
2434
#print "--- blevel: $blevel\n";
2435
#print "--- bpaths: @bpaths\n";
2436
#print "--- ulevel: $ulevel\n";
2437
#print "--- paths: @paths\n";
2438
#print "--- plevel: $plevel\n";
2439
#print "--- cpaths: @cpaths\n";
2440
#print "--- clevel: $clevel\n";
2441
#print "--- max_up: $max_up\n";
2442
 
2443
                            if ( $ulevel > $max_up )
2444
                            {
2445
                                Warning ("SetProjectBase escapes view. MaxUp: $max_up, Up: $ulevel");
2446
                                $definitionError++;
2447
                            }
2448
                        }
2449
                        else
2450
                        {
2451
                            $retval = 1;
2452
                            Warning ("SetProjectBase$eSuf MAY escape view - can't detect level")
2453
                        }
2454
                    }
2455
                }
2456
            }
2457
            close $fh;
2458
        }
2459
        else
2460
        {
2461
            Warning ("SetProjectBase$eSuf - Cannot open makefile: $file");
2462
            $retval = 1;
2463
        }
2464
    }
2465
 
2466
    #
2467
    #   Detect defined, but not used
2468
    #
2469
    if ( $usesProjectBase && ! $definesProjectBase )
2470
    {
2471
        Warning ("SetProjectBase - Uses ProjectBase without defining it");
2472
    }
2473
 
2474
    if ( ! $usesProjectBase && $definesProjectBase )
2475
    {
2476
        Warning ("SetProjectBase - Defines ProjectBase without using it");
2477
    }
2478
 
2479
    if ( $usesProjectBase && $definesProjectBase && $definitionError )
2480
    {
2481
        Warning ("SetProjectBase$eSuf - Problem detected");
2482
        $retval = 1;
2483
    }
2484
    return $retval;
2485
}
2486
 
1270 dpurdie 2487
#-------------------------------------------------------------------------------
2488
# Function        : findDirWithStuff
2489
#
2490
# Description     : Find a directory that contains more than just another subdir
2354 dpurdie 2491
#                   Note: don't use 'glob' it doesn't work if the name has a space in it.
1270 dpurdie 2492
#
2493
# Inputs          : $base               - Start of the scan
2494
#
2495
# Returns         : Path to dir with more than just a single dir in it
2496
#
2497
sub findDirWithStuff
2498
{
2499
    my ($base) = @_;
1197 dpurdie 2500
 
1270 dpurdie 2501
    while ( $base )
2502
    {
2503
    my $fileCount = 0;
2504
    my $dirCount = 0;
1272 dpurdie 2505
    my $firstDir;
1270 dpurdie 2506
 
2354 dpurdie 2507
    opendir (my $dh, $base ) || Error ("Cannot opendir $base. $!");
2508
    my @list =readdir $dh;
2509
    closedir $dh;
1270 dpurdie 2510
    foreach ( @list )
2511
    {
2512
        next if ( $_ eq '.' );
2513
        next if ( $_ eq '..' );
2354 dpurdie 2514
 
2515
        $_ = $base . '/' . $_;
1270 dpurdie 2516
        if ( -d $_ )
2517
        {
2518
            $dirCount++;
1272 dpurdie 2519
            $firstDir = $_ unless ( defined $firstDir );
2354 dpurdie 2520
            return $base
2521
                if ( $dirCount > 1  )
1270 dpurdie 2522
        }
1272 dpurdie 2523
        elsif ( -e $_ )
1270 dpurdie 2524
        {
2525
            return $base;
2526
        }
1272 dpurdie 2527
 
2528
        # else its probably a dead symlink
1270 dpurdie 2529
    }
2354 dpurdie 2530
 
2531
    return $base
2532
        unless ( $dirCount == 1  );
1272 dpurdie 2533
    $base = $firstDir;
1270 dpurdie 2534
    }
2535
}
2536
 
1197 dpurdie 2537
#-------------------------------------------------------------------------------
2538
# Function        : JatsToolPrint
2539
#
2540
# Description     : Print and Execuate a JatsTool command
2541
#
2542
# Inputs          : 
2543
#
2544
# Returns         : 
2545
#
2546
 
392 dpurdie 2547
sub JatsToolPrint
2548
{
2549
    Information ("Command: @_");
2550
    JatsTool @_;
2551
}
2552
 
2553
sub GetVname
2554
{
2555
    my ($entry) = @_;
2556
    my $me = 'NONE';
2557
    if ( $entry )
2558
        {
2559
        $me = $versions{$entry}{vname};
2560
        unless ( $me )
2561
        {
2562
            $me = 'Unknown-' . $entry;
2563
        }
2564
    }
2565
    return $me;
2566
}
2567
 
2568
sub saneLabel
2569
{
2570
    my ($entry, $pkgname) = @_;
1272 dpurdie 2571
    my $me;
2572
    $me = $versions{$entry}{vname};
392 dpurdie 2573
    $pkgname = $versions{$entry}{name} unless ( defined $pkgname );
2574
 
2575
    Error ("Package does have a version string: pvid: $entry")
2576
        unless ( defined $me );
2577
 
2578
    #
2579
    #   Convert Wip format (xxxx) into a string that can be used for a label
2580
    #
2581
    if ( $me =~ m~^(.*)\((.*)\)(.*)$~ )
2582
    {
2583
        $me = $1 . '_' . $2 . '_' . $3 . '.WIP';
2584
        $me =~ s~_\.~.~;
2585
        $me =~ s~^_~~;
2586
    }
2587
 
2588
    #
2589
    #   Allow for WIPS
2590
    #   Get rid of multiple '_'
2591
    #   Replace space with -
2592
    #
2593
    $me = $pkgname . '_' . $me;
2594
    $me =~ tr~ ~-~s;
2595
    $me =~ tr~-~-~s;
2596
    $me =~ tr~_~_~s;
2597
 
2598
    return $me;
2599
}
2600
 
1341 dpurdie 2601
sub saneString
2602
{
2603
    my ($string) = @_;
2604
    #
2605
    #   Get rid of multiple '_'
2606
    #   Replace space with -
2607
    #
2608
    $string =~ s~\W~_~g;
2609
    $string =~ tr~ ~_~s;
2610
    $string =~ tr~_-~-~s;
2611
    $string =~ tr~-_~-~s;
2612
    $string =~ tr~-~-~s;
2613
    $string =~ tr~_~_~s;
2614
    $string =~ s~-$~~;
2615
    $string =~ s~_$~~;
392 dpurdie 2616
 
1341 dpurdie 2617
    return $string;
2618
}
2619
 
2620
 
392 dpurdie 2621
exit 0;
2622
 
2623
 
2624
#-------------------------------------------------------------------------------
2625
# Function        : GetPkgIdByName
2626
#
2627
# Description     :
2628
#
2629
# Inputs          : pkg_name
2630
#
2631
# Returns         : pkg_id
2632
#
2633
sub GetPkgIdByName
2634
{
2635
    my ( $pkg_name ) = @_;
2636
    my (@row);
2637
    my $pv_id;
2638
    my $pkg_id;
2639
 
2640
    #
2641
    #   Establish a connection to Release Manager
2642
    #
2643
    connectRM(\$RM_DB) unless ( $RM_DB );
2644
 
2645
    #
2646
    #   Extract data from Release Manager
2647
    #
2648
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pkg.PKG_ID" .
2649
                   " FROM RELEASE_MANAGER.PACKAGES pkg" .
2650
                   " WHERE pkg.PKG_NAME = \'$pkg_name\'";
2651
 
2652
    my $sth = $RM_DB->prepare($m_sqlstr);
2653
    if ( defined($sth) )
2654
    {
2655
        if ( $sth->execute( ) )
2656
        {
2657
            if ( $sth->rows )
2658
            {
2659
                while ( @row = $sth->fetchrow_array )
2660
                {
2661
                    Verbose( "DATA: " . join(',', @row) );
2662
                    $pkg_id = $row[1] || 0;
2663
                    last;
2664
                }
2665
            }
2666
            else
2667
            {
2668
                Error ("GetPkgIdByName:No Data for package: $pkg_name");
2669
            }
2670
            $sth->finish();
2671
        }
2672
    }
2673
    else
2674
    {
2675
        Error("GetPkgIdByName:Prepare failure" );
2676
    }
2677
 
2678
    return $pkg_id;
2679
}
2680
 
2681
#-------------------------------------------------------------------------------
2682
# Function        : GetData_by_pkg_id
2683
#
2684
# Description     :
2685
#
2686
# Inputs          : pv_id
2687
#
2688
# Returns         :
2689
#
2690
sub GetData_by_pkg_id
2691
{
2692
    my ( $pkg_id, $packageName ) = @_;
2693
    my (@row);
2694
 
2695
    #
2696
    #   Establish a connection to Release Manager
2697
    #
2698
    Message ("Extract package versions from Release Manager: $packageName");
2699
    connectRM(\$RM_DB) unless ( $RM_DB );
2700
 
2701
    #
2702
    #   Extract data from Release Manager
2703
    #
2704
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pv.PKG_VERSION, pkg.PKG_ID, pv.PV_ID, pv.LAST_PV_ID, pv.MODIFIED_STAMP, release_manager.PK_RMAPI.return_vcs_tag(pv.PV_ID), amu.USER_NAME, pv.COMMENTS, pv.DLOCKED, pv.CREATOR_ID ".
2705
                   " FROM RELEASE_MANAGER.PACKAGES pkg, RELEASE_MANAGER.PACKAGE_VERSIONS pv, ACCESS_MANAGER.USERS amu" .
2706
                   " WHERE pv.PKG_ID = \'$pkg_id\' AND pkg.PKG_ID = pv.PKG_ID AND amu.USER_ID (+) = pv.CREATOR_ID";
2707
 
2708
 
2709
    my $sth = $RM_DB->prepare($m_sqlstr);
2710
    if ( defined($sth) )
2711
    {
2712
        if ( $sth->execute( ) )
2713
        {
2714
            if ( $sth->rows )
2715
            {
2716
                while ( @row = $sth->fetchrow_array )
2717
                {
2718
                    Verbose( "DATA: " . join(',', @row) );
2719
                    my $pkg_name = $row[0] || 'Unknown';
2720
                    my $pkg_ver = $row[1] || 'Unknown';
2721
                       $pkg_ver =~ s~\s+$~~;
2722
                       $pkg_ver =~ s~^\s+~~;
2723
                    my $pv_id = $row[3] || 'Unknown';
2724
                    my $last_pv_id = $row[4];
2725
                    my $created =  $row[5] || 'Unknown';
2726
                    my $vcstag =  $row[6] || 'Unknown';
395 dpurdie 2727
 
392 dpurdie 2728
                    my $created_id =  $row[7] || ($row[10] ? "Userid_$row[10]" :'Unknown');
2729
                    my $comment =  $row[8] || '';
2730
                    my $locked =  $row[9] || 'N';
2731
 
2732
                    #
2733
                    #   Some developers have a 'special' package version
2734
                    #   We really need to ignore them
2735
                    #
2736
                    next if ( $pkg_ver eq '23.23.23.ssw' );
2737
 
2738
                    #
2739
                    #   Add data to the hash
2740
                    #       Remove entries that address themselves
2741
                    #
2742
                    push (@{$versions{$last_pv_id}{next}}, $pv_id) unless ($pv_id == $last_pv_id || $last_pv_id == 0) ;
2743
                    $versions{$pv_id}{name} = $pkg_name;
2744
                    $versions{$pv_id}{pvid} = $pv_id;
2745
                    $versions{$pv_id}{vname} = $pkg_ver;
2746
                    $versions{$pv_id}{vcsTag} = $vcstag;
2747
                    $versions{$pv_id}{created} = $created;
2748
                    $versions{$pv_id}{created_id} = $created_id;
2749
                    $versions{$pv_id}{comment} = $comment;
2750
                    $versions{$pv_id}{locked} = $locked;
2751
                    $versions{$pv_id}{TimeStamp} = str2time( $created );
2752
                    $versions{$pv_id}{Age} = ($now - $versions{$pv_id}{TimeStamp}) / (60 * 60 * 24);
2753
                    $versions{$pv_id}{TooOld} = 1 if ( $opt_age && $opt_age <= $versions{$pv_id}{Age} );
2754
                    examineVcsTag($pv_id);
2755
 
2756
                    #
2757
                    #   Process version number
2758
                    #
2759
                    my ($suffix, $version, $isaR, $isaWip, $buildVersion ) = massageVersion($pkg_ver, $pkg_name);
2760
 
2761
                    $versions{$pv_id}{version} = $version;
2762
                    $versions{$pv_id}{buildVersion} = $buildVersion;
2763
                    $versions{$pv_id}{isaRipple} = 1 if ( $isaR );
2764
                    $versions{$pv_id}{isaWip} = 1 if ( $isaWip );
2765
 
2766
                    #
2767
                    #   Process suffix
2768
                    #
2769
                    $suffix = 'Unknown' unless ( $suffix );
2770
                    $suffix = lc ($suffix);
2771
                    $versions{$pv_id}{suffix} = $suffix;
2772
                    push @{$suffixes{$suffix}}, $pv_id;
2773
 
2774
#                    print "$pkg_name, $pkg_ver, $pv_id, $last_pv_id, $locked, $created, $created_id, $suffix\n";
2775
                }
2776
            }
2777
            else
2778
            {
2779
                Error ("GetData_by_pkg_id: No Data: $m_sqlstr");
2780
            }
2781
            $sth->finish();
2782
        }
2783
        else
2784
        {
2785
                Error ("GetData_by_pkg_id: Execute: $m_sqlstr");
2786
        }
2787
    }
2788
    else
2789
    {
2790
        Error("GetData_by_pkg_id:Prepare failure" );
2791
    }
2792
}
2793
 
2794
#-------------------------------------------------------------------------------
2795
# Function        : massageVersion
2796
#
2797
# Description     : Process a version number and return usful bits
2798
#
2799
# Inputs          : Version Number
2800
#                   Package Name - debug only
2801
#
2802
# Returns         : An array
2803
#                       suffix
2804
#                       multipart version string useful for text comparisons
2805
#
2806
sub massageVersion
2807
{
2808
    my ($version, $name) = @_;
2809
    my ($major, $minor, $patch, $build, $suffix);
2810
    my $result;
2811
    my $buildVersion;
2812
    my $isaRipple;
2813
    my $isaWIP;
2814
    $build = 0;
2815
 
2816
#print "--- $name, $version\n";
2817
    $version =~ s~^_~~;
2818
    $version =~ s~^${name}_~~;
2819
 
2820
    #
2821
    #   xxxxxxxxx.nnnn.cots
2822
    #
2823
    if ( $version =~ m~(.*)\.cots$~ ) {
2824
        my $cots_base = $1;
2825
        $suffix = '.cots';
2826
        if ( $version =~ m~(.*?)\.([0-9]{4})\.cots$~ )
2827
        {
2828
            $result = $1 . sprintf (".%4.4d", $2) . $suffix;
2829
        }
2830
        else
2831
        {
2832
            $result = $cots_base . '.0000.cots';
2833
        }
2834
    }
2835
    #
2836
    #   Convert version into full form for comparisions
2837
    #       nnn.nnn.nnn.[p]nnn.xxx
2838
    #       nnn.nnn.nnn.[p]nnn-xxx
2839
    #       nnn.nnn.nnn-[p]nnn.xxx
2840
    #       nnn.nnn.nnn-[p]nnn-xxx
2841
    #       nnn.nnn.nnn[p]nnn-xxx
2842
    #   Don't flag as ripples - they are patches
2843
    #
2844
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)[-.p][p]?(\d+)([-.](.*))?$~ ) {
2845
        $major = $1;
2846
        $minor = $2;
2847
        $patch = $3;
2848
        $build = $4;
2849
        $suffix = defined $6 ? ".$6" : '';
2850
        $isaRipple = 0;
2851
    }
2852
    #
2853
    #       nn.nnn.nnnnn.xxx
2854
    #       nn.nnn.nnnnn-xxx
2855
    #       nnn.nnn.nnnx.xxx
2856
    #   Don't flag as ripples - they are patches
2857
    #
2858
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)\w?([-.](.*))?$~ ) {
2859
        $major = $1;
2860
        $minor = $2;
2861
        $patch = $3;
2862
        if ( length( $patch) >= 4 )
2863
        {
2864
            $build = substr( $patch, -3 ,3);
2865
            $patch = substr( $patch,  0 ,length($patch)-3);
2866
        }
2867
        $suffix = defined $5 ? ".$5" : '';
2868
    }
2869
 
2870
    #
2871
    #       nnn.nnn.nnn
2872
    #       nnn.nnn-nnn
2873
    #       nnn.nnn_nnn
2874
    #
2875
    elsif ( $version =~ m~^(\d+)\.(\d+)[-._](\d+)$~ ) {
2876
        $major = $1;
2877
        $minor = $2;
2878
        $patch = $3;
2879
        $suffix = '';
2880
    }
2881
 
2882
    #
2883
    #       nnn.nnn.nnn.nnn
2884
    #       nnn.nnn.nnn-nnn
2885
    #       nnn.nnn.nnn_nnn
2886
    #
2887
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)[-._](\d+)$~ ) {
2888
        $major = $1;
2889
        $minor = $2;
2890
        $patch = $3;
2891
        $build = $4;
2892
        $suffix = '';
2893
        $isaRipple = 0;
2894
    }
2895
 
2896
 
2897
    #
2898
    #       nnn.nnn
2899
    #
2900
    elsif ( $version =~ m~^(\d+)\.(\d+)$~ ) {
2901
        $major = $1;
2902
        $minor = $2;
2903
        $patch = 0;
2904
        $suffix = '';
2905
    }
2906
    #
2907
    #       nnn.nnn.xxx
2908
    #
2909
    elsif ( $version =~ m~^(\d+)\.(\d+)(\.\w+)$~ ) {
2910
        $major = $1;
2911
        $minor = $2;
2912
        $patch = 0;
2913
        $suffix = $3;
2914
    }
2915
 
2916
    #
2917
    #       nnn.nnn.nnnz
2918
    #
2919
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)([a-z])$~ ) {
2920
        $major = $1;
2921
        $minor = $2;
2922
        $patch = $3;
2923
        $build = ord($4) - ord('a');
2924
        $suffix = '.cots';
2925
        $isaRipple = 0;
2926
    }
2927
    #
2928
    #       ???REV=???
2929
    #
2930
    elsif ( $version =~ m~REV=~ ) {
2931
        $suffix = '.cots';
2932
        $result = $version . '.0000.cots';
2933
    }
2934
 
2935
    #
2936
    #   Wip Packages
2937
    #   (nnnnnn).xxx
2938
    #   Should be essential, but want to sort very low
2939
    #
2940
    elsif ($version =~ m~\((.*)\)(\..*)?~) {
2941
        $suffix = $2 || '';
2942
        $result = "000.000.000.000$suffix";
2943
        $isaWIP = 1;
2944
    }
2945
 
2946
    #
2947
    #   !current
2948
    #
2949
    elsif ($version eq '!current' || $version eq 'current_$USER' || $version eq 'current' || $version eq 'beta' || $version eq 'latest' || $version eq 'beta.cr' || $version eq 'CREATE') {
2950
        $suffix = '';
2951
        $result = "000.000.000.000$suffix";
2952
        $isaWIP = 1;
2953
    }
2954
 
2955
    #
2956
    #   Also WIP: FINRUN.103649.BEI.WIP
2957
    elsif ($version =~ m~(\.[a-zA-Z]+)\.WIP$~) {
2958
        $suffix = lc($1);
2959
        $result = "000.000.000.000$suffix";
2960
        $isaWIP = 1;
2961
    }
2962
 
2963
    #
2964
    #   Also ERGOFSSLS190100_015
2965
    #   Don't flag as a ripple
2966
    elsif ($version =~ m~^ERG[A-Z]+(\d\d)(\d\d)(\d\d)[-_](\d+)(\.\w+)?$~) {
2967
        $major = $1;
2968
        $minor = $2;
2969
        $patch = $3;
2970
        $build = $4;
2971
        $suffix = $5 || '.sls';
2972
        $isaRipple = 0;
2973
    }
2974
 
2975
    #
2976
    #   Stuff we don't yet handle
2977
    #
2978
    else  {
2979
        Warning ("Unknown version number: $name,$version");
2980
        $version =~ m~(\.\w+)$~;
2981
        $suffix = $1 || '';
2982
        $result = $version;
2983
    }
2984
 
2985
    $isaRipple = ($build > 0) unless defined $isaRipple;
2986
    unless ( $result )
2987
    {
2988
        # Major and minor of 99.99 are normally funy versions
2989
        # Don't make important desicions on them
2990
        #
2991
        if ( $major == 99 && $minor == 99 )
2992
        {
2993
            $major = 0;
2994
            $minor = 0;
2995
            $patch = 0;
2996
        }
2997
 
2998
        $result = sprintf("%3.3d.%3.3d.%3.3d.%3.3d%s", $major,$minor,$patch,$build,$suffix || '.0000');
2999
        $buildVersion = [ $major, $minor, $patch, $build ];
3000
    }
3001
 
3002
    $suffix = lc( $suffix );
3003
    if ( exists $suffixFixup{$suffix} )
3004
    {
3005
        $suffix = $suffixFixup{$suffix} ;
3006
    }
3007
 
3008
    return ($suffix, $result, $isaRipple, $isaWIP, $buildVersion );
3009
}
3010
 
3011
#-------------------------------------------------------------------------------
395 dpurdie 3012
# Function        : vcsCleanup
3013
#
3014
# Description     : Cleanup and rewrite a vcstag
3015
#
3016
#                   DUPLICATED IN:
3017
#                       - cc2svn_procdata
3018
#                       - cc2svn_importpackage
3019
#
3020
# Inputs          : vcstag
3021
#
3022
# Returns         : Cleaned up vcs tag
3023
#
3024
sub vcsCleanup
3025
{
3026
    my ($tag) = @_;
3027
    $tag =~ tr~\\/~/~;
3028
    if ( $tag =~ m~^CC::~ )
3029
    {
2354 dpurdie 3030
        $tag =~ s~CC::load\s+~CC::~;                # Load rule
3031
        $tag =~ s~CC::\s+~CC::~;                    # Leading white space
3032
        $tag =~ s~CC::[A-Za-z]\:/~CC::/~;           # Leading driver letter
3033
        $tag =~ s~CC::/+~CC::/~;                    # Multiple initial /'s
2319 dpurdie 3034
        $tag =~ s~/build.pl::~::~i;
3035
        $tag =~ s~/src::~::~i;
395 dpurdie 3036
        $tag =~ s~MASS_Dev_Bus/Cbp/~MASS_Dev_Bus/CBP/~i;
3037
        $tag =~ s~MASS_Dev_Bus~MASS_Dev_Bus~i;
3038
        $tag =~ s~/MASS_Dev/Infra~MASS_Dev_Infra~i;
3039
        $tag =~ s~/MASS_Dev/Bus/web~/MASS_Dev_Bus/web~i;
3040
 
3041
        $tag =~ s~/Vastraffik/~/Vasttrafik/~;
3042
        $tag =~ s~/MREF_Package/ergpostmongui$~/MREF_Package/ergpostmongui~i;
3043
        $tag =~ s~DPC_SWCode/~DPG_SWCode/~i;
3044
    }
3045
    return $tag;
3046
}
3047
 
3048
#-------------------------------------------------------------------------------
392 dpurdie 3049
# Function        : examineVcsTag
3050
#
3051
# Description     : Examine a VCS Tag and determine if it looks like rubbish
395 dpurdie 3052
#                   Give it a clean
392 dpurdie 3053
#
3054
# Inputs          : $entry
3055
#
3056
# Returns         : Will add Data to the $entry
3057
#
3058
sub examineVcsTag
3059
{
3060
    my ($entry) = @_;
3061
    my $bad = 0;
395 dpurdie 3062
 
3063
    $versions{$entry}{vcsTag} = vcsCleanup($versions{$entry}{vcsTag});
392 dpurdie 3064
    my $vcstag = $versions{$entry}{vcsTag};
395 dpurdie 3065
 
392 dpurdie 3066
    if ( $vcstag =~ m~^SVN::~ ) {
3067
        $versions{$entry}{isSvn} = 1;
3068
 
3069
    } elsif ( $vcstag =~ m~^CC::(.*?)(::(.+))?$~ ) {
3070
        my $path = $1  || '';
3071
        my $label = $2 || '';
3072
        $bad = 1 unless ( $label );
3073
        $bad = 1 if ( $label =~ m~^N/A$~i || $label  =~ m~^na$~i );
3074
 
3075
        $bad = 1 unless ( $path );
3076
        $bad = 1 if ( $path =~ m~^N/A$~i || $path  =~ m~^na$~i );
3077
        $bad = 1 if ( $path =~ m~^/dpkg_archive~ || $path  =~ m~^dpkg_archive~ );
3078
        $bad = 1 if ( $path =~ m~^/devl/~ || $path  =~ m~^devl/~ );
395 dpurdie 3079
        $bad = 1 if ( $path =~ m~^CVS~ );
392 dpurdie 3080
        $bad = 1 if ( $path =~ m~^http:~i );
3081
        $bad = 1 if ( $path =~ m~^[A-Za-z]\:~ );
3082
        $bad = 1 if ( $path =~ m~^//~ );
395 dpurdie 3083
        $bad = 1 if ( $path =~ m~^/*none~i );
3084
        $bad = 1 if ( $path =~ m~^/*NoWhere~i );
3085
        $bad = 1 if ( $path =~ m~^-$~i );
392 dpurdie 3086
        $bad = 1 if ( $path =~ m~^cvsserver:~ );
3087
        $bad = 1 if ( $path =~ m~,\s*module:~ );
3088
#        $bad = 1 unless ( $path =~ m~^/~ );
3089
    }
3090
    else
3091
    {
3092
        $bad = 1;
3093
    }
3094
    $versions{$entry}{badVcsTag} = 1 if ( $bad );
3095
}
3096
 
3097
#-------------------------------------------------------------------------------
3098
# Function        : logToFile
3099
#
3100
# Description     : Log some data to a named file
3101
#                   Use file locking to allow multiple process to log
3102
#
3103
# Inputs          : $filename           - Name of file to log
3104
#                   ...                 - Data to log
3105
#
3106
# Returns         : Nothing
3107
#
3108
sub logToFile
3109
{
3110
    my ($file, @data) = @_;
3111
 
3112
    open  (LOGFILE, '>>', $file);
3113
    flock (LOGFILE, LOCK_EX);
3114
    print  LOGFILE "@data\n";
3115
    flock (LOGFILE, LOCK_UN);
3116
    close (LOGFILE);
3117
}
3118
 
3119
#-------------------------------------------------------------------------------
3120
# Function        : createImages
3121
#
3122
# Description     : Create nice images of the RM version tree
3123
#
3124
# Inputs          : 
3125
#
3126
# Returns         : 
3127
#
3128
sub createImages
3129
{
3130
 
3131
    my $filebase = "${packageNames}";
3132
    open (FH, '>', "$filebase.dot" ) or die "Cannot open output";
3133
    print FH "digraph \"${packageNames}\" {\n";
3134
    #print FH "rankdir=LR;\n";
3135
    print FH "node[fontsize=16];\n";
3136
    print FH "node[target=_graphviz];\n";
3137
#    print FH "subgraph cluster_A {\n";
3138
#    print FH "node[fontsize=12];\n";
3139
 
3140
    {
3141
        my @text;
3142
        push @text, $packageNames;
3143
        push @text, 'HyperLinked to Release Manager';
3144
        push @text, 'Created:' . localtime();
3145
        push @text, '|';
3146
 
3147
        push @text, 'Total RM versions: ' . $totalVersions;
3148
        push @text, 'Essential Entries: ' . scalar @EssentialPackages;
3149
        push @text, 'Initial trees: ' . $initialTrees;
3150
 
1270 dpurdie 3151
        push @text, 'Number of Entries: ' . $processTotal;
392 dpurdie 3152
        push @text, 'Type : ' . $packageType;
3153
        push @text, 'All versions in Subversion' if ( $allSvn );
3154
 
3155
        push @text, '|';
3156
        push @text, 'Total Project Branches: ' . $ProjectCount;
3157
        foreach ( sort keys %knownProjects )
3158
        {
3159
            my $count = $knownProjects{$_}{count} || 0;
3160
            if ( $count )
3161
            {
3162
                my $text = 'Project Branch: ' . $_;
3163
                $text .= " (" . $count . ")" if ( $count > 1 );
3164
                push @text, $text;
3165
            }
3166
        }
3167
 
3168
        push @text, '|';
3169
        push @text, 'Bad VCS : ' . $badVcsCount;
3170
        push @text, 'Bad Singletions : ' . $badSingletonCount;
3171
        push @text, 'Deadwood entries : ' . $trimCount;
3172
        push @text, 'Walking Mode : Flat' if ($opt_flat);
3173
        push @text, 'Pruned Mode : ' . $pruneModeString;
3174
        push @text, 'Pruned entries : ' . $pruneCount;
1272 dpurdie 3175
        push @text, 'Recent entries : ' . $recentCount;
392 dpurdie 3176
 
3177
        if ( @unknownProjects )
3178
        {
3179
            push @text, '|';
3180
            push @text, 'Unknown Projects';
3181
            push @text, 'Unknown Project: ' . $_ foreach (sort @unknownProjects );
3182
        }
3183
 
3184
        #
3185
        #   Multiple Paths
3186
        #
3187
        if ( scalar @multiplePaths > 1 )
3188
        {
3189
            push @text, '|';
3190
            push @text, 'Multiple Paths';
3191
            push @text, @multiplePaths;
3192
        }
3193
 
3194
        #
3195
        #   Bad essentials
3196
        #
3197
        if ( @badEssentials  )
3198
        {
3199
            push @text, '|';
3200
            push @text, 'Bad Essential Versions';
3201
            push @text, GetVname($_) foreach ( @badEssentials );
3202
        }
3203
 
3204
        #
3205
        #   Subversion Data
3206
        #
3207
        if ( %svnData )
3208
        {
3209
            push @text, '|';
3210
            push @text, 'Subversion';
3211
            push @text, 'Trunk used' if exists $svnData{branches}{trunk} ;
3212
            push @text, 'Labels: ' . scalar keys %{$svnData{tags}} ;
3213
            push @text, 'Branches: ' . scalar keys %{$svnData{branches}} ;
3214
        }
3215
 
3216
        push @text, '';
3217
        my $text = join '\l', @text;
3218
        $text =~ s~\|\\l~|~g;
3219
 
3220
        my @attributes;
3221
        push @attributes, "shape=record";
3222
        push @attributes, "label=\"{$text}\"";
3223
        push @attributes, "tooltip=\"$packageNames\"";
1272 dpurdie 3224
        push (@attributes, "URL=\"" . $GBE_RM_URL . "/view_by_version.asp?pkg_id=$first_pkg_id" . "\"" )if $first_pkg_id;
392 dpurdie 3225
        push @attributes, "color=red";
3226
        my $attr = join( ' ', @attributes);
3227
 
3228
        my $tld_done = 'TitleBlock';
3229
        print FH "$tld_done [$attr]\n";
3230
    }
3231
 
3232
    #
3233
    #   Generate Legend
3234
    #
3235
    {
3236
        my @text;
3237
        push @text, 'Legend';
3238
        push @text, '|';
3239
        push @text, 'Node Content';
3240
        push @text, 'Package Version';
3241
#        push @text, 'Release Manager Ref (pvid)';
3242
        push @text, 'Creation Date: yyyy-mm-dd';
3243
        push @text, '(Coded information)';
3244
        push @text, '|{Code';
3245
        push @text, '|{N: Not Locked';
3246
        push @text, 'b: Bad Singleton';
3247
        push @text, 'B: Bad VCS Tag';
3248
        push @text, 'D: DeadWood';
1272 dpurdie 3249
        push @text, 'E: Essential Release Version';
392 dpurdie 3250
        push @text, 'G: Glued into Version Tree';
2354 dpurdie 3251
        push @text, 'L: Label not in VOB';
1272 dpurdie 3252
        push @text, 'r: Recent version';
1328 dpurdie 3253
        push @text, 'R: Ripple';
392 dpurdie 3254
        push @text, 'S: Splitpoint';
3255
        push @text, 't: Glued into Project Tree';
3256
        push @text, 'T: Tip version';
3257
        push @text, 'V: In SVN';
3258
        push @text, '+: In Subversion';
2354 dpurdie 3259
        push @text, '0: Zero files extracted';
392 dpurdie 3260
        push @text, '}}';
3261
 
3262
        push @text, '|';
3263
        push @text, 'Outline';
3264
        push @text, 'Red: Dead or Bad VCS Tag';
3265
        push @text, 'Orange: Project Branch Root';
3266
        push @text, 'Green: Ripple Build Version';
3267
        push @text, 'Blue: Essential Version';
3268
        push @text, 'Darkmagenta: Entry Glued into tree';
3269
        push @text, 'Magenta: Entry added to project tree';
2354 dpurdie 3270
        push @text, 'DeepPink: Label not in VOB';
3271
        push @text, 'DarkViolet: Zero files extracted';
392 dpurdie 3272
 
3273
 
3274
        push @text, '|';
3275
        push @text, 'Fill';
3276
        push @text, 'PowderBlue: Essential Version';
3277
        push @text, 'Red: Bad Essential Version';
3278
        push @text, 'Light Green: Migrated to SVN';
3279
#        push @text, 'Red: Entry Glued into tree';
3280
#        push @text, 'Green: Entry added to project tree';
3281
 
3282
        push @text, '|';
3283
        push @text, 'Shape';
3284
        push @text, 'Oval: Normal Package Version';
3285
        push @text, 'Invhouse: Project Branch Root';
3286
        push @text, 'Octagon: Branch Point';
3287
        push @text, 'Box: Bad Single version with no history';
3288
        push @text, 'Doublecircle: Tip of a Project Branch';
3289
 
3290
        push @text, '';
3291
        my $text = join '\l', @text;
3292
        $text =~ s~\|\\l~|~g;
3293
        $text =~ s~\}\\l~}~g;
3294
 
3295
        my @attributes;
3296
        push @attributes, "shape=record";
3297
        push @attributes, "label=\"{$text}\"";
3298
        push @attributes, "color=red";
3299
        my $attr = join( ' ', @attributes);
3300
 
3301
        my $tld_done = 'LegendBlock';
3302
        print FH "$tld_done [$attr]\n";
3303
    }
3304
 
3305
#    print FH "\n}\n";
3306
    print FH "TitleBlock -> LegendBlock [style=invis]\n";
3307
 
3308
    sub genLabelText
3309
    {
3310
        my ($entry) = @_;
3311
        my @label;
3312
        push @label, $versions{$entry}{name} if ( $multiPackages );
3313
        push @label, $versions{$entry}{vname};
3314
#        push @label, $entry;       # Add PVID
3315
        push @label, substr( $versions{$entry}{created}, 0, 10); #  2008-02-19
3316
#        push @label, 'V=' . $versions{$entry}{maxVersion};
3317
#        push @label, 'B=' . $versions{$entry}{svnBranchTip} if ( exists $versions{$entry}{svnBranchTip} );
3318
 
3319
 
3320
        my $stateText = '';
3321
        $stateText .= 'N' if ($versions{$entry}{locked} eq 'N');
3322
        $stateText .= 'b' if (exists $versions{$entry}{badSingleton});
3323
        $stateText .= 'B' if (exists $versions{$entry}{badVcsTag});
3324
        $stateText .= 'G' if (exists $versions{$entry}{GluedIn});
3325
        $stateText .= 't' if (exists $versions{$entry}{MakeTree});
3326
        $stateText .= 'E' if (exists $versions{$entry}{Essential});
3327
        $stateText .= 'D' if (exists $versions{$entry}{DeadWood});
1328 dpurdie 3328
        $stateText .= 'R' if ( $versions{$entry}{isaRipple} );
1272 dpurdie 3329
        $stateText .= 'r' if (exists $versions{$entry}{keepRecent} && $versions{$entry}{keepRecent} );
392 dpurdie 3330
        $stateText .= 'S' if (exists $versions{$entry}{EssentialSplitPoint} && $versions{$entry}{EssentialSplitPoint} > 1 );
3331
        $stateText .= 'T' if (exists $versions{$entry}{Tip} );
3332
        $stateText .= 'V' if (exists $versions{$entry}{isSvn} );
3333
        $stateText .= '+' if (exists $versions{$entry}{svnVersion} );
2354 dpurdie 3334
        $stateText .= '0' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq '0');
3335
        $stateText .= 'L' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq 'L');
3336
 
3337
 
392 dpurdie 3338
#        $stateText .= 's' if (exists $versions{$entry}{branchPoint} );
3339
#        $stateText .= ' T='. $versions{$entry}{threadId} if (exists $versions{$entry}{threadId});
3340
#        $stateText .= ' EssentalPath' if (exists $versions{$entry}{EssentialPath});
3341
#        $stateText .= ' Count='. $versions{$entry}{EssentialSplitPoint} if (exists $versions{$entry}{EssentialSplitPoint});
3342
#        $stateText .= ' M='. $versions{$entry}{maxVersion} if (exists $versions{$entry}{maxVersion});
3343
 
2354 dpurdie 3344
        push @label, "(${stateText})" if ( length($stateText) );
392 dpurdie 3345
 
1341 dpurdie 3346
##       Insert Release Names
1451 dpurdie 3347
        foreach my $rtag_id ( keys %{$versions{$entry}{Releases}}  ) {
3348
            next unless ( exists $ukHopsReleases{$rtag_id} );
3349
            push @label, "Release: $versions{$entry}{Releases}{$rtag_id}{rname}";
3350
        }
1341 dpurdie 3351
 
392 dpurdie 3352
        return join ('\n', @label );
3353
    }
3354
 
3355
    sub genAttributes
3356
    {
3357
        my ($entry) = @_;
3358
        my @attributes;
3359
        push @attributes, 'label="' . genLabelText($entry) . '"';
3360
        push @attributes, 'URL="' . dotUrl($entry) . '"';
3361
        push @attributes, 'tooltip="' . "Goto: $versions{$entry}{vname}, PVID=$entry" ,'"';
3362
        my $shape;
3363
            $shape = 'box' if ($versions{$entry}{badSingleton});
3364
            $shape = 'octagon'  if ($versions{$entry}{branchPoint});
3365
            $shape = 'invhouse' if ($versions{$entry}{newSuffix});
3366
            $shape = 'doublecircle' if ($versions{$entry}{Tip});
3367
 
3368
 
3369
        push @attributes, 'shape=' . $shape if ( $shape );
3370
 
3371
        my $color;
3372
        my $fill;
3373
           $color = 'color=green style=bold' if ( $versions{$entry}{isaRipple} );
3374
           $color = 'color=orange style=bold' if ( $versions{$entry}{newSuffix} );
3375
           $color = 'color=red style=bold' if ( $versions{$entry}{DeadWood} || $versions{$entry}{badVcsTag} );
3376
           $color = 'color=blue style=bold' if ( $versions{$entry}{Essential} );
3377
           $color = 'color=darkmagenta style=bold' if ( $versions{$entry}{GluedIn} );
3378
           $color = 'color=magenta style=bold' if ( $versions{$entry}{MakeTree} );
2354 dpurdie 3379
           $color = 'color=DeepPink style=bold' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq 'L');
3380
           $color = 'color=DarkViolet style=bold' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq '0');
392 dpurdie 3381
 
3382
           $fill = 'style=filled fillcolor=powderblue' if ( $versions{$entry}{Essential} );
3383
           $fill = 'style=filled fillcolor=red' if ( $versions{$entry}{Essential} && $versions{$entry}{badVcsTag} );
3384
           $fill = 'style=filled fillcolor="#99FF99"' if ( exists $versions{$entry}{svnVersion} );
3385
 
3386
 
3387
        push @attributes, $color if ( $color );
3388
        push @attributes, $fill if ( $fill );
3389
 
3390
        return '[' . join( ' ', @attributes) . ']';
3391
    }
3392
 
3393
    sub genArrowAttributes
3394
    {
3395
        my ($not_first, $entry) = @_;
3396
        my @attributes;
3397
 
3398
        push @attributes, 'arrowhead=empty' if ( $not_first );
3399
        push ( @attributes, 'label="' . $versions{$entry}{svnBranchTip} .'"' ) if ( exists $versions{$entry}{svnBranchTip} );
3400
 
3401
        return ('[' . join( ' ', @attributes) . ']') if ( @attributes ) ;
3402
        return '';
3403
    }
3404
 
3405
    #
3406
    #   Flat
3407
    #
3408
    if ( $opt_flat )
3409
    {
3410
        my $last = 0;
3411
        foreach my $entry (@flatOrder )
3412
        {
3413
            if ( $last )
3414
            {
3415
                my $me = dotTag($last);
3416
 
3417
                print FH pentry($me)  ,' -> ', pentry(dotTag($entry)), genArrowAttributes(0, $entry) ,";\n";
3418
                print FH pentry($me)  ,genAttributes($last) . ";\n";
3419
            }
3420
            $last = $entry;
3421
        }
3422
        print FH pentry(dotTag($last))  ,genAttributes($last) . ";\n";
3423
 
3424
    }
3425
    else
3426
    {
3427
        foreach my $entry ( sort {$a <=> $b} keys(%versions) )
3428
        {
3429
            my $me = dotTag($entry);
3430
            my @versions = @{ $versions{$entry}{next}};
3431
            my $ii = 0;
3432
            foreach ( @versions )
3433
            {
3434
                print FH pentry($me)  ," -> ",pentry(dotTag($_)), genArrowAttributes($ii++, $_), ";\n";
3435
            }
3436
 
3437
            print FH pentry($me)  ,genAttributes($entry) . ";\n";
3438
        }
3439
    }
3440
 
3441
    print FH "\n};\n";
3442
    close FH;
3443
 
3444
    #
3445
    #   Convert DOT to a SVG
3446
    #
3447
    unless ( $UNIX )
3448
    {
3449
    print "Generating graphical images\n";
3450
#    system( "dot $filebase.dot -Tjpg -o$filebase.jpg" );  # -v
3451
    system( "dot $filebase.dot -Tsvg -o$filebase.svg" );  # -v
3452
#    unlink("$filebase.dot");
3453
 
3454
    #
3455
    #   Display a list of terminal packages
3456
    #   These are packages that are not used by any other package
3457
    #
3458
    print "\n";
3459
#    print "Generated: $filebase.dot\n";
3460
#    print "Generated: $filebase.jpg\n";
3461
    print "Generated: $filebase.svg\n";
3462
    }
3463
    else
3464
    {
3465
        print "Generated: $filebase.dot\n";
3466
    }
3467
}
3468
 
3469
sub dotTag
3470
{
3471
    my ($entry) = @_;
3472
 
3473
    my $label = '';
3474
    $label .= $versions{$entry}{name} if $multiPackages;
3475
    $label .= $versions{$entry}{vname};
3476
    $label =~ s~[-() ]~_~g;
3477
    return $label;
3478
}
3479
 
3480
sub dotUrl
3481
{
3482
    my ($entry) = @_;
3483
 
3484
    my $pv_base = $GBE_RM_URL . "/fixed_issues.asp?pv_id=$entry";
3485
}
3486
 
3487
#-------------------------------------------------------------------------------
3488
# Function        : pentry
3489
#
3490
# Description     : Generate an entry list as text
3491
#                   Replace "." with "_" since DOT doesn't like .'s
3492
#                   Seperate the arguments
3493
#
3494
# Inputs          : @_          - An array of entries to process
3495
#
3496
# Returns         : A string
3497
#
3498
sub pentry
3499
{
3500
    my ($data) = @_;
3501
    $data =~ s~\.~_~g;
3502
    $result = '"' . $data . '"' ;
3503
    return $result;
3504
}
3505
 
3506
#-------------------------------------------------------------------------------
3507
# Function        : getVobMapping
3508
#
3509
# Description     : Read in Package to Repository Mapping
3510
#
3511
# Inputs          : 
3512
#
3513
# Returns         : Populates %VobMapping
3514
#                             Mapping of PackageName to RepoName[/Subdir]
3515
#
3516
our %ScmRepoMap;
3517
sub getVobMapping
3518
{
3519
    Message ("Read in Vob Mapping");
3520
 
3521
    my $fname = 'cc2svn.repo.dat';
3522
    Error "Cannot locate $fname" unless ( -f $fname );
3523
    require $fname;
3524
 
3525
    Error "Data in $fname is not valid\n"
3526
        unless ( keys(%ScmRepoMap) >= 0 );
3527
 
3528
    $opt_vobMap = $ScmRepoMap{$packageNames}{repo}
3529
        if (exists $ScmRepoMap{$packageNames});
3530
 
3531
    #
3532
    #   Free the memory
3533
    #
3534
    %ScmRepoMap = ();
3535
 
3536
    #
3537
    #   Calculate Target Repo
3538
    #
3539
    Warning ("No VOB Mapping found")
3540
        unless ($opt_vobMap);
3541
    Error("No repository specified. ie -repo=DevTools or -repo=COTS")
3542
        unless ( $opt_repo || $opt_vobMap );
3543
 
3544
    my $r1 = ($opt_repo || '') . '/' . ($opt_vobMap || '');
3545
    $r1 =~ s~^/~~;
3546
    $r1 =~ s~/$~~;
3547
    $svnRepo = $opt_repo_base . $r1;
3548
 
3549
    Verbose( "Repo URL: $svnRepo");
3550
}
3551
 
3552
 
3553
#-------------------------------------------------------------------------------
3554
# Function        : getEssenialPackageVersions
3555
#
3556
# Description     : Determine the 'Essental' Package Versions
3557
#                   Read the data in from an external file
3558
#
3559
# Inputs          : 
3560
#
3561
# Returns         : Populates @EssentialPackages
3562
#
3563
 
3564
our %ScmReleases;
3565
our %ScmPackages;
3566
our %ScmSuffixes;
3567
sub getEssenialPackageVersions
3568
{
3569
    Message ("Read in Essential Package Versions");
3570
 
3571
    my $fname = 'cc2svn.raw.txt';
3572
    Error "Cannot locate $fname" unless ( -f $fname );
3573
    require $fname;
3574
 
3575
    Error "Data in $fname is not valid\n"
3576
        unless ( keys(%ScmReleases) >= 0 );
3577
 
3578
#    DebugDumpData("ScmReleases", \%ScmReleases );
3579
#    DebugDumpData("ScmPackages", \%ScmPackages );
3580
#    DebugDumpData("ScmSuffixes", \%ScmSuffixes );
3581
 
3582
    #
3583
    #   Create a list of essential packages
3584
    #   Retain packages-versions used in this program
3585
    #
3586
    foreach ( keys %ScmPackages )
3587
    {
3588
        next unless ( exists  $pkg_ids{ $ScmPackages{$_}{pkgid} } );
3589
        push @EssentialPackages, $_;
3590
        Error ("Essential Package Version not in extracted Release Manager Data: $_")
3591
            unless ( exists $versions{$_} );
3592
        $versions{$_}{Essential} = 1;
1341 dpurdie 3593
 
3594
        # Retain which RM Release this package-version is the tip
3595
        # Release of
1342 dpurdie 3596
        foreach my $rtag_id ( @{$ScmPackages{$_}{'release'}} )
1341 dpurdie 3597
        {
1342 dpurdie 3598
            $versions{$_}{Releases}{$rtag_id}{rname}   = $ScmReleases{$rtag_id}{name};
3599
            $versions{$_}{Releases}{$rtag_id}{pname}   = $ScmReleases{$rtag_id}{pName};
3600
            $versions{$_}{Releases}{$rtag_id}{proj_id} = $ScmReleases{$rtag_id}{proj_id};
1341 dpurdie 3601
        }
3602
 
392 dpurdie 3603
        #print "ESSENTIAL: $versions{$_}{name} $versions{$_}{vname}\n";
3604
    }
3605
 
1341 dpurdie 3606
 
392 dpurdie 3607
    #
3608
    #   Free memory
3609
    #
3610
    %ScmReleases = ();
3611
    %ScmPackages = ();
3612
    %ScmSuffixes = ();
3613
 
3614
#    DebugDumpData("Essential", \@EssentialPackages );
3615
    Message ("Essential Versions: " . scalar @EssentialPackages );
3616
}
3617
 
3618
#-------------------------------------------------------------------------------
3619
# Function        : ReportPathVariance
3620
#
3621
# Description     : Report variance in paths used by the versions
3622
#
3623
# Inputs          : 
3624
#
3625
# Returns         : 
3626
#
3627
my %VobPaths;
3628
sub ReportPathVariance
3629
{
3630
    Message ("Detect Multiple Paths");
3631
    foreach my $entry ( keys(%versions) )
3632
    {
3633
        my $e = $versions{$entry};
3634
        next if ( isSet ($e, 'DeadWood' ) );
3635
        next if ( isSet ($e, 'badVcsTag') );
3636
        next if ( isSet ($e, 'isSvn') );
3637
        my $tag = $e->{vcsTag};
3638
        next unless ( $tag );
3639
 
3640
        $tag =~ m~^(.+?)::(.*?)(::(.+))?$~;
3641
        my $vcsType = $1;
3642
        my $cc_label = $4;
3643
        my $cc_path = $2;
3644
        $cc_path = '/' . $cc_path;
3645
        $cc_path =~ tr~\\/~/~s;
3646
 
3647
        $VobPaths{$cc_path}++;
3648
    }
3649
 
3650
    @multiplePaths = sort keys %VobPaths;
3651
    if ( scalar @multiplePaths > 1 )
3652
    {
3653
        Warning ("Multiple Paths:" . $_ ) foreach (@multiplePaths);
3654
    }
3655
}
3656
 
3657
sub isSet
3658
{
3659
    my ($base, $element) = @_;
3660
    return 0 unless ( exists $base->{$element} );
3661
    return $base->{$element};
3662
}
3663
 
3664
 
3665
#-------------------------------------------------------------------------------
3666
# Function        : recurseList
3667
#
3668
# Description     : Return a list of all element below a given head element
3669
#
3670
# Inputs          : $head               - Head element
3671
#
3672
# Returns         : A list, not in any particular order
3673
#
3674
 
3675
our @recurseList;
3676
sub recurseList
3677
{
3678
    @recurseList = ();
3679
    recurseListBody (@_);
3680
    return @recurseList;
3681
}
3682
sub recurseListBody
3683
{
3684
    foreach my $entry ( @_ )
3685
    {
3686
        push @recurseList, $entry;
3687
no warnings "recursion";
3688
        recurseListBody (@{$versions{$entry}{next}});
3689
    }
3690
}
3691
 
3692
#-------------------------------------------------------------------------------
3693
# Function        : getSvnData
3694
#
3695
# Description     : Read the SVN tree and see what we have
3696
#
3697
# Inputs          : 
3698
#
3699
# Returns         : 
3700
#
3701
my @svnDataItems;
3702
sub getSvnData
3703
{
3704
    Message ("Examine Subversion Tree");
3705
 
3706
    #
3707
    #   Re-init data
3708
    #
3709
    @svnDataItems = ();
3710
    %svnData = ();
3711
 
3712
    #
3713
    #   Create an SVN session
3714
    #
3715
    return unless ( $svnRepo );
3716
    my $svn = NewSessionByUrl ( "$svnRepo/$packageNames" );
3717
    return unless ( $svn );
3718
 
3719
    #
3720
    #   extract data
3721
    #
3722
#    DebugDumpData("SVN", $svn );
3723
    $svn->SvnCmd ( 'log', '-v', '--xml', '--stop-on-copy', $svn->Full()
3724
                    , { 'credentials' => 1,
3725
                        'process' => \&ProcessSvnLog,
3726
                         }
3727
                        );
3728
 
3729
    #
3730
    #   Process data
3731
    foreach my $entry ( @svnDataItems )
3732
    {
3733
        my $name;
3734
        my $isaBranch;
3735
        my $target = $entry->{target};
3736
        if ( $target =~ m~/tags/(.*)~ ) {
3737
            $name = $1;
3738
            $svnData{tags}{$name} = 1;
3739
        } elsif ( $target =~ m~/branches/(.*)~ )  {
3740
            $name = $1;
3741
    #        $branches{$1} = 1;
3742
        } else {
3743
            $svnData{nonTag}{$target} = 1;
3744
        }
3745
 
3746
        my $fromBranch;
3747
        if ( $entry->{fromPath} =~ m~/trunk$~  ) {
3748
            $fromBranch = 'trunk';
3749
        } elsif ( $entry->{fromPath} =~ m~/branches/(.*)~ ) {
3750
            $fromBranch = $1;
3751
        }
3752
 
1341 dpurdie 3753
        # largest Rev number on branch
3754
        if ( exists $svnData{max}{$fromBranch} )
392 dpurdie 3755
        {
1341 dpurdie 3756
            if ( $svnData{max}{$fromBranch}{rev} <  $entry->{fromRev} )
392 dpurdie 3757
            {
1341 dpurdie 3758
                $svnData{max}{$fromBranch}{rev} =  $entry->{fromRev};
3759
                $svnData{max}{$fromBranch}{name} = $name;
392 dpurdie 3760
            }
3761
        }
1341 dpurdie 3762
        else
3763
        {
3764
            $svnData{max}{$fromBranch}{rev} =  $entry->{fromRev};
3765
            $svnData{max}{$fromBranch}{name} = $name;
3766
        }
392 dpurdie 3767
    }
1341 dpurdie 3768
 
3769
    foreach my $branch ( keys %{$svnData{max}} )
3770
    {
3771
        $svnData{tips}{$svnData{max}{$branch}{name}} = $branch;
3772
    }
3773
#    DebugDumpData("svnDataItems", \@svnDataItems);
392 dpurdie 3774
#    DebugDumpData("SvnData", \%svnData);
3775
 
1341 dpurdie 3776
 
392 dpurdie 3777
    foreach my $entry ( keys(%versions) )
3778
    {
3779
        my $import_label = saneLabel($entry);
3780
        delete $versions{$entry}{svnVersion};
3781
        delete $versions{$entry}{svnBranchTip};
3782
 
3783
        if ( exists $svnData{tags}{$import_label} )
3784
        {
3785
            $versions{$entry}{svnVersion} = 1;
3786
        }
3787
 
3788
        if ( exists $svnData{tips}{$import_label} )
3789
        {
3790
            $versions{$entry}{svnBranchTip} = $svnData{tips}{$import_label};
3791
        }
3792
    }
3793
 
1341 dpurdie 3794
    Message ( 'Trunk used: ' . (exists $svnData{'max'}{trunk} ? 'Yes' : 'No') );
392 dpurdie 3795
    Message ( 'Labels    : ' . scalar keys %{$svnData{tags}} );
1341 dpurdie 3796
    Message ( 'Branches  : ' . scalar keys %{$svnData{'max'}} );
392 dpurdie 3797
}
3798
 
3799
#-------------------------------------------------------------------------------
3800
# Function        : ProcessSvnLog
3801
#
3802
# Description     :
3803
#                   Parse
3804
#                       <logentry
3805
#                          revision="24272">
3806
#                       <author>bivey</author>
3807
#                       <date>2005-07-25T15:45:35.000000Z</date>
3808
#                       <paths>
3809
#                       <path
3810
#                          prop-mods="false"
3811
#                          text-mods="false"
3812
#                          kind="dir"
3813
#                          copyfrom-path="/enqdef/branches/Stockholm"
3814
#                          copyfrom-rev="24271"
3815
#                          action="A">/enqdef/tags/enqdef_24.0.1.sls</path>
3816
#                       </paths>
3817
#                       <msg>COTS/enqdef: Tagged by Jats Svn Import</msg>
3818
#                       </logentry>
3819
#
3820
# Inputs          : 
3821
#
3822
# Returns         : 
3823
#
3824
my $entryData;
3825
sub  ProcessSvnLog
3826
{
3827
    my ($self, $line ) = @_;
3828
#print "----- $line\n";
3829
    if ( $line =~ m~^<logentry~ ) {
3830
        $entryData = ();
3831
 
3832
    } elsif ( $line =~ m~^\s+revision="(\d+)"~ ) {
3833
        $entryData->{Rev} = $1;
3834
 
3835
    } elsif ( $line =~ m~^\s+copyfrom-path="(.*)"~ ) {
3836
        $entryData->{fromPath} = $1;
3837
 
3838
    } elsif ( $line =~ m~^\s+copyfrom-rev="(\d+)"~ ) {
3839
        $entryData->{fromRev} = $1;
3840
 
3841
    } elsif ( $line =~ m~\s+action=.*?>(.*)</path~ ) {
3842
        $entryData->{target} = $1;
3843
 
3844
    } elsif ( $line =~ m~</logentry~ ) {
3845
        if ( exists $entryData->{fromPath} )
3846
        {
3847
#            DebugDumpData("Data", $entryData);
3848
            push @svnDataItems, $entryData;
3849
        }
3850
    }
3851
 
3852
    #
3853
    #   Return 0 to keep on going
3854
    return 0;
3855
}
3856
 
1328 dpurdie 3857
#-------------------------------------------------------------------------------
392 dpurdie 3858
# Function        : saveData
3859
#
3860
# Description     : Save essential data
3861
#
3862
# Inputs          : 
3863
#
3864
# Returns         : 
3865
#
3866
sub saveData
3867
{
3868
    my $file = $cwd . "/${packageNames}.data";
3869
 
3870
    Message ("Create: $file");
3871
    my $fh = ConfigurationFile::New( $file );
3872
 
3873
    $fh->DumpData(
3874
        "\n# ScmVersions.\n#\n",
3875
        "ScmVersions", \%versions );
3876
 
3877
    #
3878
    #   Close out the file
3879
    #
3880
    $fh->Close();
3881
}
3882
 
3883
 
3884
#-------------------------------------------------------------------------------
3885
#   Documentation
3886
#
3887
 
3888
=pod
3889
 
3890
=for htmltoc    SYSUTIL::cc2svn::
3891
 
3892
=head1 NAME
3893
 
3894
cc2svn_gendata - CC2SVN tool to import an entire package into SVN
3895
 
3896
=head1 SYNOPSIS
3897
 
3898
  jats cc2svn_importpackage [options] package_name
3899
 
3900
 Options:
3901
    -help              - brief help message
3902
    -help -help        - Detailed help message
3903
    -man               - Full documentation
3904
    -repository=name   - Specify target repository
3905
    -[no]flat          - Do not create project tree. Def: -noflat
3906
    -prunemode=mode    - Mode: none, ripple, retain, severe, Def=ripple
3907
    -retain=N          - Specify retain count for pruning. Def=2
3908
    -[no]test          - Do not create packages. Def:-notest
3909
    -[no]reuse         - Keep and reuse ClearCase views
3910
    -age=nnDays        - Only keep recent package
3911
    -dump[=n]          - Dump raw data. N=0,1,2
3912
    -images[=n]        - Create SVG of version tree. N=0,1,2
3913
    -name=aaa          - Alternate output package name. Test Only
3914
    -[no]log           - Write output to log file. Def: -nolog
3915
    -[no]postimage     - Create image after transger: Def: -post
3916
    -workdir=path      - Use for temp storage (def:/work)
1270 dpurdie 3917
    -delete            - Delete SVN package before test
392 dpurdie 3918
 
3919
=head1 OPTIONS
3920
 
3921
=over 8
3922
 
3923
=item B<-help>
3924
 
3925
Print a brief help message and exits.
3926
 
3927
=item B<-help -help>
3928
 
3929
Print a detailed help message with an explanation for each option.
3930
 
3931
=item B<-man>
3932
 
3933
Prints the manual page and exits.
3934
 
3935
=item B<-prunemode=mode>
3936
 
3937
This option control the manner in which excess versions will be pruned. Valid
3938
modes are:
3939
 
3940
=over 8
3941
 
3942
=item   none
3943
 
3944
No pruning will be performed
3945
 
3946
=item   ripple
3947
 
3948
Non-Essential packages that are ripple builds will be removed.
3949
 
3950
=item   retain
3951
 
3952
Versions that preceed an Essential version will be retained.
3953
 
3954
=item   severe
3955
 
3956
Only Essential Versions, and Branching points will be retained.
3957
 
3958
=back
3959
 
3960
=back
3961
 
3962
=head1 DESCRIPTION
3963
 
3964
This program is a tool used in the conversion of ClearCase VOBS to subversion.
3965
It will take a complete package and all relevent versions from ClearCase and
3966
insert them into subversion in a sessible manner. It will attempt to retain
3967
file change order and history.
3968
 
3969
It will:
3970
 
3971
=over 8
3972
 
3973
=item *
3974
 
3975
Read in the Essential Package Version list.
3976
 
3977
=item *
3978
 
3979
Extract, from Release Manager, all known versions of the specified package.
3980
 
3981
=item *
3982
 
3983
It will attempt to determine the type of package: COTS, TOOL, CORE, PROJECT
3984
and alter the processing accordingly.
3985
 
3986
=item *
3987
 
3988
It will create a version dependency tree and determine 'new' project branch
3989
points. It will remove (prune) versions that are excess to requirements.
3990
 
3991
=item *
3992
 
3993
It will extract source from ClearCase and insert it into SVN, creating
3994
branches and tags as it goes.
3995
 
3996
=back
3997
 
3998
The program can also be used to create a SVG image of the version dependency
3999
tree. This does not work on Linux; only Windows with 'dot' installed.
4000
 
4001
=cut
4002