Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
1271 dpurdie 1
########################################################################
2
# Copyright (C) 1998-2012 Vix Technology, All rights reserved
3
#
4
# Module name   : cc2svn_importpackage3.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);
35
use JatsLocateFiles;
2438 dpurdie 36
use Encode;
1271 dpurdie 37
 
38
 
39
#use Data::Dumper;
40
use Fcntl ':flock'; # import LOCK_* constants
41
use Cwd;
42
use DBI;
43
use Getopt::Long;
44
use Pod::Usage;                             # required for help support
2412 dpurdie 45
use Encode;
1271 dpurdie 46
 
47
#
48
#   Options
49
#
50
my $opt_help = 0;
51
my $opt_manual = 0;
52
my $opt_verbose = 0;
53
my $opt_repo_base = 'AUPERASVN01/';
54
my $opt_repo = '';
2438 dpurdie 55
my $opt_repoSubdir = '';
1271 dpurdie 56
my $opt_flat;
57
my $opt_test;
58
my $opt_reuse;
59
my $opt_age;
60
my $opt_dump = 0;
61
my $opt_images = 0;
62
my $opt_retaincount = 2;
63
my $opt_pruneModeString;
64
my $opt_listTags;
65
my $opt_name;
66
my $opt_log = 0;
67
my @opt_tip;
68
my $opt_postimage = 1;
69
my $opt_workDir = '/work';
70
my $opt_vobMap;
71
my $opt_fileList;
2635 dpurdie 72
my $opt_ccbase;
1271 dpurdie 73
my $opt_preserveProjectBase;
74
my $opt_ignoreProjectBaseErrors;
2438 dpurdie 75
my $opt_ignoreMakeProjectErrors;
2635 dpurdie 76
my $opt_forceProjectBase;
77
my @opt_limitProjectBase;
78
my @opt_mergePaths;
79
my $opt_ignoreBadPaths;
1272 dpurdie 80
my $opt_delete;
2412 dpurdie 81
my $opt_recentAge = 14;             # Days
2635 dpurdie 82
my $opt_relabel = 0;
83
my $opt_protected;
84
my $opt_useSvn = 1;
85
my $opt_testRmDatabase;
86
my $opt_extractFromSvn;
87
my $opt_AllowMuliplePaths = 1;      #29-Nov-2012
88
my $opt_resume;
89
my $opt_processRipples = 1;
90
my $opt_mergePackages;
1271 dpurdie 91
 
92
################################################################################
93
#   List of Projects Suffixes and Branch Names to be used within SVN
94
#
95
#       Name        - Name of branch for the project
96
#       Trunk       - Can be a trunk project
97
#                     First one seen will be placed on the trunk
98
#                     Others will create project branches
99
#
100
my $ProjectTrunk;
101
my %ProjectsBaseCreated;
102
my %Projects = (
103
    '.sea'      => { Name => 'Seattle' },
104
    '.coct'     => { Name => 'CapeTown' },
105
    '.sls'      => { Name => 'Stockholm' },
106
    '.syd'      => { Name => 'Sydney' },
107
    '.vtk'      => { Name => 'Vasttrafik' },
108
    '.bei'      => { Name => 'Beijing' },
109
    '.bkk'      => { Name => 'Bangkok' },
110
    '.ndl'      => { Name => 'NewDelhi' },
111
    '.nzs'      => { Name => 'NewZealandStageCoach' },
112
    '.wdc'      => { Name => 'Washington' },
113
    '.oso'      => { Name => 'Oslo' },
114
    '.lvs'      => { Name => 'LasVegas' },
115
    '.mlc'      => { Name => 'BeijingMlc' },
116
    '.sfo'      => { Name => 'SanFrancisco' },
117
    '.sg'       => { Name => 'Singapore' },
118
    '.gmp'      => { Name => 'GmpteProject' },
119
    '.ssw'      => { Name => 'UkStageCoach' },
120
    '.uk'       => { Name => 'UkProject' },
121
    '.pmb'      => { Name => 'Pietermaritzburg' },
122
    '.vps'      => { Name => 'VixPayments' },
123
    '.ncc'      => { Name => 'NSWClubCard' },
124
    '.rm'       => { Name => 'Rome' },
2412 dpurdie 125
    '.vss'      => { Name => 'SmartSite' },
1271 dpurdie 126
    'unknown'   => { Name => 'UnknownProject' },
127
 
128
    '.ebr'      => { Name => 'eBrio' , Trunk => 1 },
129
    '.mas'      => { Name => 'Mass'  , Trunk => 1 },
130
    '.cr'       => { Name => 'Core'  , Trunk => 1 },
131
    '.cots'     => { Name => 'Cots'  , Trunk => 1 },
132
    '.tool'     => { Name => 'Tools' , Trunk => 1 },
133
);
134
 
135
my %suffixFixup = (
136
    '.sf'           => '.sfo',
137
    '.vt'           => '.vtk',
138
    '.lv'           => '.lvs',
139
    '.was'          => '.wdc',
140
    '.uk.1'         => '.uk',
141
    '.ssts.demo'    => '.ssts',
142
    '.u244.syd'     => '.syd',
143
    '.pxxx.sea'     => '.sea',
144
    '.pxxx.syd'     => '.syd',
145
    '.pxxx.sydddd'  => '.syd',
146
    '.oslo'         => '.oso',
147
    '.osl'          => '.oso',
148
);
149
 
150
my %specialPackages = (
2412 dpurdie 151
    'core_devl'           =>  ',all,protected,',
152
    'daf_utils_mos'       => ',flat,',
153
    'mos_packager'        => ',all,',
154
    'cfmgr-cfmgr'         => ',flat,',
155
    'daf_utils_button_st' => ',flat,',
156
    'ReleaseName'         => ',flat,',
157
    'reports'             => ',utf8,',
158
    'cda_imports'         => ',utf8,',
159
    'cdxforms'            => ',utf8,',
160
    'db_cda'              => ',utf8,',
2438 dpurdie 161
    'CommandServer'       => ',IgnoreMakeProject,',
162
    'TDSExporterControl'  => ',IgnoreMakeProject,',
163
    'cdagui'              => ',IgnoreMakeProject,',
1271 dpurdie 164
 
2412 dpurdie 165
 
2635 dpurdie 166
    'ftp'                   => ',SetProjectBase,',
167
    'ddu_app_manager'       => ',SetProjectBase,IgnoreMakeProject,',
168
    'ddu_afc'               => ',SetProjectBase,IgnoreMakeProject,',
169
    'ddu_dog'               => ',SetProjectBase,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode/projects/seattle/ddu,',
170
    'ddu_management'        => ',SetProjectBase,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode,',
171
    'ddu_fim'               => ',IgnoreMakeProject,',
172
    'ddu_mccain'            => ',SetProjectBase,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode/projects/seattle/ddu,',
173
    'ddu_mon'               => ',SetProjectBase,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode/projects/seattle,',
174
    'ddu_rcu'               => ',SetProjectBase,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode,',
175
    'ddu_status_logging'    => ',SetProjectBase,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode/projects/seattle,',
176
    'ddu_logging_lib'       => ',SetProjectBase,ForceProjectBase=/DPG_SWCode/projects/seattle/ddu,',
177
    'verifone'              => ',ForceProjectBase=/DPG_SWCode/products/verifone,',
178
    'dm_devcdfile'          => 'AllowMultiPath',
179
    'daf_ct_mcr_unified'    => 'AllowMultiPath',
180
    'cst-rms-db'            => 'AllowMultiPath',
181
    'daf_common'            => 'IgnoreProjectBase',
182
    'devcd'                 => 'AllowMultiPath',
183
    'daf_dll'                   => 'AllowMultiPath,IgnoreMakeProject',  # MakeProject not in used makefile
184
    'daf_transap_proxyman_edf'  => 'AllowMultiPath,IgnoreProjectBase',
185
    'devrelease'                => 'AllowMultiPath',
1271 dpurdie 186
 
2635 dpurdie 187
    'dm_devrelease'             => 'AllowMultiPath',
188
    'dm_rtswis'                 => 'AllowMultiPath',
189
    'dm_devcd'                  => 'AllowMultiPath',
190
    'dm_documentation'          => 'AllowMultiPath,IgnoreBadPath',
191
    'dm_eventhdr'               => 'AllowMultiPath',
192
    'dm_javaenums'              => 'AllowMultiPath',
193
    'dm_solidbasetypes'         => 'AllowMultiPath',
194
    'dm_swismetadata'           => 'AllowMultiPath',
195
    'dm_cuttables'              => 'AllowMultiPath',
196
    'dm_devudapi'               => 'AllowMultiPath',
197
    'buscdapi'                  => 'AllowMultiPath',
198
    'daf_bvt'                   => 'AllowMultiPath,IgnoreMakeProject,',  # Look OK
199
    'daf_cd_transap'            => 'AllowMultiPath,IgnoreBadPath,IgnoreProjectBase',
200
    'cdref'                     => 'AllowMultiPath',
201
    'dm_sysbasetypes'           => 'AllowMultiPath',
202
    'dm_sysswis'                => 'AllowMultiPath',
203
    'dm_syscd'                  => 'AllowMultiPath',
204
    'dm_udtypes'                => 'AllowMultiPath',
205
    'dm_systemcdtables'         => 'AllowMultiPath',
206
    'dm_utils'                  => 'AllowMultiPath',
207
    'dm_udxml'                  => 'AllowMultiPath',
208
    'HCP5000_resources'         => 'AllowMultiPath',
209
    'massrtswis'                => 'AllowMultiPath',
210
    'pcp5000'                   => 'AllowMultiPath,ForceProjectBase=/DPG_SWCode',
211
    'PFTPi'                     => 'AllowMultiPath,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode',  # Looks OK
212
    'PFTPu'                     => 'AllowMultiPath,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode',  # Looks OK
213
    'WinCEBlocker'              => ',IgnoreMakeProject,',  # Looks OK
214
    'WinCEDeviceAutoInject'     => ',IgnoreMakeProject,',  # Looks OK
215
    'WinCEReboot'               => ',IgnoreMakeProject,',  # Looks OK
216
    'rsmaint'                   => 'AllowMultiPath',
217
    'sysbasetypes'              => 'AllowMultiPath',
218
    'syscd'                     => 'AllowMultiPath',
219
    'sysswis'                   => 'AllowMultiPath',
220
    'udserialiser'              => 'AllowMultiPath',
221
    'systemcdtables'            => 'AllowMultiPath',
222
    'udxml'                     => 'AllowMultiPath',
223
    'ERGoracs'                  => 'AllowMultiPath',
224
    'daf_cd_desfireparams'      => 'AllowMultiPath',
225
    'daf_ct_mag_virtual'        => 'AllowMultiPath',
226
    'daf_br_applets'            => 'AllowMultiPath',
227
    'daf_paper_variables'       => 'AllowMultiPath',
228
    'daf_transap_api'           => 'AllowMultiPath,ForceProjectBase=/DPG_SWBase/transap',
229
    'daf_br_applets'            => 'AllowMultiPath,IgnoreProjectBase',  # Not used
230
    'daf_udlib_api'             => 'AllowMultiPath,ForceProjectBase=/DPG_SWBase/ud',
231
    'daf_ct_mcr_14443'          => 'LimitProjectBase=/DPG_SWBase/ct',
2412 dpurdie 232
 
233
 
2635 dpurdie 234
    'daftestcd_sales'               => 'AllowMultiPath,ForceProjectBase=/ProjectCD/seattle',
235
    'daftestcd_vanpool'             => 'AllowMultiPath,ForceProjectBase=/ProjectCD',
236
    'daf_transap_edf'               => 'AllowMultiPath,IgnoreProjectBase',
237
    'daf_transap_extensions'        => 'AllowMultiPath',
238
    'daf_transap_proxyman_rkf_mag'  => 'AllowMultiPath',
239
    'daf_utils_appupgrade'          => 'AllowMultiPath',
240
    'dc5000'                        => 'AllowMultiPath,IgnoreMakeProject,ForceProjectBase=/DPG_SWCode',
241
    'uiconv'                        => 'AllowMultiPath',
1271 dpurdie 242
 
2635 dpurdie 243
    'daf_ct_api'                    => 'AllowMultiPath',
244
 
245
 
246
    'ocpsupport'                    => 'AllowMultiPath,IgnoreMakeProject', # MakeProject Tested on at least one
247
    'emv_cs_test_ingenico'          => 'AllowMultiPath,IgnoreMakeProject', # MakeProject Tested on at least one
248
    'deviceicons'                   => 'AllowMultiPath,LimitProjectBase=/DPG_SWBase/resources:/DPG_SWCode/resources',
249
    'pcv_final_wce'                 => 'IgnoreMakeProject', # MakeProject Tested on at least one
250
    'pcv_wce'                       => 'IgnoreMakeProject', # MakeProject Tested on at least one
251
    'WinCEDeviceUpgrade'            => 'IgnoreMakeProject', # MakeProject Tested on at least one
252
    'scil'                          => 'LimitProjectBase=/DPG_SWCode/projects/seattle/tvm',
253
    'daf_br_compiler_support'       => 'ForceProjectBase=/DPG_SWBase/daf_br_compiler/support',
254
 
255
    'LinuxDrivers'                  => 'flatTime,LimitProjectBase=/LMOS/linux/drivers'.
256
                                       ',mergePaths=modules:bcp4600:cobra:eb5600:etx86:tp5600:viper'.
257
                                       ',Packages=linux_drivers_eb5600:linux_drivers_viper:linux_drivers_cobra:linux_drivers_bcp4600:linux_drivers_etx86:linux_drivers_tp5600',
258
 
259
 
1271 dpurdie 260
    'icl'                   => 'IgnoreProjectBase,',
261
    'itso'                  => 'IgnoreProjectBase,',
2635 dpurdie 262
#    'daf_osa_mos'           => 'IgnoreProjectBase,',
1271 dpurdie 263
    'daf_utils_mos'         => 'IgnoreProjectBase,',
264
    'itso_ud'               => 'IgnoreProjectBase,',
265
#    'mos_api'               => 'IgnoreProjectBase,',
266
#    'mos_fonts'             => 'IgnoreProjectBase,',
267
#    'sntp'                  => 'IgnoreProjectBase,',
268
#    'time_it'               => 'IgnoreProjectBase,',
269
);
270
 
271
my %notCots = (
272
    'isl'       => 1,
273
);
274
 
2412 dpurdie 275
my $ukHopsMode = 0;
276
my %ukHopsReleases = (
277
    '6222'      => { name => 'MainLine', 'trunk' => 1 },
278
    '14503'     => { name => 'Hops3' },
279
    '21864'     => { name => 'Hops3.6' },
280
    '22303'     => { name => 'Hops3.7' },
281
    '17223'     => { name => 'Hops4' },
282
);
283
 
284
# The following packages will have the version in the specified release forced to be on the trunk
285
# A trunk will be forced and the version will be on it.
286
#   May only work if the version in the release is also a TIP
287
my %ukHopsTip = (
288
    'ItsoMessaging'         => '6222',
289
    'MessageProcessor'      => '6222',
290
    'StrongNameKey'         => '6222',
291
);
292
 
1271 dpurdie 293
################################################################################
294
#   Global data
295
#
296
my $VERSION = "1.0.0";
297
my $RM_DB;
298
my $last_pv_id;
299
my %pkg_ids;
300
my $first_pkg_id;
301
my %versions;
302
my %suffixes;
303
my @processOrder;
304
my @startPoints;
305
my @allStartPoints;
306
my @endPoints;
307
my $now = time();
308
my $logSummary;
309
my $firstVersionCreated;
310
my @EssentialPackages;
311
my $createBranch;
312
my $createSuffix;
313
my $currentBranchName;
314
my $singleProject;
315
my $pruneCount = 0;
316
my $trimCount = 0;
317
my $badVcsCount = 0;
318
my $ProjectCount = 0;
319
my $totalVersions = 0;
320
my $initialTrees = 0;
321
my $globalError;
322
my @unknownProjects;
323
my %knownProjects;
324
my $badSingletonCount = 0;
325
my @flatOrder;
2635 dpurdie 326
my $flatMode;
1271 dpurdie 327
my $pruneMode;
328
my $pruneModeString;
329
my $threadId = 0;
330
my $threadCount;
331
my %tipVersions;
332
my $allSvn;
333
my @multiplePaths;
334
my @badEssentials;
335
my %svnData;
336
my $cwd;
2412 dpurdie 337
my $mustConvertFileNames;
2438 dpurdie 338
my $workDir;
1271 dpurdie 339
 
340
my $packageNames;
341
my @packageNames;
342
my $multiPackages = -1;
343
my $visitId = 0;
344
my $noTransfer;
345
my $rippleCount = 0;
346
my $svnRepo;
1272 dpurdie 347
my $processCount = 0;
348
my $processTotal = 0;
2412 dpurdie 349
my $recentCount = 0;
350
my $packageReLabelCount = 0;
351
my %saneLabels;
2635 dpurdie 352
my $adjustedPath = 0;
353
my $forceImportFlush = 0;
354
my %restoreData;
355
my @ComboPackageList;
1271 dpurdie 356
 
357
our $GBE_RM_URL;
358
my $UNIX = $ENV{'GBE_UNIX'};
359
 
360
my $result = GetOptions (
361
                "help+"         => \$opt_help,          # flag, multiple use allowed
362
                "manual:3"      => \$opt_help,
363
                "verbose:+"     => \$opt_verbose,       # Versose
364
                "repository:s"  => \$opt_repo,          # Name of repository
2412 dpurdie 365
                'rbase:s'       => \$opt_repo_base,     # Base of the repo
1271 dpurdie 366
                "flat!"         => \$opt_flat,          # Flat structure
367
                "test!"         => \$opt_test,          # Test operations
368
                "reuse!"        => \$opt_reuse,         # Reuse ClearCase views
369
                "age:i"         => \$opt_age,           # Only recent versions
370
                "dump:1"        => \$opt_dump,          # Dump Data
371
                "images:1"      => \$opt_images,        # Create DOT images
372
                "retain:i"      => \$opt_retaincount,   # Retain N packages
373
                "pruneMode:s"   => \$opt_pruneModeString,
374
                "listtags:i"    => \$opt_listTags,
375
                "name:s"        => \$opt_name,          # Alternate output
376
                "tip:s"         => \@opt_tip,           # Force tip version(s)
377
                "log!"          => \$opt_log,
1272 dpurdie 378
                "delete!"       => \$opt_delete,
1271 dpurdie 379
                "postimage!"    => \$opt_postimage,
2635 dpurdie 380
                'workdir:s'         => \$opt_workDir,
381
                'relabel!'          => \$opt_relabel,
382
                'svn!'              => \$opt_useSvn,
383
                'testRmDatabase'    => \$opt_testRmDatabase,
384
                'fromSvn!'          => \$opt_extractFromSvn,
385
                'resume'            => \$opt_resume,
386
                'mergePackages:s'   => \$opt_mergePackages,
387
 
388
                # File list support
1271 dpurdie 389
                'filelist:s'    => \$opt_fileList,      # A list of CC tags
2635 dpurdie 390
                'subdir:s'      => \$opt_repoSubdir,    # Subdir within repo
391
                'ccbase:s'      => \$opt_ccbase,        # ClearCase Base for CC Tags
392
 
1271 dpurdie 393
                );
394
 
395
#
396
#   Process help and manual options
397
#
398
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
399
pod2usage(-verbose => 1)  if ($opt_help == 2 );
400
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));
401
 
402
#
403
#   Configure the error reporting process now that we have the user options
404
#
405
SystemConfig ('ExitOnError' => 1);
406
ErrorConfig( 'name'    =>'CC2SVN_IMPORT',
407
             'verbose' => $opt_verbose,
408
              );
409
 
410
Error("Workdir does not exist" ) unless ( -d $opt_workDir );
411
Error("Specify a package as 'name'" ) unless ( defined $ARGV[0] );
2635 dpurdie 412
Error("-Filelist requires -ccbase") unless ( !$opt_fileList || ($opt_fileList && $opt_ccbase) );
413
 
1271 dpurdie 414
EnvImport('GBE_RM_URL');
415
$cwd = Getcwd();
416
 
417
#
2635 dpurdie 418
#   Allow use of the test database
419
#   Defaut is live data, but some error recovery stuff can be done via
420
#   the test database.
421
#
422
if ( $opt_testRmDatabase )
423
{
424
    Warning ("Using Test Database");
425
    $ENV{GBE_RM_USERNAME} = 'RELEASE_MANAGER';
426
    $ENV{GBE_RM_PASSWORD} = 'RELEASE_MANAGER';
427
    $ENV{GBE_RM_LOCATION} = 'jdbc:oracle:thin:@auperaora07.vix.local:1521:RELMANU1';
428
}
429
 
430
#
1271 dpurdie 431
#   Init the pruning mode
432
#
433
setPruneMode( $opt_pruneModeString || 'ripple');
434
 
2635 dpurdie 435
#
436
#   Detect Merge Package Request
437
#   These use pre-configured bits
438
#
439
if ( $opt_mergePackages )
440
{
441
    if ( $opt_mergePackages eq 'LinuxDrivers' )
442
    {
443
        @ARGV = qw (linux_drivers_eb5600
444
                    linux_drivers_viper
445
                    linux_drivers_cobra
446
                    linux_drivers_etx86
447
                    linux_drivers_tp5600);
448
#                    linux_drivers_bcp4600
449
 
450
        $opt_name = $opt_mergePackages;
451
    } else
452
    {
453
        Error ("Unknown Merge Package Name: $opt_mergePackages");
454
    }
455
}
456
 
457
 
1271 dpurdie 458
if ( $opt_fileList )
459
{
460
    GetData_by_filelist( $opt_fileList );
461
    push @packageNames, $ARGV[0];
462
    $multiPackages++;
463
 
464
}
465
else
466
{
467
    #
468
    #   Get data for all packages
469
    #
470
    foreach my $packageName ( @ARGV )
471
    {
472
        next unless ( $packageName );
473
        Verbose( "Base Package: $packageName");
474
 
475
        my $pkg_id = GetPkgIdByName ( $packageName );
476
        GetData_by_pkg_id ( $pkg_id, $packageName  );
477
        $pkg_ids{$pkg_id} = 1;
478
        $first_pkg_id = $pkg_id unless ( $first_pkg_id );
479
        push @packageNames, $packageName;
480
        $multiPackages++;
481
    }
482
 
483
    {
484
        #
485
        #   Delete entries that have been created as we read in
486
        #   data, but don't exist in RM. They will not have a pvid.
487
        #
488
        foreach my $entry ( keys(%versions) )
489
        {
490
            delete $versions{$entry}
491
                unless ( exists $versions{$entry}{pvid} );
492
        }
493
    }
494
}
495
 
496
$totalVersions = scalar keys %versions;
497
Error ("No packages specified") unless ( $multiPackages >= 0 );
498
Warning ("Multiple Packages being processed") if ( $multiPackages > 1 );
499
$packageNames = join ('_', @packageNames );
500
$packageNames = $opt_name if ( defined $opt_name );
501
Message ("PackageName: $packageNames" );
502
 
503
#
504
#   Save logging data
505
#
506
if ( $opt_log )
507
{
508
    my $opt_logfile = $packageNames . '.import';
509
    Message ("Logging outout: $opt_logfile" );
510
    open STDOUT, '>', $opt_logfile  or die "Can't redirect STDOUT: $!";
511
    open STDERR, ">&STDOUT"         or die "Can't dup STDOUT: $!";
512
}
513
 
514
#
515
#   Prepare tip version hash
516
#
517
$tipVersions{$_} = 1 foreach ( @opt_tip );
518
 
519
#
520
#   Read in external data and massage it all
521
#
522
getEssenialPackageVersions() unless $opt_fileList;
523
getVobMapping();
524
smartPackageType();                 # Determine special prune mode
525
ReportPathVariance();
526
massageData();
527
getSvnData();
528
smartPackageType();                 # Have another go
2635 dpurdie 529
restoreData() if ( $opt_resume );
1271 dpurdie 530
 
531
my @missedTips = keys %tipVersions;
532
Error ("Specified tip version not found: @missedTips") if ( @missedTips );
533
 
534
if ( $opt_flat )
535
{
536
#    @flatOrder = sort {$versions{$a}{version} cmp $versions{$b}{version}} keys(%versions);
537
#    @flatOrder = sort {$versions{$a}{created} cmp $versions{$b}{created}} keys(%versions);
2635 dpurdie 538
 
539
    if ( $flatMode == 1 ) {
540
        Message ("Flat import. Sorted by TimeStamp");
541
        @flatOrder = sort {$versions{$a}{TimeStamp} cmp $versions{$b}{TimeStamp}} keys(%versions);
542
    } else {
543
        @flatOrder = sort {$a <=> $b} keys(%versions);
544
    }
1271 dpurdie 545
    my $tip = $flatOrder[-1];
546
    $versions{$tip}{Tip} = 1 if $tip;
547
}
548
 
549
#
550
#   Generate dumps and images
551
#
552
if ( $opt_images )
553
{
554
    createImages();
555
}
556
 
557
if ( $opt_dump )
558
{
559
    DebugDumpData ("Versions", \%versions );
560
    DebugDumpData ("Starts", \@startPoints );
561
    DebugDumpData ("Ends", \@endPoints );
562
    DebugDumpData ("Suffixes", \%suffixes );
563
}
564
 
565
 
566
#   Display VCS tags
567
#
568
if ( $opt_listTags )
569
{
570
    foreach my $entry (sort {$versions{$a}{version} cmp $versions{$b}{version}} keys(%versions) )
571
    {
572
        print $versions{$entry}{vcsTag} || '-' ,"\n";
573
    }
574
}
575
exit if ( ($opt_dump > 1) || ($opt_images > 1) );
576
 
577
transferPackageToSvn();
578
 
579
if ( $opt_postimage )
580
{
581
    getSvnData();
582
    createImages();
583
}
584
 
585
exit 0;
586
 
587
#-------------------------------------------------------------------------------
588
# Function        : transferPackageToSvn
589
#
590
# Description     : Transfer the package to SVN
591
#
592
# Inputs          : 
593
#
594
# Returns         : 
595
#
596
sub transferPackageToSvn
597
{
598
    Error ("Repository Path not setup")
599
        unless ( $svnRepo );
600
 
601
    #
602
    #   Going to do serious work
603
    #   Need to ensure we have more arguments
604
    #
2635 dpurdie 605
    if ( $opt_protected )
606
    {
607
        Warning("Protected Package not transferred: $packageNames - $opt_protected",
608
                "See cc2svn_protected.txt for details");
609
        exit 0;
610
    }
611
 
1271 dpurdie 612
    if ( $noTransfer )
613
    {
2635 dpurdie 614
        Warning("Protected Package not transferred: $packageNames",
615
                "Configured within this program");
1271 dpurdie 616
        exit 0;
617
    }
618
 
619
    #
620
    #   Perform all the work in a package specific subdirectory
621
    #
2438 dpurdie 622
    $workDir = $opt_workDir . '/' . $packageNames;
1271 dpurdie 623
    mkdir $workDir unless ( -d $workDir );
624
    chdir $workDir || Error ("Cannot cd to $workDir");
625
 
626
    #
627
    #   Process all packages
628
    #       Going to create versions based on RM structure
629
    #       May have several starting points: Process each
630
    #
631
    newPackage();
632
    if ( $opt_flat )
633
    {
634
        newProject();
635
        foreach my $entry (@flatOrder )
636
        {
637
            newPackageVersion( $entry, $versions{$entry}{suffix} );
2635 dpurdie 638
            unless ( $globalError )
639
            {
640
                getSvnData();
641
                createImages();
642
            }
1271 dpurdie 643
        }
644
    }
645
    else
646
    {
647
        processBranch(@allStartPoints);
648
    }
649
    endPackage();
650
 
651
    chdir $cwd || Error ("Cannot cd back to $cwd");
652
    rmdir $workDir;
653
    Warning ("Work Directory still exists: $workDir");
654
    saveData();
655
}
656
 
657
#-------------------------------------------------------------------------------
658
# Function        : setPruneMode
659
#
660
# Description     : Set the pruning mode
661
#
662
# Inputs          : mode                    - Text mode value
663
#
664
# Returns         : Nothing
665
#
666
sub setPruneMode
667
{
668
    my ($mode) = @_;
669
    my $value;
670
    if ( $mode )
671
    {
672
        if ( $mode =~ m/none/i) {
673
            $value = 0;
674
        } elsif ( $mode =~ m/ripple/i) {
675
            $value = 1;
676
        } elsif ( $mode =~ m/retain/i) {
677
            $value = 2;
678
        } elsif ( $mode =~ m/severe/i) {
679
            $value = 3;
680
        } else {
681
            Error ("Unknown pruning mode", "Use: none, ripple, retain or severe");
682
        }
683
 
684
        $pruneModeString = $mode;
685
        $pruneMode = $value;
686
    }
687
}
688
 
689
#-------------------------------------------------------------------------------
690
# Function        : smartPackageType
691
#
692
# Description     : Have a look at the projects in the package set and
693
#                   attempt to determine what sort of mechanism to use
694
#
695
# Inputs          : Uses %suffixes data
696
#
697
# Returns         : 
698
#
699
my $packageType = 'UNKNOWN';
700
sub smartPackageType
701
{
702
    #
703
    #   Rebuild suffixes hash based on  post massaged versions
704
    #
705
    my %suffixes;
706
    my @unknown;
707
    foreach my $entry ( keys %versions )
708
    {
709
        my $suffix = $versions{$entry}{suffix} || '';
710
        push (@unknown, $entry) if ($suffix eq 'unknown');
711
 
712
        next if ( exists $suffixes{$suffix} );
713
        next if ( $versions{$entry}{badSingleton} );
714
        next if ( $versions{$entry}{locked} eq 'N' || $versions{$entry}{isaWip} );
715
        $suffixes{$suffix} = 1;
716
        $knownProjects{$suffix}{seen} = 1;
717
 
718
    }
719
 
720
    #
721
    #   The 'unknown' suffix is really an 'empty' suffix
722
    #   Try to be clever
723
    #       Map unknown to 'cr' or 'mas' if present
724
    #
725
    #
726
    if ( exists $suffixes{'unknown'}  )
727
    {
728
        my $new_suffix;
729
        if ( exists $suffixes{'.cr'} ) {
730
            $new_suffix = '.cr';
731
        } elsif ( exists $suffixes{'.mas'} ) {
732
            $new_suffix = '.mas';
733
        }
734
 
735
        if ( $new_suffix )
736
        {
737
            foreach my $entry ( @unknown )
738
            {
739
                $versions{$entry}{suffix} = $new_suffix;
740
            }
741
            delete $suffixes{'unknown'};
742
            delete $knownProjects{'unknown'}{seen};
743
        }
744
    }
745
 
746
    if ( exists $suffixes{'.cots'} && !exists ($notCots{$packageNames}) ) {
747
        $packageType = 'COTS';
748
        $Projects{'.cots'}{Trunk} = 1;
749
        $singleProject = 1;
750
        $opt_flat = 1 unless defined $opt_flat;
751
        setPruneMode('none') unless (defined $opt_pruneModeString);
752
 
753
    } elsif ( exists $suffixes{'.tool'} ) {
754
        $packageType = 'TOOL';
2412 dpurdie 755
        $Projects{'.tool'}{Trunk} = 1;
1271 dpurdie 756
        $singleProject = 1;
757
        setPruneMode('none') unless (defined $opt_pruneModeString);
758
#        $opt_flat = 1;
759
 
760
    } elsif ( scalar (keys %suffixes ) == 1 ) {
761
        $packageType = 'SINGLE_PROJECT';
762
        $singleProject = 1;
763
 
764
    } else {
765
        $packageType = 'MULTIPLE_PROJECT';
766
    }
767
 
768
    #
769
    #   Some packages are special
770
    #
2412 dpurdie 771
    if ( $svnRepo =~ m~/Manufacturing(/|$)~ )
772
    {
773
        Message ("Set Manufacturing Repo style");
774
        $opt_flat = 1;
775
        setPruneMode('none') unless (defined $opt_pruneModeString);
776
    }
1271 dpurdie 777
 
2412 dpurdie 778
 
2635 dpurdie 779
    if ( $packageNames =~ m'^br_applet_' )
1271 dpurdie 780
    {
2412 dpurdie 781
      $opt_flat = 1 unless defined $opt_flat;
1271 dpurdie 782
    }
783
 
2635 dpurdie 784
    if ( exists $specialPackages{$packageNames} )
2412 dpurdie 785
    {
2635 dpurdie 786
        my $data = ',' . $specialPackages{$packageNames} . ',';
2412 dpurdie 787
 
1271 dpurdie 788
        if ( index( $data, ',all' ) >= 0) {
789
            setPruneMode('none') unless (defined $opt_pruneModeString);
790
        }
791
 
2635 dpurdie 792
        if ( index( $data, ',protected,' ) >= 0) {
1271 dpurdie 793
            $noTransfer = 1;
794
        }
795
 
2635 dpurdie 796
        if ( index( $data, ',flat,' ) >= 0) {
1271 dpurdie 797
            $opt_flat = 1;
798
        }
799
 
2635 dpurdie 800
        if ( index( $data, ',flatTime,' ) >= 0) {
801
            Message ("Flatten import tree. Sort by Time");
802
            $opt_flat = 1;
803
            $flatMode = 1;          # By Time
804
            $opt_processRipples = 0;
805
        }
806
 
807
 
808
        if ( index( $data, ',SetProjectBase,' ) >= 0) {
1271 dpurdie 809
            $opt_preserveProjectBase = 1;
810
            $opt_ignoreProjectBaseErrors = 1;
811
            Message ("Preserving ProjectBase");
812
        }
813
 
2635 dpurdie 814
        if ( index( $data, ',AllowMultiPath,' ) >= 0) {
815
            $opt_AllowMuliplePaths = 1;
816
            Message ("Allowing Multiple Paths");
817
        }
818
 
819
        if ( $data =~ m~,ForceProjectBase=(.*?),~ ) {
820
            $opt_forceProjectBase = $1;
821
            $opt_AllowMuliplePaths = 1;
822
            Message ("Force Project Base: $opt_forceProjectBase");
823
        }
824
 
825
        if ( $data =~ m~,LimitProjectBase=(.*?),~ ) {
826
            $opt_AllowMuliplePaths = 1;
827
            @opt_limitProjectBase = split(':', $1);
828
            Message ("Limit Project Base: @opt_limitProjectBase");
829
        }
830
 
831
        if ( $data =~ m~,mergePaths=(.*?),~ ) {
832
            @opt_mergePaths = split(':', $1);
833
            Message ("Merge Paths: @opt_mergePaths");
834
        }
835
 
836
        if ( $data =~ m~,Packages=(.*?),~ ) {
837
            @ComboPackageList =  split(':', $1);
838
            Message ("ComboPackage: @ComboPackageList");
839
        }
840
 
841
        if ( index( $data, ',IgnoreProjectBase,' ) >= 0) {
1271 dpurdie 842
            $opt_ignoreProjectBaseErrors = 1;
843
            Message ("Ignore ProjectBase Errors");
844
        }
845
 
2635 dpurdie 846
        if ( index( $data, ',IgnoreMakeProject,' ) >= 0) {
2438 dpurdie 847
            $opt_ignoreMakeProjectErrors = 1;
848
            Message ("Ignore MakeProject Usage");
849
        }
2635 dpurdie 850
 
851
        if ( index( $data, ',IgnoreBadPath,' ) >= 0) {
852
            $opt_ignoreBadPaths = 1;
853
            Message ("Ignore Bad Paths in makefile Usage");
854
        }
2438 dpurdie 855
 
2635 dpurdie 856
        if ( index( $data, ',utf8,' ) >= 0) {
2412 dpurdie 857
            $mustConvertFileNames = 1;
858
            Message ("Convert filenames to UTF8");
859
        }
1271 dpurdie 860
    }
861
 
862
    Message("Package Type: $packageType, $pruneModeString");
863
}
864
 
865
 
866
#-------------------------------------------------------------------------------
867
# Function        : massageData
868
#
869
# Description     : Massage all the data to create a tree of package versions
870
#                   that can be used to create images as well as an import order
871
#
872
# Inputs          : 
873
#
874
# Returns         : 
875
#
876
my $reprocess=0;
877
sub calcLinks
878
{
879
    #
880
    #   Process the 'versions' hash and:
881
    #   Add back references
882
    #   Find starts and ends
883
    #       Entry with no previous
884
    #       Entry with no next
885
    #
886
    $reprocess = 0;
887
    foreach my $entry ( keys(%versions) )
888
    {
889
        foreach ( @{ $versions{$entry}{next}} )
890
        {
891
            $versions{$_}{last} = $entry;
892
        }
893
    }
894
    @allStartPoints = ();
895
    @startPoints = ();
896
    @endPoints = ();
897
    foreach my $entry ( keys(%versions) )
898
    {
899
        push @startPoints, $entry
900
            unless ( exists $versions{$entry}{last} || $versions{$entry}{badSingleton} );
901
 
902
        push @allStartPoints, $entry
903
            unless ( exists $versions{$entry}{last} );
904
 
905
        push @endPoints, $entry
906
            unless ( @{$versions{$entry}{next}} > 0  )
907
    }
908
}
909
 
910
sub massageData
911
{
912
    #
913
    #   Report unknown suffixes
914
    #   Handle bad, or little known project suffixes by creating them
915
    #
916
    foreach my $suffix ( keys %suffixes )
917
    {
918
        if ( exists $Projects{$suffix} )
919
        {
920
            next;
921
        }
922
        Message ("Unknown project suffix: '$suffix'");
923
        push @unknownProjects, $suffix;
924
        my $cleanSuffix = ucfirst(lc(substr( $suffix, 1)));
925
        $Projects{$suffix}{Name} = 'Project_' . $cleanSuffix;
926
    }
927
 
928
    calcLinks();
929
 
930
    $initialTrees = scalar @allStartPoints;
931
    Message ('Total RM versions: ' . $totalVersions );
932
    Message ('Initial trees: ' . $initialTrees );
933
    #
934
    #   Attempt to glue all the start points into one chain.
935
    #   This should allow us to track projects that branch from each other
936
    #   in cases where the RM data is incorrect/incomplete
937
    #       Strays are those that have no next or last
938
    #
939
    #   Glue based on Name, then PVID (Creation Order)
940
    #
941
    {
942
        #
943
        #   Examine threads. If it is a single entry thats bad then drop it
944
        #   This is simple to do. Should examine all entries, but thats a
945
        #   bit harder. Perhaps later.
946
        #
947
        if (1) {
948
            Message ("Dropping Bad Singletons");
949
            my $badSingletons;
950
            foreach my $entry ( sort {$a <=> $b} @startPoints )
951
            {
952
                my $ep = $versions{$entry};
953
                unless ( $ep->{last} || $ep->{next}[0] )
954
                {
955
#                    if (  $ep->{isaWip}  )
956
                    if ( (exists $ep->{badVcsTag} && $ep->{badVcsTag}) || $ep->{isaWip}  )
957
                    {
958
                        $ep->{badSingleton} = 1;
959
                        $reprocess = 1;
960
                        $badSingletonCount++;
961
 
962
                        # Add to a list of its own.
963
                        if ( $badSingletons )
964
                        {
965
                            push @{$versions{$badSingletons}{next}}, $entry;
966
                        }
967
                        $badSingletons = $entry;
968
                    }
969
                }
970
            }
971
            calcLinks()
972
                if ( $reprocess );
973
        }
974
 
975
        #
976
        #   Create simple trees out of the chains
977
        #   Tree is based on suffix (project) and version
978
        #
979
        {
980
            my %trees;
981
            Message ("Entries into trees");
982
            foreach my $single ( @startPoints )
983
            {
984
                my $suffix = $versions{$single}{suffix} || '';
985
                push @{$trees{$suffix}}, $single;
986
            }
987
 
988
            foreach  ( keys %trees )
989
            {
990
                my $last;
991
                foreach my $entry ( sort { $versions{$a}{version} cmp $versions{$b}{version}  } @{$trees{$_}} )
992
                {
993
                    if ( $last )
994
                    {
995
                        $versions{$last}{MakeTree} = 1;
996
                        push @{$versions{$last}{next}}, $entry;
997
                        $reprocess = 1;
998
                    }
999
                    $last = $entry;
1000
                }
1001
            }
1002
            calcLinks()
1003
                if ( $reprocess );
1004
        }
1005
 
1006
        #
1007
        #   Have a number of trees that are project related
1008
        #   Attempt to create a single tree by inserting
1009
        #   Secondary trees into the main line at suitable points
1010
        #
1011
        my @AllVersions = sort { $a <=> $b } @startPoints;
1012
        my $lastEntry = shift @AllVersions;
1013
        Error ("Oldest entry has a previous version") if ( $versions{$lastEntry}{last}  );
1014
#print "Oldest: $lastEntry\n";
1015
        #
1016
        #   Insert remaining entries into out list, which is now sorted
1017
        #
1018
        my @completeList;
1019
        foreach my $base ( @AllVersions  )
1020
        {
1021
            push @completeList, recurseList($lastEntry);
1022
            @completeList = sort {$a <=> $b} @completeList;
1023
#            Message("Complete List: ", @completeList);
1024
#            Message("Complete List($completeList[0]) Length: " . scalar @completeList);
1025
            $lastEntry = $base;
1026
 
1027
            my $last;
1028
            foreach my $entry ( @completeList )
1029
            {
1030
                if ( $entry > $base )
1031
                {
1032
                    Error ("Not expecting last to be empty. $base, $entry") unless ( $last );
1033
                    last;
1034
                }
1035
                $last = $entry;
1036
            }
1037
 
1038
            #
1039
            #   Insert at end if point not yet found
1040
            #
1041
#print "Inserting $base at $last\n";
1042
            push @{$versions{$last}{next}}, $base;
1043
            $versions{$base}{GluedIn} = 1;
1044
            $reprocess = 1;
1045
        }
1046
 
1047
        #
1048
        #   Recalc basic links if any processing done
1049
        #
1050
        calcLinks()
1051
            if ( $reprocess );
1052
 
1053
    }
1054
 
1055
 
1056
    #
1057
    #   Remove Dead Ends
1058
    #   Packages that were never released
1059
    #       Not locked, unless essential or a branchpoint
1060
    #   Won't consider these to be mainline path.
1061
    #
1062
    {
1063
        Message ("Remove Dead Ends");
1064
        foreach my $entry ( @endPoints )
1065
        {
1066
            my $deadWood;
1067
            while ( $entry )
1068
            {
1069
                last if ( $versions{$entry}{Essential} );
1070
 
1071
                my @next = @{$versions{$entry}{next}};
1072
                my $count = @next;
1073
                last if ( $count > 1 );
1074
 
1075
                last unless ( $versions{$entry}{locked} eq 'N' || $versions{$entry}{isaWip} );
1076
 
1077
                $versions{$entry}{DeadWood} = 1;
1078
                $trimCount++;
1079
            } continue {
1080
                $entry = $versions{$entry}{last};
1081
            }
1082
        }
1083
    }
1084
 
1085
    #
1086
    #   Walk each starting point list and determine new Projects
1087
    #   branchpoints.
1088
    #
1089
    Message ("Locate Projects branch points");
1090
    foreach my $bentry ( keys(%versions) )
1091
    {
1092
        my $baseSuffix = $versions{$bentry}{suffix};
1093
        foreach my $entry ( @{$versions{$bentry}{next}} )
1094
        {
1095
            if ( $baseSuffix ne $versions{$entry}{suffix})
1096
            {
1097
                unless ( exists $versions{$entry}{DeadWood} || $versions{$entry}{badSingleton} )
1098
                {
1099
#print "--- Project Branch $versions{$entry}{vname}\n";
1100
                    $versions{$entry}{branchPoint} = 1;
1101
                    $versions{$entry}{newSuffix} = 1;
1102
                }
1103
            }
1104
        }
1105
    }
2412 dpurdie 1106
 
1107
    #
1108
    #   Mark UkHops special points
1109
    #
1110
    foreach my $entry ( keys(%versions) ) {
1111
        foreach my $rtag_id ( keys %{$versions{$entry}{Releases}}  ) {
1112
            next unless ( exists $ukHopsReleases{$rtag_id} );
1113
            next unless ( $svnRepo =~ m~/ITSO_TRACS$~ );
1114
 
1115
            #
1116
            #   This package is current in a special ukHops release
1117
            #   Need to handle the differently
1118
            #
1119
            my $ukData =  $ukHopsReleases{$rtag_id};
1120
 
1121
            # Mark version we want on the trunk
1122
            # Will calculate tip later
1123
            if ( $ukData->{trunk} )
1124
            {
1125
                #
1126
                #   Can only place on trunk IFF its a tip
1127
                #   May have a WIP.
1128
                #   Solution. Walk to the tip, but only if there is one
1129
                #             path.
1130
                #
1131
                my $end = $entry;
1132
                my $last;
1133
                while ( $end )
1134
                {
1135
                    $last = $end;
1136
                    if ( @{$versions{$end}{next}} > 1)
1137
                    {
1138
                        Warning ("Uk Release. Preferred trunk is not a tip: $versions{$entry}{vname}");
1139
                        last;
1140
                    }
1141
 
1142
                    $end = @{$versions{$end}{next}}[0];
1143
                }
1144
                $versions{$last}{ukTrunk} = 1 ;
1145
            }
1146
 
1147
            #
1148
            #   What to do if the version is in more than one release
1149
            #
1150
            $versions{$entry}{ukBranch}++;
1151
            if ( $versions{$entry}{ukBranch} > 1 )
1152
            {
1153
                Warning ("Version found in multiple Uk Releases - don't know what to do");
1154
            }
1155
 
1156
            #
1157
            #   What to do if the package has multiple version in a release
1158
            #
1159
            $ukData->{count}++;
1160
            if ( $ukData->{count} > 1 )
1161
            {
1162
                Warning ("Package has multiple versions in the one Uk Release: $versions{$entry}{Releases}{$rtag_id}{rname}");
1163
            }
1164
        }
1165
    }
1271 dpurdie 1166
 
1167
    #
1168
    #   Prune
2635 dpurdie 1169
    #       Marks paths to root for all essential packages
1170
    #       Marks the last-N from all essential packages
1271 dpurdie 1171
    #
1172
    if ( $pruneMode )
1173
    {
1174
        Message ("Prune Tree: $pruneModeString");
1175
        foreach ( @EssentialPackages )
1176
        {
1177
            #next unless ( exists $versions{$_} );      # Aleady deleted
1178
 
1179
            # Mark previous-N to be retained as well
1180
            my $entry = $_;
1181
            my $count = 0;
1182
            while ( $entry )
1183
            {
1184
                last if ( $versions{$entry}{KeepMe} );
2412 dpurdie 1185
#                unless ( $versions{$entry}{isaRipple} )
1271 dpurdie 1186
                {
1187
                    my $keepFlag = ($count++ < $opt_retaincount);
1188
                    last unless ( $keepFlag );
1189
                    $versions{$entry}{KeepMe} = $keepFlag;
1190
                }
1191
                $entry = $versions{$entry}{last}
1192
            }
1193
        }
1194
 
1195
        #
2412 dpurdie 1196
        #   Keep recent versions
1197
        #       Keep versions created in the last N days
1198
        #       Will keep recent ripples too
1199
        #
2635 dpurdie 1200
        if ( $pruneMode == 1 )                      # 1 == ripple
2412 dpurdie 1201
        {
1202
            foreach my $entry ( keys(%versions) )
1203
            {
1204
                next unless ( $versions{$entry}{Age} <= $opt_recentAge  );
1205
                $versions{$entry}{keepRecent} = 1;
1206
                $recentCount++;
1207
#print "--- Recent version $versions{$entry}{vname}, $versions{$entry}{Age} <= $opt_recentAge\n";
1208
            }
1209
 
2635 dpurdie 1210
            #
1211
            #   Keep the tip of each branch
1212
            #
1213
            foreach my $entry ( @endPoints )
1214
            {
1215
#print "--- Tip version $versions{$entry}{vname}\n";
1216
                my $count = 0;
1217
                while ( $entry && $count < 2)
1218
                {
1219
                    last if ( $versions{$entry}{Essential} );
1220
                    last if ( $versions{$entry}{keepRecent} );
1221
 
1222
                    next if ( $versions{$entry}{locked} eq 'N'  );
1223
                    next if ( $versions{$entry}{DeadWood} );
1224
 
1225
#print "--- Keeping Tip version $versions{$entry}{vname}\n";
1226
                    $versions{$entry}{keepRecent} = 1;
1227
                    $count++;
1228
 
1229
                } continue {
1230
                    $entry = $versions{$entry}{last};
1231
                }
1232
            }
2412 dpurdie 1233
        }
1234
 
1235
        #
1271 dpurdie 1236
        #   Keep versions that are common parents to Essential Versions
1237
        #       Mark paths through the tree to essential versions
1238
        #       Mark nodes with the number of essential versions that they sprout
1239
        #   Don't do it if we are ripple pruning
1240
        #
1241
        Message ("Prune Tree keep common parents");
1242
        if ( $pruneMode != 1 )
1243
        {
1244
            foreach my $entry ( @endPoints )
1245
            {
1246
                my $hasEssential = 0;
1247
                $visitId++;
1248
                while ( $entry )
1249
                {
1250
                    $hasEssential = 1 if ( exists ($versions{$entry}{Essential}) && $versions{$entry}{Essential} );
1251
                    if ( $hasEssential )
1252
                    {
1253
                        if ( @{$versions{$entry}{next}} > 1 )
1254
                        {
1255
                            $versions{$entry}{EssentialSplitPoint}++;
1256
                        }
1257
                        last if ( exists $versions{$entry}{EssentialPath} );
1258
                        $versions{$entry}{EssentialPath} = 1;
1259
                    }
1260
 
1261
                    if ( ($versions{$entry}{visitId} || 0) == $visitId )
1262
                    {
1263
                        DebugDumpData ("Versions", \%versions );
1264
                        Warning ("Circular dependency");
1265
                        last;
1266
                    }
1267
                    $versions{$entry}{visitId} = $visitId;
1268
 
1269
                    $entry = $versions{$entry}{last};
1270
                }
1271
            }
1272
        }
1273
 
1274
        #
1275
        #   Keep first version of each ripple. Must keep first
1276
        #   Group ripples together so that they can be proccessed at the same time
1277
        #
1278
        calcRippleGroups()
1279
            if ( $pruneMode == 1);
1280
 
1281
        #
1282
        #   Delete all nodes that are not marked for retention
1283
        #   This is rough on the tree
1284
        #
1285
        Message ("Prune Tree Deleting");
1286
 
1287
        # 0 - Keep me
1288
        # 1 - Prune me
1289
        sub pruneMe
1290
        {
1291
            my ($entry) = @_;
1292
 
1293
            return 0 unless ( exists $versions{$entry} );
1294
            return 0 unless ( $versions{$entry}{last} );
2412 dpurdie 1295
#            return 0 if ( ($pruneMode == 2) && exists $versions{$entry}{KeepMe} );
1296
            return 0 if ( exists $versions{$entry}{KeepMe} );
1271 dpurdie 1297
            return 0 if ( exists $versions{$entry}{Essential} );
1298
            return 0 if ( $versions{$entry}{newSuffix} );
1299
            return 0 if ( $versions{$entry}{newSuffix} && (exists $versions{$entry}{EssentialPath}) );
1300
#            return 1 if ( exists $versions{$entry}{DeadWood} );
1301
            return 0 if ( exists $versions{$entry}{EssentialSplitPoint} && $versions{$entry}{EssentialSplitPoint} > 1 );
1302
            return 0 if ( exists $versions{$entry}{keepLowestRipple} &&  $versions{$entry}{keepLowestRipple} );
1303
            return 0 if ( ($pruneMode == 1) && ! $versions{$entry}{isaRipple} );
2412 dpurdie 1304
            return 0 if ( exists $versions{$entry}{keepRecent} && $versions{$entry}{keepRecent} );
1271 dpurdie 1305
            return 1;
1306
        }
1307
 
1308
        foreach my $entry ( keys(%versions) )
1309
        {
1310
#last;
1311
            next unless ( pruneMe($entry) );
1312
#print "--- Prune: $versions{$entry}{vname}\n";
1313
 
1314
            # Delete the current node
1315
            #
1316
            my @newNext;
1317
            $pruneCount++;
1318
            my $last = $versions{$entry}{last};
1319
            foreach ( @{$versions{$last}{next}} )
1320
            {
1321
                next if ( $_ == $entry );
1322
                push @newNext, $_;
1323
            }
1324
            foreach ( @{$versions{$entry}{next}} )
1325
            {
1326
                push @newNext, $_;
1327
                $versions{$_}{last} = $last;
1328
            }
1329
 
1330
            @{$versions{$last}{next}} = @newNext;
1331
            delete $versions{$entry};
1332
        }
1333
 
1334
        # Recalculate endpoints
1335
        calcLinks();
1336
    }
1337
    else
1338
    {
1339
        #   No rippling happening
1340
        #   Some process still need to happen
1341
        #
1342
        calcRippleGroups();
1343
    }
1344
 
1345
    #
2412 dpurdie 1346
    #   Want some versions to be forced to tip trunk
1347
    #
1348
    foreach my $name ( keys %ukHopsTip )
1349
    {
1350
        foreach my $entry ( keys(%versions) )
1351
        {
1352
            next unless ( $versions{$entry}{name} eq $name  );
1353
            next unless ( exists $versions{$entry}{Releases}{$ukHopsTip{$name}} );
1354
 
1355
            #
1356
            #   Force this suffix to be the trunk
1357
            #   Remove all others
1358
            #
1359
            foreach my $suffix ( keys %Projects )
1360
            {
1361
                delete $Projects{$suffix}{Trunk};
1362
            }
1363
            my $suffix = $versions{$entry}{suffix};
1364
            $Projects{$suffix}{Trunk} = 1;
1365
        }
1366
    }
1367
 
1368
    #
1271 dpurdie 1369
    #   Calculate best through-path for branches in the tree
1370
    #   Attempt to keep that 'max' version on the mainline
1371
    #   May be modified by -tip=nnnn
1372
    #
1373
    #   For each leaf (end point), walk backwards and mark each node with the
1374
    #   max version see. If we get to a node which already has been marked then
1375
    #   stop if our version is greater. We want the value to be the max version
1376
    #   to a leaf
1377
    #
1378
    #   Account for 'suffix'. When suffix changes, then the 'max' version must
1379
    #   be recalculated
1380
    #
1381
 
1382
    Message ("Calculate Max Version");
1383
    my $maxVersion;
1384
    foreach my $entry ( @endPoints )
1385
    {
1386
        my $lastSuffix;
1387
        my $forceTip;
1388
        while ( $entry )
1389
        {
1390
            if (!defined($lastSuffix) || ($versions{$entry}{suffix} ne $lastSuffix) )
1391
            {
1392
                $maxVersion = '0';
1393
                $visitId++;
1394
                $forceTip = ( exists $tipVersions{$versions{$entry}{vname}} );
2412 dpurdie 1395
                $forceTip = 1 if $versions{$entry}{ukTrunk};
1271 dpurdie 1396
                delete $tipVersions{$versions{$entry}{vname}};
1397
                $maxVersion = '999.999.999.999.zzz' if ( $forceTip );
1398
                $lastSuffix = $versions{$entry}{suffix};
1399
#print "---Tip Found\n" if $forceTip;
1400
            }
1401
 
1402
            # Detect circular dependencies
1403
            if ( ($versions{$entry}{visitId} || 0) == $visitId )
1404
            {
1405
                DebugDumpData ("Circular dependency: Versions", \%versions );
1406
                Warning ("Circular dependency");
1407
                last;
1408
            }
1409
            $versions{$entry}{visitId} = $visitId;
1410
 
1411
            my $thisVersion = $versions{$entry}{version} || '';
1412
            if ( $thisVersion gt $maxVersion )
1413
            {
1414
                $maxVersion = $thisVersion;
1415
            }
1416
 
1417
            if ( exists $versions{$entry}{maxVersion} )
1418
            {
1419
                if ( $versions{$entry}{maxVersion} gt $maxVersion )
1420
                {
1421
                    last;
1422
                }
1423
            }
1424
 
1425
            $versions{$entry}{maxVersion} = $maxVersion;
1426
            $entry = $versions{$entry}{last};
1427
        }
1428
    }
1429
 
1430
 
1431
    #
1432
    #   Locate all instances where a package-version branches
1433
    #   Determine the version that should be on the non-branching path
1434
    #
1435
    #   Reorder the 'next' list so that the first item is the non-branching
1436
    #   path. This will be used in the data-insertion phase to simplify the
1437
    #   processing.
1438
    #
1439
    Message ("Calculate package version branches");
1440
    foreach my $entry ( sort {$a <=> $b} keys(%versions) )
1441
    {
1442
        calculateWalkOrder($entry);
1443
    }
1444
 
1445
    #
1446
    #   Mark Project Branch Tips as they will be in the Repository
1447
    #   Find each project head and walk primary entry to the end.
1448
    #
1449
    foreach my $entry ( keys(%versions) )
1450
    {
1451
        #
1452
        #   Root of each tree is 'new'
1453
        #
1454
        unless ( defined $versions{$entry}{last})
1455
        {
1456
            unless ( $versions{$entry}{badSingleton} )
1457
            {
1458
                $versions{$entry}{newSuffix} = 1;
1459
            }
1460
        }
1461
 
1462
        #
1463
        #   Update stats
1464
        #
1465
        $badVcsCount++ if ( $versions{$entry}{badVcsTag} );
1466
        $ProjectCount++ if ( $versions{$entry}{newSuffix} );
1467
        next if ( $opt_flat );
1468
 
1469
        next unless ($versions{$entry}{newSuffix} );
1470
#print "--- Project new Suffix $versions{$entry}{vname}\n";
1471
 
1472
 
1473
        my $suffix = $versions{$entry}{suffix};
1474
        $knownProjects{$suffix}{count}++;
1475
 
1476
        my $next = $versions{$entry}{next}[0];
1477
        my $tip;
1478
        while ( $next )
1479
        {
1480
            last if ( $suffix ne $versions{$next}{suffix} );
1481
            $tip = $next unless (exists ($versions{$next}{DeadWood}) || $versions{$next}{badSingleton});
1482
            $next = $versions{$next}{next}[0];
1483
        }
1484
 
1485
        $versions{$tip}{Tip} = 1 if $tip;
1486
    }
1487
 
1488
    unless ( $opt_flat )
1489
    {
1490
        my $finalTrees = scalar @startPoints;
1491
        Warning ("Still have multiple trees: $finalTrees") unless ( $finalTrees == 1 );
1492
    }
1493
 
1494
    #
1495
    #   Display warnings about multiple
1496
    #
1497
    foreach ( sort keys %knownProjects )
1498
    {
1499
        my $count = $knownProjects{$_}{count} || 0;
1500
        Warning ("Multiple Project Roots: $_ ($count)" )
1501
            if ( $count > 1 );
1502
    }
1503
 
1504
    #
1505
    #   Display warnings about Bad Essential Packages
1506
    #
1507
    $allSvn = 1;
1508
    foreach my $entry ( keys(%versions) )
1509
    {
1510
        $rippleCount++ if ( exists($versions{$entry}{isaRipple}) && $versions{$entry}{isaRipple} );
1511
        $allSvn = 0 unless ( $versions{$entry}{isSvn} );
1512
        next unless ( exists $versions{$entry}{Essential}  );
1513
        next unless ( $versions{$entry}{badVcsTag}  );
1514
        push @badEssentials, $entry;
1515
        Warning ("BadVCS Essential: " . GetVname($entry))
1516
    }
1517
 
1518
    #
1519
    #   All done
1520
    #
1272 dpurdie 1521
    $processTotal = scalar keys %versions;
1522
    Message("Retained entries: $processTotal" );
1271 dpurdie 1523
    Message("Pruned entries: $pruneCount");
1524
    Message("Deadwood entries: $trimCount");
1525
    Message("Bad Singletons: $badSingletonCount");
1526
    Message("Ripples: $rippleCount");
2412 dpurdie 1527
    Message("Recent entries: $recentCount");
1271 dpurdie 1528
}
1529
 
1530
sub calculateWalkOrder
1531
{
1532
    my ($entry) = @_;
1533
    my @next = @{$versions{$entry}{next}};
1534
    my $count = @next;
1535
    my @ordered;
1536
    my $main;
1537
 
1538
    if ( $count > 1 )
1539
    {
1540
        # Array to hash to simplify removal
1541
        my %nexts = map { $_ => 1 } @next;
1542
        foreach my $e ( @next )
1543
        {
1544
 
1545
            #
1546
            #   Locate branch points that are not a part of a new project
1547
            #   These will not be preferred paths for walking
1548
            #
1549
            if ( !defined($versions{$e}{branchPoint}) && $versions{$entry}{suffix} ne $versions{$e}{suffix} )
1550
            {
1551
                unless ( exists $versions{$e}{DeadWood} || $versions{$e}{badSingleton}  )
1552
                {
1553
#print "--- Project Branch (1) $versions{$e}{vname}\n";
1554
                    $versions{$e}{branchPoint} = 1;
1555
                    $versions{$e}{newSuffix} = 1;
1556
                }
1557
            }
1558
 
1559
            #
1560
            #   Remove those that already have a branch,
1561
            #
1562
            if ( $versions{$e}{branchPoint} || $versions{$e}{newSuffix} || $versions{$e}{DeadWood}  )
1563
            {
1564
                push @ordered, $e;
1565
                delete $nexts{$e};
1566
            }
1567
        }
1568
        #
1569
        #   Select longest arm as the non-branching path
1570
        #   Note: Reverse sort order
1571
        #         Done so that 'newest' item is given preference
1572
        #         to the main trunk in cases where all subtrees are
1573
        #         the same length
1574
        #
1575
        my $maxData = '';
1576
        my $countEntry;
1577
        foreach my $e ( sort {$b <=> $a} keys %nexts )
1578
        {
1579
            if ( $versions{$e}{maxVersion} gt $maxData )
1580
            {
1581
                $maxData = $versions{$e}{maxVersion};
1582
                $countEntry = $e;
1583
            }
1584
        }
1585
        if ($countEntry)
1586
        {
1587
            $main = $countEntry;
1588
            delete $nexts{$countEntry};
1589
        }
1590
 
1591
        #
1592
        #   Append the remaining
1593
        #
1594
        push @ordered, keys %nexts;
1595
 
1596
        #
1597
        #   Re-order 'next' so that the main path is first
1598
        #   Sort (non main) by number
1599
        #
1600
        @ordered = sort {$a <=> $b} @ordered;
1601
        unshift @ordered, $main if ( $main );
1602
        @{$versions{$entry}{next}} = @ordered;
1603
 
1604
        #
1605
        #   Ensure all except the first are a branch point
1606
        #   First may still be a branch point
1607
        #
1608
        shift @ordered;
1609
        foreach my $e ( @ordered )
1610
        {
1611
            $versions{$e}{branchPoint} = 1;
1612
        }
1613
    }
1614
}
1615
 
1616
#-------------------------------------------------------------------------------
1617
# Function        : calcRippleGroups
1618
#
1619
# Description     : Locate and mark ripple groups
2412 dpurdie 1620
#                   packages that are ripples of each other
1271 dpurdie 1621
#                       Keep first version of each ripple. Must keep first
1622
#                       Group ripples together so that they can be
1623
#                       proccessed at the same time
1624
#
1625
# Inputs          : 
1626
#
1627
# Returns         : 
1628
#
1629
sub calcRippleGroups
1630
{
1631
    my %rippleVersions;
1632
    foreach my $entry ( keys(%versions) )
1633
    {
1634
        my $ep = $versions{$entry};
1635
        if ( defined $ep->{buildVersion} )
1636
        {
1637
            my $suffix = $ep->{suffix};
1638
            my ($major, $minor, $patch, $build) = @{$ep->{buildVersion}};
1639
#print "--- $major, $minor, $patch, $build, $suffix\n";
1640
            $rippleVersions{$suffix}{"$major.$minor.$patch"}{count}++;
1641
            my $rp = $rippleVersions{$suffix}{"$major.$minor.$patch"};
1642
            $rp->{list}{$entry} = 1;
1643
 
1644
            next if ( $ep->{badVcsTag} );
1645
            next if ( $ep->{locked} eq 'N');
1646
            if (!defined ($rp->{min}) || $rp->{min} > $build )
1647
            {
1648
                $rp->{pvid} = $entry;
1649
                $rp->{min} = $build;
1650
            }
1651
        }
1652
    }
1653
#            DebugDumpData("rippleVersions", \%rippleVersions );
1654
 
1655
    while ( my($suffix, $e1) = each %rippleVersions )
1656
    {
1657
        while ( my( $mmp, $e2) = each %{$e1} )
1658
        {
1659
            next unless ( exists  $e2->{pvid} );
1660
            my $entry = $e2->{pvid};
1661
            if ( !exists $versions{$entry} )
1662
            {
1663
                Error ("Internal: Expected entry not found: $entry, $mmp");
1664
            }
1665
 
1666
            $versions{$entry}{keepLowestRipple} = 1;
1667
#print "--- Keep Riple $versions{$entry}{vname}\n";
1668
 
1669
            #
1670
            #   Update entry with list of associated ripples, removing lowest
1671
            #
1672
            delete $e2->{list}{$entry};
1673
            my @rippleList = sort keys %{$e2->{list}};
1674
            if ( @rippleList)
1675
            {
1676
#DebugDumpData("LIST: $entry", $e2->{list}, \@rippleList  );
1677
                @{$versions{$entry}{rippleList}} = @rippleList;
1678
            }
1679
        }
1680
    }
1681
}
1682
 
1683
#-------------------------------------------------------------------------------
1684
# Function        : processBranch
1685
#
1686
# Description     : Process one complete branch within the tree of versions
1687
#                   May be called recursivly to walk the tree
1688
#
1689
# Inputs          : Array of package-version ID to process
1690
#
1691
# Returns         : Nothing
1692
#
1693
 
1694
sub processBranch
1695
{
1696
    foreach my $entry ( @_ )
1697
    {
1698
        #
1699
        #   Do we need to create a branch before we can process this package
1700
        #
1701
        if ( $versions{$entry}{newSuffix} || $versions{$entry}{branchPoint} )
1702
        {
1703
            newProject();
1704
            $createBranch = 1;
1705
            $createSuffix = 1 if $versions{$entry}{newSuffix};
1706
        }
1707
 
1708
        newPackageVersion( $entry );
2412 dpurdie 1709
        unless ( $globalError )
1710
        {
1711
            getSvnData();
1712
            createImages();
1713
        }
1714
 
1271 dpurdie 1715
no warnings "recursion";
1716
        processBranch (@{$versions{$entry}{next}});
1717
    }
1718
}
1719
 
1720
#-------------------------------------------------------------------------------
1721
# Function        : newPackageVersion
1722
#
1723
# Description     : Create a package version
1724
#
1725
# Inputs          : $entry              - Ref to entry being proccessed
1726
#
1727
# Returns         :
1728
#
1729
sub newPackageVersion
1730
{
1731
    my ($entry) = @_;
1732
    my %data;
1733
    my $flags = 'e';
1734
    my $rv = 1;
1735
    my $startTime = time();
1736
    my $timestamp = localtime;
1737
 
1738
    $data{rmRef} = 'ERROR';
1739
    $data{tag} = 'ERROR';
1740
 
1741
    #
1742
    #   If its been processed then fake that its been done
1743
    #   May have been a ripple that we processed
1744
    #
1272 dpurdie 1745
    return if ($versions{$entry}{Processed});
1746
    $processCount++;
1271 dpurdie 1747
    Message ("------------------------------------------------------------------" );
1272 dpurdie 1748
    Message ("Package $processCount of $processTotal");
1749
 
1271 dpurdie 1750
    Message ("New package-version: " . GetVname($entry) . " Tag: " . $versions{$entry}{vcsTag} );
1751
 
2412 dpurdie 1752
    #
1753
    #   Detect user abort
1754
    #
1755
    if ( -f $cwd . '/stopfile' )
1756
    {
1757
        $globalError = 1;
1758
        Message ("Stop file located");
1759
    }
1271 dpurdie 1760
 
1761
    #
1762
    #   If we have a global error,then we pretend to process, but we
1763
    #   report errors for the logging system
1764
    #
2412 dpurdie 1765
    if ( $globalError )
1271 dpurdie 1766
    {
2412 dpurdie 1767
        Message ("Global error prevents futher importation");
1768
    }
1769
    else
1770
    {
1271 dpurdie 1771
        #
1772
        #   Call worker function
1773
        #   It will exist on any error so that it can be logged
1774
        #
1775
        $rv = newPackageVersionBody( \%data, @_ );
1776
        $globalError = 1 if ( $rv >= 10 );
1777
    }
1778
 
1779
    #
1780
    #   Highlight essential packages that failed to transfer
1781
    #
1782
    if ( $globalError ) {
1783
        $flags = 'e';
1784
    } elsif ( $rv && ( exists $versions{$entry}{Essential} ) ) {
1785
        $flags = 'X';
1786
    } elsif ( $rv ) {
1787
        $flags = 'E';
1788
    } else {
1789
        $flags = 'G';
1790
    }
1791
 
1792
    #
1793
    #   Always log results to a file
1794
    #   Flags:
1795
    #       e - Error: Global Fatal causes other versions to be ignored
1796
    #       X - Essential Package NOT proccessed
1797
    #       E - Error processing package
1798
    #       G - Good
1799
    #
1800
    my $duration = time() - $startTime;
1801
    my $line = join(';',
1802
            $flags,
1803
            $entry,
1804
            $packageNames,
1805
            $versions{$entry}{vname},
1806
            $data{rmRef},
1807
            $data{tag},
1808
            $timestamp,
1809
            $duration,
1810
            $data{errStr} || ''
1811
            );
1812
    logToFile( $cwd . '/importsummary.txt', ";$line;");
1813
 
1814
    #
1815
    #   Sava data
1816
    #
2635 dpurdie 1817
    if ( $rv != 6 )
1818
    {
1819
        $data{errFlags} = $flags;
1820
        $data{duration} = $duration;
1821
    }
1271 dpurdie 1822
    $versions{$entry}{rmRef} = $data{rmRef};
1272 dpurdie 1823
    delete $data{rmRef};
1824
    delete $data{tag};
2412 dpurdie 1825
    ##delete $data{ViewRoot};
1272 dpurdie 1826
    $versions{$entry}{data} = \%data;
1271 dpurdie 1827
 
1828
    #
1829
    #   Delete the created view
1830
    #   Its just a directory, so delete it
1831
    #
1832
    if ( $data{ViewRoot} && -d $data{ViewRoot})
1833
    {
2635 dpurdie 1834
        if ( !$opt_reuse || ($rv && ($rv != 4 && $rv != 12 && $rv != 5 )) )
2412 dpurdie 1835
        {
1836
            Message ("Delete View: $data{ViewRoot}");
1837
            RmDirTree ($data{ViewRoot} );
1838
        }
1839
        else
1840
        {
1841
            Message ("Retaining View: $data{ViewRoot}");
1842
        }
1843
 
1271 dpurdie 1844
    }
2412 dpurdie 1845
    else
1846
    {
2438 dpurdie 1847
        Message ("No view to delete");
2412 dpurdie 1848
    }
1271 dpurdie 1849
 
1850
 
2635 dpurdie 1851
    if($opt_processRipples)
1271 dpurdie 1852
    {
2635 dpurdie 1853
        #
1854
        #   If this version has any 'ripples' then process them while we have the
1855
        #   main view. Note the ripple list may contain entries that do not
1856
        #   exist - they will have been pruned.
1857
        #
1858
        foreach my $rentry ( @{$versions{$entry}{rippleList}} )
1859
        {
1860
            next unless( exists $versions{$rentry} );
1271 dpurdie 1861
 
2635 dpurdie 1862
            if ($versions{$rentry}{Processed})
1863
            {
1864
                Warning ("Ripple Processed before main entry");
1865
                $versions{$rentry}{rippleProcessed} = 1;
1866
            }
1867
 
1868
            Message ("Proccessing associated Ripple: " . GetVname($rentry));
1869
            newPackageVersion($rentry);
1271 dpurdie 1870
        }
1871
    }
1872
}
1873
 
1874
#-------------------------------------------------------------------------------
1875
# Function        : newPackageVersionBody
1876
#
1877
# Description     : Perform the bulk of the work in creating a new PackageVersion
1878
#                   Designed to return on error and have error processing
1879
#                   performed by caller
1880
#
1881
# Inputs          : $data               - Shared data
1882
#                   $entry              - Package entry to process
1883
#
1884
# Returns         : Error Code
1885
#                         0 - All is well
1886
#                       <10 - Recoverable error
2635 dpurdie 1887
#                               1 - Bad VCS Tag
1888
#                               2 - No Files in the extracted view
1889
#                                   Label not found
1890
#                                   Failed to extract files from CC
1891
#                                   No Files in the extracted view after labeling dirs
1892
#                               3 - Deadwood
1893
#                               4 - Bad usage of ProjectBase detected
1894
#                                   Use of MakeProject detected
1895
#                               5  - Subversion Import disabled
1896
#                               6  - Restored via resume
1271 dpurdie 1897
#                       >10 - Fatal error
1898
#
1899
sub newPackageVersionBody
1900
{
1901
    my ($data, $entry) = @_;
1902
    my $rv;
2635 dpurdie 1903
    my $vcs_type;
1271 dpurdie 1904
    my $cc_label;
1905
    my $cc_path;
2412 dpurdie 1906
    my $cc_path_original;
1271 dpurdie 1907
 
1908
    #
1909
    #   Init Data
1910
    #
1911
    $data->{rmRef} = 'ERROR';
1912
    $data->{tag} = '';
1913
    $data->{ViewRoot} = undef;
1914
    $data->{ViewPath} = undef;
1915
    $data->{errStr} = '';
1916
    $versions{$entry}{Processed} = 1;
1917
 
1918
 
1919
    SystemConfig ('ExitOnError' => 0);
1920
 
1921
    push @processOrder, $entry;
1922
    return 0 if ( $opt_test );
1923
 
2635 dpurdie 1924
    #
1925
    #   Calculate the label for the target package
1926
    #   Use format <packageName>_<PackageVersion>
1927
    #   Need to handle WIPs too.
1928
    #
1929
    my $import_label = saneLabel($entry);
1930
 
1931
    #
1932
    #   If resuming - then test existence
1933
    #
1934
    if ( $opt_resume )
1935
    {
1936
        if ( exists $restoreData{$entry}  )
1937
        {
1938
 
1939
            #
1940
            #   May be able to test existence by looking at $versions{$entry}{svnVersion}
1941
            #   The hard work may have been done
1942
            #
1943
            my $isInSvn = 0;
1944
            if ( exists $versions{$entry}{svnVersion} && $versions{$entry}{svnVersion}  )
1945
            {
1946
                $isInSvn = 1;
1947
            }
1948
            Message("SvnVersion check: $isInSvn");
1949
 
1950
            $rv = testSvnLabel( "$svnRepo/$packageNames", $import_label );
1951
            unless ( $rv )
1952
            {
1953
                Message ("Skip import - resume detected presense");
1954
                $firstVersionCreated = $entry unless ( $firstVersionCreated );
1955
                $versions{$entry}{TagCreated} = 2;
1956
                foreach  ( keys %{$restoreData{$entry}} )
1957
                {
1958
                    $data->{$_} = $restoreData{$entry}{$_};
1959
                }
1960
                $forceImportFlush = 1;
1961
DebugDumpData('Data', $data );
1962
                return 6;
1963
            }
1964
        }
1965
        else
1966
        {
1967
            Warning ("Resume data missing");
1968
        }
1969
    }
1970
 
1271 dpurdie 1971
#   Keep DeadWood. May be a WIP
1972
#    if ( exists $versions{$entry}{DeadWood} && $versions{$entry}{DeadWood} )
1973
#    {
1974
#        $data->{errStr} = 'Package is DeadWood';
1975
#        return 3;
1976
#    }
1977
 
1978
    #
1979
    #   Determine version information
1980
    #
1981
    $data->{tag} = $versions{$entry}{vcsTag} || '';
1982
    if ( $versions{$entry}{badVcsTag} )
1983
    {
1984
        Warning ("Error: Bad VcsTag for: " . GetVname($entry),
1985
                 "Tag: $data->{tag}" );
1986
        $data->{errStr} = 'VCS Tag Marked as Bad';
1987
        return 1;
2635 dpurdie 1988
 
1271 dpurdie 1989
    }
1990
 
1991
 
1992
    $data->{tag} =~ m~^(.+?)::(.*?)(::(.+))?$~;
2635 dpurdie 1993
    $vcs_type = $1;
1271 dpurdie 1994
    $cc_label = $4;
1995
    $cc_path = $2;
1996
    $cc_path = '/' . $cc_path;
1997
    $cc_path =~ tr~\\/~/~s;
2412 dpurdie 1998
    $cc_path_original = $cc_path;
1271 dpurdie 1999
 
2000
    #
2635 dpurdie 2001
    #   Correct well known path mistakes in CC paths
1271 dpurdie 2002
    #
2635 dpurdie 2003
    if ( $vcs_type eq 'CC' )
2004
    {
2005
        $cc_path =~ s~/build.pl$~~i;
2006
        $cc_path =~ s~/src$~~i;
2007
        $cc_path =~ s~/cpp$~~i;
2008
        $cc_path =~ s~/MASS_Dev/Infra/~/MASS_Dev_Infra/~i;
2009
        $cc_path =~ s~/MASS_Dev/Tools/~/MASS_Dev_Tools/~i;
2010
        $cc_path =~ s~/MASS_Dev/Bus/~/MASS_Dev_Bus/~i;
2011
        $cc_path =~ s~/MASS_Dev_Bus/Cbp/~/MASS_Dev_Bus/CBP/~i;
2012
        $cc_path =~ s~/MREF_Package/ergpostmongui$~/MREF_Package/ergpostmongui~i;
2013
        $cc_path =~ s~/MREF_../MREF_Package/~/MREF_Package/~i;
2014
        $cc_path =~ s~/MREF_Package/mass_ergocdp/~/MREF_Package/ergocdp/~i;
2015
        $cc_path =~ s~/MASS_Dev_Bus/CBP/systemCD.ejb~/MASS_Dev_Bus/CBP/systemCD/ejb~i;
2016
        $cc_path =~ s~/MASS_Dev_Bus/Financial/cpp/paymentmanager~/MASS_Dev_Bus/Financial/cpp/paymentmanager~i;
2017
        $cc_path =~ s~/MASS_Dev_Bus/WebServices~/MASS_Dev_Bus/WebServices~i;
2018
        $cc_path =~ s~/MASS_Dev_Bus/CBP/nullAdapter~//MASS_Dev_Bus/CBP/nullAdaptor~i;
1271 dpurdie 2019
 
2635 dpurdie 2020
        $cc_path = '/MASS_Dev_Bus' if ( $cc_path =~ m~/MASS_Dev_Bus/ImageCapture(/|$)~i );
2021
        $cc_path = '/MASS_Dev_Bus/CBP/enquiry' if ( $versions{$entry}{name} eq 'EJBEnqPxyConnector');
2022
        $cc_path = '/MASS_Dev_Bus/CBP/enquiry' if ( $versions{$entry}{name} eq 'proxyif4j');
2023
        $cc_path = '/MASS_Dev_Bus' if ( $versions{$entry}{name} eq 'ImageCaptureTomcatDeployment');
2024
        $cc_path = '/MASS_Dev_Bus/WebServices/MassWS' if ( $versions{$entry}{name} eq 'MassWebServicesImpl');
1271 dpurdie 2025
 
2635 dpurdie 2026
        if (   $versions{$entry}{name} =~ m/^ERGagency$/i
2027
            || $versions{$entry}{name} =~ m/^ERGavm$/i
2028
            || $versions{$entry}{name} =~ m/^ERGboi$/i
2029
            || $versions{$entry}{name} =~ m/^ERGcallcenter$/i
2030
            || $versions{$entry}{name} =~ m/^ERGcardholder$/i
2031
            || $versions{$entry}{name} =~ m/^ERGcdaimports$/i
2032
            || $versions{$entry}{name} =~ m/^ERGcda$/i
2033
            || $versions{$entry}{name} =~ m/^ERGcscedit$/i
2034
            || $versions{$entry}{name} =~ m/^ERGcs$/i
2035
            || $versions{$entry}{name} =~ m/^ERGofs$/i
2036
            || $versions{$entry}{name} =~ m/^ERGols$/i
2037
            || $versions{$entry}{name} =~ m/^ERGtpf$/i
2038
            || $versions{$entry}{name} =~ m/^ERGorasys$/i
2039
            || $versions{$entry}{name} =~ m/^ERGoracs$/i
2040
            || $versions{$entry}{name} =~ m/^ERGpxyif$/i
2041
            || $versions{$entry}{name} =~ m/^ERGtp5upg$/i
2042
            || $versions{$entry}{name} =~ m/^ERGinstitutional$/i
2043
            || $versions{$entry}{name} =~ m/^ERGinfra$/i
2044
            || $versions{$entry}{name} =~ m/^ERGcrrpts$/i
2045
            || $versions{$entry}{name} =~ m/^ERGmiddle$/i
2046
            || $versions{$entry}{name} =~ m/^ERGmiddleapi$/i
2047
            || $versions{$entry}{name} =~ m/^ERGwebapi$/i
2048
            || $versions{$entry}{name} =~ m/^ERGwebtestui$/i
2049
            || $versions{$entry}{name} =~ m/^ERGwebesbui$/i
2050
            || $versions{$entry}{name} =~ m/^ERGwspiv$/i
2051
            || $versions{$entry}{name} =~ m/^ERGwscst$/i
2052
            || $versions{$entry}{name} =~ m/^sposMUG$/i
2053
            || $versions{$entry}{name} =~ m/^ERGfinman$/i
2054
            || $versions{$entry}{name} =~ m/^ERGkm$/i
2055
            || $versions{$entry}{name} =~ m/^ERGxml$/i
2056
            || $versions{$entry}{name} =~ m/^ERGoradacw$/i
2057
            || $versions{$entry}{name} =~ m/^ERGtru$/i
2058
            )
1271 dpurdie 2059
        {
2412 dpurdie 2060
            $cc_path = '/MREF_Package';
1271 dpurdie 2061
        }
2062
 
2635 dpurdie 2063
        if (   $versions{$entry}{name} =~ m/^tp5000_MUG$/i )
2064
        {
2065
            if ( $versions{$entry}{version} =~ m~vtk$~ )
2066
            {
2067
                $cc_path = '/MREF_Package';
2068
            }
2069
        }
2070
 
2071
        $cc_path = $opt_forceProjectBase
2072
            if ( $opt_forceProjectBase );
2073
 
2074
        foreach ( @opt_limitProjectBase )
2075
        {
2076
            if ( $cc_path =~ m~$_~ )
2077
            {
2078
                $cc_path = $_;
2079
                last;
2080
            }
2081
        }
2082
 
2083
        if ( $cc_path_original ne $cc_path )
2084
        {
2085
                Message ("Package: $versions{$entry}{name}. Forcing CC path to: $cc_path" );
2086
        }
2412 dpurdie 2087
    }
2088
 
2089
#print "--- Path: $cc_path, Label: $cc_label\n";
1271 dpurdie 2090
 
2635 dpurdie 2091
    if ( $vcs_type eq 'SVN' )
2092
    {
2093
        $rv = extractFilesFromSubversion( $data, $entry );
2094
        return $rv if ( $rv );
2095
    }
2096
    else
2097
    {
2098
        #
2099
        #   Create CC view
2100
        #   Import into Subversion View
2101
        #
2102
        $rv = extractFilesFromClearCase( $data, $cc_path, $cc_label );
2103
        return $rv if ( $rv );
2104
    }
2412 dpurdie 2105
 
2106
    #
1272 dpurdie 2107
    #   Developers have been slack
2108
    #       Sometime the mark the source path as 'GMTPE2005'
2109
    #       Sometimes as 'GMTPE2005/Package/Fred/Jill/Harry'
2110
    #
2111
    #   Attempt to suck up empty directories below the specified
2112
    #   source path
2113
    #
2635 dpurdie 2114
    unless ( $opt_preserveProjectBase || $opt_forceProjectBase || @opt_limitProjectBase)
1272 dpurdie 2115
    {
2116
        #
2117
        #   Look in ViewPath
2118
        #   If it contains only ONE directory then we can suck it up
2119
        #
2120
        my $testDir = findDirWithStuff( $data->{ViewPath} );
2412 dpurdie 2121
 
1272 dpurdie 2122
        unless ( $data->{ViewPath} eq $testDir  )
2123
        {
2124
            Message ("Adjust Base Dir: $testDir");
2125
            $data->{adjustedPath} = $data->{ViewPath};
2126
            $data->{ViewPath} = $testDir;
2635 dpurdie 2127
            $adjustedPath++;
1272 dpurdie 2128
        }
2129
    }
2635 dpurdie 2130
    Message ("BaseDir: $data->{ViewPath}");
2131
 
2438 dpurdie 2132
    #
2635 dpurdie 2133
    #   Check for bad source paths
2134
    #
2135
    if (detectBadMakePaths($data) )
2136
    {
2137
        unless ( $opt_ignoreBadPaths )
2138
        {
2139
            $data->{BadPath}++;
2140
            $data->{errStr} = 'Bad Paths in Makefile';
2141
            return 4;           # Lets see what the others look like too
2142
#            return 14;
2143
        }
2144
    }
2145
 
2146
    #
2438 dpurdie 2147
    #   Some really ugly packages make use of a Jats feature called 'SetProjectBase'
2148
    #   Detect such packages as we will need to handle them differently
2149
    #   Can't really handle it on the fly
2150
    #   All we can do is detect it and report it - at the moment
2151
    #
2635 dpurdie 2152
    if (detectProjectBaseUsage($data) )
2438 dpurdie 2153
    {
2154
        unless ( $opt_ignoreProjectBaseErrors )
2155
        {
2156
            $data->{BadProjectBase}++;
2157
            $data->{errStr} = 'Bad usage of ProjectBase detected';
2635 dpurdie 2158
            Warning ("ProjectBase Error");
2438 dpurdie 2159
            return 4;           # Lets see what the others look like too
2160
#            return 14;
2161
        }
2162
    }
2412 dpurdie 2163
 
2164
    #
2438 dpurdie 2165
    #   Some really really ugly packgaes make use of the MakeProject directive
2166
    #   and then use an 'include.txt file to access paths all over the VOB
2167
    #   The problem is with lines like
2168
    #           /I ..\..\..\..\..\..\DPG_SWCode\projects\seattle\ddu\component\DTIApp\dsi\inc
2169
    #   Two problems:
2170
    #       Vob Name is not a part of the migration
2171
    #       If we 'SuckUp' empty directories then this may break
2172
    #       the pathing.
2173
    #   All we can do is detect it and report it - at the moment
2174
    #
2635 dpurdie 2175
    if (detectMakeProjectUsage($data) )
2438 dpurdie 2176
    {
2177
        unless ( $opt_ignoreMakeProjectErrors )
2178
        {
2179
            $data->{BadMakeProject}++;
2180
            $data->{errStr} = 'Use of MakeProject detected';
2181
            return 4;           # Lets see what the others look like too
2182
#            return 14;
2183
        }
2184
    }
2185
 
2186
    #
2412 dpurdie 2187
    #   Some packages have filenames that are need to be converted
2188
    #
2438 dpurdie 2189
    if ( $mustConvertFileNames  )
2412 dpurdie 2190
    {
2191
        $rv = system ( '/home/dpurdie/svn/tools/convmv-1.15/convmv',
2192
                 '-fiso-8859-1',
2193
                 '-tutf8',
2194
                 '-r',
2195
                 '--notest',
2196
                 $data->{ViewPath} );
2197
 
2198
        if ( $rv )
2199
        {
2200
            $data->{errStr} = 'Failed to convert filenames to UTF8';
2201
            return 14;
2202
        }
2438 dpurdie 2203
 
2204
        #
2205
        #   Check to see if our ViewPath has been changed
2206
        #   If so, then try to fix it
2207
        #
2208
        unless ( -d $data->{ViewPath} )
2209
        {
2210
            Message ("Correct UTF-8 change to ViewPath");
2211
            $data->{ViewPath} = encode('UTF-8', $data->{ViewPath}, Encode::FB_DEFAULT);
2212
            Warning ("Correct UTF-8 change to ViewPath - FAILED") unless ( -d $data->{ViewPath} );
2213
        }
2412 dpurdie 2214
    }
1272 dpurdie 2215
 
2216
    #
1271 dpurdie 2217
    #   Have a CC view
2218
    #   Now we can create the SVN package and branching point before we
2219
    #   import the CC data into SVN
2220
    #
2635 dpurdie 2221
    if ( !$opt_useSvn )
2222
    {
2223
            $data->{errStr} = 'Subversion Import disabled' unless $data->{errStr};
2224
            return 5;
2225
    }
2226
 
1271 dpurdie 2227
    my @args;
2228
 
2229
    #
2230
    #   Calculate args for functions
2231
    #
2232
    my $author = $versions{$entry}{created_id};
2233
    if ( $author )
2234
    {
2235
        push @args, '-author', $author;
2236
    }
2237
    my $created = $versions{$entry}{created};
2238
    if ( $created )
2239
    {
2240
        $created =~ s~ ~T~;
2241
        $created .= '00000Z';
2242
        push @args, '-date', $created;
2243
    }
2244
 
2245
    my $log = $versions{$entry}{comment};
2246
    if ( $log )
2247
    {
2248
        push @args, '-log', $log;
2249
    }
2250
 
2251
    #
2252
    #   Create package skeleton if needed
2253
    #
2254
    $rv = createPackage( $author, $created);
2255
    if ( $rv )
2256
    {
2257
        $data->{errStr} = 'Failed to create Package';
2258
        return 10;
2259
    }
2260
 
2261
    #
2262
    #   May need to create the branchpoint
2263
    #   The process is delayed until its needed so avoid creating unneeded
2264
    #   branch points
2265
    #
2266
    if ( $createBranch )
2267
    {
2268
        $rv = createBranchPoint ($entry, $author, $created);
2269
        $createBranch = 0;
2270
        $createSuffix = 0;
2271
        if ( $rv )
2272
        {
2273
            $data->{errStr} = 'Failed to create Branch Point';
2274
            return 11;
2275
        }
2276
    }
2635 dpurdie 2277
 
2278
    #
2279
    #   If we are in resume mode then we MUST kill the import directory
2280
    #   if we have skipped anything
2281
    #
2282
    if ( $forceImportFlush )
2283
    {
2284
        $forceImportFlush = 0;
2285
        RmDirTree ('SvnImportDir');
2286
    }
2287
 
1271 dpurdie 2288
    push @args, "-branch=$currentBranchName" if ( defined $currentBranchName );
2635 dpurdie 2289
    my $datafile = "importdata.$import_label.properties";
2290
    push (@args, "-mergePaths", join(',', @opt_mergePaths) ) if ( @opt_mergePaths );
1271 dpurdie 2291
 
2292
    $rv = JatsToolPrint ( 'jats_svn', 'import', '-reuse' ,
2293
                    "-package=$svnRepo/$packageNames",
2294
                    "-dir=$data->{ViewPath}",
2295
                    "-label=$import_label",
2296
                    "-datafile=$datafile",
2297
                    @args,
2298
                     );
2299
 
2300
    if ( $rv )
2301
    {
2302
        $data->{errStr} = 'Failed to import to SVN';
2303
        return 12;
2304
    }
2305
 
2412 dpurdie 2306
    $versions{$entry}{TagCreated} = 1;
2307
    $firstVersionCreated = $entry unless ( $firstVersionCreated );
2308
 
1271 dpurdie 2309
    #
2310
    #   Read in the Rm Reference
2311
    #   Retain entries in a global file
2312
    #
2313
    if ( -f $datafile  )
2314
    {
2315
        my $rmData = JatsProperties::New($datafile);
2635 dpurdie 2316
        if ( $rmData->getProperty('subversion.tag') )
2317
        {
2318
            $data->{rmRef} = 'SVN::' . $rmData->getProperty('subversion.tag');
2319
        }
2320
        else
2321
        {
2322
            Warning ("Property files has no subversion.tag");
2323
        }
2324
        $data->{fileCount}    = $rmData->getProperty('files.base', 0);
2325
        $data->{filesRemoved} = $rmData->getProperty('files.removed',0);
2326
        $data->{filesAdded}   = $rmData->getProperty('files.added',0);
1271 dpurdie 2327
    }
2328
 
2329
    unless ( $data->{rmRef}  )
2330
    {
2331
        $data->{errStr} = 'Failed to determine Rm Reference';
2332
        return 13;
2333
    }
2334
 
2412 dpurdie 2335
######################## Deleted ###############################################
2336
#
2337
#
2338
#    #
2339
#    #   Add supplemental tags if this version is in a 'Release'
2340
#    #   But only for some packages - else looks like a mess
2341
#    #   Just a solution for the ITSO guys
2342
#    #
2343
#    foreach my $rtag_id ( keys %{$versions{$entry}{Releases}}  )
2344
#    {
2345
#        next unless ( $svnRepo =~ m~/ITSO_TRACS(/|$)~);
2346
#
2347
#        my $prog_id = $versions{$entry}{Releases}{$rtag_id}{proj_id};
2348
#        Message ("Adding Release Tag:$prog_id:$rtag_id");
2349
#
2350
#        my $rtext = 'Release_' . saneString($versions{$entry}{Releases}{$rtag_id}{rname});
2351
#        my @comment;
2352
#        push @comment, "Tagged by ClearCase to Subversion import";
2353
#        push @comment, "Project:$prog_id:$versions{$entry}{Releases}{$rtag_id}{pname}";
2354
#        push @comment, "Release:$rtag_id:$versions{$entry}{Releases}{$rtag_id}{rname}";
2355
#
2356
#        $data->{ReleaseTag}{$prog_id}{$rtag_id}{name} = $rtext;
2357
#
2358
#        $rv = JatsToolPrint ( 'jats_svnlabel' ,
2359
#                    '-comment', encode('UTF-8', join("\n", @comment), Encode::FB_DEFAULT),
2360
#                    $data->{rmRef},
2361
#                    '-clone',
2362
#                    $rtext,
2363
##                    @args,
2364
#                    '-author=buildadm',
2365
#                     );
2366
#        $data->{ReleaseTag}{$prog_id}{$rtag_id}{eState} = $rv;
2367
#        $data->{ReleaseTag}{tCount}++;
2368
#
2369
#        if ( $rv )
2370
#        {
2371
#            $data->{ReleaseTag}{eCount}++;
2372
#            Warning("Failed to add Release Tag: $rtext");
2373
#        }
2374
#    }
2375
#
2376
######################## Deleted ###############################################
2377
 
1271 dpurdie 2378
    Message ("RM Ref: $data->{rmRef}");
2379
    unlink $datafile;
2380
 
2381
    #
2382
    #   All is good
2383
    #
2384
    $data->{errStr} = '';
2385
    return 0;
2386
}
2387
 
2388
 
2389
#-------------------------------------------------------------------------------
2390
# Function        : newProject
2391
#
2392
# Description     : Start a new project within a package
2393
#
2394
# Inputs          : 
2395
#
2396
# Returns         : 
2397
#
2398
sub newProject
2399
{
2400
#    Message ("---- New Project");
2401
    $createSuffix = 0;
2402
 
2403
    #
2404
    #   New project
2405
    #   Kill the running import directory
2406
    #
2407
    RmDirTree ('SvnImportDir');
2408
}
2409
 
2410
#-------------------------------------------------------------------------------
2411
# Function        : newPackage
2412
#
2413
# Description     : Start processing a new package
2414
#
2415
# Inputs          : 
2416
#
2417
# Returns         : 
2418
#
2419
my $createPackageDone;
2420
sub newPackage
2421
{
2422
#    Message( "---- New Package");
2423
 
2424
    #
2425
    #   Create a package specific log file
2426
    #
2427
    $logSummary = $packageNames . ".summary.log";
2428
    unlink $logSummary;
2429
    Message( "PackageName: $packageNames");
2430
    $createPackageDone = 1;
2431
    $createBranch = 0;
2432
    $createSuffix = 0;
2433
 
2434
    #
2435
    #   First entry being created
2436
    #   Prime the work area
2437
    #
2438
    RmDirTree ('SvnImportDir');
2439
}
2440
 
2441
#-------------------------------------------------------------------------------
2442
# Function        : createPackage
2443
#
2444
# Description     : Create a new Package in SVN
2445
#                   Called before any serious SVN operation to ensure that the
2446
#                   package has been created. Don't create a package until
2447
#                   we expect to put something into it.
2448
#
2449
#                   Will only create a package once
2450
 
2451
#
2452
# Inputs          : $author         - Who done it
2453
#                   $date           - When
2454
#
2455
# Returns         : 
2456
#
2457
sub createPackage
2458
{
2459
    my ($author, $date) = @_;
2460
    my @opts;
2461
    push (@opts, '-date', $date) if ( $date );
2462
    push (@opts, '-author', $author) if ( $author );
2463
    #
2464
    #   Only do once
2465
    #
2466
    return unless ( $createPackageDone );
2635 dpurdie 2467
    return if ( $opt_resume );
1271 dpurdie 2468
    $createPackageDone = 0;
2469
 
1272 dpurdie 2470
    #
2471
    #   Real import
2472
    #       Do not Delete package if it exists
2473
    #       Package must NOT exist
2474
    #
1271 dpurdie 2475
    Message ("Creating new SVN package: $packageNames");
1272 dpurdie 2476
    if ( $opt_delete )
2477
    {
2478
        Message ("Delete existing version of package: $packageNames");
2479
        JatsToolPrint ( 'jats_svn', 'delete-package', '-noerror',  "$svnRepo/$packageNames" );
2480
    }
2481
    JatsToolPrint ( 'jats_svn', 'create', "$svnRepo/$packageNames", '-new', @opts );
1271 dpurdie 2482
}
2483
 
2484
 
2485
#-------------------------------------------------------------------------------
2486
# Function        : createBranchPoint
2487
#
2488
# Description     : Create a branch point for the current work
2489
#                   Perform the calculation to determine the details of
2490
#                   the branch point. The work will only be done when its
2491
#                   needed. This will avoid the creation of branchpoints
2492
#                   that are not used.
2493
#
2494
# Inputs          : $entry                  Entry being processed
2495
#                   $author         - Who done it
2496
#                   $date           - When
2497
#
2498
# Returns         : 
2499
#
2500
sub createBranchPoint
2501
{
2502
    my ($entry, $author, $date) = @_;
2503
    my $forceNewProject;
2504
 
2505
#    Message ("---- Create Branch Point");
2506
 
2507
    #
2508
    #   Find previous good tag
2509
    #   We are walking a tree so something should have been created, but
2510
    #   the one we want may have had an error
2511
    #
2512
    #   Walk backwards looking for one that has been created
2513
    #
2514
    my $last = $versions{$entry}{last};
2515
    while ( $last )
2516
    {
2517
        unless ( $versions{$last}{TagCreated} )
2518
        {
2519
            $last = $versions{$last}{last};
2520
        }
2521
        else
2522
        {
2523
            last;
2524
        }
2525
    }
2526
 
2527
    #
2528
    #   If we have walked back to the base of the tree
2529
    #   If we transferred any software at all, then use the first
2530
    #   version as the base for this disconnected version
2531
    #
2532
    #   Otherwise we create a new, and empty, view
2533
    #
2534
    unless ( $last )
2535
    {
2536
        if ( $firstVersionCreated )
2537
        {
2538
            Warning ("Cannot find previous version to branch. Use first version");
2539
            $last = $firstVersionCreated;
2540
        }
2541
        else
2542
        {
2543
            Warning ("Forcing First instance of a Project");
2544
            $forceNewProject = 1;
2545
        }
2546
    }
2547
 
2548
    #
2549
    #   Determine source name
2550
    #   This MUST have been created before we can branch
2551
    #
2552
    my $src_label;
2553
    $src_label = saneLabel($last) if $last;
2554
 
2555
    #
2556
    #   Create target name
2557
    #
2558
    my $tgt_label;
2559
    if ( $forceNewProject || $versions{$entry}{newSuffix} || $createSuffix || !defined $src_label )
2560
    {
2561
        #
2562
        #   Create target name based on project
2563
        #
2564
        return if ( $singleProject );
2565
 
2566
        my $suffix = $versions{$entry}{suffix};
2567
        if ( $suffix )
2568
        {
2569
            Error ("Unknown Project: $suffix") unless ( defined $Projects{$suffix} );
2570
 
2571
            #
2572
            #   If this project can be considered to be a truck, then 'claim' the
2573
            #   truck for the first created element.
2574
            #
2575
            if ( $Projects{$suffix}{Trunk} )
2576
            {
2577
                # This project can use the trunk, if it has not been allocated.
2578
                $ProjectTrunk = $suffix unless ( defined $ProjectTrunk );
2579
 
2580
                #
2581
                #   If this package has multiple instances of the potential
2582
                #   trunk, then don't place either of them on the trunk as it
2583
                #   may cause confusion
2584
                #
2585
                if ($knownProjects{$suffix}{count} < 2 )
2586
                {
2587
                    if ( $suffix eq $ProjectTrunk )
2588
                    {
2589
                        return unless $currentBranchName;
2590
                    }
2591
                }
2592
            }
2593
 
2594
            $tgt_label = $Projects{$suffix}{Name};
2595
            $tgt_label = $versions{$entry}{name} . '_' . $tgt_label if ($multiPackages);
2596
            if ( !exists $ProjectsBaseCreated{$tgt_label}  )
2597
            {
2598
                $ProjectsBaseCreated{$tgt_label} = 1;
2599
            }
2600
            else
2601
            {
2602
                #   Project Base Already taken
2603
                #   Have disjoint starting points
2604
                $tgt_label .= '.' . $ProjectsBaseCreated{$tgt_label} ++;
2605
            }
2606
        }
2607
        else
2608
        {
2609
            #
2610
            #   No suffix in use
2611
            #
2612
            #   Currently not handled
2613
            #   May have to force the use of the trunk
2614
            #
2615
            Error ("INTERNAL ERROR: No suffix present");
2616
        }
2617
    }
2618
    else
2619
    {
2620
        $tgt_label = saneLabel($entry, $src_label . '_for_');
2621
    }
2622
 
2623
    #
2624
    #   Save branch name for use when populating sandbox
2625
    #
2626
    $currentBranchName = $tgt_label;
2627
 
2628
    #
2629
    #   Perform the branch
2630
    #
2631
    if ( defined $src_label )
2632
    {
2635 dpurdie 2633
        if ( $opt_resume )
2634
        {
2635
            my $rv = JatsToolPrint ( 'jats_svnlabel',
2636
                        '-check',
2637
                        '-packagebase', "$svnRepo/$packageNames",
2638
                        '-branch',
2639
                        $tgt_label );
2640
            return unless ( $rv );
2641
        }
2642
 
2412 dpurdie 2643
        #
2644
        #   The 'clone' operation will backtrack the branch point
2645
        #   to the source of the label. This will make the output version
2646
        #   tree much prettier
2647
        #
1271 dpurdie 2648
        my @opts;
2649
        push (@opts, '-date', $date) if ( $date );
2650
        push (@opts, '-author', $author) if ( $author );
2651
 
2652
        JatsToolPrint ( 'jats_svnlabel',
2653
                        '-packagebase', "$svnRepo/$packageNames",
2654
                        'tags/' . $src_label,
2655
                        '-branch',
2656
                        '-clone', $tgt_label,
2657
                        @opts
2658
                      );
2659
    }
2660
}
2661
 
2662
 
2663
#-------------------------------------------------------------------------------
2664
# Function        : endPackage
2665
#
2666
# Description     : End of package processing
2667
#                   Clean up and display problems
2668
#
2669
# Inputs          : 
2670
#
2671
# Returns         : 
2672
#
2673
sub endPackage
2674
{
2412 dpurdie 2675
    Message ("-- Import Summary ------------------------------------------------" );
1271 dpurdie 2676
    RmDirTree ('SvnImportDir');
2635 dpurdie 2677
    my $processedCount = 0;
2678
    my $inernalErrorCount = 0;
2679
    my $notProcessedCount = 0;
2680
    my $badPathCount = 0;
2681
    my $badProjectBaseCount = 0;
2682
    my $badMakeProjectCount = 0;
1271 dpurdie 2683
 
2684
    #
2685
    #   Display versions that did get captured
2686
    #
2687
    foreach my $entry ( @processOrder )
2688
    {
2689
        $versions{$entry}{Scanned} = 1;
2690
        next unless ( $versions{$entry}{TagCreated} );
2635 dpurdie 2691
        my $eflag = $versions{$entry}{Essential} ? 'E' : ' ';
2692
        Warning ("Processed:$eflag:" . GetVname($entry) . ' :: ' . $versions{$entry}{rmRef} || $versions{$entry}{errStr} || '???' );
1271 dpurdie 2693
    }
2694
 
2695
    #
2696
    #   Display versions that did not get created
2697
    #
2698
    foreach my $entry ( @processOrder )
2699
    {
2700
        $versions{$entry}{Scanned} = 1;
2635 dpurdie 2701
        if ( $versions{$entry}{TagCreated} )
2702
        {
2703
            $processedCount++;
2704
            $badPathCount++ if ($versions{$entry}{data}{BadPath} );
2705
            $badProjectBaseCount++ if ($versions{$entry}{data}{BadProjectBase} );
2706
            $badMakeProjectCount++ if ($versions{$entry}{data}{BadMakeProject} );
2707
            next;
2708
        }
2709
 
2412 dpurdie 2710
        my $reason = $versions{$entry}{data}{errStr} || '';
2711
        my $tag = $versions{$entry}{vcsTag}|| 'No Tag';
2635 dpurdie 2712
        my $eflag = $versions{$entry}{Essential} ? 'E' : ' ';
2713
        Warning ("Not Processed:$eflag: " . GetVname($entry) . ':' . $tag . ' : ' . $reason );
2714
        $notProcessedCount++;
1271 dpurdie 2715
    }
2716
 
2717
    foreach my $entry ( keys(%versions) )
2718
    {
2719
        next if ( $versions{$entry}{Scanned} );
2720
        Warning ("(E) INTERNAL ERROR. Package Not Processed: " . GetVname($entry) );
2635 dpurdie 2721
        $inernalErrorCount++;
1271 dpurdie 2722
    }
2723
 
2635 dpurdie 2724
    if ( $adjustedPath || 1 )
2725
    {
2726
        Information ("Package Info: Files, Removed, Added, Version, ViewPath");
2727
        foreach my $entry ( @processOrder )
2728
        {
2729
            my $viewPath = $versions{$entry}{data}{ViewPath} || '';
2730
            Information (sprintf "%4s, %4s, %4s, %20s : %s",
2731
                        $versions{$entry}{data}{fileCount} || '-',
2732
                        $versions{$entry}{data}{filesRemoved} || '-',
2733
                        $versions{$entry}{data}{filesAdded} || '-',
2734
                        GetVname($entry), $viewPath);
2735
        }
2736
    }
2737
 
2738
    Message ("Packages processed: $processedCount");
2739
    Warning ("Packages not processed: $notProcessedCount") if ( $notProcessedCount );
2740
    Warning ("Internal Errors: $inernalErrorCount") if ( $inernalErrorCount );
2741
    Warning ("Multiple source paths", @multiplePaths ) if ( scalar @multiplePaths > 1 );
2412 dpurdie 2742
    Message ("Packages Relabled: $packageReLabelCount") if ( $packageReLabelCount );
2635 dpurdie 2743
    Warning ("Packages with Bad Paths: $badPathCount") if ( $badPathCount );
2744
    Warning ("Packages with Bad ProjectBase: $badProjectBaseCount") if ( $badProjectBaseCount );
2745
    Warning ("Packages with MakeProjects: $badMakeProjectCount") if ( $badMakeProjectCount );
2746
    Warning ("Global Error Detected") if ( $globalError );
2747
    Message ("---- All Done -----");
1271 dpurdie 2748
}
2749
 
2750
#-------------------------------------------------------------------------------
2412 dpurdie 2751
# Function        : extractFilesFromClearCase
2752
#
2753
# Description     : Extract files from ClearCase
2754
#                   May take a while as we handle nasty errors
2755
#
2756
# Inputs          : $data           - Hash of good stuff from newPackageVersionBody
2757
#                   $cc_path
2758
#                   $cc_label
2759
#
2760
# Returns         : exit code
2761
#                   Sets up
2762
#                       $data->{errStr}
2763
#                       $data->{errCode}
2764
#                   As per newPackageVersionBody
2765
#
2766
sub extractFilesFromClearCase
2767
{
2768
    my ($data, $cc_path, $cc_label) = @_;
2769
    my $tryCount = 0;
2770
    my $rv = 99;
2771
 
2635 dpurdie 2772
    $data->{ViewRoot} = ( defined $opt_name && ! defined $opt_mergePackages )? $opt_name : "$cc_label";
2412 dpurdie 2773
    $data->{ViewPath} =  $data->{ViewRoot} . $cc_path;
2774
 
2635 dpurdie 2775
    if ( $opt_preserveProjectBase && !$opt_forceProjectBase )
2412 dpurdie 2776
    {
2777
        my $cc_vob = $cc_path;
2778
        $cc_vob =~ s~^/~~;
2779
        $cc_vob =~ s~/.*~~;
2780
        $data->{ViewPath} =  $data->{ViewRoot} . '/' . $cc_vob;
2781
        Message ("Preserving Project Base");
2782
    }
2783
    $data->{ViewPath} =~  tr~/~/~s;
2784
 
2785
    if ( $opt_reuse && -d $data->{ViewPath}  )
2786
    {
2787
        Message ("Reusing view: $cc_label");
2788
        return 0;
2789
    }
2790
 
2791
    while ( $rv == 99 ) {
2792
        my @args;
2635 dpurdie 2793
        push (@args, '-view', $opt_name ) if ( defined $opt_name && ! defined $opt_mergePackages );
2412 dpurdie 2794
        $rv = JatsToolPrint ( 'jats_ccrelease', '-extractfiles', '-root=.' , '-noprefix',
2795
                    "-label=$cc_label" ,
2796
                    "-path=$cc_path",
2797
                    @args
2798
                    );
2799
 
2800
        if ( $rv == 10 ) {
2801
 
2802
            #
2803
            #   No files found
2804
            #   If this is the first time then try really hard to find them
2805
            #
2806
            unless ( $tryCount++ )
2807
            {
2808
                if ( $opt_relabel )
2809
                {
2810
                    $packageReLabelCount++;
2811
                    $rv = JatsToolPrint('cc2svn_labeldirs',
2812
                                            '-vob', $cc_path,
2813
                                            $cc_label,
2814
                                            );
2815
                    $data->{DirsLabled} = 100 + $rv;
2816
                }
2817
 
2818
                #
2819
                #   Second attempt - massage the users path
2820
                #   We should have labled up to the VOB root so lets
2821
                #   just use the VOB and not the path
2822
                #
2823
                #   If we are not relabeling then we can still do this
2824
                #   in an attempt to fix user stupidity
2825
                #
2826
                $cc_path =~ s~^/~~;
2827
                $cc_path =~ s~/.*~~;
2828
                $cc_path = '/' . $cc_path;
2829
                $data->{ViewPath} =  $data->{ViewRoot} . $cc_path;
2830
                redo;
2831
            }
2832
 
2833
            $data->{errStr}  = 'No Files in the extracted view';
2834
            $data->{errCode} = '0';
2835
            return 2;
2836
        }
2837
        elsif ( $rv == 11 ) {
2838
            $data->{errStr} = 'Label not found';
2839
            $data->{errCode} = 'L';
2840
            return 2;
2841
        }
2842
 
2843
        unless ( -d $data->{ViewPath}  )
2844
        {
2845
            $data->{errStr} = 'Failed to extract files from CC';
2846
            return 2;
2847
        }
2848
 
2849
        #
2850
        #   Looks good
2851
        #
2852
        return 0;
2853
    };
2854
 
2855
    $data->{errStr}  = 'No Files in the extracted view after labeling dirs';
2856
    $data->{errCode} = '0';
2857
    return 2;
2858
 
2859
}
2860
 
2861
#-------------------------------------------------------------------------------
2635 dpurdie 2862
# Function        : extractFilesFromSubversion
2863
#
2864
# Description     : Extract files from Subversion
2865
#                   May take a while as we handle nasty errors
2866
#
2867
# Inputs          : $data           - Hash of good stuff from newPackageVersionBody
2868
#                   $entry          - All the PV information
2869
#
2870
# Returns         : exit code
2871
#                   Sets up
2872
#                       $data->{errStr}
2873
#                       $data->{errCode}
2874
#                   As per newPackageVersionBody
2875
#
2876
sub extractFilesFromSubversion
2877
{
2878
    my ($data, $entry ) = @_;
2879
    my $tryCount = 0;
2880
    my $rv = 99;
2881
 
2882
    #
2883
    #   Create a nice name for the import
2884
    #
2885
    my $import_label = saneLabel($entry);
2886
 
2887
 
2888
    $data->{ViewRoot} = $opt_name ? $opt_name : $import_label;
2889
    $data->{ViewPath} =  $data->{ViewRoot};
2890
    $data->{ViewPath} =~  tr~/~/~s;
2891
 
2892
    if ( $opt_reuse && -d $data->{ViewPath}  )
2893
    {
2894
        Message ("Reusing view: $import_label");
2895
        return 0;
2896
    }
2897
 
2898
    #
2899
    #   Only allow import from SVN if asked nicely
2900
    #   May be used if we are correcting a package - and some have been
2901
    #   placed in SVN
2902
    #
2903
    unless ( $opt_extractFromSvn )
2904
    {
2905
        $data->{errStr} = 'Some Packages are in SVN';
2906
        return 15;
2907
    }
2908
 
2909
 
2910
#print "--- ViewRoot: $data->{ViewPath}\n";
2911
    $rv = JatsToolPrint ( 'jats_svnrelease',
2912
                          '-extractfiles',
2913
                          '-root=.' ,
2914
                          '-noprefix',
2915
                          '-DevMode=escrow',
2916
                          '-label', $data->{tag},
2917
                          '-view', $data->{ViewPath},
2918
                );
2919
 
2920
    if ( $rv == 10 ) {
2921
        $data->{errStr}  = 'No Files in the extracted view';
2922
        $data->{errCode} = '0';
2923
        return 2;
2924
 
2925
    } elsif ( $rv == 11 ) {
2926
        $data->{errStr} = 'Label not found';
2927
        $data->{errCode} = 'L';
2928
        return 2;
2929
    } elsif ( $rv ) {
2930
        $data->{errStr} = 'Subversion reported error';
2931
        return 2;
2932
    }
2933
 
2934
    unless ( -d $data->{ViewPath}  )
2935
    {
2936
        $data->{errStr} = 'Failed to extract files from Subversion';
2937
        return 2;
2938
    }
2939
 
2940
    #
2941
    #   Looks good
2942
    #
2943
    return 0;
2944
}
2945
 
2946
#-------------------------------------------------------------------------------
2438 dpurdie 2947
# Function        : detectMakeProjectUsage
2948
#
2949
# Description     : etect and report usage of the MakeProject directive
2950
#
2951
# Inputs          : $data               - Ref to a hash of bits
2952
#
2953
# Returns         : true    - Bad usage (Really good usage not detected)
2954
#                   false   - Good usage detected
2955
#
2956
sub detectMakeProjectUsage
2957
{
2635 dpurdie 2958
    my ($data) = @_;
2438 dpurdie 2959
    my $retval = 0;
2960
    my $eSuf = $opt_ignoreMakeProjectErrors ? '' : 'Error';
2961
 
2962
    #
2963
    #   Find makefile.pl
2964
    #
2635 dpurdie 2965
    Message ("Detect MakeProject Usage");
2438 dpurdie 2966
    my $usesMakeProject = 0;
2967
    my $badIncludeFile = 0;
2968
 
2969
    my $search = JatsLocateFiles->new("--Recurse=1",
2970
                                       "--FilterIn=makefile.pl",
2971
                                       );
2972
    my @makefiles = $search->search($data->{ViewRoot});
2973
    foreach my $file ( @makefiles )
2974
    {
2975
#print "---Reading: $workDir/$data->{ViewRoot}/$file\n";
2976
        if ( open( my $fh, '<', "$data->{ViewRoot}/$file" ) )
2977
        {
2978
            my $eof = 0;
2979
            my $line = '';
2980
            until ( $eof )
2981
            {
2982
                my $in = <$fh>;
2983
                unless ( defined $in )
2984
                {
2985
                    $eof = 1;
2986
                }
2987
                else
2988
                {
2989
                $in =~ s~\s+$~~;
2990
                $in =~ s~^\s+~~;
2991
                $in =~ s~^#.*$~~;
2992
                $in =~ s~\s*[^\$]#.*$~~;
2993
                $line .= ' ' if ( $line );
2994
                $line .= $in;
2995
                $line =~ s~\s+~ ~g;
2996
#print "====== '$line'\n";
2997
                redo unless ( $line =~ m~;$~  );
2998
                }
2999
#print "---- $line\n";
3000
                if ( $line =~ m~^MakeProject~ )
3001
                {
3002
                    $usesMakeProject++;
3003
                    $data->{UsesMakeProject}++;
3004
                    Warning ("Package uses MakeProject:",
3005
                             "Line: " . $line,
3006
                             "Root: " . "$data->{ViewRoot}",
3007
                             "File: " . "$data->{ViewRoot}/$file",
3008
                            );
3009
 
3010
                    #
3011
                    #   Extract out the project name
3012
                    #
3013
                    my @myArgs;
3014
                    my $myProjectDir;
3015
                    my $myProject = "$data->{ViewRoot}/$file";
3016
                    $myProject =~ s~/[^/]+$~~;
2635 dpurdie 3017
 
3018
                    unless ($line =~ m~\s*(\w+)\s*\((.*)\)\s*;\s*$~ )
3019
                    {
3020
                        Error("Could not detect arguments: $line");
3021
                    }
3022
                    my $args = $2;
3023
                    $args =~ tr~'" ~ ~s;
3024
                    @myArgs = split (/\s*,\s*/, $args);
2438 dpurdie 3025
                    shift @myArgs;
3026
                    foreach ( @myArgs )
3027
                    {
3028
                        next if ( m~^--~ );
3029
                        $myProject .= '/' . $_;
3030
                        $myProjectDir = $myProject;
3031
                        $myProjectDir =~ s~/[^/]+$~~;
3032
                        last;
3033
                    }
3034
                    Error ("No project Found") unless ( defined $myProjectDir);
2635 dpurdie 3035
 
3036
                    #
3037
                    #   Look for 'include.txt' that may be bwteen the makefile and the project
3038
                    #
3039
 
3040
 
2438 dpurdie 3041
                    if ( -f "$myProjectDir/include.txt" )
3042
                    {
3043
                        Warning ("Co-located 'include.txt' file also found");
3044
                    }
3045
 
3046
                    # The only problem is if the include.txt file
3047
                    # escapes from the VOB - or even uses the vob root
3048
                    #
3049
                    # Examine the include file
3050
                    # Expect it to look like
3051
                    #   /I Path
3052
                    #
3053
 
3054
                    #
3055
                    #   Determine safe level
3056
                    #   Relative to the include file
3057
                    #
3058
                    my $depthPath = $myProjectDir;
3059
                    my $depth = 0;
3060
                    Error ("Expect this to work") unless ( $depthPath =~ s~^$data->{ViewRoot}/~~ );
3061
                    foreach ( split('/', $depthPath) )
3062
                    {
3063
                        if ( $_ eq '..' ) {
3064
                            $depth--;
3065
                        } else {
3066
                            $depth++;
3067
                        }
3068
                    }
3069
#print "Depth: $depth, $depthPath\n";
3070
 
3071
                    if ( open( my $if, '<', "$myProjectDir/include.txt" ) )
3072
                    {
3073
                        while ( <$if> )
3074
                        {
3075
                            s~\s+$~~;
3076
                            s~^\s+~~;
3077
                            next unless ( $_ );
3078
                            if ( m~/I\s+(.*)~ )
3079
                            {
3080
                                my $path = $1;
3081
                                $path =~ tr~\\/~/~s;
3082
                                $path =~ s~\\~/~g;
3083
#print "Examine: $path\n";
3084
                                my $minLevel = 0;
3085
                                my $level = 0;
3086
                                foreach ( split('/', $path) )
3087
                                {
3088
                                    if ( $_ eq '..' )
3089
                                    {
3090
                                        $level--;
3091
                                        $minLevel = $level if ($level < $minLevel);
3092
                                    }
3093
                                    else
3094
                                    {
3095
                                        $level++;
3096
                                    }
3097
                                }
3098
#print "Min: $minLevel, $level, ($depth + $minLevel)\n";
3099
                                if ( $depth + $minLevel <= 0)
3100
                                {
3101
                                    $badIncludeFile++;
3102
                                    Warning ("Included path escapes package:",
3103
                                             "Line: " . $_,
3104
                                             "File: " . "$myProjectDir/include.txt",
3105
                                            );
3106
                                    last;
3107
                                }
3108
                            }
3109
                        }
3110
                        close $if;
3111
                    }
3112
 
3113
                }
3114
                $line = '';
3115
            }
3116
            close $fh;
3117
        }
3118
        else
3119
        {
3120
            Warning ("MakeProject$eSuf - Cannot open makefile: $file");
3121
            $retval = 1;
3122
        }
3123
    }
3124
 
3125
    #
3126
    #   Used
3127
    #   May be improved latter
3128
    #
3129
    if ( $usesMakeProject && $badIncludeFile)
3130
    {
3131
        Warning ("MakeProject$eSuf - Problem detected");
3132
        $retval = 1;
3133
    }
3134
 
3135
    #
3136
    #   Until we have more faith in the detection algorithm
3137
    #
3138
    if ( $usesMakeProject )
3139
    {
3140
        Warning ("MakeProject$eSuf - Makeproject used. Must check manually");
3141
        $retval = 1;
3142
    }
3143
 
3144
    return $retval;
3145
}
3146
 
3147
#-------------------------------------------------------------------------------
2635 dpurdie 3148
# Function        : detectBadMakePaths
3149
#
3150
# Description     : Detect and report bad usage of some directives
3151
#
3152
# Inputs          : $data               - Ref to a hash of bits
3153
#
3154
# Returns         : true    - Bad usage (Really good usage not detected)
3155
#                   false   - Good usage detected
3156
#
3157
sub detectBadMakePaths
3158
{
3159
    my ($data) = @_;
3160
    my $retval = 0;
3161
    my $eSuf = $opt_ignoreBadPaths ? '' : 'Error';
3162
 
3163
    #
3164
    #   Find makefile.pl
3165
    #
3166
    Message ("Detect Bad Source Paths");
3167
    my $badPath = 0;
3168
 
3169
    my $search = JatsLocateFiles->new("--Recurse=1",
3170
                                       "--FilterIn=makefile.pl",
3171
                                       );
3172
    my @makefiles = $search->search($data->{ViewPath});
3173
    foreach my $file ( @makefiles )
3174
    {
3175
        $file =~ tr~/~/~s;
3176
        my $max_up = ($file =~ tr~/~/~);
3177
        my $shownPath;
3178
#print "---Reading: $workDir/$data->{ViewPath}/$file\n";
3179
        if ( open( my $fh, '<', "$data->{ViewPath}/$file" ) )
3180
        {
3181
            my $eof = 0;
3182
            my $line = '';
3183
 
3184
            until ( $eof )
3185
            {
3186
                my $in = <$fh>;
3187
                unless ( defined $in )
3188
                {
3189
                    $eof = 1;
3190
                }
3191
                else
3192
                {
3193
                $in =~ s~\s+$~~;
3194
                $in =~ s~^\s+~~;
3195
                $in =~ s~^#.*$~~;
3196
                $in =~ s~\s*[^\$]#.*$~~;
3197
                $line .= ' ' if ( $line );
3198
                $line .= $in;
3199
                $line =~ s~\s+~ ~g;
3200
#print "====== '$line'\n";
3201
                redo unless ( $line =~ m~;$~  );
3202
                }
3203
                if ( $line =~ m~^AddDir~ || $line =~ m~^AddSrcDir~ || $line =~ m~^AddIncDir~ || $line =~ m~^Src~ )
3204
                {
3205
                    #
3206
                    #   Extract out the arguments
3207
                    #
3208
                    my @myArgs;
3209
                    my $myProjectDir;
3210
                    my $myProject = "$data->{ViewRoot}/$file";
3211
                    $myProject =~ s~/[^/]+$~~;
3212
 
3213
                    unless ($line =~ m~\s*(\w+)\s*\((.*)\)\s*;\s*$~ )
3214
                    {
3215
                        Error("Could not detect arguments: $line");
3216
                    }
3217
                    my $args = $2;
3218
                    $args =~ tr~'" ~ ~s;
3219
                    @myArgs = split (/\s*,\s*/, $args);
3220
                    shift @myArgs;
3221
                    foreach ( @myArgs )
3222
                    {
3223
                        next if ( m~^--~ );
3224
                        next unless ( m~^\.\./~ );
3225
                        my $tmp = $_;
3226
                        $tmp =~ s~Z~z~g;
3227
                        $tmp =~ s~\.\./~Z~g;
3228
                        my $upCount = ( $tmp =~ tr~Z~Z~ );
3229
                        if ( $upCount > $max_up )
3230
                        {
3231
                            Warning ("Makefile Path: $file ") unless $shownPath;
3232
                            Warning ("Path escapes view: $max_up, $upCount, $_");
3233
                            $badPath++;
3234
                            $shownPath = 1;
3235
                        }
3236
#print "---x Path : $max_up, $upCount, $_\n";
3237
                    }
3238
                }
3239
                $line = '';
3240
            }
3241
            close $fh;
3242
        }
3243
        else
3244
        {
3245
            Warning ("detectBadMakePaths$eSuf - Cannot open makefile: $file");
3246
            $retval = 1;
3247
        }
3248
    }
3249
 
3250
    #
3251
    #   Used
3252
    #   May be improved latter
3253
    #
3254
    if ( $badPath )
3255
    {
3256
        Warning ("detectBadMakePaths$eSuf - Bad Path seen. Must check manually");
3257
        $retval = 1;
3258
    }
3259
 
3260
    return $retval;
3261
}
3262
 
3263
 
3264
#-------------------------------------------------------------------------------
1271 dpurdie 3265
# Function        : detectProjectBaseUsage
3266
#
3267
# Description     : Detect and report usage of the SetProjectBase directive
3268
#
3269
# Inputs          : $data               - Ref to a hash of bits
3270
#
3271
# Returns         : true    - Bad usage (Really good usage not detected)
3272
#                   false   - Good usage detected
3273
#
3274
sub detectProjectBaseUsage
3275
{
2635 dpurdie 3276
    my ($data) = @_;
1271 dpurdie 3277
    my $retval = 0;
3278
    my $eSuf = $opt_ignoreProjectBaseErrors ? '' : 'Error';
3279
 
3280
    #
3281
    #   Find makefile.pl
3282
    #
2635 dpurdie 3283
    Message ("Detect ProjectBase Usage");
1271 dpurdie 3284
    my $usesProjectBase = 0;
3285
    my $definesProjectBase = 0;
3286
    my $definitionError = 0;
3287
 
3288
    my $search = JatsLocateFiles->new("--Recurse=1",
3289
                                       "--FilterIn=makefile.pl",
3290
                                       );
2635 dpurdie 3291
    my @makefiles = $search->search($data->{ViewPath});
1271 dpurdie 3292
    foreach my $file ( @makefiles )
3293
    {
2635 dpurdie 3294
        if ( open( my $fh, '<', "$data->{ViewPath}/$file" ) )
1271 dpurdie 3295
        {
3296
            while ( <$fh> )
3297
            {
3298
                s~\s+$~~;
3299
                s~^\s+~~;
3300
                next if ( m~^#~ );
3301
 
3302
                if ( m~\$ProjectBase~ )
3303
                {
3304
                    $usesProjectBase++;
3305
                    Message ("Project Base Use: $_");
3306
                    $data->{UsesProjectBase}++;
3307
                }
3308
 
3309
                if ( m~^SetProjectBase~ )
3310
                {
3311
                    $definesProjectBase++;
3312
                    $data->{DefinesProjectBase}++;
2412 dpurdie 3313
                    Warning ("Package initialises SetProjectBase:",
2635 dpurdie 3314
                             "Line : " . $_,
3315
                             "Root : " . "$data->{ViewRoot}",
3316
                             "Path : " . "$data->{ViewPath}",
3317
                             "File : " . "$data->{ViewPath}/$file",
1271 dpurdie 3318
                            );
3319
 
3320
                    # The only problem is if the user attempts to escape
3321
                    # from the root of the view.
3322
                    #
3323
                    # Examine the depth of the makefile with the directive
3324
                    # Examine the depth of the view base
3325
                    #
3326
                    #
3327
                    # Locate the build.pl file
3328
                    # This is the basis for for the directive
3329
                    #
3330
                    my $blevel;
3331
                    my @bpaths = split ('/', $file );
2635 dpurdie 3332
                    my $buildFile;
1271 dpurdie 3333
                    while ( @bpaths )
3334
                    {
3335
                        $bpaths[-1] = 'build.pl';
3336
                        my $bfile = join '/', @bpaths ;
2635 dpurdie 3337
                        $buildFile = "$data->{ViewPath}/$bfile";
3338
                        if ( -f $buildFile )
1271 dpurdie 3339
                        {
3340
                            $blevel = scalar @bpaths;
3341
                            last;
3342
                        }
3343
                        pop @bpaths;
3344
                    }
3345
                    unless (defined $blevel)
3346
                    {
3347
                        Warning ("SetProjectBase$eSuf calculation failed - can't find build.pl");
2412 dpurdie 3348
#                        $retval = 1;
3349
                         $definitionError++;
1271 dpurdie 3350
                    }
3351
                    else
3352
                    {
3353
                        #
3354
                        #   Determine the depth of the view root
3355
                        #
2635 dpurdie 3356
                        Warning ("Build: $buildFile");
3357
                        my $countPath = ($data->{ViewPath} =~ tr~/~/~);
3358
                        my $countBuild = ($buildFile =~ tr~/~/~);
3359
                        my $max_up = $countBuild - $countPath -1;
1271 dpurdie 3360
 
3361
                        m~--Up=(\d+)~i;
3362
                        my $ulevel = $1;
3363
                        if ( defined $ulevel )
3364
                        {
3365
                            my @paths = split ('/', $file );
3366
                            my $plevel = scalar @paths;
3367
 
3368
#print "--- blevel: $blevel\n";
3369
#print "--- bpaths: @bpaths\n";
3370
#print "--- ulevel: $ulevel\n";
3371
#print "--- paths: @paths\n";
3372
#print "--- plevel: $plevel\n";
3373
#print "--- max_up: $max_up\n";
3374
 
3375
                            if ( $ulevel > $max_up )
3376
                            {
3377
                                Warning ("SetProjectBase escapes view. MaxUp: $max_up, Up: $ulevel");
3378
                                $definitionError++;
3379
                            }
3380
                        }
3381
                        else
3382
                        {
3383
                            $retval = 1;
3384
                            Warning ("SetProjectBase$eSuf MAY escape view - can't detect level")
3385
                        }
3386
                    }
3387
                }
3388
            }
3389
            close $fh;
3390
        }
3391
        else
3392
        {
3393
            Warning ("SetProjectBase$eSuf - Cannot open makefile: $file");
3394
            $retval = 1;
3395
        }
3396
    }
3397
 
3398
    #
3399
    #   Detect defined, but not used
3400
    #
3401
    if ( $usesProjectBase && ! $definesProjectBase )
3402
    {
3403
        Warning ("SetProjectBase - Uses ProjectBase without defining it");
3404
    }
3405
 
3406
    if ( ! $usesProjectBase && $definesProjectBase )
3407
    {
3408
        Warning ("SetProjectBase - Defines ProjectBase without using it");
3409
    }
3410
 
3411
    if ( $usesProjectBase && $definesProjectBase && $definitionError )
3412
    {
3413
        Warning ("SetProjectBase$eSuf - Problem detected");
3414
        $retval = 1;
3415
    }
3416
    return $retval;
3417
}
3418
 
1272 dpurdie 3419
#-------------------------------------------------------------------------------
3420
# Function        : findDirWithStuff
3421
#
3422
# Description     : Find a directory that contains more than just another subdir
2412 dpurdie 3423
#                   Note: don't use 'glob' it doesn't work if the name has a space in it.
1272 dpurdie 3424
#
3425
# Inputs          : $base               - Start of the scan
3426
#
3427
# Returns         : Path to dir with more than just a single dir in it
3428
#
3429
sub findDirWithStuff
3430
{
3431
    my ($base) = @_;
1271 dpurdie 3432
 
1272 dpurdie 3433
    while ( $base )
3434
    {
3435
    my $fileCount = 0;
3436
    my $dirCount = 0;
2412 dpurdie 3437
    my $firstDir;
1272 dpurdie 3438
 
2412 dpurdie 3439
    opendir (my $dh, $base ) || Error ("Cannot opendir $base. $!");
3440
    my @list =readdir $dh;
3441
    closedir $dh;
1272 dpurdie 3442
    foreach ( @list )
3443
    {
3444
        next if ( $_ eq '.' );
3445
        next if ( $_ eq '..' );
2412 dpurdie 3446
 
3447
        $_ = $base . '/' . $_;
1272 dpurdie 3448
        if ( -d $_ )
3449
        {
3450
            $dirCount++;
2412 dpurdie 3451
            $firstDir = $_ unless ( defined $firstDir );
3452
            return $base
3453
                if ( $dirCount > 1  )
1272 dpurdie 3454
        }
2412 dpurdie 3455
        elsif ( -e $_ )
1272 dpurdie 3456
        {
3457
            return $base;
3458
        }
2412 dpurdie 3459
 
3460
        # else its probably a dead symlink
1272 dpurdie 3461
    }
2412 dpurdie 3462
 
3463
    return $base
3464
        unless ( $dirCount == 1  );
3465
    $base = $firstDir;
1272 dpurdie 3466
    }
3467
}
3468
 
1271 dpurdie 3469
#-------------------------------------------------------------------------------
3470
# Function        : JatsToolPrint
3471
#
3472
# Description     : Print and Execuate a JatsTool command
3473
#
3474
# Inputs          : 
3475
#
3476
# Returns         : 
3477
#
3478
 
3479
sub JatsToolPrint
3480
{
3481
    Information ("Command: @_");
3482
    JatsTool @_;
3483
}
3484
 
3485
sub GetVname
3486
{
3487
    my ($entry) = @_;
3488
    my $me = 'NONE';
3489
    if ( $entry )
3490
        {
3491
        $me = $versions{$entry}{vname};
3492
        unless ( $me )
3493
        {
3494
            $me = 'Unknown-' . $entry;
3495
        }
3496
    }
3497
    return $me;
3498
}
3499
 
2412 dpurdie 3500
#-------------------------------------------------------------------------------
3501
# Function        : saneLabel
3502
#
3503
# Description     : Generate a sane version label
3504
#                   Handle suplicates (due to character squishing)
3505
#                   Cache results for repeatability
3506
#
3507
# Inputs          : $entry          - Version info
3508
#                   $pkgname        - Alternate pkgname (branching)
3509
#
3510
# Returns         : Sane string
3511
#
1271 dpurdie 3512
sub saneLabel
3513
{
3514
    my ($entry, $pkgname) = @_;
3515
    my $me;
2412 dpurdie 3516
    $me = $versions{$entry}{vname};
3517
    $pkgname = $versions{$entry}{name} unless ( defined $pkgname );
1271 dpurdie 3518
 
2412 dpurdie 3519
    #
3520
    #   If we have calculated it, then reuse it.
3521
    #
3522
    if ( exists $versions{$entry}{saneLabel}{$pkgname} )
1271 dpurdie 3523
    {
2412 dpurdie 3524
        return $versions{$entry}{saneLabel}{$pkgname};
1271 dpurdie 3525
    }
3526
 
2412 dpurdie 3527
 
1271 dpurdie 3528
    Error ("Package does have a version string: pvid: $entry")
3529
        unless ( defined $me );
3530
 
3531
    #
3532
    #   Convert Wip format (xxxx) into a string that can be used for a label
3533
    #
3534
    if ( $me =~ m~^(.*)\((.*)\)(.*)$~ )
3535
    {
3536
        $me = $1 . '_' . $2 . '_' . $3 . '.WIP';
3537
        $me =~ s~_\.~.~;
3538
        $me =~ s~^_~~;
3539
    }
3540
 
3541
    #
3542
    #   Allow for WIPS
3543
    #   Get rid of multiple '_'
3544
    #   Replace space with -
3545
    #
3546
    $me = $pkgname . '_' . $me;
3547
    $me =~ tr~ ~-~s;
3548
    $me =~ tr~-~-~s;
3549
    $me =~ tr~_~_~s;
3550
 
2412 dpurdie 3551
    #
3552
    #   Due to some sillyness ( package version starting with _ )
3553
    #   we may get duplicates. Detect and allocate different numbers
3554
    #
3555
    if ( exists $saneLabels{$me} )
3556
    {
3557
        $saneLabels{$me}++;
3558
        $me = $me . '.' . $saneLabels{$me};
3559
        Message ("Duplicate SaneLabel resolved as: $me");
3560
    }
3561
    else
3562
    {
3563
        $saneLabels{$me} = 0;
3564
    }
3565
 
3566
    #
3567
    #   Cache value
3568
    #
3569
    $versions{$entry}{saneLabel}{$pkgname} = $me;
1271 dpurdie 3570
    return $me;
3571
}
3572
 
2412 dpurdie 3573
sub saneString
3574
{
3575
    my ($string) = @_;
3576
    #
3577
    #   Get rid of multiple '_'
3578
    #   Replace space with -
3579
    #
3580
    $string =~ s~\W~_~g;
3581
    $string =~ tr~ ~_~s;
3582
    $string =~ tr~_-~-~s;
3583
    $string =~ tr~-_~-~s;
3584
    $string =~ tr~-~-~s;
3585
    $string =~ tr~_~_~s;
3586
    $string =~ s~-$~~;
3587
    $string =~ s~_$~~;
1271 dpurdie 3588
 
2412 dpurdie 3589
    return $string;
3590
}
3591
 
3592
 
1271 dpurdie 3593
exit 0;
3594
 
3595
 
3596
#-------------------------------------------------------------------------------
3597
# Function        : GetPkgIdByName
3598
#
3599
# Description     :
3600
#
3601
# Inputs          : pkg_name
3602
#
3603
# Returns         : pkg_id
3604
#
3605
sub GetPkgIdByName
3606
{
3607
    my ( $pkg_name ) = @_;
3608
    my (@row);
3609
    my $pv_id;
3610
    my $pkg_id;
3611
 
3612
    #
3613
    #   Establish a connection to Release Manager
3614
    #
3615
    connectRM(\$RM_DB) unless ( $RM_DB );
3616
 
3617
    #
3618
    #   Extract data from Release Manager
3619
    #
3620
    my $m_sqlstr = "SELECT pkg.PKG_NAME, pkg.PKG_ID" .
3621
                   " FROM RELEASE_MANAGER.PACKAGES pkg" .
3622
                   " WHERE pkg.PKG_NAME = \'$pkg_name\'";
3623
 
3624
    my $sth = $RM_DB->prepare($m_sqlstr);
3625
    if ( defined($sth) )
3626
    {
3627
        if ( $sth->execute( ) )
3628
        {
3629
            if ( $sth->rows )
3630
            {
3631
                while ( @row = $sth->fetchrow_array )
3632
                {
3633
                    Verbose( "DATA: " . join(',', @row) );
3634
                    $pkg_id = $row[1] || 0;
3635
                    last;
3636
                }
3637
            }
3638
            else
3639
            {
3640
                Error ("GetPkgIdByName:No Data for package: $pkg_name");
3641
            }
3642
            $sth->finish();
3643
        }
3644
    }
3645
    else
3646
    {
3647
        Error("GetPkgIdByName:Prepare failure" );
3648
    }
3649
 
3650
    return $pkg_id;
3651
}
3652
 
3653
#-------------------------------------------------------------------------------
3654
# Function        : GetData_by_pkg_id
3655
#
3656
# Description     :
3657
#
3658
# Inputs          : pv_id
3659
#
3660
# Returns         :
3661
#
3662
sub GetData_by_pkg_id
3663
{
3664
    my ( $pkg_id, $packageName ) = @_;
3665
    my (@row);
3666
 
3667
    #
3668
    #   Establish a connection to Release Manager
3669
    #
3670
    Message ("Extract package versions from Release Manager: $packageName");
3671
    connectRM(\$RM_DB) unless ( $RM_DB );
3672
 
3673
    #
3674
    #   Extract data from Release Manager
3675
    #
2412 dpurdie 3676
    my $m_sqlstr = "SELECT " .
3677
                       "pkg.PKG_NAME, " .                                       # row[0]
3678
                       "pv.PKG_VERSION, " .                                     # row[1]
3679
                       "pkg.PKG_ID, " .                                         # row[2]
3680
                       "pv.PV_ID, " .                                           # row[3]
3681
                       "pv.LAST_PV_ID, " .                                      # row[4]
3682
                       "pv.MODIFIED_STAMP, " .                                  # row[5]
3683
                       "release_manager.PK_RMAPI.return_vcs_tag(pv.PV_ID), " .  # row[6]
3684
                       "amu.USER_NAME, " .                                      # row[7]
3685
                       "pv.COMMENTS, " .                                        # row[8]
3686
                       "pv.DLOCKED, " .                                         # row[9]
3687
                       "pv.CREATOR_ID, ".                                       # row[10]
3688
                       "pv.BUILD_TYPE ".                                        # row[11]
3689
                   " FROM " .
3690
                        "RELEASE_MANAGER.PACKAGES pkg, " .
3691
                        "RELEASE_MANAGER.PACKAGE_VERSIONS pv, " .
3692
                        "ACCESS_MANAGER.USERS amu" .
3693
                   " WHERE " .
3694
                        "pv.PKG_ID = \'$pkg_id\' " .
3695
                        "AND pkg.PKG_ID = pv.PKG_ID " .
3696
                        "AND amu.USER_ID (+) = pv.CREATOR_ID";
3697
 
1271 dpurdie 3698
    my $sth = $RM_DB->prepare($m_sqlstr);
3699
    if ( defined($sth) )
3700
    {
3701
        if ( $sth->execute( ) )
3702
        {
3703
            if ( $sth->rows )
3704
            {
3705
                while ( @row = $sth->fetchrow_array )
3706
                {
3707
                    Verbose( "DATA: " . join(',', @row) );
3708
                    my $pkg_name = $row[0] || 'Unknown';
3709
                    my $pkg_ver = $row[1] || 'Unknown';
3710
                       $pkg_ver =~ s~\s+$~~;
3711
                       $pkg_ver =~ s~^\s+~~;
3712
                    my $pv_id = $row[3] || 'Unknown';
3713
                    my $last_pv_id = $row[4];
3714
                    my $created =  $row[5] || 'Unknown';
3715
                    my $vcstag =  $row[6] || 'Unknown';
3716
 
3717
                    my $created_id =  $row[7] || ($row[10] ? "Userid_$row[10]" :'Unknown');
3718
                    my $comment =  $row[8] || '';
3719
                    my $locked =  $row[9] || 'N';
2412 dpurdie 3720
                    my $manual = $row[11] || 'M';
1271 dpurdie 3721
 
3722
                    #
3723
                    #   Some developers have a 'special' package version
3724
                    #   We really need to ignore them
3725
                    #
3726
                    next if ( $pkg_ver eq '23.23.23.ssw' );
3727
 
3728
                    #
3729
                    #   Add data to the hash
3730
                    #       Remove entries that address themselves
3731
                    #
3732
                    push (@{$versions{$last_pv_id}{next}}, $pv_id) unless ($pv_id == $last_pv_id || $last_pv_id == 0) ;
3733
                    $versions{$pv_id}{name} = $pkg_name;
3734
                    $versions{$pv_id}{pvid} = $pv_id;
3735
                    $versions{$pv_id}{vname} = $pkg_ver;
3736
                    $versions{$pv_id}{vcsTag} = $vcstag;
3737
                    $versions{$pv_id}{created} = $created;
3738
                    $versions{$pv_id}{created_id} = $created_id;
3739
                    $versions{$pv_id}{comment} = $comment;
3740
                    $versions{$pv_id}{locked} = $locked;
3741
                    $versions{$pv_id}{TimeStamp} = str2time( $created );
3742
                    $versions{$pv_id}{Age} = ($now - $versions{$pv_id}{TimeStamp}) / (60 * 60 * 24);
3743
                    $versions{$pv_id}{TooOld} = 1 if ( $opt_age && $opt_age <= $versions{$pv_id}{Age} );
2412 dpurdie 3744
                    $versions{$pv_id}{BuildType} = $manual;
1271 dpurdie 3745
                    examineVcsTag($pv_id);
3746
 
3747
                    #
3748
                    #   Process version number
3749
                    #
3750
                    my ($suffix, $version, $isaR, $isaWip, $buildVersion ) = massageVersion($pkg_ver, $pkg_name);
3751
 
3752
                    $versions{$pv_id}{version} = $version;
3753
                    $versions{$pv_id}{buildVersion} = $buildVersion;
3754
                    $versions{$pv_id}{isaWip} = 1 if ( $isaWip );
3755
 
3756
                    #
2412 dpurdie 3757
                    #   New methof for detecting a ripple
3758
                    #       Don't look at the version number
3759
                    #       Use RM data
3760
                    #       Inlude the comment - there are some cases where the comment
3761
                    #       appears to have been user modified.
3762
                    #
3763
#                    $versions{$pv_id}{isaRipple} = 1 if ( $isaR );
3764
#                    $versions{$pv_id}{isaRipple} = 1 if ( uc($manual) eq 'Y' );
3765
                    $versions{$pv_id}{isaRipple} = ( $comment =~ m~^Rippled Build~i && ( uc($manual) eq 'Y' ));
3766
 
3767
                    #
1271 dpurdie 3768
                    #   Process suffix
3769
                    #
3770
                    $suffix = 'Unknown' unless ( $suffix );
3771
                    $suffix = lc ($suffix);
3772
                    $versions{$pv_id}{suffix} = $suffix;
3773
                    push @{$suffixes{$suffix}}, $pv_id;
3774
 
3775
#                    print "$pkg_name, $pkg_ver, $pv_id, $last_pv_id, $locked, $created, $created_id, $suffix\n";
3776
                }
3777
            }
3778
            else
3779
            {
3780
                Error ("GetData_by_pkg_id: No Data: $m_sqlstr");
3781
            }
3782
            $sth->finish();
3783
        }
3784
        else
3785
        {
3786
                Error ("GetData_by_pkg_id: Execute: $m_sqlstr");
3787
        }
3788
    }
3789
    else
3790
    {
3791
        Error("GetData_by_pkg_id:Prepare failure" );
3792
    }
3793
}
3794
 
3795
#-------------------------------------------------------------------------------
3796
# Function        : massageVersion
3797
#
3798
# Description     : Process a version number and return usful bits
3799
#
3800
# Inputs          : Version Number
3801
#                   Package Name - debug only
3802
#
3803
# Returns         : An array
3804
#                       suffix
3805
#                       multipart version string useful for text comparisons
3806
#
3807
sub massageVersion
3808
{
3809
    my ($version, $name) = @_;
3810
    my ($major, $minor, $patch, $build, $suffix);
3811
    my $result;
3812
    my $buildVersion;
3813
    my $isaRipple;
3814
    my $isaWIP;
3815
    $build = 0;
3816
 
3817
#print "--- $name, $version\n";
3818
    $version =~ s~^_~~;
3819
    $version =~ s~^${name}_~~;
3820
 
3821
    #
3822
    #   xxxxxxxxx.nnnn.cots
3823
    #
3824
    if ( $version =~ m~(.*)\.cots$~ ) {
3825
        my $cots_base = $1;
3826
        $suffix = '.cots';
3827
        if ( $version =~ m~(.*?)\.([0-9]{4})\.cots$~ )
3828
        {
3829
            $result = $1 . sprintf (".%4.4d", $2) . $suffix;
3830
        }
3831
        else
3832
        {
3833
            $result = $cots_base . '.0000.cots';
3834
        }
3835
    }
3836
    #
3837
    #   Convert version into full form for comparisions
3838
    #       nnn.nnn.nnn.[p]nnn.xxx
3839
    #       nnn.nnn.nnn.[p]nnn-xxx
3840
    #       nnn.nnn.nnn-[p]nnn.xxx
3841
    #       nnn.nnn.nnn-[p]nnn-xxx
3842
    #       nnn.nnn.nnn[p]nnn-xxx
3843
    #   Don't flag as ripples - they are patches
3844
    #
3845
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)[-.p][p]?(\d+)([-.](.*))?$~ ) {
3846
        $major = $1;
3847
        $minor = $2;
3848
        $patch = $3;
3849
        $build = $4;
3850
        $suffix = defined $6 ? ".$6" : '';
3851
        $isaRipple = 0;
3852
    }
3853
    #
3854
    #       nn.nnn.nnnnn.xxx
3855
    #       nn.nnn.nnnnn-xxx
3856
    #       nnn.nnn.nnnx.xxx
3857
    #   Don't flag as ripples - they are patches
3858
    #
3859
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)\w?([-.](.*))?$~ ) {
3860
        $major = $1;
3861
        $minor = $2;
3862
        $patch = $3;
3863
        if ( length( $patch) >= 4 )
3864
        {
3865
            $build = substr( $patch, -3 ,3);
3866
            $patch = substr( $patch,  0 ,length($patch)-3);
3867
        }
3868
        $suffix = defined $5 ? ".$5" : '';
3869
    }
3870
 
3871
    #
3872
    #       nnn.nnn.nnn
3873
    #       nnn.nnn-nnn
3874
    #       nnn.nnn_nnn
3875
    #
3876
    elsif ( $version =~ m~^(\d+)\.(\d+)[-._](\d+)$~ ) {
3877
        $major = $1;
3878
        $minor = $2;
3879
        $patch = $3;
3880
        $suffix = '';
3881
    }
3882
 
3883
    #
3884
    #       nnn.nnn.nnn.nnn
3885
    #       nnn.nnn.nnn-nnn
3886
    #       nnn.nnn.nnn_nnn
3887
    #
3888
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)[-._](\d+)$~ ) {
3889
        $major = $1;
3890
        $minor = $2;
3891
        $patch = $3;
3892
        $build = $4;
3893
        $suffix = '';
3894
        $isaRipple = 0;
3895
    }
3896
 
3897
 
3898
    #
3899
    #       nnn.nnn
3900
    #
3901
    elsif ( $version =~ m~^(\d+)\.(\d+)$~ ) {
3902
        $major = $1;
3903
        $minor = $2;
3904
        $patch = 0;
3905
        $suffix = '';
3906
    }
3907
    #
3908
    #       nnn.nnn.xxx
3909
    #
3910
    elsif ( $version =~ m~^(\d+)\.(\d+)(\.\w+)$~ ) {
3911
        $major = $1;
3912
        $minor = $2;
3913
        $patch = 0;
3914
        $suffix = $3;
3915
    }
3916
 
3917
    #
3918
    #       nnn.nnn.nnnz
3919
    #
3920
    elsif ( $version =~ m~^(\d+)\.(\d+)\.(\d+)([a-z])$~ ) {
3921
        $major = $1;
3922
        $minor = $2;
3923
        $patch = $3;
3924
        $build = ord($4) - ord('a');
3925
        $suffix = '.cots';
3926
        $isaRipple = 0;
3927
    }
3928
    #
3929
    #       ???REV=???
3930
    #
3931
    elsif ( $version =~ m~REV=~ ) {
3932
        $suffix = '.cots';
3933
        $result = $version . '.0000.cots';
3934
    }
3935
 
3936
    #
3937
    #   Wip Packages
3938
    #   (nnnnnn).xxx
3939
    #   Should be essential, but want to sort very low
3940
    #
3941
    elsif ($version =~ m~\((.*)\)(\..*)?~) {
3942
        $suffix = $2 || '';
3943
        $result = "000.000.000.000$suffix";
3944
        $isaWIP = 1;
3945
    }
3946
 
3947
    #
3948
    #   !current
3949
    #
3950
    elsif ($version eq '!current' || $version eq 'current_$USER' || $version eq 'current' || $version eq 'beta' || $version eq 'latest' || $version eq 'beta.cr' || $version eq 'CREATE') {
3951
        $suffix = '';
3952
        $result = "000.000.000.000$suffix";
3953
        $isaWIP = 1;
3954
    }
3955
 
3956
    #
3957
    #   Also WIP: FINRUN.103649.BEI.WIP
3958
    elsif ($version =~ m~(\.[a-zA-Z]+)\.WIP$~) {
3959
        $suffix = lc($1);
3960
        $result = "000.000.000.000$suffix";
3961
        $isaWIP = 1;
3962
    }
3963
 
3964
    #
3965
    #   Also ERGOFSSLS190100_015
3966
    #   Don't flag as a ripple
3967
    elsif ($version =~ m~^ERG[A-Z]+(\d\d)(\d\d)(\d\d)[-_](\d+)(\.\w+)?$~) {
3968
        $major = $1;
3969
        $minor = $2;
3970
        $patch = $3;
3971
        $build = $4;
3972
        $suffix = $5 || '.sls';
3973
        $isaRipple = 0;
3974
    }
3975
 
3976
    #
3977
    #   Stuff we don't yet handle
3978
    #
3979
    else  {
3980
        Warning ("Unknown version number: $name,$version");
3981
        $version =~ m~(\.\w+)$~;
3982
        $suffix = $1 || '';
3983
        $result = $version;
3984
    }
3985
 
3986
    $isaRipple = ($build > 0) unless defined $isaRipple;
3987
    unless ( $result )
3988
    {
3989
        # Major and minor of 99.99 are normally funy versions
3990
        # Don't make important desicions on them
3991
        #
3992
        if ( $major == 99 && $minor == 99 )
3993
        {
3994
            $major = 0;
3995
            $minor = 0;
3996
            $patch = 0;
3997
        }
3998
 
3999
        $result = sprintf("%3.3d.%3.3d.%3.3d.%3.3d%s", $major,$minor,$patch,$build,$suffix || '.0000');
4000
        $buildVersion = [ $major, $minor, $patch, $build ];
4001
    }
4002
 
4003
    $suffix = lc( $suffix );
4004
    if ( exists $suffixFixup{$suffix} )
4005
    {
4006
        $suffix = $suffixFixup{$suffix} ;
4007
    }
4008
 
4009
    return ($suffix, $result, $isaRipple, $isaWIP, $buildVersion );
4010
}
4011
 
4012
#-------------------------------------------------------------------------------
4013
# Function        : vcsCleanup
4014
#
4015
# Description     : Cleanup and rewrite a vcstag
4016
#
4017
#                   DUPLICATED IN:
4018
#                       - cc2svn_procdata
4019
#                       - cc2svn_importpackage
4020
#
4021
# Inputs          : vcstag
4022
#
4023
# Returns         : Cleaned up vcs tag
4024
#
4025
sub vcsCleanup
4026
{
4027
    my ($tag) = @_;
2635 dpurdie 4028
    $tag =~ tr~\\/~/~;                              # Force use of /
4029
    $tag =~ s~/+$~~;                                # Trailing /
1271 dpurdie 4030
    if ( $tag =~ m~^CC::~ )
4031
    {
2635 dpurdie 4032
        $tag =~ s~CC::/VOB:/~CC::/~;                # Kill stuff
2412 dpurdie 4033
        $tag =~ s~CC::load\s+~CC::~;                # Load rule
4034
        $tag =~ s~CC::\s+~CC::~;                    # Leading white space
4035
        $tag =~ s~CC::[A-Za-z]\:/~CC::/~;           # Leading driver letter
4036
        $tag =~ s~CC::/+~CC::/~;                    # Multiple initial /'s
4037
        $tag =~ s~/build.pl::~::~i;
4038
        $tag =~ s~/src::~::~i;
1271 dpurdie 4039
        $tag =~ s~MASS_Dev_Bus/Cbp/~MASS_Dev_Bus/CBP/~i;
4040
        $tag =~ s~MASS_Dev_Bus~MASS_Dev_Bus~i;
4041
        $tag =~ s~/MASS_Dev/Infra~MASS_Dev_Infra~i;
4042
        $tag =~ s~/MASS_Dev/Bus/web~/MASS_Dev_Bus/web~i;
4043
 
4044
        $tag =~ s~/Vastraffik/~/Vasttrafik/~;
4045
        $tag =~ s~/MREF_Package/ergpostmongui$~/MREF_Package/ergpostmongui~i;
4046
        $tag =~ s~DPC_SWCode/~DPG_SWCode/~i;
4047
    }
4048
    return $tag;
4049
}
4050
 
4051
#-------------------------------------------------------------------------------
4052
# Function        : examineVcsTag
4053
#
4054
# Description     : Examine a VCS Tag and determine if it looks like rubbish
4055
#                   Give it a clean
4056
#
4057
# Inputs          : $entry
4058
#
4059
# Returns         : Will add Data to the $entry
4060
#
4061
sub examineVcsTag
4062
{
4063
    my ($entry) = @_;
4064
    my $bad = 0;
4065
 
4066
    $versions{$entry}{vcsTag} = vcsCleanup($versions{$entry}{vcsTag});
4067
    my $vcstag = $versions{$entry}{vcsTag};
4068
 
4069
    if ( $vcstag =~ m~^SVN::~ ) {
4070
        $versions{$entry}{isSvn} = 1;
4071
 
4072
    } elsif ( $vcstag =~ m~^CC::(.*?)(::(.+))?$~ ) {
4073
        my $path = $1  || '';
4074
        my $label = $2 || '';
4075
        $bad = 1 unless ( $label );
4076
        $bad = 1 if ( $label =~ m~^N/A$~i || $label  =~ m~^na$~i );
4077
 
4078
        $bad = 1 unless ( $path );
4079
        $bad = 1 if ( $path =~ m~^N/A$~i || $path  =~ m~^na$~i );
4080
        $bad = 1 if ( $path =~ m~^/dpkg_archive~ || $path  =~ m~^dpkg_archive~ );
4081
        $bad = 1 if ( $path =~ m~^/devl/~ || $path  =~ m~^devl/~ );
4082
        $bad = 1 if ( $path =~ m~^CVS~ );
4083
        $bad = 1 if ( $path =~ m~^http:~i );
4084
        $bad = 1 if ( $path =~ m~^[A-Za-z]\:~ );
4085
        $bad = 1 if ( $path =~ m~^//~ );
2635 dpurdie 4086
        $bad = 1 if ( $path =~ m~^/blade1/~ );
4087
        $bad = 1 if ( $path =~ m~^/devl/~ );
1271 dpurdie 4088
        $bad = 1 if ( $path =~ m~^/*none~i );
4089
        $bad = 1 if ( $path =~ m~^/*NoWhere~i );
4090
        $bad = 1 if ( $path =~ m~^-$~i );
4091
        $bad = 1 if ( $path =~ m~^cvsserver:~ );
4092
        $bad = 1 if ( $path =~ m~,\s*module:~ );
2635 dpurdie 4093
        $bad = 1 if ( $path =~ m~[()]~ );
1271 dpurdie 4094
#        $bad = 1 unless ( $path =~ m~^/~ );
4095
    }
4096
    else
4097
    {
4098
        $bad = 1;
4099
    }
4100
    $versions{$entry}{badVcsTag} = 1 if ( $bad );
4101
}
4102
 
4103
#-------------------------------------------------------------------------------
4104
# Function        : logToFile
4105
#
4106
# Description     : Log some data to a named file
4107
#                   Use file locking to allow multiple process to log
4108
#
4109
# Inputs          : $filename           - Name of file to log
4110
#                   ...                 - Data to log
4111
#
4112
# Returns         : Nothing
4113
#
4114
sub logToFile
4115
{
4116
    my ($file, @data) = @_;
4117
 
4118
    open  (LOGFILE, '>>', $file);
4119
    flock (LOGFILE, LOCK_EX);
4120
    print  LOGFILE "@data\n";
4121
    flock (LOGFILE, LOCK_UN);
4122
    close (LOGFILE);
4123
}
4124
 
4125
#-------------------------------------------------------------------------------
4126
# Function        : createImages
4127
#
4128
# Description     : Create nice images of the RM version tree
4129
#
4130
# Inputs          : 
4131
#
4132
# Returns         : 
4133
#
4134
sub createImages
4135
{
4136
 
4137
    my $filebase = "${packageNames}";
2412 dpurdie 4138
    open (FH, '>', $cwd . "/$filebase.dot" ) or die "Cannot open output";
1271 dpurdie 4139
    print FH "digraph \"${packageNames}\" {\n";
4140
    #print FH "rankdir=LR;\n";
4141
    print FH "node[fontsize=16];\n";
4142
    print FH "node[target=_graphviz];\n";
4143
#    print FH "subgraph cluster_A {\n";
4144
#    print FH "node[fontsize=12];\n";
4145
 
4146
    {
4147
        my @text;
4148
        push @text, $packageNames;
4149
        push @text, 'HyperLinked to Release Manager';
4150
        push @text, 'Created:' . localtime();
4151
        push @text, '|';
4152
 
4153
        push @text, 'Total RM versions: ' . $totalVersions;
4154
        push @text, 'Essential Entries: ' . scalar @EssentialPackages;
4155
        push @text, 'Initial trees: ' . $initialTrees;
4156
 
1272 dpurdie 4157
        push @text, 'Number of Entries: ' . $processTotal;
1271 dpurdie 4158
        push @text, 'Type : ' . $packageType;
4159
        push @text, 'All versions in Subversion' if ( $allSvn );
4160
 
4161
        push @text, '|';
4162
        push @text, 'Total Project Branches: ' . $ProjectCount;
4163
        foreach ( sort keys %knownProjects )
4164
        {
4165
            my $count = $knownProjects{$_}{count} || 0;
4166
            if ( $count )
4167
            {
4168
                my $text = 'Project Branch: ' . $_;
4169
                $text .= " (" . $count . ")" if ( $count > 1 );
4170
                push @text, $text;
4171
            }
4172
        }
4173
 
4174
        push @text, '|';
4175
        push @text, 'Bad VCS : ' . $badVcsCount;
4176
        push @text, 'Bad Singletions : ' . $badSingletonCount;
4177
        push @text, 'Deadwood entries : ' . $trimCount;
4178
        push @text, 'Walking Mode : Flat' if ($opt_flat);
4179
        push @text, 'Pruned Mode : ' . $pruneModeString;
4180
        push @text, 'Pruned entries : ' . $pruneCount;
2412 dpurdie 4181
        push @text, 'Recent entries : ' . $recentCount;
1271 dpurdie 4182
 
4183
        if ( @unknownProjects )
4184
        {
4185
            push @text, '|';
4186
            push @text, 'Unknown Projects';
4187
            push @text, 'Unknown Project: ' . $_ foreach (sort @unknownProjects );
4188
        }
4189
 
4190
        #
4191
        #   Multiple Paths
4192
        #
4193
        if ( scalar @multiplePaths > 1 )
4194
        {
4195
            push @text, '|';
4196
            push @text, 'Multiple Paths';
4197
            push @text, @multiplePaths;
4198
        }
4199
 
4200
        #
4201
        #   Bad essentials
4202
        #
4203
        if ( @badEssentials  )
4204
        {
4205
            push @text, '|';
4206
            push @text, 'Bad Essential Versions';
4207
            push @text, GetVname($_) foreach ( @badEssentials );
4208
        }
4209
 
4210
        #
4211
        #   Subversion Data
4212
        #
4213
        if ( %svnData )
4214
        {
4215
            push @text, '|';
4216
            push @text, 'Subversion';
4217
            push @text, 'Trunk used' if exists $svnData{branches}{trunk} ;
4218
            push @text, 'Labels: ' . scalar keys %{$svnData{tags}} ;
4219
            push @text, 'Branches: ' . scalar keys %{$svnData{branches}} ;
2412 dpurdie 4220
            push @text, 'Relabled Packages : ' . $packageReLabelCount;
1271 dpurdie 4221
        }
4222
 
4223
        push @text, '';
4224
        my $text = join '\l', @text;
4225
        $text =~ s~\|\\l~|~g;
4226
 
4227
        my @attributes;
4228
        push @attributes, "shape=record";
4229
        push @attributes, "label=\"{$text}\"";
4230
        push @attributes, "tooltip=\"$packageNames\"";
4231
        push (@attributes, "URL=\"" . $GBE_RM_URL . "/view_by_version.asp?pkg_id=$first_pkg_id" . "\"" )if $first_pkg_id;
4232
        push @attributes, "color=red";
4233
        my $attr = join( ' ', @attributes);
4234
 
4235
        my $tld_done = 'TitleBlock';
4236
        print FH "$tld_done [$attr]\n";
4237
    }
4238
 
4239
    #
4240
    #   Generate Legend
4241
    #
4242
    {
4243
        my @text;
4244
        push @text, 'Legend';
4245
        push @text, '|';
4246
        push @text, 'Node Content';
4247
        push @text, 'Package Version';
4248
#        push @text, 'Release Manager Ref (pvid)';
4249
        push @text, 'Creation Date: yyyy-mm-dd';
4250
        push @text, '(Coded information)';
4251
        push @text, '|{Code';
4252
        push @text, '|{N: Not Locked';
4253
        push @text, 'b: Bad Singleton';
4254
        push @text, 'd: A dependency';
4255
        push @text, 'B: Bad VCS Tag';
4256
        push @text, 'D: DeadWood';
4257
        push @text, 'e: Essential BOM Version';
4258
        push @text, 'E: Essential Release Version';
2412 dpurdie 4259
        push @text, 'F: Package directories labled';
1271 dpurdie 4260
        push @text, 'G: Glued into Version Tree';
2412 dpurdie 4261
        push @text, 'L: Label not in VOB';
4262
        push @text, 'r: Recent version';
4263
        push @text, 'R: Ripple';
1271 dpurdie 4264
        push @text, 'S: Splitpoint';
4265
        push @text, 't: Glued into Project Tree';
4266
        push @text, 'T: Tip version';
4267
        push @text, 'V: In SVN';
4268
        push @text, '+: In Subversion';
2412 dpurdie 4269
        push @text, '0: Zero files extracted';
1271 dpurdie 4270
        push @text, '}}';
4271
 
4272
        push @text, '|';
4273
        push @text, 'Outline';
4274
        push @text, 'Red: Dead or Bad VCS Tag';
4275
        push @text, 'Orange: Project Branch Root';
4276
        push @text, 'Green: Ripple Build Version';
4277
        push @text, 'Blue: Essential Version';
4278
        push @text, 'Darkmagenta: Entry Glued into tree';
4279
        push @text, 'Magenta: Entry added to project tree';
2412 dpurdie 4280
        push @text, 'DeepPink: Label not in VOB';
4281
        push @text, 'DarkViolet: Zero files extracted';
1271 dpurdie 4282
 
4283
 
4284
        push @text, '|';
4285
        push @text, 'Fill';
4286
        push @text, 'PowderBlue: Essential Version';
4287
        push @text, 'Red: Bad Essential Version';
4288
        push @text, 'Light Green: Migrated to SVN';
4289
#        push @text, 'Red: Entry Glued into tree';
4290
#        push @text, 'Green: Entry added to project tree';
4291
 
4292
        push @text, '|';
4293
        push @text, 'Shape';
4294
        push @text, 'Oval: Normal Package Version';
4295
        push @text, 'Invhouse: Project Branch Root';
4296
        push @text, 'Octagon: Branch Point';
4297
        push @text, 'Box: Bad Single version with no history';
4298
        push @text, 'Doublecircle: Tip of a Project Branch';
4299
 
4300
        push @text, '';
4301
        my $text = join '\l', @text;
4302
        $text =~ s~\|\\l~|~g;
4303
        $text =~ s~\}\\l~}~g;
4304
 
4305
        my @attributes;
4306
        push @attributes, "shape=record";
4307
        push @attributes, "label=\"{$text}\"";
4308
        push @attributes, "color=red";
4309
        my $attr = join( ' ', @attributes);
4310
 
4311
        my $tld_done = 'LegendBlock';
4312
        print FH "$tld_done [$attr]\n";
4313
    }
4314
 
4315
#    print FH "\n}\n";
4316
    print FH "TitleBlock -> LegendBlock [style=invis]\n";
4317
 
4318
    sub genLabelText
4319
    {
4320
        my ($entry) = @_;
4321
        my @label;
4322
        push @label, $versions{$entry}{name} if ( $multiPackages );
4323
        push @label, $versions{$entry}{vname};
4324
#        push @label, $entry;       # Add PVID
4325
        push @label, substr( $versions{$entry}{created}, 0, 10); #  2008-02-19
4326
#        push @label, 'V=' . $versions{$entry}{maxVersion};
4327
#        push @label, 'B=' . $versions{$entry}{svnBranchTip} if ( exists $versions{$entry}{svnBranchTip} );
4328
 
4329
        my $reason = '';
4330
        if (exists $versions{$entry}{Essential})
4331
        {
4332
            $reason = 'E';
4333
            if (exists $versions{$entry}{Reason})
4334
            {
4335
                if ( $versions{$entry}{Reason} =~ m~bom~ )
4336
                {
4337
                    $reason = 'e';
4338
                }
4339
                if ( $versions{$entry}{Reason} =~ m~Depend~ )
4340
                {
4341
                    $reason .= 'd';
4342
                }
4343
            }
4344
        }
4345
 
4346
        my $stateText = '';
4347
        $stateText .= 'N' if ($versions{$entry}{locked} eq 'N');
4348
        $stateText .= 'b' if (exists $versions{$entry}{badSingleton});
4349
        $stateText .= 'B' if (exists $versions{$entry}{badVcsTag});
4350
        $stateText .= 'G' if (exists $versions{$entry}{GluedIn});
4351
        $stateText .= 't' if (exists $versions{$entry}{MakeTree});
4352
#        $stateText .= 'E' if (exists $versions{$entry}{Essential});
4353
        $stateText .= $reason if ( $reason );
4354
        $stateText .= 'D' if (exists $versions{$entry}{DeadWood});
2412 dpurdie 4355
        $stateText .= 'R' if ( $versions{$entry}{isaRipple} );
4356
        $stateText .= 'r' if (exists $versions{$entry}{keepRecent} && $versions{$entry}{keepRecent} );
1271 dpurdie 4357
        $stateText .= 'S' if (exists $versions{$entry}{EssentialSplitPoint} && $versions{$entry}{EssentialSplitPoint} > 1 );
4358
        $stateText .= 'T' if (exists $versions{$entry}{Tip} );
4359
        $stateText .= 'V' if (exists $versions{$entry}{isSvn} );
4360
        $stateText .= '+' if (exists $versions{$entry}{svnVersion} );
2412 dpurdie 4361
        $stateText .= '0' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq '0');
4362
        $stateText .= 'L' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq 'L');
4363
        $stateText .= 'F' if ($versions{$entry}{data}{DirsLabled});
4364
 
4365
 
1271 dpurdie 4366
#        $stateText .= 's' if (exists $versions{$entry}{branchPoint} );
4367
#        $stateText .= ' T='. $versions{$entry}{threadId} if (exists $versions{$entry}{threadId});
4368
#        $stateText .= ' EssentalPath' if (exists $versions{$entry}{EssentialPath});
4369
#        $stateText .= ' Count='. $versions{$entry}{EssentialSplitPoint} if (exists $versions{$entry}{EssentialSplitPoint});
4370
#        $stateText .= ' M='. $versions{$entry}{maxVersion} if (exists $versions{$entry}{maxVersion});
4371
 
2412 dpurdie 4372
        push @label, "(${stateText})" if ( length($stateText) );
1271 dpurdie 4373
 
2412 dpurdie 4374
##       Insert Release Names
4375
        foreach my $rtag_id ( keys %{$versions{$entry}{Releases}}  ) {
4376
            next unless ( exists $ukHopsReleases{$rtag_id} );
4377
            push @label, "Release: $versions{$entry}{Releases}{$rtag_id}{rname}";
4378
        }
4379
 
1271 dpurdie 4380
        return join ('\n', @label );
4381
    }
4382
 
4383
    sub genAttributes
4384
    {
4385
        my ($entry) = @_;
4386
        my @attributes;
4387
        push @attributes, 'label="' . genLabelText($entry) . '"';
4388
        unless ( $opt_fileList )
4389
        {
4390
            push @attributes, 'URL="' . dotUrl($entry) . '"';
4391
            push @attributes, 'tooltip="' . "Goto: $versions{$entry}{vname}, PVID=$entry" ,'"';
4392
        }
2635 dpurdie 4393
        else
1271 dpurdie 4394
        {
4395
            push @attributes, 'URL="' . "Dummy" . '"';
4396
            push @attributes, 'tooltip="' . "Original Label: $versions{$entry}{realLabel}" ,'"';
4397
        }
4398
        my $shape;
4399
            $shape = 'box' if ($versions{$entry}{badSingleton});
4400
            $shape = 'octagon'  if ($versions{$entry}{branchPoint});
4401
            $shape = 'invhouse' if ($versions{$entry}{newSuffix});
4402
            $shape = 'doublecircle' if ($versions{$entry}{Tip});
4403
 
4404
 
4405
        push @attributes, 'shape=' . $shape if ( $shape );
4406
 
4407
        my $color;
4408
        my $fill;
4409
           $color = 'color=green style=bold' if ( $versions{$entry}{isaRipple} );
4410
           $color = 'color=orange style=bold' if ( $versions{$entry}{newSuffix} );
4411
           $color = 'color=red style=bold' if ( $versions{$entry}{DeadWood} || $versions{$entry}{badVcsTag} );
4412
           $color = 'color=blue style=bold' if ( $versions{$entry}{Essential} );
4413
           $color = 'color=darkmagenta style=bold' if ( $versions{$entry}{GluedIn} );
4414
           $color = 'color=magenta style=bold' if ( $versions{$entry}{MakeTree} );
2412 dpurdie 4415
           $color = 'color=DeepPink style=bold' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq 'L');
4416
           $color = 'color=DarkViolet style=bold' if (exists $versions{$entry}{data}{errCode} && $versions{$entry}{data}{errCode} eq '0');
1271 dpurdie 4417
 
4418
           $fill = 'style=filled fillcolor=powderblue' if ( $versions{$entry}{Essential} );
4419
           $fill = 'style=filled fillcolor=red' if ( $versions{$entry}{Essential} && $versions{$entry}{badVcsTag} );
4420
           $fill = 'style=filled fillcolor="#99FF99"' if ( exists $versions{$entry}{svnVersion} );
4421
 
4422
 
4423
        push @attributes, $color if ( $color );
4424
        push @attributes, $fill if ( $fill );
4425
 
4426
        return '[' . join( ' ', @attributes) . ']';
4427
    }
4428
 
4429
    sub genArrowAttributes
4430
    {
4431
        my ($not_first, $entry) = @_;
4432
        my @attributes;
4433
 
4434
        push @attributes, 'arrowhead=empty' if ( $not_first );
4435
        push ( @attributes, 'label="' . $versions{$entry}{svnBranchTip} .'"' ) if ( exists $versions{$entry}{svnBranchTip} );
4436
 
4437
        return ('[' . join( ' ', @attributes) . ']') if ( @attributes ) ;
4438
        return '';
4439
    }
4440
 
4441
    #
4442
    #   Flat
4443
    #
4444
    if ( $opt_flat )
4445
    {
4446
        my $last = 0;
4447
        foreach my $entry (@flatOrder )
4448
        {
4449
            if ( $last )
4450
            {
4451
                my $me = dotTag($last);
4452
 
4453
                print FH pentry($me)  ,' -> ', pentry(dotTag($entry)), genArrowAttributes(0, $entry) ,";\n";
4454
                print FH pentry($me)  ,genAttributes($last) . ";\n";
4455
            }
4456
            $last = $entry;
4457
        }
4458
        print FH pentry(dotTag($last))  ,genAttributes($last) . ";\n";
4459
 
4460
    }
4461
    else
4462
    {
4463
        foreach my $entry ( sort {$a <=> $b} keys(%versions) )
4464
        {
4465
            my $me = dotTag($entry);
4466
            my @versions = @{ $versions{$entry}{next}};
4467
            my $ii = 0;
4468
            foreach ( @versions )
4469
            {
4470
                print FH pentry($me)  ," -> ",pentry(dotTag($_)), genArrowAttributes($ii++, $_), ";\n";
4471
            }
4472
 
4473
            print FH pentry($me)  ,genAttributes($entry) . ";\n";
4474
        }
4475
    }
4476
 
4477
    print FH "\n};\n";
4478
    close FH;
4479
 
4480
    #
4481
    #   Convert DOT to a SVG
4482
    #
4483
    unless ( $UNIX )
4484
    {
4485
    print "Generating graphical images\n";
4486
#    system( "dot $filebase.dot -Tjpg -o$filebase.jpg" );  # -v
4487
    system( "dot $filebase.dot -Tsvg -o$filebase.svg" );  # -v
4488
#    unlink("$filebase.dot");
4489
 
4490
    #
4491
    #   Display a list of terminal packages
4492
    #   These are packages that are not used by any other package
4493
    #
4494
    print "\n";
4495
#    print "Generated: $filebase.dot\n";
4496
#    print "Generated: $filebase.jpg\n";
4497
    print "Generated: $filebase.svg\n";
4498
    }
4499
    else
4500
    {
4501
        print "Generated: $filebase.dot\n";
4502
    }
4503
}
4504
 
4505
sub dotTag
4506
{
4507
    my ($entry) = @_;
4508
 
4509
    my $label = '';
4510
    if ( $versions{$entry}{realLabel} )
4511
    {
4512
        $label .= $versions{$entry}{realLabel};
4513
    }
4514
    else
4515
    {
4516
        $label .= $versions{$entry}{name} if $multiPackages;
4517
        $label .= $versions{$entry}{vname};
4518
    }
4519
    $label =~ s~[-() ]~_~g;
4520
    return $label;
4521
}
4522
 
4523
sub dotUrl
4524
{
4525
    my ($entry) = @_;
4526
 
4527
    my $pv_base = $GBE_RM_URL . "/fixed_issues.asp?pv_id=$entry";
4528
}
4529
 
4530
#-------------------------------------------------------------------------------
4531
# Function        : pentry
4532
#
4533
# Description     : Generate an entry list as text
4534
#                   Replace "." with "_" since DOT doesn't like .'s
4535
#                   Seperate the arguments
4536
#
4537
# Inputs          : @_          - An array of entries to process
4538
#
4539
# Returns         : A string
4540
#
4541
sub pentry
4542
{
4543
    my ($data) = @_;
4544
    $data =~ s~\.~_~g;
4545
    $result = '"' . $data . '"' ;
4546
    return $result;
4547
}
4548
 
4549
#-------------------------------------------------------------------------------
4550
# Function        : getVobMapping
4551
#
4552
# Description     : Read in Package to Repository Mapping
4553
#
4554
# Inputs          : 
4555
#
4556
# Returns         : Populates %VobMapping
4557
#                             Mapping of PackageName to RepoName[/Subdir]
4558
#
4559
our %ScmRepoMap;
4560
sub getVobMapping
4561
{
4562
    Message ("Read in Vob Mapping");
4563
 
4564
    my $fname = 'cc2svn.repo.dat';
4565
    Error "Cannot locate $fname" unless ( -f $fname );
4566
    require $fname;
4567
 
4568
    Error "Data in $fname is not valid\n"
4569
        unless ( keys(%ScmRepoMap) >= 0 );
4570
 
4571
    $opt_vobMap = $ScmRepoMap{$packageNames}{repo}
4572
        if (exists $ScmRepoMap{$packageNames});
4573
 
2635 dpurdie 4574
    $opt_protected = $ScmRepoMap{$packageNames}{protected}
4575
        if (exists $ScmRepoMap{$packageNames}{protected});
1271 dpurdie 4576
    #
4577
    #   Free the memory
4578
    #
4579
    %ScmRepoMap = ();
4580
 
4581
    #
4582
    #   Calculate Target Repo
4583
    #
4584
    Warning ("No VOB Mapping found")
4585
        unless ($opt_vobMap);
4586
    Error("No repository specified. ie -repo=DevTools or -repo=COTS")
4587
        unless ( $opt_repo || $opt_vobMap );
2438 dpurdie 4588
    my $r1 = ($opt_repo || '') . '/' . ($opt_vobMap || '') . '/' . ($opt_repoSubdir || '') ;
4589
    $r1 =~ s~//~/~g;
1271 dpurdie 4590
    $r1 =~ s~^/~~;
4591
    $r1 =~ s~/$~~;
4592
    $svnRepo = $opt_repo_base . $r1;
4593
 
4594
    Verbose( "Repo URL: $svnRepo");
4595
}
4596
 
4597
 
4598
#-------------------------------------------------------------------------------
4599
# Function        : getEssenialPackageVersions
4600
#
4601
# Description     : Determine the 'Essental' Package Versions
4602
#                   Read the data in from an external file
4603
#
4604
# Inputs          : 
4605
#
4606
# Returns         : Populates @EssentialPackages
4607
#
4608
 
4609
our %ScmReleases;
4610
our %ScmPackages;
4611
our %ScmSuffixes;
4612
sub getEssenialPackageVersions
4613
{
4614
    Message ("Read in Essential Package Versions");
4615
 
4616
    my $fname = 'cc2svn.raw.txt';
4617
    Error "Cannot locate $fname" unless ( -f $fname );
4618
    require $fname;
4619
 
4620
    Error "Data in $fname is not valid\n"
4621
        unless ( keys(%ScmReleases) >= 0 );
4622
 
4623
#    DebugDumpData("ScmReleases", \%ScmReleases );
4624
#    DebugDumpData("ScmPackages", \%ScmPackages );
4625
#    DebugDumpData("ScmSuffixes", \%ScmSuffixes );
4626
 
4627
    #
4628
    #   Create a list of essential packages
4629
    #   Retain packages-versions used in this program
4630
    #
4631
    foreach ( keys %ScmPackages )
4632
    {
4633
        next unless ( exists  $pkg_ids{ $ScmPackages{$_}{pkgid} } );
4634
        push @EssentialPackages, $_;
4635
        Error ("Essential Package Version not in extracted Release Manager Data: $_")
4636
            unless ( exists $versions{$_} );
4637
        $versions{$_}{Essential} = 1;
2635 dpurdie 4638
        $versions{$_}{Reason} = $ScmPackages{$_}{Reason} if exists $ScmPackages{$_}{Reason}  ;
2412 dpurdie 4639
 
4640
        # Retain which RM Release this package-version is the tip
4641
        # Release of
4642
        foreach my $rtag_id ( @{$ScmPackages{$_}{'release'}} )
4643
        {
4644
            $versions{$_}{Releases}{$rtag_id}{rname}   = $ScmReleases{$rtag_id}{name};
4645
            $versions{$_}{Releases}{$rtag_id}{pname}   = $ScmReleases{$rtag_id}{pName};
4646
            $versions{$_}{Releases}{$rtag_id}{proj_id} = $ScmReleases{$rtag_id}{proj_id};
4647
        }
4648
 
4649
        #print "ESSENTIAL: $versions{$_}{name} $versions{$_}{vname}\n";
1271 dpurdie 4650
    }
4651
 
4652
    #
4653
    #   Free memory
4654
    #
4655
    %ScmReleases = ();
4656
    %ScmPackages = ();
4657
    %ScmSuffixes = ();
4658
 
4659
#    DebugDumpData("Essential", \@EssentialPackages );
4660
    Message ("Essential Versions: " . scalar @EssentialPackages );
4661
}
4662
 
4663
#-------------------------------------------------------------------------------
4664
# Function        : ReportPathVariance
4665
#
4666
# Description     : Report variance in paths used by the versions
4667
#
4668
# Inputs          : 
4669
#
4670
# Returns         : 
4671
#
4672
my %VobPaths;
4673
sub ReportPathVariance
4674
{
4675
    Message ("Detect Multiple Paths");
4676
    foreach my $entry ( keys(%versions) )
4677
    {
4678
        my $e = $versions{$entry};
4679
        next if ( isSet ($e, 'DeadWood' ) );
4680
        next if ( isSet ($e, 'badVcsTag') );
4681
        next if ( isSet ($e, 'isSvn') );
4682
        my $tag = $e->{vcsTag};
4683
        next unless ( $tag );
4684
 
4685
        $tag =~ m~^(.+?)::(.*?)(::(.+))?$~;
4686
        my $vcsType = $1;
4687
        my $cc_label = $4;
4688
        my $cc_path = $2;
4689
        $cc_path = '/' . $cc_path;
4690
        $cc_path =~ tr~\\/~/~s;
2635 dpurdie 4691
        $cc_path =~ s~/+$~~;
1271 dpurdie 4692
 
4693
        $VobPaths{$cc_path}++;
4694
    }
4695
 
4696
    @multiplePaths = sort keys %VobPaths;
4697
    if ( scalar @multiplePaths > 1 )
4698
    {
4699
        Warning ("Multiple Paths:" . $_ ) foreach (@multiplePaths);
2635 dpurdie 4700
 
4701
        # Kill SVN import
4702
        # User will need to configure one path
4703
        unless ( $opt_AllowMuliplePaths )
4704
        {
4705
            Warning ("Multiple Paths detected: Import supressed");
4706
            $opt_useSvn = 0
4707
        }
4708
        else
4709
        {
4710
            Message ("Multiple Paths detected: Allowed");
4711
        }
1271 dpurdie 4712
    }
4713
}
4714
 
4715
sub isSet
4716
{
4717
    my ($base, $element) = @_;
4718
    return 0 unless ( exists $base->{$element} );
4719
    return $base->{$element};
4720
}
4721
 
4722
 
4723
#-------------------------------------------------------------------------------
4724
# Function        : recurseList
4725
#
4726
# Description     : Return a list of all element below a given head element
4727
#
4728
# Inputs          : $head               - Head element
4729
#
4730
# Returns         : A list, not in any particular order
4731
#
4732
 
4733
our @recurseList;
4734
sub recurseList
4735
{
4736
    @recurseList = ();
4737
    recurseListBody (@_);
4738
    return @recurseList;
4739
}
4740
sub recurseListBody
4741
{
4742
    foreach my $entry ( @_ )
4743
    {
4744
        push @recurseList, $entry;
4745
no warnings "recursion";
4746
        recurseListBody (@{$versions{$entry}{next}});
4747
    }
4748
}
4749
 
4750
#-------------------------------------------------------------------------------
4751
# Function        : getSvnData
4752
#
4753
# Description     : Read the SVN tree and see what we have
4754
#
4755
# Inputs          : 
4756
#
4757
# Returns         : 
4758
#
4759
my @svnDataItems;
4760
sub getSvnData
4761
{
4762
    Message ("Examine Subversion Tree");
4763
 
4764
    #
4765
    #   Re-init data
4766
    #
4767
    @svnDataItems = ();
4768
    %svnData = ();
4769
 
4770
    #
4771
    #   Create an SVN session
4772
    #
4773
    return unless ( $svnRepo );
4774
    my $svn = NewSessionByUrl ( "$svnRepo/$packageNames" );
4775
    return unless ( $svn );
4776
 
4777
    #
4778
    #   extract data
4779
    #
4780
#    DebugDumpData("SVN", $svn );
4781
    $svn->SvnCmd ( 'log', '-v', '--xml', '--stop-on-copy', $svn->Full()
4782
                    , { 'credentials' => 1,
4783
                        'process' => \&ProcessSvnLog,
4784
                         }
4785
                        );
4786
 
4787
    #
4788
    #   Process data
4789
    foreach my $entry ( @svnDataItems )
4790
    {
4791
        my $name;
4792
        my $isaBranch;
4793
        my $target = $entry->{target};
4794
        if ( $target =~ m~/tags/(.*)~ ) {
4795
            $name = $1;
4796
            $svnData{tags}{$name} = 1;
4797
        } elsif ( $target =~ m~/branches/(.*)~ )  {
4798
            $name = $1;
4799
    #        $branches{$1} = 1;
4800
        } else {
4801
            $svnData{nonTag}{$target} = 1;
4802
        }
4803
 
4804
        my $fromBranch;
4805
        if ( $entry->{fromPath} =~ m~/trunk$~  ) {
4806
            $fromBranch = 'trunk';
4807
        } elsif ( $entry->{fromPath} =~ m~/branches/(.*)~ ) {
4808
            $fromBranch = $1;
4809
        }
4810
 
2412 dpurdie 4811
        # largest Rev number on branch
4812
        if ( exists $svnData{max}{$fromBranch} )
1271 dpurdie 4813
        {
2412 dpurdie 4814
            if ( $svnData{max}{$fromBranch}{rev} <  $entry->{fromRev} )
1271 dpurdie 4815
            {
2412 dpurdie 4816
                $svnData{max}{$fromBranch}{rev} =  $entry->{fromRev};
4817
                $svnData{max}{$fromBranch}{name} = $name;
1271 dpurdie 4818
            }
4819
        }
2412 dpurdie 4820
        else
4821
        {
4822
            $svnData{max}{$fromBranch}{rev} =  $entry->{fromRev};
4823
            $svnData{max}{$fromBranch}{name} = $name;
4824
        }
1271 dpurdie 4825
    }
2412 dpurdie 4826
 
4827
    foreach my $branch ( keys %{$svnData{max}} )
4828
    {
4829
        $svnData{tips}{$svnData{max}{$branch}{name}} = $branch;
4830
    }
4831
#    DebugDumpData("svnDataItems", \@svnDataItems);
1271 dpurdie 4832
#    DebugDumpData("SvnData", \%svnData);
4833
 
2412 dpurdie 4834
 
1271 dpurdie 4835
    foreach my $entry ( keys(%versions) )
4836
    {
4837
        my $import_label = saneLabel($entry);
4838
        delete $versions{$entry}{svnVersion};
4839
        delete $versions{$entry}{svnBranchTip};
4840
 
4841
        if ( exists $svnData{tags}{$import_label} )
4842
        {
4843
            $versions{$entry}{svnVersion} = 1;
4844
        }
4845
 
4846
        if ( exists $svnData{tips}{$import_label} )
4847
        {
4848
            $versions{$entry}{svnBranchTip} = $svnData{tips}{$import_label};
4849
        }
4850
    }
4851
 
2412 dpurdie 4852
    Message ( 'Trunk used: ' . (exists $svnData{'max'}{trunk} ? 'Yes' : 'No') );
1271 dpurdie 4853
    Message ( 'Labels    : ' . scalar keys %{$svnData{tags}} );
2412 dpurdie 4854
    Message ( 'Branches  : ' . scalar keys %{$svnData{'max'}} );
1271 dpurdie 4855
}
4856
 
4857
#-------------------------------------------------------------------------------
4858
# Function        : ProcessSvnLog
4859
#
4860
# Description     :
4861
#                   Parse
4862
#                       <logentry
4863
#                          revision="24272">
4864
#                       <author>bivey</author>
4865
#                       <date>2005-07-25T15:45:35.000000Z</date>
4866
#                       <paths>
4867
#                       <path
4868
#                          prop-mods="false"
4869
#                          text-mods="false"
4870
#                          kind="dir"
4871
#                          copyfrom-path="/enqdef/branches/Stockholm"
4872
#                          copyfrom-rev="24271"
4873
#                          action="A">/enqdef/tags/enqdef_24.0.1.sls</path>
4874
#                       </paths>
4875
#                       <msg>COTS/enqdef: Tagged by Jats Svn Import</msg>
4876
#                       </logentry>
4877
#
4878
# Inputs          : 
4879
#
4880
# Returns         : 
4881
#
4882
my $entryData;
4883
sub  ProcessSvnLog
4884
{
4885
    my ($self, $line ) = @_;
4886
#print "----- $line\n";
4887
    if ( $line =~ m~^<logentry~ ) {
4888
        $entryData = ();
4889
 
4890
    } elsif ( $line =~ m~^\s+revision="(\d+)"~ ) {
4891
        $entryData->{Rev} = $1;
4892
 
4893
    } elsif ( $line =~ m~^\s+copyfrom-path="(.*)"~ ) {
4894
        $entryData->{fromPath} = $1;
4895
 
4896
    } elsif ( $line =~ m~^\s+copyfrom-rev="(\d+)"~ ) {
4897
        $entryData->{fromRev} = $1;
4898
 
4899
    } elsif ( $line =~ m~\s+action=.*?>(.*)</path~ ) {
4900
        $entryData->{target} = $1;
4901
 
4902
    } elsif ( $line =~ m~</logentry~ ) {
4903
        if ( exists $entryData->{fromPath} )
4904
        {
4905
#            DebugDumpData("Data", $entryData);
4906
            push @svnDataItems, $entryData;
4907
        }
4908
    }
4909
 
4910
    #
4911
    #   Return 0 to keep on going
4912
    return 0;
4913
}
4914
 
4915
#-------------------------------------------------------------------------------
4916
# Function        : saveData
4917
#
4918
# Description     : Save essential data
4919
#
4920
# Inputs          : 
4921
#
4922
# Returns         : 
4923
#
4924
sub saveData
4925
{
4926
    my $file = $cwd . "/${packageNames}.data";
4927
 
4928
    Message ("Create: $file");
4929
    my $fh = ConfigurationFile::New( $file );
4930
 
4931
    $fh->DumpData(
4932
        "\n# ScmVersions.\n#\n",
4933
        "ScmVersions", \%versions );
4934
 
4935
    #
4936
    #   Close out the file
4937
    #
4938
    $fh->Close();
4939
}
2635 dpurdie 4940
 
1271 dpurdie 4941
#-------------------------------------------------------------------------------
2635 dpurdie 4942
# Function        : restoreData
4943
#
4944
# Description     : Read in essential information
4945
#                   Used during a resume operation
4946
#
4947
# Inputs          : 
4948
#
4949
# Returns         : 
4950
#
4951
our %ScmVersions;
4952
sub restoreData
4953
{
4954
    my $file = $cwd . "/${packageNames}.data";
4955
    Message ("Restoring: $file");
4956
    Error "Cannot locate restoration file: $file" unless ( -f $file );
4957
    require $file;
4958
 
4959
    Error "Resume Data in $file is not valid\n"
4960
        unless ( keys(%ScmVersions) >= 0 );
4961
 
4962
    foreach  ( keys %ScmVersions )
4963
    {
4964
        $restoreData{$_} = $ScmVersions{$_}{data};
4965
        $restoreData{$_}{rmRef} = $ScmVersions{$_}{rmRef};
4966
    }
4967
    %ScmVersions = ();
4968
}
4969
 
4970
#-------------------------------------------------------------------------------
4971
# Function        : testSvnLabel
4972
#
4973
# Description     : Test existence of an SVN label
4974
#
4975
# Inputs          :     Package
4976
#                       Label to test
4977
#
4978
# Returns         : 0   - Tag in place
4979
#                   1   - Not in place
4980
#
4981
sub testSvnLabel
4982
{
4983
    my ($svnPkg, $svnTag) = @_;
4984
 
4985
    my $rv = JatsToolPrint ( 'jats_svnlabel',
4986
                    '-check',
4987
                    "-packagebase=$svnPkg",
4988
                    "$svnTag",
4989
                     );
4990
    Message ("testSvnLabel: $svnTag - $rv");
4991
    return $rv;
4992
}
4993
 
4994
 
4995
#-------------------------------------------------------------------------------
1271 dpurdie 4996
# Function        : GetData_by_filelist
4997
#
4998
# Description     : Read in source data from a file
4999
#
5000
# Inputs          : FileName
5001
#                   Format is 2002-03-05T17:13:50+08 rmussell MASS_DATAMAN_D1.0.0
5002
#
5003
# Returns         : 
5004
#
5005
sub GetData_by_filelist
5006
{
5007
    my ($fname) = @_;
5008
    my $pv_id = 0;
5009
#print "GetData_by_filelist\n";
5010
 
5011
    open (my $fh, '<', $fname ) || Error ("Cannot open Filelist");
5012
    while ( <$fh> )
5013
    {
5014
        next if ( m~^\s*\#~ );
5015
        my @data = split( /\s+/, $_);
5016
#print "@data\n";
5017
        if ( @data == 3 )
5018
        {
5019
            $data[2] =~ m~^(.*)_(.*)~;
5020
            my $pkg_name = $1;
5021
            my $pkg_ver = $2;
5022
            $pkg_ver =~ s~^[a-zA-Z]\.*~~;
5023
print "$data[2] : $pkg_name, $pkg_ver\n";
5024
 
2412 dpurdie 5025
#           Expecting Clearcase format:
5026
#               2011-08-30T13:49:21+08
5027
#               2010-11-16T03:24:34Z
1271 dpurdie 5028
#           Need 'YYYY-MM-DDTHH:MM:SS.M'
5029
            my $cdate = $data[0];
5030
            $cdate =~ s~ ~T~;
5031
            $cdate =~ s~\+.*~~;
2412 dpurdie 5032
            $cdate =~ s~Z+.*~~;
1271 dpurdie 5033
            $cdate .= '.00';
5034
 
5035
            $pv_id++;
5036
#            $versions{$pv_id}{fileListEntry} = $_;
5037
            $versions{$pv_id}{name} = $pkg_name;
5038
            $versions{$pv_id}{pvid} = $pv_id;
5039
            $versions{$pv_id}{vname} = $pkg_ver;
2635 dpurdie 5040
            $versions{$pv_id}{vcsTag} = "CC::/${opt_ccbase}::$data[2]";
1271 dpurdie 5041
            $versions{$pv_id}{created} = $cdate;
5042
            $versions{$pv_id}{created_id} = $data[1];
5043
            $versions{$pv_id}{realLabel} = $data[2];
5044
            $versions{$pv_id}{comment} = "Label Import: $data[2]";
5045
            $versions{$pv_id}{locked} = 'Y';
5046
            $versions{$pv_id}{TimeStamp} = str2time( $versions{$pv_id}{created} );
5047
            $versions{$pv_id}{Age} = ($now - $versions{$pv_id}{TimeStamp}) / (60 * 60 * 24);
5048
            $versions{$pv_id}{TooOld} = 1 if ( $opt_age && $opt_age <= $versions{$pv_id}{Age} );
5049
            examineVcsTag($pv_id);
5050
 
5051
            #
5052
            #   Process version number
5053
            #
5054
            my ($suffix, $version, $isaR, $isaWip, $buildVersion ) = massageVersion($pkg_ver, $pkg_name);
5055
 
5056
            $versions{$pv_id}{version} = $version;
5057
            $versions{$pv_id}{buildVersion} = $buildVersion;
5058
            $versions{$pv_id}{isaRipple} = 1 if ( $isaR );
5059
            $versions{$pv_id}{isaWip} = 1 if ( $isaWip );
5060
 
5061
            #
5062
            #   Process suffix
5063
            #
5064
            $suffix = 'Unknown' unless ( $suffix );
5065
            $suffix = lc ($suffix);
5066
            $versions{$pv_id}{suffix} = $suffix;
5067
            push @{$suffixes{$suffix}}, $pv_id;
5068
 
5069
#DebugDumpData("PKG ", $versions{$pv_id} );
5070
 
5071
        }
5072
    }
5073
    close $fh;
5074
}
5075
 
5076
#-------------------------------------------------------------------------------
5077
#   Documentation
5078
#
5079
 
5080
=pod
5081
 
5082
=for htmltoc    SYSUTIL::cc2svn::
5083
 
5084
=head1 NAME
5085
 
5086
cc2svn_gendata - CC2SVN tool to import an entire package into SVN
5087
 
5088
=head1 SYNOPSIS
5089
 
5090
  jats cc2svn_importpackage [options] package_name
5091
 
5092
 Options:
5093
    -help              - brief help message
5094
    -help -help        - Detailed help message
5095
    -man               - Full documentation
5096
    -repository=name   - Specify target repository
5097
    -[no]flat          - Do not create project tree. Def: -noflat
5098
    -prunemode=mode    - Mode: none, ripple, retain, severe, Def=ripple
5099
    -retain=N          - Specify retain count for pruning. Def=2
5100
    -[no]test          - Do not create packages. Def:-notest
5101
    -[no]reuse         - Keep and reuse ClearCase views
5102
    -age=nnDays        - Only keep recent package
5103
    -dump[=n]          - Dump raw data. N=0,1,2
5104
    -images[=n]        - Create SVG of version tree. N=0,1,2
5105
    -name=aaa          - Alternate output package name. Test Only
5106
    -[no]log           - Write output to log file. Def: -nolog
5107
    -[no]postimage     - Create image after transger: Def: -post
5108
    -workdir=path      - Use for temp storage (def:/work)
1272 dpurdie 5109
    -delete            - Delete SVN package before test
2412 dpurdie 5110
    -[no]relabel       - Attempt to relabel dirs in packages that don't extract
5111
    -filelist=path     - Use named list of files
2635 dpurdie 5112
    -testRmDatabase    - Use test database
5113
    -[no]fromSvn       - Also extract packages from SVN
1271 dpurdie 5114
 
5115
=head1 OPTIONS
5116
 
5117
=over 8
5118
 
5119
=item B<-help>
5120
 
5121
Print a brief help message and exits.
5122
 
5123
=item B<-help -help>
5124
 
5125
Print a detailed help message with an explanation for each option.
5126
 
5127
=item B<-man>
5128
 
5129
Prints the manual page and exits.
5130
 
5131
=item B<-prunemode=mode>
5132
 
5133
This option control the manner in which excess versions will be pruned. Valid
5134
modes are:
5135
 
5136
=over 8
5137
 
5138
=item   none
5139
 
5140
No pruning will be performed
5141
 
5142
=item   ripple
5143
 
5144
Non-Essential packages that are ripple builds will be removed.
5145
 
5146
=item   retain
5147
 
5148
Versions that preceed an Essential version will be retained.
5149
 
5150
=item   severe
5151
 
5152
Only Essential Versions, and Branching points will be retained.
5153
 
5154
=back
5155
 
5156
=back
5157
 
5158
=head1 DESCRIPTION
5159
 
5160
This program is a tool used in the conversion of ClearCase VOBS to subversion.
5161
It will take a complete package and all relevent versions from ClearCase and
5162
insert them into subversion in a sessible manner. It will attempt to retain
5163
file change order and history.
5164
 
5165
It will:
5166
 
5167
=over 8
5168
 
5169
=item *
5170
 
5171
Read in the Essential Package Version list.
5172
 
5173
=item *
5174
 
5175
Extract, from Release Manager, all known versions of the specified package.
5176
 
5177
=item *
5178
 
5179
It will attempt to determine the type of package: COTS, TOOL, CORE, PROJECT
5180
and alter the processing accordingly.
5181
 
5182
=item *
5183
 
5184
It will create a version dependency tree and determine 'new' project branch
5185
points. It will remove (prune) versions that are excess to requirements.
5186
 
5187
=item *
5188
 
5189
It will extract source from ClearCase and insert it into SVN, creating
5190
branches and tags as it goes.
5191
 
5192
=back
5193
 
5194
The program can also be used to create a SVG image of the version dependency
5195
tree. This does not work on Linux; only Windows with 'dot' installed.
5196
 
5197
=cut
5198