Subversion Repositories DevTools

Rev

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

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